Repository navigation
Fix tests due to dropping attn mask - #48903
Conversation
| if ( | ||
| not self.config.is_encoder_decoder | ||
| and accepts_attention_mask | ||
| and self.config.get_text_config()._attn_implementation != "eager" |
There was a problem hiding this comment.
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, | ||
| ) |
There was a problem hiding this comment.
otherwise the fix is this one but i think the issue with eager might happen with other models as well
There was a problem hiding this comment.
should be fine, no reason to do this prev pattern
There was a problem hiding this comment.
okay then we can probably drop the eager check no ?
There was a problem hiding this comment.
The eager check was only needed for this?
There was a problem hiding this comment.
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
|
remember to run-slow and check results on the job run page 🙏 |
vasqu
left a comment
There was a problem hiding this comment.
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?
| if ( | ||
| not self.config.is_encoder_decoder | ||
| and accepts_attention_mask | ||
| and self.config.get_text_config()._attn_implementation != "eager" |
There was a problem hiding this comment.
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, | ||
| ) |
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
ig this comes from other qwen vls? at least the pattern
There was a problem hiding this comment.
would like Raushan's opinion on this
|
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
left a comment
There was a problem hiding this comment.
thanks, i have only one concern on text-only generation
| def _prepare_position_ids_for_generation(self, inputs_tensor, model_kwargs): | ||
| # Overwritten -- requires 3D position ids | ||
|
|
| 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"), | ||
| ) |
There was a problem hiding this comment.
and if there are multimodal inputs, i think it will throw an error otherwise trying to pop inputs from empty grid_thw
| 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 |
There was a problem hiding this comment.
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 🤞🏻
| 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( |
There was a problem hiding this comment.
same here, might need a check has_multimodal_data
|
|
run-slow: imagegpt, kyutai_speech_to_text, moshi, qwen3_omni_moe |
AMD CIThis comment contains models: ["models/imagegpt", "models/kyutai_speech_to_text", "models/moshi", "models/qwen3_omni_moe"] |
Nvidia CIThis comment contains models: ["models/imagegpt", "models/kyutai_speech_to_text", "models/moshi", "models/qwen3_omni_moe"] |
CI Results (AMD)Commit Info
Model CI Report❌ 2 new failed tests from this PR 😭
|
zucchini-nlp
left a comment
There was a problem hiding this comment.
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)) |
There was a problem hiding this comment.
or audio_seqlens is not None :)
|
Okay I will fix this ! |
|
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 |
|
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 |
|
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 (after seq length computation)not beautiful but should work |
|
[For maintainers] Suggested jobs to run (before merge) run-slow: imagegpt, kyutai_speech_to_text, moshi, qwen3_omni_moe |
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. |
CI recapDashboard: View test results in Grafana |
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
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 receivepast_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
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
Nonebut 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
We need to refactor to use the new api with
_prepare_position_ids_for_generationthat 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