Coverage for transformer_lens/tools/analysis/_model_state.py: 100%
20 statements
« prev ^ index » next coverage.py v7.10.1, created at 2026-09-21 19:27 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2026-09-21 19:27 +0000
1"""Shared model-state validation for analysis tools."""
3from typing import Any
5import torch
8def require_eval_mode(model: Any, *, operation: str) -> None:
9 """Reject training state anywhere in a wrapped model without mutating it."""
10 training_modules: dict[int, str] = {}
11 roots = (("", model), ("original_model", getattr(model, "original_model", None)))
12 for prefix, root in roots:
13 if not isinstance(root, torch.nn.Module):
14 continue
15 for name, module in root.named_modules():
16 if not module.training:
17 continue
18 qualified_name = ".".join(part for part in (prefix, name) if part)
19 training_modules.setdefault(id(module), qualified_name or "<root>")
20 if not training_modules:
21 return
23 names = list(training_modules.values())
24 preview = ", ".join(names[:3])
25 if len(names) > 3:
26 preview += f", and {len(names) - 3} more"
27 raise ValueError(
28 f"{operation} requires the model and all submodules to be in evaluation "
29 f"mode; found training mode at {preview}. Call model.eval() before running "
30 "the analysis."
31 )