Skip to content

[Bugfix] Reland #53020: tie lm_head.weight for Nemotron Parse when checkpoint omits it - #60272

Merged
DarkLight1337 merged 1 commit into
vllm-project:mainfrom
aniskumar-nv:fix/nemotron-parse-tied-lm-head-reland
Oct 8, 2026
Merged

DarkLight1337 merged 1 commit into
vllm-project:mainfrom
aniskumar-nv:fix/nemotron-parse-tied-lm-head-reland

Conversation

@aniskumar-nv

Copy link
Copy Markdown
Contributor

Purpose

Re-lands #53020 (commit 83cadd65d9), reverted in #59805. The diff is byte-identical to the reverted commit (git patch-id matches). Original bug report: #53019. Supersedes #60266, which carries the same diff; thanks @DiegoCao for preparing it.

NemotronParseForConditionalGeneration builds a standalone ParallelLMHead and only populates it from lm_head.* weights. A checkpoint that sets tie_word_embeddings and ships no lm_head.weight, such as nvidia/NVIDIA-Nemotron-Parse-2.0, therefore keeps a randomly initialized output head. Nothing reports it: the server starts, reports healthy, and returns garbage.

Why this can land now

#59805 did not revert because the fix was wrong. It reverted because the NVIDIA-Nemotron-Parse-2.0 case added to test_nemotron_parse.py failed in the nightly full CI run while loading that checkpoint's tokenizer, before any model code ran:

transformers/tokenization_utils_tokenizers.py:120 in convert_to_native_format
    local_kwargs["tokenizer_object"] = TokenizerFast.from_file(fast_tokenizer_file)
E   Exception: DuplicatePatternError: [225, 131, 156] at line 449472 column 1

The cause was the CI pin tokenizers==0.23.1. The 2.0 tokenizer.json uses an NFKC normalizer, and 14 pairs of its added tokens become identical after normalization (for example ნ U+10DC and ჼ U+10FC both normalize to e1 83 9c, the [225, 131, 156] in the error). 0.23.1 rejects the duplicates when it builds its matcher; 0.23.2 (daachorse 1.0.1 → 3.0.0, huggingface/tokenizers#2050) accepts them. #59796 bumped the pin.

PR merged (UTC)
fix #53020 2026-10-01 16:26
revert #59805 2026-10-02 17:19
tokenizer bump that unblocks it #59796 2026-10-02 18:33

Tokenizer.from_file on the 2.0 tokenizer.json, by tokenizers version:

0.22.2 0.23.1 0.23.2 1.0.0rc2
loads DuplicatePatternError loads loads

Under the current CI pins (tokenizers==0.23.2, transformers==5.18.0), AutoTokenizer.from_pretrained("nvidia/NVIDIA-Nemotron-Parse-2.0") loads (TokenizersBackend, vocab 72,249).

Test Plan

  • tests/models/multimodal/generation/test_nemotron_parse.py::test_models: the nvidia/NVIDIA-Nemotron-Parse-2.0 parametrization is restored. It is the only coverage of the tied-head path and is the case that must be green before merge.
  • That test runs in Multimodal Models (Extended Generation 1), which is optional: true, so it did not run on [Bugfix] Tie lm_head.weight for Nemotron Parse when checkpoint omits it #53020's PR CI and only surfaced in the nightly run. Could a maintainer include that step when triggering CI here?
  • nvidia/NVIDIA-Nemotron-Parse-v1.2 stays in the same parametrization and is unaffected (see below).

Test Result

Out-of-CI validation on one RTX 6000 Ada, serving the 2.0 checkpoint with vllm serve … --dtype bfloat16 --trust-remote-code --limit-mm-per-prompt '{"image": 1}', one greedy request (50 max tokens) with the model's documented control-token prompt on the deterministic test image from the model repo's test_golden.py:

build output
vLLM v0.30.0 without this patch <s><s><s>… (50 × <s>)
v0.30.0 with this patch <x_0.3906><y_0.5969>\begin{tabular}{ccccc}\n\end{tabular}<x_0.6084><y_0.6367><class_Table>

The patched output is byte-identical to what the model's own shipped workaround (vllm_tied_patch/sitecustomize.py in the HF repo) produces on the same input.

Why v1.2 cannot be affected: the two checkpoints differ exactly where the new branch reads.

checkpoint tie_word_embeddings (config / config.decoder) lm_head.weight in checkpoint tensors
NVIDIA-Nemotron-Parse-v1.2 false / false present 667
NVIDIA-Nemotron-Parse-2.0 true / true absent 666

The tie goes through ParallelLMHead.tie_weights(), so it routes via quant_method.tie_weights rather than assigning .weight directly.

ruff check and ruff format --check pass on both files.

Notes

cc @DarkLight1337 @Thangnguyenvn98 @hmellor @djramic

Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).

  • AI assistance was used during the creation of this PR.

  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.

  • Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.

  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.

  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

