You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/source/content/compatibility_mode.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,6 +64,21 @@ After `enable_compatibility_mode()`, these HT hook names fire on the **pre-norm
64
64
-**Post-norm architectures** (OLMo 2, BERT-style) read the **post-attention residual** instead, because the norm semantically lives elsewhere in the block.
65
65
-**MLA blocks** (DeepSeek V2 / V3 / R1) do **not** expose the split-qkv aliases — MLA's compressed K/V doesn't have a clean split.
66
66
67
+
On post-norm architectures (Gemma 2/3's `ln1_post`/`ln2_post`, OLMo 2/3's `ln1`/`ln2`),
68
+
`blocks.{i}.hook_attn_out` / `hook_mlp_out` fire **after** the post-sublayer norm, so
69
+
that they capture the tensor added to the residual stream and the identities
70
+
`resid_pre + attn_out == resid_mid` and `resid_mid + mlp_out == resid_post` hold
One consequence for head-level direct logit attribution: per-head contributions from
73
+
`attn.hook_result` no longer sum to `hook_attn_out`, because the norm sits between
74
+
them. This is inherent to post-norm — decompose heads on the pre-norm side
75
+
(`attn.hook_out` for the raw module output) or attribute through the norm explicitly.
76
+
The Granite family has the same raw-vs-contribution split for a different reason:
77
+
HF scales each sublayer output by `residual_multiplier` before the residual add, so
78
+
`hook_attn_out` / `hook_mlp_out` fire on the scaled contribution while
79
+
`attn.hook_out` / `mlp.hook_out` stay raw — `attn.hook_result` sums to the raw
80
+
output, off from the contribution by the multiplier.
81
+
67
82
An adapter author for a new post-norm or MLA-style architecture must handle these carve-outs in `setup_hook_compatibility`. The Gemma1/Gemma2 adapters are exemplars of when **not** to override `setup_hook_compatibility` — `GemmaTextScaledWordEmbedding` already scales internally, so any added `hook_conversion` would double-scale `embed.hook_out`.
0 commit comments