Skip to content

Fix tests due to dropping attn mask - #48903

Merged
SunMarc merged 7 commits into
mainfrom
fix-no-attn-mask-test
Sep 18, 2026
Merged

SunMarc merged 7 commits into
mainfrom
fix-no-attn-mask-test

Conversation

@SunMarc

@SunMarc SunMarc commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

CPU CI GPU run-slow

What does this PR do?

This PR fixes the following tests that were broken due to removing the attn mask early from this PR #48814

ImageGPT — tests/models/imagegpt/test_modeling_imagegpt.py

  • ImageGPTModelTest::test_onnx_export_generate_dynamic
  • ImageGPTModelTest::test_torch_export_generate_dynamic

RuntimeError: The size of tensor a (s70 + s85) must match the size of tensor b (s70) at non-singleton dimension 3)"

Its create_bidirectional_mask() call didn’t receive past_key_values. Previously, the 2D attention mask supplied the full length: cached tokens plus new tokens. Once that mask became None, the helper inferred the length from only the new embeddings. Attention scores still included cached tokens, producing the reported s70 + s85 versus s70 mismatch.

Moshi — tests/models/moshi/test_modeling_moshi.py

  • MoshiDecoderTest::test_cached_decode_matches_cacheless (flaky tests btw)

For Moshi, the issue is that we were using the eager attn implementation that requires a mask.

Previously, the 2D mask reached Moshi but now, there is no mask. The controlled comparison was 100/100 passing seeds before the PR, 97/100 after, and 100/100 with the fix. The apparent flakiness comes from which random inputs expose the incorrect behavior.

Three ways to solves this: always create the mask or we don't drop the attn mask when we use eager. Last solution would be to fix eager to deal with the case where the mask is None but I don't think we should assume that the mask is all ones ?

Qwen3-Omni — tests/models/qwen3_omni_moe/test_modeling_qwen3_omni_moe.py

  • Qwen3OmniModelIntegrationTest::test_small_model_integration_test_batch_audio_matches_single
  • Qwen3OmniModelIntegrationTest::test_small_model_integration_test_w_audio

We need to refactor to use the new api with _prepare_position_ids_for_generation that is in generate where the mask is still not dropped. the changes are similar to this PR #47872. Some arch might also need this fix ? @zucchini-nlp

