Skip to content

Fix tie_word_embeddings not lifted from text_config for some VLM configs (BC regression) - #45857

Merged
zucchini-nlp merged 4 commits into
mainfrom
fix-vlm-tie-word-embeddings-bc
Aug 25, 2026
Merged

zucchini-nlp merged 4 commits into
mainfrom
fix-vlm-tie-word-embeddings-bc

Conversation

@qgallouedec

@qgallouedec qgallouedec commented May 9, 2026 •

Copy link
Copy Markdown
Member

CPU CI GPU run-slow

For Qwen2_5_VLConfig, Qwen2VLConfig, Glm4vConfig, and Glm4vMoeConfig, pre-v5 saves placed tie_word_embeddings inside text_config (and dropped it from the root) because the inner text class declared the field. v5 moved the field to the outer config (#42420) but __post_init__ doesn't lift the value from text_config. The outer attribute therefore falls through to its dataclass default (False), get_expanded_tied_weights_keys returns {}, no tying happens, lm_head.weight is reported MISSING and randomly initialized — the model loads silently broken.

Regression introduced in #41541, which removed the forwarding line kwargs["tie_word_embeddings"] = self.text_config.tie_word_embeddings originally added in #42420 with a FIXME: tying has to be used from the text config comment. The vestigial tie_word_embeddings: bool = False field was later removed from the inner text classes in #44976.

This patch mirrors the existing fix in LlavaConfig.__post_init__: when text_config arrives as a dict (the deserialization path), forward tie_word_embeddings to the outer when the root is the default and the dict has a truthy value.

Reproducer

# transformers v5 (e.g. main / 5.8.0.dev0)
from transformers import Qwen2_5_VLForConditionalGeneration

m = Qwen2_5_VLForConditionalGeneration.from_pretrained("trl-internal-testing/tiny-Qwen2_5_VLForConditionalGeneration")
print("outer tie_word_embeddings:", m.config.tie_word_embeddings)
print("lm_head tied:", m.lm_head.weight.data_ptr() == m.model.language_model.embed_tokens.weight.data_ptr())

Before this PR (loud LOAD REPORT, broken model):

Qwen2_5_VLForConditionalGeneration LOAD REPORT from: trl-internal-testing/tiny-Qwen2_5_VLForConditionalGeneration
Key            | Status  |
---------------+---------+
lm_head.weight | MISSING |
- MISSING: those params were newly initialized because missing from the checkpoint.

outer tie_word_embeddings: False
lm_head tied: False

After this PR:

outer tie_word_embeddings: True
lm_head tied: True

(no LOAD REPORT printed)

The Hub artifact above was saved by transformers 4.57.5; under 4.x its __post_init__ still propagated tie_word_embeddings from text → root, so the bug is v5-only and only triggers on configs saved by 4.x (the vast majority of pre-existing Hub repos for these architectures).

Affected configs

Empirically determined by saving each composite VLM config under transformers 4.56.2 with tie_word_embeddings=True and inspecting the resulting config.json:

config root text_config needs lift in v5?
qwen2_5_vl <absent> True yes
qwen2_vl <absent> True yes
glm4v <absent> True yes
glm4v_moe <absent> True yes
got_ocr2 <absent> True no — outer class default is True already
llava{,_next,_next_video,_onevision} True <absent> no — already saved at root or already has the lift
idefics3, smolvlm, llama4, pix2struct, fuyu True — no

Files touched: qwen2_5_vl, qwen2_vl, glm4v (configuration + modular), glm4v_moe.

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

Huh interesting, I suppose testing models tie weights unlike official releases

We can fix it in case there are more models like that on the hub (which i am not really sure), but we have to check text config after it is fully initialized imo

@forest-david

forest-david commented Aug 15, 2026 •

Copy link
Copy Markdown

@qgallouedec @zucchini-nlp I reproduced two gaps in the current implementation with a minimal
Qwen2-VL model construction test.

  1. The patch only handles text_config when it is a dict. When callers
    pass a pre-initialized Qwen2VLTextConfig(tie_word_embeddings=True),
    the top-level value remains false and lm_head is not tied:

legacy dict input:
root_tie_after_patch=True, lm_head_tied=True

pre-initialized Qwen2VLTextConfig input:
root_tie_after_patch=False, lm_head_tied=False

  1. if not self.tie_word_embeddings cannot distinguish a missing
    top-level key from an explicitly supplied tie_word_embeddings=false.
    The current logic overwrites an explicit false with the nested true.

I also reproduced the real-world impact with
OpenDataLab/MinerU2.5-Pro-2604-1.2B: its legacy config has the flag
only under text_config, while its checkpoint has no standalone
lm_head.weight; the resulting untied head produces corrupted
generation.

Would you be okay with me opening a superseding PR that preserves
explicit top-level values, handles both dict and PreTrainedConfig
inputs after text-config initialization, and adds regression tests?

@ArthurZucker

Copy link
Copy Markdown
Collaborator

run-slow: glm4v, glm4v_moe, qwen2_5_vl, qwen2_vl

@github-actions

Copy link
Copy Markdown
Contributor

Workflow Run ⚙️

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

models: ["models/glm4v", "models/glm4v_moe", "models/qwen2_5_vl", "models/qwen2_vl"]
quantizations: []

@github-actions

Copy link
Copy Markdown
Contributor

CI Results

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN f6d96246 workflow commit (merge commit)
PR d6c09677 branch commit (from PR)
main e378772d base commit (on main)

✅ No failing test specific to this PR 🎉 👏 !

@vasqu

vasqu commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Any status here @qgallouedec @ArthurZucker?

@qgallouedec

Copy link
Copy Markdown
Member Author

Updated in 5f9d739: the check now runs after text_config is fully initialized, per @zucchini-nlp's review, so both the legacy dict path and a pre-initialized text config are handled. @zucchini-nlp if you want to have another look

@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'll trigger slow CI and lets merge if it's all green

@zucchini-nlp

Copy link
Copy Markdown
Member

@bot /repo

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Repo. Consistency bot fixed some files and pushed the changes.

@github-actions

Copy link
Copy Markdown
Contributor

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

run-slow: glm4v, glm4v_moe, glm_ocr, paddleocr_vl, qwen2_5_vl, qwen2_vl

@zucchini-nlp

Copy link
Copy Markdown
Member

run-slow: glm4v, glm4v_moe, glm_ocr, paddleocr_vl, qwen2_5_vl, qwen2_vl

@github-actions

Copy link
Copy Markdown
Contributor

Workflow Run ⚙️

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

models: ["models/glm4v", "models/glm4v_moe", "models/glm_ocr", "models/paddleocr_vl", "models/qwen2_5_vl", "models/qwen2_vl"]
quantizations: []

@github-actions

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 32801180304:1
Result: success | Jobs: 5 | Tests: 1,013 | Failures: 1 | Duration: 8m 36s

@github-actions

Copy link
Copy Markdown
Contributor

CI Results

Workflow Run ⚙️

Commit Info

Context Commit Description
RUN faac9ad1 workflow commit (merge commit)
PR 4fb82a94 branch commit (from PR)
main 9bb5f6a8 base commit (on main)

✅ No failing test specific to this PR 🎉 👏 !

@zucchini-nlp
zucchini-nlp added this pull request to the merge queue Aug 25, 2026
Merged via the queue into main with commit cb1e460 Aug 25, 2026
48 checks passed
@zucchini-nlp
zucchini-nlp deleted the fix-vlm-tie-word-embeddings-bc branch August 25, 2026 10:16
sbucaille pushed a commit to sbucaille/transformers that referenced this pull request Sep 16, 2026
…configs (BC regression) (huggingface#45857)

* Fix `tie_word_embeddings` not lifted from `text_config` for some VLM configs (BC regression)

* Lift tie_word_embeddings after text_config init so pre-initialized text configs are covered too

* Apply repo consistency fixes

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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.

6 participants