Skip to content

Remove stale and redundant _no_split_modules entries - #47645

Merged
guarin merged 7 commits into
huggingface:mainfrom
guarin:fix-stale-no-split-modules
Aug 3, 2026
Merged

Remove stale and redundant _no_split_modules entries#47645
guarin merged 7 commits into
huggingface:mainfrom
guarin:fix-stale-no-split-modules

Conversation

@guarin

@guarin guarin commented Jul 30, 2026

Copy link
Copy Markdown
Member

CI

This PR removes or updates _no_split_modules entires with the addition of a new mlinter rule: huggingface/transformers-mlinter#12

The new rule verifies that _no_split_modules contains only entries from modules defined in modeling_*.py, modular_*.py or a file in the same model directory.

This helps avoiding wrong _no_split_modules entries. It also simplifies reviews.

Updates can be grouped into these cases:

  • remove unknown class (e.g. Idefics2DecoderLayer)
  • fix typo (e.g. Data2VecTextForTextEmbeddings -> Data2VecTextEmbeddings)
  • remove classes already in _no_split_modules of submodule (e.g. T5Block in blip_2)
  • empty _no_split_modules to avoid inheriting entry for parent class (e.g. in DeepseekVLPreTrainedModel to avoid inheriting JanusVisionEncoderLayer)

There are some special cases that are automatically handled by the linter:

  • Parametrized* classes created through torch.nn.utils.parametrize are ignored as they are only created at runtime
  • TimmWrapperForImageClassification is ignored

Note

There are still some blind spots for the linter. As the linter only checks non-autogenerated files, it can miss cases where a modular file doesn't define _no_split_modules and the generated modeling.py file inherits a wrong name from the parent class. For example AriaPreTrainedModel doesn't have _no_split_modules:

class AriaPreTrainedModel(LlamaPreTrainedModel):
config: AriaConfig
base_model_prefix = "model"
_can_compile_fullgraph = False # MoE models don't work with torch.compile (dynamic slicing)
_supports_attention_backend = True

which gets automatically extended to this in modeling_aria.py:

class AriaPreTrainedModel(PreTrainedModel):
config: AriaConfig
base_model_prefix = "model"
supports_gradient_checkpointing = True
_no_split_modules = ["AriaDecoderLayer"]

where AriaDecoderLayer is automatically renamed from LlamaDecoderLayer but there is no AriaDecoderLayer.

Code Agent Policy

The Transformers repo is currently being overwhelmed by a large number of PRs and issue comments written by
code agents. These often are low-quality, or fix extremely minor issues that occur rarely or never in practice.
As a result, we're instituting a rule that first-time contributors should not use code agents to submit PRs or issues.
We'd also ask autonomous "OpenClaw"-like agents not to open any PRs or issues.

Issues/PRs from first-time contributors that violate this rule will probably just be closed without review, and we
might block you, especially if you open more than one or appear to be deliberately ignoring this. We especially do not
want new contributors to jump in on random issues to contribute an agent-written fix. This creates lots of noise
for reviewers and other users and will almost certainly get you blocked.

For more information, please read CONTRIBUTING.md.

  • (First-time contributors only): I confirm that this PR description and code is not written by an LLM or code agent

Before submitting

  • This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
  • Did you read the contributor guideline and the
    Pull Request checks?
  • Was this discussed/approved via a Github issue or the forum? Please add a link
    to it if that's the case.
  • Did you make sure to update the documentation with your changes according to the guidelines?
  • Did you write any new necessary tests?

Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.

Some models list `_no_split_modules` entries naming classes that do not exist
anywhere in transformers, so `device_map` never matches them and the modules
they were meant to keep together get split across devices:

  - idefics2: Idefics2DecoderLayer
  - idefics3: Idefics3DecoderLayer
  - video_llava: VideoLlavaVisionAttention