Comment thread src/transformers/generation/utils.py Outdated
if (
not self.config.is_encoder_decoder
and accepts_attention_mask
and self.config.get_text_config()._attn_implementation != "eager"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

should do that @Cyrilvallez ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

hmm I know flex attn was never actually used for inference but was it considered at some point? 😢

attention_mask=attention_mask,
past_key_values=past_key_values,
position_ids=position_ids,
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

otherwise the fix is this one but i think the issue with eager might happen with other models as well

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should be fine, no reason to do this prev pattern

@SunMarc SunMarc Sep 17, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

okay then we can probably drop the eager check no ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The eager check was only needed for this?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Imo, we should never do

if mask is none: create_mask

that portion should properly handle the skips and creation and is an anti pattern to the create fn

@ydshieh

ydshieh commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

remember to run-slow and check results on the job run page 🙏

@vasqu vasqu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Imo fine to fix this way, I'd like Raushan's opinion on the qwen part because im wondering where this came from 👀

Other than that, for the future: Was flex attn considered?

Comment thread src/transformers/generation/utils.py Outdated
if (
not self.config.is_encoder_decoder
and accepts_attention_mask
and self.config.get_text_config()._attn_implementation != "eager"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

hmm I know flex attn was never actually used for inference but was it considered at some point? 😢

attention_mask=attention_mask,
past_key_values=past_key_values,
position_ids=position_ids,
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should be fine, no reason to do this prev pattern


return position_ids

def _expand_inputs_for_generation(self, expand_size=1, is_encoder_decoder=False, input_ids=None, **model_kwargs):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ig this comes from other qwen vls? at least the pattern

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

would like Raushan's opinion on this

@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.

@zucchini-nlp zucchini-nlp 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.

thanks, i have only one concern on text-only generation

Comment on lines +1774 to +1776
def _prepare_position_ids_for_generation(self, inputs_tensor, model_kwargs):
# Overwritten -- requires 3D position ids

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.

oh i love qwen!

Comment on lines +1796 to +1805
if is_input_ids and attention_mask is not None:
vision_positions, rope_deltas = self.get_rope_index(
inputs_tensor,
image_grid_thw=model_kwargs.get("image_grid_thw"),
video_grid_thw=model_kwargs.get("video_grid_thw"),
attention_mask=attention_mask,
use_audio_in_video=model_kwargs.get("use_audio_in_video") or False,
audio_seqlens=model_kwargs.get("audio_feature_lengths"),
second_per_grids=model_kwargs.get("video_second_per_grid"),
)

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.

and if there are multimodal inputs, i think it will throw an error otherwise trying to pop inputs from empty grid_thw

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

indeed, fixed !

Comment on lines +1819 to +1830
def _expand_inputs_for_generation(self, expand_size=1, is_encoder_decoder=False, input_ids=None, **model_kwargs):
position_ids = model_kwargs.pop("position_ids", None)
input_ids, model_kwargs = super()._expand_inputs_for_generation(
expand_size=expand_size,
is_encoder_decoder=is_encoder_decoder,
input_ids=input_ids,
**model_kwargs,
)
if position_ids is not None:
batch_dim = 1 if position_ids.ndim == 3 else 0
model_kwargs["position_ids"] = position_ids.repeat_interleave(expand_size, dim=batch_dim)
return input_ids, model_kwargs

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.

this defi doesn't work well for images/videos 😆

old hidden bug, but let it be - this model is almost never used atm, and we'll remove all overriden expansion soon 🤞🏻

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

okay XD

Comment on lines +1754 to +1757
if past_length == 0 or self.rope_deltas is None:
if attention_mask is None:
attention_mask = torch.ones((batch_size, seq_length), dtype=torch.long, device=inputs_tensor.device)
position_ids, rope_deltas = self.get_rope_index(

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.

same here, might need a check has_multimodal_data

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added !

@SunMarc

SunMarc commented Sep 17, 2026

Copy link
Copy Markdown
Member Author

Other than that, for the future: Was flex attn considered?
cc @Cyrilvallez for this !

@SunMarc

SunMarc commented Sep 17, 2026

Copy link
Copy Markdown
Member Author

run-slow: imagegpt, kyutai_speech_to_text, moshi, qwen3_omni_moe

@github-actions

Copy link
Copy Markdown
Contributor

AMD CI

Workflow Run ⚙️

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

models: ["models/imagegpt", "models/kyutai_speech_to_text", "models/moshi", "models/qwen3_omni_moe"]

@github-actions

Copy link
Copy Markdown
Contributor

Nvidia CI

Workflow Run ⚙️

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

models: ["models/imagegpt", "models/kyutai_speech_to_text", "models/moshi", "models/qwen3_omni_moe"]
quantizations: []

@github-actions

Copy link
Copy Markdown
Contributor

CI Results (AMD)

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN 8f0e49a5 workflow commit (merge commit)
PR 868c6d5c branch commit (from PR)
main da58b892 base commit (on main)

Model CI Report

❌ 2 new failed tests from this PR 😭

  • qwen3_omni_moe:
    tests/models/qwen3_omni_moe/test_modeling_qwen3_omni_moe.py::Qwen3OmniModelIntegrationTest::test_small_model_integration_test_batch_flashatt2 (❌ ⟹ ❌)
    tests/models/qwen3_omni_moe/test_modeling_qwen3_omni_moe.py::Qwen3OmniModelIntegrationTest::test_small_model_integration_test_batch_audio_matches_single (❌ ⟹ ❌)

@zucchini-nlp zucchini-nlp 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.

Ig slow ci is failing because of audio, otherwise lgm

) -> torch.Tensor:
batch_size, seq_length = inputs_tensor.shape[:2]
past_length = 0 if past_key_values is None else past_key_values.get_seq_length()
has_multimodal_data = any(grid is not None and grid.numel() > 0 for grid in (image_grid_thw, video_grid_thw))

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.

or audio_seqlens is not None :)

@github-actions

Copy link
Copy Markdown
Contributor

CI Results (Nvidia)

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN 8f0e49a5 workflow commit (merge commit)
PR 868c6d5c branch commit (from PR)
main da58b892 base commit (on main)

✅ No failing test specific to this PR 🎉 👏 !

@vasqu vasqu left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's remove the eager attn check as well no? like mentioned the is mask is none pattern is an anti pattern the create mask fn should handle it imo

@SunMarc

SunMarc commented Sep 17, 2026

Copy link
Copy Markdown
Member Author

Okay I will fix this !

@Cyrilvallez Cyrilvallez 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.

Would like to understand why we don't drop if eager please before merge?

Comment thread src/transformers/generation/utils.py Resolved
@Cyrilvallez

Copy link
Copy Markdown
Member

If it's for a specific model that explicitly uses the 2D mask all the time, IMO needs to be fixed on the model side directly! (i.e. something along mask = torch.ones() if mask is None else mask)

@molbap

molbap commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Yes, will fail on mllama and idefics currently, in cases where the random test sets the mask to all ones (happens) will be dropped, so the query and image mask will have different lenghts and it will crash

@molbap

molbap commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

for idefics a block like this in the crosss attention mask computation

            padding_length = seq_length - image_attention_mask.shape[1]
            if padding_length > 0:
                image_attention_mask = torch.cat(
                    [
                        image_attention_mask,
                        image_attention_mask[:, -1:].expand(-1, padding_length, -1),
                    ],
                    dim=1,
                )

should work, there

seq_length = model_inputs["input_ids"].shape[1]
(after seq length computation)
not beautiful but should work

@github-actions

Copy link
Copy Markdown
Contributor

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

run-slow: imagegpt, kyutai_speech_to_text, moshi, qwen3_omni_moe

@SunMarc
SunMarc enabled auto-merge September 18, 2026 15:20
@SunMarc

SunMarc commented Sep 18, 2026 •

Copy link
Copy Markdown
Member Author

Yes, will fail on mllama and idefics currently, in cases where the random test sets the mask to all ones (happens) will be dropped, so the query and image mask will have different lenghts and it will crash

I didn't manage to reproduce the failing test even with all ones masks (maybe bcause i'm running this on cpu/mps ?) We can have a look at this in a follow-up PR ! I'll first merge to this PR, so that the other models are fixed.

@SunMarc
SunMarc added this pull request to the merge queue Sep 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 35352874234:1
Result: success | Jobs: 16 | Tests: 190,602 | Failures: 24 | Duration: 13h 16m

Merged via the queue into main with commit b856a67 Sep 18, 2026
114 checks passed
@SunMarc
SunMarc deleted the fix-no-attn-mask-test branch September 18, 2026 15:38
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.

7 participants