Skip to content

Mistral: use fork-capable attention bridge (enable hook_attn_in / set_use_attn_in)#1497

Merged
jlarson4 merged 3 commits into
TransformerLensOrg:devfrom
almogtavor:feat/bridge-attn-in-hook
Jul 23, 2026
Merged

Mistral: use fork-capable attention bridge (enable hook_attn_in / set_use_attn_in)#1497
jlarson4 merged 3 commits into
TransformerLensOrg:devfrom
almogtavor:feat/bridge-attn-in-hook

Conversation

@almogtavor

@almogtavor almogtavor commented Jul 9, 2026

Copy link
Copy Markdown

Mistral loads through the plain AttentionBridge, which delegates q/k/v to HF and exposes no per-receiver fork point. So on a bridged Mistral, set_use_attn_in(True) raises and blocks.{i}.hook_attn_in (and the q/k/v input forks) never exist, making per-head attention-input interventions (activation/path patching that edits a receiver input) impossible.

Mistral is structurally identical to Qwen2 here (separate q/k/v/o_proj, RoPE, GQA, RMSNorm, gated MLP), which uses PositionEmbeddingsAttentionBridge.

Fix

  • Point the Mistral adapter at PositionEmbeddingsAttentionBridge (same bridge as Qwen2/Qwen3).
  • Pass config to Mistral's BlockBridge so hook_mlp_in is wired too.

Test

tests/unit/model_bridge/test_mistral_attn_in_fork.py boots hf-internal-testing/tiny-random-MistralForCausalLM and checks the bridge is PositionEmbeddingsAttentionBridge, hook_attn_in fires at [batch, pos, n_heads, d_model], and zeroing a single head's forked input changes the logits.

Mistral has separate q/k/v/o projections with RoPE and GQA, structurally
identical to Qwen2, but its adapter used the plain AttentionBridge, which
delegates q/k/v to HF and exposes no per-receiver fork point. As a result
set_use_attn_in() raised and blocks.{i}.hook_attn_in did not exist, so
per-head input interventions (activation/path patching on attention inputs)
were impossible on Mistral.

Switch the Mistral adapter to PositionEmbeddingsAttentionBridge (the same
fork-capable bridge Qwen2/Qwen3 use) and pass config to its BlockBridge so
hook_mlp_in is wired too. Add a test booting the tiny random Mistral that
checks the attention bridge is fork-capable, hook_attn_in fires at
[batch, pos, n_heads, d_model], and zeroing a single head's forked input
actually changes the logits.
@jlarson4

jlarson4 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

@almogtavor This looks good to me, from my review. Please just update or remove the stale test that is causing CI to fail. test_mistral_adapter.py::test_attn_is_not_position_embeddings_subclass currently asserts "Mistral uses plain AttentionBridge, not PositionEmbeddingsAttentionBridge." This is no longer true, and is tripping CI.

@jlarson4

Copy link
Copy Markdown
Collaborator

@almogtavor I did find one additional item while running some verify_models runs against this change. It breaks quantized models.

Run pytest tests/integration/model_bridge/test_bridge_integration.py -k quantized and fix the regression (most likely solution will be porting the fp-dtype guard into PositionEmbeddingsAttentionBridge from AttentionBridge.forward)

@almogtavor

Copy link
Copy Markdown
Author

@jlarson4 Awesome, I'll fix it thanks !

@jlarson4

Copy link
Copy Markdown
Collaborator

Hey @almogtavor! Just wanted to touch base and see if you'll have an opportunity to wrap this up within the next couple days. I am getting ready to do a release, and would love to include this if it will be ready.

Thank you!

@almogtavor

Copy link
Copy Markdown
Author

@jlarson4 Of course, I'll wrap it up on the weekend :)

PositionEmbeddingsAttentionBridge used the first param's dtype, which is
integer storage on quantized models (uint8 bnb, int32 GPTQ), so fp hidden
states got cast to it. Ported the guard from AttentionBridge.

Also updates the two Mistral tests that still assumed a plain
AttentionBridge. The quantized one reads the dtype at q_proj now, since
the reimplemented bridge never calls the HF attention forward.
@almogtavor

almogtavor commented Jul 23, 2026

Copy link
Copy Markdown
Author

@jlarson4 Both fixed :)

The stale assert is inverted now. For quantized, ported the non-fp param skip into PositionEmbeddingsAttentionBridge. Had to touch that test too: it captured dtype by stubbing the HF attention forward, and the reimplemented bridge doesn't call it, so it reads the dtype at q_proj now. Verified it still fails without the guard.

@jlarson4

Copy link
Copy Markdown
Collaborator

Looks great on my end! Thanks for putting this together! Merging now @almogtavor

@jlarson4
jlarson4 merged commit 0554545 into TransformerLensOrg:dev Jul 23, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants