Skip to content

[GPT2] Fix encoder_attention_mask being silently discarded in cross-attention - #47946

Merged
Rocketknight1 merged 2 commits into
huggingface:mainfrom
DavidJohnQuinlan:gpt2_cross_attention_discarding_encoder_attention_mask
Aug 18, 2026
Merged

Rocketknight1 merged 2 commits into
huggingface:mainfrom
DavidJohnQuinlan:gpt2_cross_attention_discarding_encoder_attention_mask

Conversation

@DavidJohnQuinlan

@DavidJohnQuinlan DavidJohnQuinlan commented Aug 13, 2026 •

Copy link
Copy Markdown
Contributor

CI

What does this PR do?

On line 591 (encoder_attention_mask = None) in GPT2Model in src/transformers/models/gpt2/modeling_gpt2.py appears to be a bug. The user defined encoder_attention_mask is overwritten and set to None before it is passed to create_bidirectional_mask. This has a knock on effect on the creation of an encoder_attention_mask in the case that there are padding tokens present in the input. This causes padding tokens not be ignored during the cross attention calculation with attention_mask=None (since encoder_attention_mask=None) when calling torch.nn.functional.scaled_dot_product_attention.

This bug was introduced in the recent masking refactor [Attn] New attn mask interface everywhere (#42848) (4b8ba25). I appreciate that this is not the default use case for GPT2 but seemed wrong to not highlight/fix when reviewing GPT2 model code.

What's implemented

The fix involves simply removing this line of code from the GPT2Model in addition to removing the same bug from the DecisionTransformer model which copies code from the GPT2 model. Additionally, to ensure that this type of error does not re-occur I have added a regression test to the GPT2 tests. This test assigns some of the input tokens as padding tokens which should be removed, a copy of the encoder hidden states is also generated with their padded tokens assigned corrupted values. A comparison is made between the last hidden state of the clean and corrupted encoder hidden states. The idea being that these tokens will never be output due to the mask fix, however, when the mask was set to None these output values would be different due to the addition of the corrupted data.

AI assistance

I identified the bug, wrote the fix and created the test. Claude Code was used as a review and feedback tool during development.

Before submitting

Who can review?

@Rocketknight1 @qgallouedec @vasqu

@Rocketknight1 Rocketknight1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one fix!

Comment thread tests/models/gpt2/test_modeling_gpt2.py Resolved
@Rocketknight1

Copy link
Copy Markdown
Member

run-slow: decision_transformer, gpt2

@github-actions

Copy link
Copy Markdown
Contributor

[For maintainers] Suggested jobs to run (before merge)

run-slow: decision_transformer, gpt2

@github-actions

Copy link
Copy Markdown
Contributor

Workflow Run ⚙️

This comment contains run-slow, running the specified jobs:

models: ["models/decision_transformer", "models/gpt2"]
quantizations: []

DavidJohnQuinlan and others added 2 commits August 14, 2026 12:50
…ss-attention

The new attn mask interface (huggingface#42848) rewired GPT2Model and its decision_transformer
copy to build the cross-attention mask via create_bidirectional_mask, but added an
encoder_attention_mask = None line directly above the call that overwrote the incoming
mask before it was passed in. As a result, encoder padding was ignored in cross-attention.
Remove the line and add a regression test.
@Rocketknight1
Rocketknight1 force-pushed the gpt2_cross_attention_discarding_encoder_attention_mask branch from 567ca8f to 72a9509 Compare August 14, 2026 11:50
@github-actions

Copy link
Copy Markdown
Contributor

CI Results

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN 0fba2bc3 workflow commit (merge commit)
PR 567ca8f1 branch commit (from PR)
main ed3edd87 base commit (on main)

✅ No failing test specific to this PR 🎉 👏 !

@github-actions

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 31797865877:2
Result: success | Jobs: 16 | Tests: 180,662 | Failures: 0 | Duration: 16h 8m

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@Rocketknight1
Rocketknight1 added this pull request to the merge queue Aug 18, 2026
Merged via the queue into huggingface:main with commit e0aeab4 Aug 18, 2026
114 checks passed
@vasqu

vasqu commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Oh wow, thanks for fixing @DavidJohnQuinlan! That one is probably on me 😬

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.

4 participants