Others hardcode classes owned by a submodel that is loaded through the Auto*
classes. `post_init` already collects `_no_split_modules` from child submodels,
so these entries are redundant, and in blip_2's case actively wrong: it declared
both T5Block and OPTDecoderLayer regardless of which language model the
checkpoint actually uses.

  - blip_2: T5Block, OPTDecoderLayer
  - depth_anything: DPTViTEmbeddings (the backbone is an AutoBackbone, so this
    never matched; it now correctly reports the backbone's Dinov2Layer)
  - llava_next: LlamaDecoderLayer
  - moshi: MimiTransformerLayer

The resulting runtime sets are more accurate than the hardcoded lists were.

Generated modeling files updated with the modular converter, which propagates
the removals to smolvlm, llava_next_video, llava_onevision,
kyutai_speech_to_text and prompt_depth_anything. deepseek_ocr2 and
granite4_vision only shift the position of their own override.
@guarin

guarin commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

run-slow: blip_2, deepseek_ocr2, depth_anything, granite4_vision, idefics2, idefics3, kyutai_speech_to_text, llava_next, llava_next_video, llava_onevision, moshi, prompt_depth_anything, smolvlm, video_llava

@github-actions

Copy link
Copy Markdown
Contributor

Workflow Run ⚙️

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

models: ["models/blip_2", "models/deepseek_ocr2", "models/depth_anything", "models/granite4_vision", "models/idefics2", "models/idefics3", "models/kyutai_speech_to_text", "models/llava_next", "models/llava_next_video", "models/llava_onevision", "models/moshi", "models/prompt_depth_anything", "models/smolvlm", "models/video_llava"]
quantizations: []

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

@github-actions

Copy link
Copy Markdown
Contributor

CI Results

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN 3e618b40 workflow commit (merge commit)
PR 35a211fc branch commit (from PR)
main 560f36cc base commit (on main)

✅ No failing test specific to this PR 🎉 👏 !

@guarin
guarin marked this pull request as draft July 30, 2026 13:22
@guarin
guarin marked this pull request as ready for review July 30, 2026 15:56

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

🧹 🧹
Nice and clean! Happy for the linter too 🎉

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.

I think above this one, cohere_asr also has a CohereEncoderLayer that does not exist, but maybe more are like this, your linter rule will help!

@guarin guarin Aug 3, 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.

I think this is the loophole that still exists, see Note in the PR description

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 can't really follow tbh. Shouldn't the linter follow the modeling files? Or is there an conflict of order of applications re fix/check repo?

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.

ah indeed, same as you described, I think it's fixable in modular_model_converter (and should be): we could either include it as a regex str match in convert_modular_file , just would need re.findall(r"_no_split_modules = \ somewhere and would not cost much

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.

Hmm, I can't really follow tbh. Shouldn't the linter follow the modeling files? Or is there an conflict of order of applications re fix/check repo?

The issue is that the linter doesn't check modeling files that are generated. Agree with @molbap that this should be fixed in modular converter.

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 issue is that the linter doesn't check modeling files that are generated

That kind of seems like a self contained issue in itself? I would expect modeling to be checked as well. But yea anyways, agree that it could be done at modular level as well (I just find it a bit less intuitive)

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.

Yes I was surprised to learn that the linter doesn't check the auto-generated files. The motivation seems to be that errors should be reported in the modular files instead. But in this case here it would definitely also make sense to check the modeling file. Will ask Tarek once he is back.

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

Some small questions but nothing major, thanks 🫡 maybe also run slow ci for some whom that should fix?

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 can't really follow tbh. Shouldn't the linter follow the modeling files? Or is there an conflict of order of applications re fix/check repo?

Comment thread src/transformers/models/deepseek_vl/modular_deepseek_vl.py Outdated
Comment thread src/transformers/models/qwen3_asr/modular_qwen3_asr.py Outdated
@guarin

guarin commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

run-slow: blip_2, data2vec, deepseek_ocr2, deepseek_vl, deepseek_vl_hybrid, depth_anything, diffusion_gemma, exaone4_5, gemma3, granite4_vision, higgs_audio_v2_tokenizer, idefics2, idefics3, janus, kyutai_speech_to_text, llava_next

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

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

run-slow: blip_2, dac, data2vec, deepseek_ocr2, deepseek_vl, deepseek_vl_hybrid, depth_anything, diffusion_gemma, exaone4_5, gemma3, granite4_vision, higgs_audio_v2_tokenizer, idefics2, idefics3, janus, kyutai_speech_to_text

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Workflow Run ⚙️

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

models: ["models/blip_2", "models/data2vec", "models/deepseek_ocr2", "models/deepseek_vl", "models/deepseek_vl_hybrid", "models/depth_anything", "models/diffusion_gemma", "models/exaone4_5", "models/gemma3", "models/granite4_vision", "models/higgs_audio_v2_tokenizer", "models/idefics2", "models/idefics3", "models/janus", "models/kyutai_speech_to_text", "models/llava_next"]
quantizations: []

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 30819654874:1
Result: failure | Jobs: 16 | Tests: 148,999 | Failures: 1 | Duration: 15h 39m

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

CI Results

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN febffdb3 workflow commit (merge commit)
PR 59114f4e branch commit (from PR)
main 583f1942 base commit (on main)

✅ No failing test specific to this PR 🎉 👏 !

@guarin
guarin added this pull request to the merge queue Aug 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 3, 2026
@guarin
guarin added this pull request to the merge queue Aug 3, 2026
Merged via the queue into huggingface:main with commit d09f53a Aug 3, 2026
212 of 214 checks passed
@guarin
guarin deleted the fix-stale-no-split-modules branch August 3, 2026 16:31
ArthurZucker pushed a commit to huggingface/transformers-mlinter that referenced this pull request Aug 4, 2026
TRF005 only validates the shape of `_no_split_modules`. TRF022
additionally checks that each entry names a class that actually exists,
resolving it against the classes defined in the modeling file, the names
it imports, and the classes defined by sibling modules of the same model
directory.

`device_map` matches these strings against `module.__class__.__name__`
at runtime, so a stale or misspelled entry is silently ignored. Entries
naming another model's classes are flagged too: `post_init` already
collects `_no_split_modules` from child submodels, so hardcoding them is
redundant.

Corresponding transformers PR to make checks pass:
huggingface/transformers#47645

---------

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
@guarin guarin mentioned this pull request Aug 4, 2026
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