Analysis Runner Usage#
Status: Working design document Audience: Contributors working with Interpretune’s analysis pipeline
Overview#
Interpretune provides two runner implementations in src/interpretune/runners/:
Runner |
Module |
Phases |
Use Case |
|---|---|---|---|
|
|
|
Standard training and evaluation workflows |
|
|
|
Extends |
Both runners operate in the core (non-Lightning) framework context. The Lightning adapter delegates loop orchestration to its own Trainer and does not currently use these runners.
SessionRunner#
SessionRunner is a barebones trainer that orchestrates training and testing when no framework adapter is specified during ITSession composition.
Lifecycle#
__init__— Accepts aSessionRunnerCfg(or dict), validates supported commands, callsit_init().it_init()— Dispatches the framework-independentit_initfunction which prepares the data module, model, and optimizers._run(phase, loop_fn)— Sets the currentCorePhasesenum, calls the loop function with the runner config, then dispatchesit_session_end().it_session_end()— Fires phase-specific session-end hooks.
Loop Functions#
core_train_loop— Multi-epoch training with optional validation. Managesmodel.train()/model.eval()transitions, optimizer steps, and epoch-level hooks.core_test_loop— Single-epoch evaluation undertorch.inference_mode(). Prints accumulatedlog()/log_dict()metrics at epoch end.
Entry Points#
runner = SessionRunner(run_cfg)
runner.test() # Dispatches core_test_loop
runner.train() # Dispatches core_train_loop
AnalysisRunner#
AnalysisRunner extends SessionRunner with the analysis phase and provides the primary interface for running analysis workflows.
Additional Capabilities#
analysisphase — Apartialmethodthat dispatchescore_analysis_loop.run_analysis(analysis_cfg)— High-level entry point accepting one or moreAnalysisCfgobjects._run_analysis_cfg()— Wraps execution in anactivated_analysis_cfgcontext manager and dispatches the analysis loop.Dataset generation — Uses
Dataset.from_generator()withanalysis_store_generatorto produce HFDatasetobjects from model inference steps.Analysis hooks — Fires
on_analysis_start,on_analysis_epoch_end, andon_analysis_endhooks.
core_analysis_loop#
The analysis loop creates a streaming pipeline:
Calls
run_step(step_fn=..., as_generator=True)which yields per-batch outputs.Wraps the generator in
analysis_store_generatorto apply output formatting.Passes to
Dataset.from_generator()with features derived from the op’s output schema viaschema_to_features().Saves the resulting dataset to the analysis output store.
Returns the
AnalysisStoreProtocolobject.
Entry Points#
runner = AnalysisRunner(run_cfg)
runner.test() # Inherited from SessionRunner
runner.train() # Inherited from SessionRunner
runner.run_analysis(cfg) # Analysis-specific
AnalysisCfg#
AnalysisCfg is the dataclass that configures an analysis run:
Field |
Purpose |
|---|---|
|
Where to save analysis results |
|
Optional input dataset for multi-step composition |
|
Which step function to use (e.g., |
|
Schema defining the output dataset columns |
|
Optional filter for specific hook point names |
|
Directory for caching intermediate results |
Comparison: Core Test Loop vs Analysis Loop#
Aspect |
|
|
|---|---|---|
Output |
Metrics printed at epoch end |
HF |
Inference mode |
|
|
Hook dispatch |
|
|
Metric logging |
|
Not applicable |
Return value |
None |
|
Generator support |
No |
Yes ( |
Execution Helpers: execute_analysis_op and execute_analysis_step#
Beyond the AnalysisRunner loop, Interpretune exposes two lower-level helpers in
interpretune.analysis.execution for interactive and one-shot analysis workflows:
execute_analysis_op#
Executes a single analysis op on a module without entering the full runner loop:
from interpretune.analysis.execution import execute_analysis_op
result = execute_analysis_op(
module,
batch,
batch_idx=0,
analysis_cfg=my_cfg, # AnalysisCfg with a resolved op
analysis_inputs=my_inputs, # optional AnalysisInputs or dict
)
# result is an AnalysisBatch containing op outputs
Internally it:
Resolves the
analysis_cfg(from the argument ormodule.analysis_cfg).Enters an
activated_analysis_cfgcontext that temporarily setsmodule.analysis_cfgand callsinit_analysis_cfgs.Builds merged
AnalysisInputsfrom config-backed and caller-provided values.Calls
active_cfg.op(module, analysis_batch, batch, batch_idx, ...).
execute_analysis_step#
Wraps execute_analysis_op with serialization — it executes the op, then
yields serialized rows via resolved_cfg.save_batch(...):
from interpretune.analysis.execution import execute_analysis_step
for row in execute_analysis_step(module, batch, batch_idx=0, analysis_cfg=my_cfg):
print(row) # serialized dict suitable for Dataset.from_generator
This is the same function the AnalysisRunner uses internally. When
AnalysisCfg.apply(module) finds no manual analysis_step, it generates one
that delegates to execute_analysis_step.
When to use each#
Function |
Returns |
Use Case |
|---|---|---|
|
|
Interactive exploration, debugging, multi-step composition |
|
Generator of serialized dicts |
Building HF Datasets, feeding |
|
|
Full pipeline: loop + hooks + dataset persistence |
Relationship to the runner#
AnalysisRunner.run_analysis()
└─ core_analysis_loop()
└─ run_step(as_generator=True)
└─ generated analysis_step
└─ execute_analysis_step()
└─ execute_analysis_op()
└─ analysis_cfg.op(module, batch, ...)
Notebook and Interactive Usage#
Top-level op wrappers#
In notebooks and interactive scripts, prefer top-level op wrappers:
import interpretune as it
import interpretune.analysis # ensure op wrappers are registered
result = it.concept_direction(...)
result = it.compute_attribution_graph(...)
These are OpWrapper proxies registered on the interpretune module when
interpretune.analysis is first imported. They lazily instantiate the
underlying AnalysisOp from the DISPATCHER on first call.
Direct execute_analysis_op usage#
For workflows that require explicit AnalysisCfg control (e.g., setting
analysis_inputs, input_store, or composing multiple ops), call
execute_analysis_op directly:
from interpretune.analysis import AnalysisCfg, execute_analysis_op
import interpretune as it
cfg = AnalysisCfg(
target_op=it.concept_direction,
# ... other config
)
result = execute_analysis_op(module, batch, analysis_cfg=cfg, analysis_inputs=inputs)
This is the pattern the planned circuit-tracer cross-backend composition demo will use
(tracked in #224; see
circuit_tracer_backend_support.md — no committed notebook demonstrates it yet).
Current Limitations#
Lightning integration —
AnalysisRunnerextendsSessionRunner(core framework). Running analysis workflows through a LightningTraineris not yet supported.Single-process only — Analysis loops do not support distributed execution.
Core-only hooks — Analysis hooks (
on_analysis_start, etc.) are only fired by the core runner, not by Lightning callbacks.