🤖 Generated with Claude Code

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify mergify Bot added multi-modality Related to multi-modality (#4194) bug Something isn't working labels Oct 6, 2026
@DarkLight1337
DarkLight1337 enabled auto-merge (squash) October 6, 2026 18:01
@DarkLight1337

Copy link
Copy Markdown
Member

/ci run --allow-stale

@github-actions github-actions Bot added the ready ONLY add when PR is ready to merge/full CI is needed label Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93150 for commit 3587afa57537.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

@DarkLight1337 thanks! One thing: pre-run-check/pre-commit ran before ready landed and the bot-added label didn't retrigger them, so they're stale-red on this head. Could you re-run the failed pre-commit workflow (run 37507745770)? It will pass now; I'd rather not push a new commit and disable auto-merge.

@mergify

mergify Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Hi @aniskumar-nv, the pre-commit checks have failed. Please run:

uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

@vllm-agent

vllm-agent commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

CI selector (shadow): 5 test steps (28 jobs) instead of 62 (97 jobs)

Shadow mode: this changes nothing about what CI runs. It shows what the evidence-based selector would pick for this PR, next to today's rules. How it works.

Feedback welcome: reply here if it would skip a step this change needs, or runs something unrelated.

steps (jobs) Today's rules Selector Would skip Would add
NVIDIA, CPU and others 62 (97) 5 (28) 58 (72) 1 (3)
AMD mirrors 58 (85) 2 (18) 56 (67) 0 (0)
Selector would run (5)
  • arm-cpu-test ×3
  • basic-models-tests-extra-initialization ×14
  • cpu-language-generation-and-pooling-model-tests ×3
  • cpu-multi-modal-model-tests-n ×4
  • multi-modal-processor ×4
Would skip (today's rules run them) (58)
  • amd-lm-eval-small-models-harness
  • amd-qwen3-next-mtp-async-eplb-accuracy
  • ascend-npu-test
  • async-engine-inputs-utils-worker
  • basic-correctness ×2
  • basic-correctness-cpu-offload
  • basic-correctness-cumem
  • basic-correctness-prefetch-offload
  • basic-correctness-sleep-mode
  • basic-models-test-other-cpu
  • basic-models-tests-initialization
  • basic-models-tests-other
  • benchmarks-cli-test
  • cpu-qwen2-5-vl-multimodal-tests
  • distributed-model-tests-2-gpus ×3
  • entrypoints-integration-api-server ×4
  • entrypoints-integration-api-server-generate
  • entrypoints-integration-api-server-openai-chat_completion
  • entrypoints-integration-api-server-openai-completion
  • entrypoints-integration-llm
  • entrypoints-integration-multimodal
  • entrypoints-integration-pooling
  • entrypoints-integration-responses-api
  • entrypoints-integration-speech_to_text
  • fusion-e2e-quick-h100
  • fusion-e2e-tp2-b200
  • fusion-e2e-tp2-quick-h100
  • kernels-fla-ops-test-b200
  • kernels-mhc-test-b200
  • kernels-root-misc-test-b200
  • language-models-tests-extra-standard ×2
  • language-models-tests-granite-l4-compatibility
  • language-models-tests-hybrid ×2
  • language-models-tests-standard
  • metrics-tracing-2-gpus
  • model-executor
  • multi-modal-models-standard-1-qwen2
  • multi-modal-models-standard-2-qwen3-gemma
  • multi-modal-models-standard-3-llava-qwen2-vl
  • multi-modal-models-standard-4-other-whisper
  • multi-modal-processor-cpu ×4
  • pipeline-context-parallelism-4-gpus
  • pytorch-compilation-dynamic-shapes
  • pytorch-compilation-passes-unit-tests
  • pytorch-compilation-unit-tests
  • pytorch-compilation-unit-tests-h100
  • pytorch-fullgraph-cudagraph-l4-compatibility
  • pytorch-fullgraph-test
  • regression
  • rl-entrypoints-tests
  • v1-core
  • v1-executor-worker
  • v1-kv-connectors ×4
  • v1-kv-offload
  • v1-logits-oracle
  • v1-metrics-lmeval
  • v1-sample
  • v1-spec-decode
Would add (today's rules do not run them) (1)
  • arm-cpu-test ×3 (code map)
AMD mirrors: would skip (56)
  • async-engine-inputs-utils-worker
  • basic-correctness ×2
  • basic-correctness-cpu-offload
  • basic-correctness-cumem
  • basic-correctness-prefetch-offload
  • basic-correctness-sleep-mode
  • basic-models-tests-initialization
  • basic-models-tests-other
  • benchmarks-cli-test
  • distributed-model-tests-2-gpus ×3
  • entrypoints-integration-api-server ×4
  • entrypoints-integration-api-server-generate
  • entrypoints-integration-api-server-openai-chat_completion
  • entrypoints-integration-api-server-openai-completion
  • entrypoints-integration-llm
  • entrypoints-integration-multimodal
  • entrypoints-integration-pooling
  • entrypoints-integration-responses-api
  • entrypoints-integration-speech_to_text
  • fusion-e2e-quick-h100
  • fusion-e2e-tp2-ar-rms-config-sweep-h100
  • fusion-e2e-tp2-b200
  • fusion-e2e-tp2-quick-h100
  • kernels-fla-ops-test-b200
  • kernels-mhc-test-b200
  • kernels-root-misc-test-b200
  • language-models-tests-extra-standard ×2
  • language-models-tests-granite-l4-compatibility
  • language-models-tests-hybrid ×2
  • language-models-tests-standard
  • lm-eval-small-models
  • metrics-tracing-2-gpus
  • model-executor
  • mrcr-eval-small-models
  • multi-modal-models-standard-1-qwen2
  • multi-modal-models-standard-2-qwen3-gemma
  • multi-modal-models-standard-3-llava-qwen2-vl
  • multi-modal-models-standard-4-other-whisper
  • pipeline-context-parallelism-4-gpus
  • platform-tests
  • pytorch-compilation-dynamic-shapes
  • pytorch-compilation-passes-unit-tests
  • pytorch-compilation-unit-tests
  • pytorch-compilation-unit-tests-h100
  • pytorch-fullgraph-cudagraph-l4-compatibility
  • pytorch-fullgraph-test
  • regression
  • rl-entrypoints-tests
  • v1-core
  • v1-executor-worker
  • v1-kv-connectors ×4
  • v1-kv-offload
  • v1-logits-oracle
  • v1-metrics-lmeval
  • v1-sample
  • v1-spec-decode
AMD mirrors: would add (0)

none

2 changed files · base d169c5a903 · head 91b560fbd6 · Python record: build 93039 at 1e5d0ea888 · kernel record: table 43b4aae (build 93244), map 43b4aae · not counted: 10 build steps, 5 A100 steps the generator no longer emits, 3 optional steps the selector would also run

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

The pre-commit failure is mypy on vllm/model_executor/models/embedding_gemma2.py:1023 (safe-super / missing vllm_config), introduced by #60254; main's own pre-commit has been red since that merge. Nothing in this diff touches that file, so this needs a re-run once main is fixed rather than a push here.

@DarkLight1337

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93164 for commit 0524569f9321.

@aniskumar-nv

aniskumar-nv commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

The two basic-models-other failures are test_registry_imports[EmbeddingGemma2Model], introduced by #60254 and fixed on main by #60295 (merged after this build started); nothing in this diff is involved. Rebasing onto current main to pick up #60295, then re-running CI on the new head.
cc @DarkLight1337

auto-merge was automatically disabled October 7, 2026 15:43

Head branch was pushed to by a user without write access

@aniskumar-nv
aniskumar-nv force-pushed the fix/nemotron-parse-tied-lm-head-reland branch from 0524569 to 17506d8 Compare October 7, 2026 15:43
@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

/ci run

@DarkLight1337
DarkLight1337 enabled auto-merge (squash) October 7, 2026 15:50
@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

/ci run --allow-stale

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93363 for commit 17506d8f95f0.

⚠️ This PR is 3 commits behind upstream main. Running CI at your own risk because --allow-stale was requested; outdated CI configuration may cause failures. Before merging, merge or rebase onto the latest main, then rerun /ci run on the latest PR commit.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

/ci retry

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Queued 1 failed job(s) for retry in Buildkite CI #93363.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ No failed, timed-out, or expired jobs need retrying: https://buildkite.com/vllm/ci/builds/93363

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

The remaining red is one basic-models-extra-initialization shard: test_can_initialize_large_subset for the Laguna-XS and Mistral-Large-3 NVFP4 cases fails at engine init with ValueError: No compatible Humming input schema … (the related fix is #60337). The same step is red on main today and nothing in this diff touches that path; the Nemotron Parse initialization case in the same step passed. Retrying the failed job.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

/ci retry

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Queued 1 failed job(s) for retry in Buildkite CI #93363.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

Retry reproduced the same Humming schema error, so it is deterministic in the current CI environment and gated on #60337. The amd-mi355-basic-models-other red is test_deepseek_v4_dspark_rocm (red on main as well) and that mirror step is optional. Will update the branch and re-run once #60337 lands.

auto-merge was automatically disabled October 7, 2026 18:46

Head branch was pushed to by a user without write access

@aniskumar-nv
aniskumar-nv force-pushed the fix/nemotron-parse-tied-lm-head-reland branch from 17506d8 to 6e2e9d6 Compare October 7, 2026 18:46
@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93386 for commit 6e2e9d6df5bc.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

CI on the rebased head: every NVIDIA step is green, including the extra-initialization shards that were failing before the #60337 fix. The only remaining red is the AMD mirror amd-mi355-basic-models-other, failing on test_deepseek_v4_rocm_dspark* (red on main, unrelated to this diff; auto-retry reproduced it). The fix for that test is #60462. Happy to update and re-run once it lands, or merge over it if that is acceptable.

@aniskumar-nv

aniskumar-nv commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

@DarkLight1337 all NVIDIA steps are green here; the only red is the AMD mirror failing on test_deepseek_v4_rocm_dspark*, a main-side test bug, not this diff. The fix (#60462) has just merged, so I will update the branch and re-run CI; auto-merge will need re-enabling afterwards.

…arse when checkpoint omits it

Reverts vllm-project#59805 (7cfd233), restoring vllm-project#53020 (83cadd6) unchanged.

nvidia/NVIDIA-Nemotron-Parse-2.0 sets tie_word_embeddings=True and ships no
lm_head.weight; without the tie, NemotronParseForConditionalGeneration keeps a
randomly initialized output head and every response is garbage while the
server reports healthy.

vllm-project#53020 was reverted because the Parse-2.0 test case it added failed in the
nightly full CI run at tokenizer load (TokenizerFast.from_file ->
DuplicatePatternError), before any model code ran. The cause was the CI pin
tokenizers==0.23.1, which rejects added tokens that collide after NFKC
normalization (14 such pairs in this tokenizer). vllm-project#59796 bumped the pin to
0.23.2, which loads the file, so the test case can run as written.

Co-authored-by: Cyrus Leung <tlleungac@connect.ust.hk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Anish Kumar <aniskumar@nvidia.com>
@aniskumar-nv
aniskumar-nv force-pushed the fix/nemotron-parse-tied-lm-head-reland branch from 6e2e9d6 to 91b560f Compare October 7, 2026 22:19
@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #93437 for commit 91b560fbd670.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

CI is fully green on the rebased head (155/155, including the AMD mirror after #60462). Ready to merge; auto-merge was disabled by the branch update, so it needs re-enabling or a manual merge.

@aniskumar-nv

Copy link
Copy Markdown
Contributor Author

@DarkLight1337 ready to merge?

@DarkLight1337
DarkLight1337 enabled auto-merge (squash) October 8, 2026 04:40
@DarkLight1337
DarkLight1337 merged commit 775792f into vllm-project:main Oct 8, 2026
156 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working multi-modality Related to multi-modality (#4194) ready ONLY add when PR is ready to merge/full CI is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants