Skip to content

fix: keep the causal mask for broadcast 4D padding masks - #1971

Merged
jlarson4 merged 1 commit into
TransformerLensOrg:devfrom
YHC66:fix-causal-mask-broadcast-padding-4d
Nov 4, 2026
Merged

jlarson4 merged 1 commit into
TransformerLensOrg:devfrom
YHC66:fix-causal-mask-broadcast-padding-4d

Conversation

@YHC66

@YHC66 YHC66 commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Description

AttentionBridge._apply_reconstruct_attention_mask treats every 4D mask as already encoding causal semantics and skips the local causal mask. That holds for the [batch, 1, seq, seq] masks most models build, but HF's OpenAIGPTModel passes a padding-only [batch, 1, 1, seq] mask and leaves the causal part to the attention module's bias buffer. So on GPT-1, any attention mask lets every position attend to later tokens.

This is reachable by passing attention_mask= or padding_side="left" to the bridge. Without a mask, and for right-padded string lists (which pass no mask), GPT-1 was already correct.

On openai-community/openai-gpt with "the capital of france is" and an all-ones mask:

Before After
Max logit difference from HF 20.59 2.1e-5 (same as with no mask)
Top-1 next token all (HF: a) a
Attention from position 0 to later tokens, block 0 ~0.78 0

The fix only treats a 4D mask as authoritative when it has its own query rows (shape[-2] != 1). A single query row is also what a causal 4D mask looks like on a cached decode step, but the causal mask allows every key for that row, so applying it there changes nothing; there is a test for that case.

I found this with a padding comparison across the supported causal LM architectures, following #1952. GPT-1 was the only one showing it, and it is the only supported architecture I found in transformers that passes this mask shape.

Not related to #1969, which is about hook_out on the same model.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Testing

  • New tests in test_mask_slicing.py and test_openai_gpt_adapter.py (the GPT-1 ones use a tiny random model, no download): 4 fail before the fix, all 12 pass after.
  • tests/unit -m "not slow" on the locked environment: 8117 passed, 0 failed.
  • test_openai_gpt_adapter, test_forward_padding_side, test_left_padding_positions, test_generate_attention_mask, test_inspect_attention_mask, test_encoder_right_padding_mask and test_attention_score_sentinel: 118 passed.
  • test_mask_slicing, test_openai_gpt_adapter and test_forward_padding_side also pass on transformers 5.20.2 / torch 2.14.1.
  • black, isort, pycln and mypy . are clean.

I did not run the full integration or acceptance suites locally.

Checklist:

  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have not rewritten tests relating to key interfaces which would affect backward compatibility

_apply_reconstruct_attention_mask treated every 4D mask as already encoding
causal semantics. GPT-1 passes a [batch, 1, 1, seq] padding-only mask to its
blocks and leaves the causal mask to the attention module, so any attention
mask opened attention to later tokens. Only skip the local causal mask when
the 4D mask has its own query rows.
@jlarson4
jlarson4 merged commit 4628b39 into TransformerLensOrg:dev Nov 4, 2026
29 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