Skip to content

fix: AttributeError for Qwen3_omni_moe - #43593

Merged
zucchini-nlp merged 2 commits into
huggingface:mainfrom
Vallabh-1504:fix-attribute-error
Feb 4, 2026
Merged

fix: AttributeError for Qwen3_omni_moe#43593
zucchini-nlp merged 2 commits into
huggingface:mainfrom
Vallabh-1504:fix-attribute-error

Conversation

@Vallabh-1504

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR fixes a crash when initializing Qwen3OmniMoeTalkerCodePredictorConfig due to a missing attribute reference.

Specifically, it:

  1. Removes the reference to the non-existent use_sliding_window attribute, which was causing an AttributeError.
  2. Adds the missing max_window_layers initialization (defaulting to 28). The existing layer_types logic relies on this attribute, and without it, sliding_window causes a secondary crash.
  3. Adds a new test case (test_code_predictor_config_init) to ensure the configuration initializes correctly.

Fixes #43531

Before submitting

Who can review?

@Rocketknight1

Copy link
Copy Markdown
Member

cc @vasqu since you commented on the issue!

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

max_window_layers seems like an unnecessary attribute added + let's move the test, please no new files

rope_parameters: int | None = None,
attention_bias: bool | None = False,
sliding_window: int | None = None,
max_window_layers: int = 28,

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.

Seems irrelevant?

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 test should be still under test_modeling_xxx

@Vallabh-1504

Vallabh-1504 commented Jan 29, 2026

Copy link
Copy Markdown
Contributor Author

hi, @vasqu, thanks for the review.
when I was running pytest I was getting an error regarding max_window_layers.
This attribute is used in the layer_types list comprehension (around line 612).

    def __getattribute__(self, key):
        if key != "attribute_map" and key in super().__getattribute__("attribute_map"):
            key = super().__getattribute__("attribute_map")[key]
>       return super().__getattribute__(key)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E       AttributeError: 'Qwen3OmniMoeTalkerCodePredictorConfig' object has no attribute 'max_window_layers'

src\transformers\configuration_utils.py:163: AttributeError

self.intermediate_size = intermediate_size
self.num_hidden_layers = num_hidden_layers
self.num_attention_heads = num_attention_heads
self.sliding_window = sliding_window if self.use_sliding_window else None

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.

Ok I checked what happened and it seems it was unintentionally added in #41541, but since I'm not super familiar with this model I'd rather wait for @zucchini-nlp to answer here

Imo we should just do self.sliding_window = sliding_window (use_sliding_window was never used at all and should be removed from the docstring) - max_window_layers should be removed alongside it (not reintroduced)

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.

Also the changes should be done in modular and then reapplied via python utils/modular_model_converter.py qwen3_omni_moe

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.

Indeed a bad copy, no need for use_sliding_window. Model always uses sliding layers together with full attention

**kwargs,
):
self.sliding_window = sliding_window
self.max_window_layers = max_window_layers

@zucchini-nlp zucchini-nlp Jan 30, 2026

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.

it is a recurring pattern in many qwen-multimodal models and I think authors incorrectly copied it when adding Qwen3-Omni-MoE. The official checkpoints have max_window_layers saved in config therefore we don't see errore at inference

IMO we need to keep it to match the model's default behavior and to match with docstring

@zucchini-nlp

Copy link
Copy Markdown
Member

@Vallabh-1504 hey, any updates on the PR? Would be great to merge it before the next planned release, which I believe should be around this week

@zucchini-nlp zucchini-nlp added the for patch Tag issues / labels that should be included in the next patch label Feb 3, 2026
@Vallabh-1504

Copy link
Copy Markdown
Contributor Author

hi @zucchini-nlp, I was working on it but hitting a bit of a wall.

I was applying changes through modular_qwen3_omni_moe.py, as previously i did manual changes which was wrong. but for some reason, the modular_model_converter.py keeps regenerating the use_sliding_window logic in the final config, even after i removed it from modular_qwen3_omni_moe.py.

kinda stuck in a loop where the generator keeps the code i'm trying to remove.

I also don't know what to do with the max_window_layers, as this is also not initialized anywhere.

Can you guide me through this. If i'm missing a step or if there's some cache with the converter?

@zucchini-nlp

Copy link
Copy Markdown
Member

Smth like this should work, we need to delete unused attributed explicitly and re-assign the "differing" attr. For max_window_layers, let's keep it without deleting

https://github.com/Vallabh-1504/transformers/blob/9041720191cdef9348f09f7c1695db606223d353/src/transformers/models/qwen3_omni_moe/modular_qwen3_omni_moe.py#L571-L572

@Vallabh-1504

Copy link
Copy Markdown
Contributor Author

@zucchini-nlp, I have applied the changes as requested!

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

One tiny comment and let's wait for @vasqu's review

self.num_code_groups = num_code_groups
self.vocab_size = vocab_size
self.max_position_embeddings = max_position_embeddings
self.hidden_size = hidden_size
self.intermediate_size = intermediate_size
self.num_hidden_layers = num_hidden_layers
self.num_attention_heads = num_attention_heads
self.sliding_window = sliding_window if self.use_sliding_window else None
self.sliding_window = sliding_window
self.max_window_layers = max_window_layers

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.

nit: duplicate

@@ -473,6 +475,7 @@ def __init__(
**kwargs,
):
self.sliding_window = sliding_window
self.max_window_layers = max_window_layers

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.

not needed, super assigns it already which is why we got duplicates in auto-generated code :)

Comment on lines +917 to +924
class TestQwen3OmniMoeCodePredictorConfig(unittest.TestCase):
def test_code_predictor_config_init(self):
"""
Test that Qwen3OmniMoeTalkerCodePredictorConfig initializes correctly
and accepts max_window_layers while removing use_sliding_window.
"""

config = Qwen3OmniMoeTalkerCodePredictorConfig(

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.

ideally we need a complete model test for the 'TalkerModel' model. But I realize that the model doesn't follow transformers standards and we'll skip anyway many tests from ModelTesterMixin, or override a lot of them

I'm fine with deleting the current test in that case, @vasqu wdyt?

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 can add a small regression test under

class Qwen3OmniMoeThinkerForConditionalGenerationTester:
at least, we don't need a separate class for this

Just a tad weird because the naming is weird but if we don't test it we ought to repeat it in a refactor 😬

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

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

Don't have much to add onto @zucchini-nlp's comments, I'd just prefer to move the test under the general tester class

Comment on lines +917 to +924
class TestQwen3OmniMoeCodePredictorConfig(unittest.TestCase):
def test_code_predictor_config_init(self):
"""
Test that Qwen3OmniMoeTalkerCodePredictorConfig initializes correctly
and accepts max_window_layers while removing use_sliding_window.
"""

config = Qwen3OmniMoeTalkerCodePredictorConfig(

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 can add a small regression test under

class Qwen3OmniMoeThinkerForConditionalGenerationTester:
at least, we don't need a separate class for this

Just a tad weird because the naming is weird but if we don't test it we ought to repeat it in a refactor 😬

@github-actions

github-actions Bot commented Feb 4, 2026

Copy link
Copy Markdown
Contributor

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

run-slow: qwen3_omni_moe

@zucchini-nlp
zucchini-nlp enabled auto-merge (squash) February 4, 2026 10:36
@zucchini-nlp
zucchini-nlp merged commit 257a602 into huggingface:main Feb 4, 2026
19 checks passed
pull Bot pushed a commit to j3din00b/openvino.genai that referenced this pull request Jul 22, 2026
<!-- Keep your pull requests (PRs) as atomic as possible. That increases
the likelihood that an individual PR won't be stuck because of adjacent
problems, merge conflicts, or code review.
Your merged PR is going to appear in the automatically generated release
notes on GitHub. So the clearer the title the better. -->
## Description
<!-- Please include a summary of the change. Also include relevant
motivation and context. -->

The main reason is
huggingface/transformers#43593.
I've checked the changelog and run it through the agent - no breaking
changes for WWB or LLM_bench were introduced.

Changes to llm_bench hooks with the new transformers:
**v5.4.0** — _get_initial_cache_position was removed and _prefill
stopped writing cache_position; the inputs_embeds slicing in _prefill
switched to computing next_sequence_length instead of mutating
model_kwargs["inputs_embeds"]
(https://github.com/huggingface/transformers/blob/v5.13.0/src/transformers/generation/utils.py#L3852).
**v5.11.0** — _sample gained pad_token_id =
pad_token_id.to(input_ids.device) right after unfinished_sequences is
created
(https://github.com/huggingface/transformers/blob/v5.13.0/src/transformers/generation/utils.py#L2760).
**v5.13.0** — _beam_search's end-of-iteration cache reorder now scans
ALL_CACHE_NAMES, has an elif hasattr(cache, "reorder_cache") branch, and
raises ValueError for unreorderable caches
(https://github.com/huggingface/transformers/blob/v5.13.0/src/transformers/generation/utils.py#L3185).

<details>
  <summary>Diffs:</summary>
5.3 vs 5.4

```python
8c8
<         self,
---
>         self: "GenerativePreTrainedModel",
32,34c32
<             # Always directly slice the inputs_embeds if present, as `prepare_inputs_for_generation` never need them full and `_get_initial_cache_position`
<             # rely on its size explicitly. For input_ids, we need to use `next_sequence_length` to slice later instead of explicit slicing,
<             # as some model need them full for correct input preparation inside `prepare_inputs_for_generation` (i.e. audio models)
---
>             # It will be sliced as input_embeds = inputs_embeds[:, -next_sequence_length:, :] in `prepare_inputs_for_generation`
36c34
<                 model_kwargs["inputs_embeds"] = inputs_embeds[:, past_length:, :]
---
>                 next_sequence_length = model_kwargs["inputs_embeds"].shape[1] - past_length
47,49d44
<             # The cache is already taken into account in `_get_initial_cache_position`, so the length is only the new tokens if we slice
<             effective_input_length = next_sequence_length if next_sequence_length is not None else input_ids.shape[1]
<             model_kwargs = self._get_initial_cache_position(effective_input_length, input_ids.device, model_kwargs)
62c57
<             torch._dynamo.config.cache_size_limit = 64
---
>             getattr(torch, "_dynamo").config.cache_size_limit = 64
85,87d79
<                 model_kwargs["cache_position"] = torch.arange(
<                     past_length, current_length, dtype=torch.long, device=input_chunk.device
<                 )
97,99d88
<             model_kwargs["cache_position"] = torch.arange(
<                 input_ids.shape[1], dtype=torch.long, device=input_ids.device
<             )
107c96
<         self,
---
>         self: "GenerativePreTrainedModel",
293c282
<         self,
---
>         self: "GenerativePreTrainedModel",
```

5.8 vs 5.9 (comment):
```python
32c32
<             # It will be sliced as input_embeds = inputs_embeds[:, -next_sequence_length:, :] in `prepare_inputs_for_generation`
---
>             # It will be sliced as inputs_embeds = inputs_embeds[:, -next_sequence_length:, :] in `prepare_inputs_for_generation`
```

5.10 vs 5.11:
```python
164a165,171
> 
>         # `pad_token_id` is created on `inputs_tensor.device` in `_prepare_special_tokens`. For multimodal models
>         # (e.g. BLIP-2, LLaVA) sharded across devices via `device_map="auto"`, `inputs_tensor` (e.g. `pixel_values`
>         # on the vision encoder) and `input_ids` (on the language model) can live on different devices, so we need to
>         # realign `pad_token_id` with `input_ids` to avoid cross-device ops below.
>         if pad_token_id is not None:
>             pad_token_id = pad_token_id.to(input_ids.device)
```

5.12 vs 5.13:
```python
559c559,560
<             if model_kwargs.get("past_key_values") is not None:
---
>             if any(cache_key in model_kwargs for cache_key in ALL_CACHE_NAMES):
>                 cache_key = next(cache_key for cache_key in ALL_CACHE_NAMES if cache_key in model_kwargs)
562c563,565
<                     model_kwargs["past_key_values"] = self._reorder_cache(model_kwargs["past_key_values"], beam_idx)
---
>                     model_kwargs[cache_key] = self._reorder_cache(model_kwargs[cache_key], beam_idx)
>                 elif hasattr(model_kwargs[cache_key], "reorder_cache"):
>                     model_kwargs[cache_key].reorder_cache(beam_idx)
564c567,569
<                     model_kwargs["past_key_values"].reorder_cache(beam_idx)
---
>                     raise ValueError(
>                         f"{self.__class__.__name__} cannot use beam search with a cache currently, as the cache cannot be reordered"
>                     )
```

</details>

Added new modules that will work with transformers >=5.4, <=5.13.

Limitations: Optimum-Intel still supports transformers < 5.1 only.
Benchmarks allow that version too, so it is not a breaking change.

## Checklist:
- [x] This PR follows [GenAI Contributing
guidelines](https://github.com/openvinotoolkit/openvino.genai?tab=contributing-ov-file#contributing).
<!-- Always follow them. If there are deviations, explain what and why.
-->
- [ ] Tests have been updated or added to cover the new code. <!--
Specify exactly which tests were added or updated. If the change isn't
maintenance related, update the tests at
https://github.com/openvinotoolkit/openvino.genai/tree/master/tests or
explain in the description why the tests don't need an update. -->
- [ ] This PR fully addresses the ticket. <!--- If not, explain clearly
what is covered and what is not. If follow-up pull requests are needed,
specify in the description. -->
- [ ] I have made corresponding changes to the documentation. <!-- Run
github.com/\<username>/openvino.genai/actions/workflows/deploy_gh_pages.yml
on your fork with your branch as a parameter to deploy a test version
with the updated content. Replace this comment with the link to the
built docs. If the documentation is updated in a separate PR, clearly
specify it. -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

for patch Tag issues / labels that should be included in the next patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sliding_window issue with Qwen3-MoE models

5 participants