transformer_lens.model_bridge.generalized_components.block module¶
Block bridge component.
This module contains the bridge component for transformer blocks.
- class transformer_lens.model_bridge.generalized_components.block.BlockBridge(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None, mlp_reads_resid_directly: bool = False)¶
Bases:
GeneralizedComponentBridge component for transformer blocks.
This component provides standardized input/output hooks and monkey-patches HuggingFace blocks to insert hooks at positions matching HookedTransformer.
- __init__(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None, mlp_reads_resid_directly: bool = False)¶
Initialize the block bridge.
- Parameters:
name – The name of the component in the model
config – Optional configuration (unused for BlockBridge)
submodules – Dictionary of submodules to register
hook_alias_overrides – Optional dictionary to override default hook aliases. For example, {“hook_attn_out”: “ln1_post.hook_out”} will make hook_attn_out point to ln1_post.hook_out instead of the default attn.hook_out.
mlp_reads_resid_directly – True for post-norm blocks where the MLP consumes the mid-residual with no pre-MLP norm (OLMo 2 layout). Moves the hook_mlp_in capture from ln2 (whose input there is the raw MLP output) to the MLP itself.
- forward(*args: Any, **kwargs: Any) Any¶
Forward pass through the block bridge.
- Parameters:
*args – Input arguments
**kwargs – Input keyword arguments
- Returns:
The output from the original component
- Raises:
StopAtLayerException – If stop_at_layer is set and this block should stop execution
- hook_aliases: Dict[str, str | List[str]] = {'hook_attn_in': 'attn.hook_attn_in', 'hook_attn_out': 'attn.hook_out', 'hook_k_input': 'attn.hook_k_input', 'hook_mlp_out': 'mlp.hook_out', 'hook_q_input': 'attn.hook_q_input', 'hook_resid_mid': 'ln2.hook_in', 'hook_resid_post': 'hook_out', 'hook_resid_pre': 'hook_in', 'hook_v_input': 'attn.hook_v_input'}¶
- hook_out_is_single_residual_stream: bool = True¶
- is_list_item: bool = True¶
- real_components: Dict[str, tuple]¶
- training: bool¶
- class transformer_lens.model_bridge.generalized_components.block.DelegatedAttentionBlockBridge(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None)¶
Bases:
BlockBridgeBlock whose attention is delegated wholesale to HF (no split-qkv fork).
For architectures with heterogeneous per-layer attention structure — e.g. Gemma 4, where KV-shared layers have no
k_proj/v_projat all and K==V layers have nov_proj— there is no uniform HookPoint that represents “input that becomes Q/K/V”, so the block-levelhook_q_input/hook_k_input/hook_v_input/hook_attn_inaliases do not apply. Type-level distinction means a reader of the adapter seesDelegatedAttentionBlockBridgeand knows those hooks are absent.- maintain_native_attention: bool = True¶
- real_components: Dict[str, tuple]¶
- training: bool¶
- class transformer_lens.model_bridge.generalized_components.block.MLABlockBridge(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None)¶
Bases:
BlockBridgeBlock wrapping Multi-Head Latent Attention (DeepSeek V2/V3/R1).
MLA has no standalone q/k/v projections — Q flows through compressed q_a_proj→q_a_layernorm→q_b_proj, and K/V share a joint kv_a_proj_with_mqa entry point. There is no single HookPoint that represents “input that becomes Q/K/V”, so the block-level
hook_q_input/hook_k_input/hook_v_input/hook_attn_inaliases do not apply. Type-level distinction means a reader of the adapter seesMLABlockBridgeand knows those hooks are absent.
- class transformer_lens.model_bridge.generalized_components.block.ParallelBlockBridge(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None)¶
Bases:
BlockBridgeBlock where attn and MLP both read the pre-attention residual.
For GPT-J, NeoX, Pythia, Phi, Cohere, CodeGen, and some Falcon variants, output = resid_pre + attn_out + mlp_out — no distinct post-attention residual exists. Matches legacy HookedTransformer which omits hook_resid_mid when
cfg.parallel_attn_mlp=True. Type-level distinction means a reader of the adapter seesParallelBlockBridgeand knows the hook is absent.
- class transformer_lens.model_bridge.generalized_components.block.ScaledResidualBlockBridge(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None, mlp_reads_resid_directly: bool = False, residual_contribution_scale: float = 1.0, scaled_attn_submodule: str = 'attn', scaled_mlp_submodule: str | None = 'mlp')¶
Bases:
BlockBridgeBlock whose sublayer outputs are scaled before the residual add.
Granite-family HF blocks compute
residual + sublayer_out * residual_multiplierinline, so no submodule output equals the tensor added to the residual stream and the legacy aliases cannot be fixed by re-pointing.hook_attn_out/hook_mlp_outbecome real HookPoints on the block firing on the scaled contribution:no hooks attached: the forward is untouched (bit-exact);
read-only hooks: they observe
module_out * scale, forward stays bit-exact;a hook that changes the tensor (returned new or mutated in place): the module output is rewritten to
hooked / scaleso HF’s multiply reconstructs the written value as the contribution (~1-ulp rounding; exact for zero-ablation);any backward hooks: the rewrite always happens so the autograd graph routes through the HookPoint.
- __init__(name: str, config: Any | None = None, submodules: Dict[str, GeneralizedComponent] | None = None, hook_alias_overrides: Dict[str, str] | None = None, mlp_reads_resid_directly: bool = False, residual_contribution_scale: float = 1.0, scaled_attn_submodule: str = 'attn', scaled_mlp_submodule: str | None = 'mlp')¶
scaled_mlp_submodule=None when no single submodule feeds the MLP-side add (GraniteMoeHybrid sums moe + shared_mlp inline) — hook_mlp_out then stays absent rather than firing with a partial tensor.
- set_original_component(original_component: Module) None¶
Prune contribution HookPoints the bound layer cannot fire.
Heterogeneous blocks (GraniteMoeHybrid mamba layers) lack the attn submodule; a HookPoint that exists but never fires is a silent-no-op intervention trap, so the name must be absent instead.