Coverage for transformer_lens/utilities/position_ids.py: 100%
22 statements
« prev ^ index » next coverage.py v7.10.1, created at 2026-10-23 20:45 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2026-10-23 20:45 +0000
1"""Shared eligibility gate for mask-derived position IDs."""
3import inspect
5from torch import nn
8def accepts_mask_derived_position_ids(model: nn.Module) -> bool:
9 """Accept explicit/kwargs positions unless the model owns their derivation."""
10 parameters = inspect.signature(model.forward).parameters
11 if "position_ids" not in parameters and not any(
12 p.kind is inspect.Parameter.VAR_KEYWORD for p in parameters.values()
13 ):
14 return False
15 # ``get_rope_index`` lives on the inner text model, not the ForConditionalGeneration wrapper.
16 for module in (model, getattr(model, "model", None), getattr(model, "language_model", None)):
17 if module is not None and hasattr(module, "get_rope_index"):
18 return False
19 # Config-level backstop for mRoPE models that spell the derivation differently; the
20 # section list is what makes positions 3-D.
21 config = getattr(model, "config", None)
22 for candidate in (config, getattr(config, "text_config", None)):
23 scaling = getattr(candidate, "rope_scaling", None)
24 if isinstance(scaling, dict) and "mrope_section" in scaling:
25 return False
26 # fairseq-style (RoBERTa) embeddings start positions at padding_idx + 1; an injected
27 # 0-based arange would put content tokens on the reserved rows.
28 for module in model.modules():
29 if callable(getattr(module, "create_position_ids_from_input_ids", None)):
30 return False
31 # A positional embedding that takes the mask derives positions for itself; only
32 # embeddings that override nn.Embedding.forward are worth inspecting.
33 for module in model.modules():
34 if isinstance(module, nn.Embedding) and type(module).forward is not nn.Embedding.forward:
35 if "attention_mask" in inspect.signature(module.forward).parameters:
36 return False
37 return True