Skip to content

[LoRA][Nemotron] Add LoRA support for Nemotron VL models (for the language model only) - #56231

Merged
vllm-bot merged 5 commits into
vllm-project:mainfrom
de-inf:nemo_vl_lora
Sep 16, 2026
Merged

vllm-bot merged 5 commits into
vllm-project:mainfrom
de-inf:nemo_vl_lora

Conversation

@danisereb

@danisereb danisereb commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

At this time Nemotron VL models fail if used with LoRA adapters:

ValueError: NemotronH_Nano_VL_V2 does not support LoRA yet.

This PR enables LoRA on the language model of Nemotron VL models.

Both text and media embeddings flow through the language model after the multimodal merge, adapters apply to media tokens too.
What's not covered is LoRA on the encoders and connectors themselves (RADIO, mlp1, Parakeet), which vLLM gates behind the supports_tower_connector_lora opt-in that this model does not declare.

From docs/models/supported_models.md:

!!! note
    vLLM currently supports adding LoRA adapters to the language backbone for most multimodal models. Additionally, vLLM now experimentally supports adding LoRA to the tower and connector modules for some multimodal models. See [this page](../features/lora.md).

Note: AI assistance was used in this PR.

Test Plan

Verify correctness using evals (gsm8k) with Nemotron VL model (with/without LoRA adapter).

Test Result

GSM8K results for Nemotron-3-Nano-Omni-30B-A3B:

vllm serve nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16 \
--served-model-name my_model --host 0.0.0.0 --port 8000 \
--trust-remote-code --tensor-parallel-size 4 --enable-expert-parallel \
--enable-lora --max-lora-rank 8 --max-loras 1 \
--lora-modules '{"name": "lora_model", "path": "/my_home/hf_models/oridos/nemotron-tinystories-lora/", "base_model_name": "my_model"}'

# vLLM main (nightly-2a02f6efe319c885e3ccbcecde402e0028f9ec1e), base model

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value |   |Stderr|
|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k|      3|flexible-extract|     5|exact_match|↑  |0.8203|±  |0.0106|
|     |       |strict-match    |     5|exact_match|↑  |0.8415|±  |0.0101|

# This PR, base model

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value |   |Stderr|
|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k|      3|flexible-extract|     5|exact_match|↑  |0.8241|±  |0.0105|
|     |       |strict-match    |     5|exact_match|↑  |0.8423|±  |0.0100|

# This PR,
# with LoRA adapter:
# https://huggingface.co/oridos/nemotron-tinystories-lora

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value |   |Stderr|
|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k|      3|flexible-extract|     5|exact_match|↑  |0.8256|±  |0.0105|
|     |       |strict-match    |     5|exact_match|↑  |0.8218|±  |0.0105|

Essential Elements of an Effective PR Description Checklist
  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan, such as providing test command.
  • The test results, such as pasting the results comparison before and after, or e2e results
  • (Optional) The necessary documentation update, such as updating supported_models.md and examples for a new model.

@danisereb
danisereb marked this pull request as ready for review September 10, 2026 09:16

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

@danisereb danisereb changed the title Add LoRA support for Nemotron VL models (language model only) Add LoRA support for Nemotron VL models (for the language model only) Sep 10, 2026

@qthequartermasterman qthequartermasterman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is timely. I was just looking this afternoon what would be needed for LoRA support for Nemotron 3 Omni. This PR looks good to me.

@jeejeelee @DarkLight1337

@linitra24 linitra24 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall, looks good to me. I also noticed that this model is not listed in docs/models/supported_models.md. Should we add it there as well?

# the LoRA delta is undefined for tokens with no mapping entry.
embed_tokens = self.get_language_model().model.embed_tokens
if isinstance(embed_tokens, BaseLayerWithLoRA):
embed_tokens = embed_tokens.base_layer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

QQ: If embed_tokens is adapted during training, wouldn’t the internally generated text/special tokens that are not replaced by video embeddings also receive the LoRA delta?

@danisereb danisereb Sep 14, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I had to dig deeper to give a proper answer (with some help from Claude for the vision/video code), and you're correct.

Video marker tokens - the per-frame separator text (e.g. Frame 1 sampled at 0.50 seconds:) and the <img> / </img> tags wrapping each frame do not get the embedding LoRA delta.

They're generated inside the encoder by _create_final_video_embeddings, so they never appear in the scheduled token batch that vLLM builds the per-token LoRA adapter index mapping from - and there can be more of them than max_num_batched_tokens, which is what that mapping is sized for.

Without this PR, that path raises an error, so video + LoRA doesn't work at all today.

This issue is unlikely to be a problem in practice:

  • peft with target_modules="all-linear" does not include nn.Embedding. you'd have to name embed_tokens explicitly. The public adapter I tested (https://huggingface.co/oridos/nemotron-tinystories-lora) has no embedding weights. I am not sure if LoRA weights for the embedding is common / popular.
  • With no embedding LoRA, this change is a no-op (the delta would be zero).

For basic enablement of LoRA for Nemotron VL models, I think this change is OK.

@linitra24 tell me if something here doesn't align with your understanding of the flow.

@jeejeelee is there any code change you think would help?
Raising an error if embedding LoRA is detected doesn't sound like a good idea - no model in vLLM rejects adapters with embedding weights today, so Nemotron VL would become uniquely strict.

Note:
Similar flow (and likely limitation) seems to exist for Qwen3-VL (see function _create_final_video_embeddings in file vllm/model_executor/models/qwen3_vl.py).

@jeejeelee

Copy link
Copy Markdown
Member

please respond to @linitra24's comment

@danisereb

danisereb commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor Author

@linitra24 I added the Nemotron-VL models to supported_models

@mergify

mergify Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Documentation preview: https://vllm--56231.org.readthedocs.build/en/56231/

@mergify mergify Bot added the documentation Improvements or additions to documentation label Sep 14, 2026
@jeejeelee

Copy link
Copy Markdown
Member

/ci run

@jeejeelee
jeejeelee enabled auto-merge (squash) September 15, 2026 14:42

@linitra24 linitra24 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks!

@github-actions

Copy link
Copy Markdown

❌ This PR is 282 commits behind upstream main. Your branch must contain every commit currently on upstream main. No new CI build was started. Merge or rebase onto the latest main, then rerun /ci run. To test this branch at your own risk, use /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 Sep 15, 2026
Signed-off-by: Daniel Serebrenik <daserebrenik@nvidia.com>
Signed-off-by: Daniel Serebrenik <daserebrenik@nvidia.com>
Signed-off-by: Daniel Serebrenik <daserebrenik@nvidia.com>
…orted_models

Signed-off-by: Daniel Serebrenik <daserebrenik@nvidia.com>
auto-merge was automatically disabled September 15, 2026 14:52

Head branch was pushed to by a user without write access

@danisereb

danisereb commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Rebased on main to allow CI run.

@jeejeelee can you re-enable auto-merge ?

@danisereb danisereb changed the title Add LoRA support for Nemotron VL models (for the language model only) [Nemotron][LoRA] Add LoRA support for Nemotron VL models (for the language model only) Sep 15, 2026
@danisereb danisereb changed the title [Nemotron][LoRA] Add LoRA support for Nemotron VL models (for the language model only) [LoRA][Nemotron] Add LoRA support for Nemotron VL models (for the language model only) Sep 15, 2026
@benchislett
benchislett enabled auto-merge (squash) September 15, 2026 15:04
@benchislett

Copy link
Copy Markdown
Member

/ci run

@github-actions

Copy link
Copy Markdown

❌ This PR is 3 commits behind upstream main. Your branch must contain every commit currently on upstream main. No new CI build was started. Merge or rebase onto the latest main, then rerun /ci run. To test this branch at your own risk, use /ci run --allow-stale.

@danisereb

Copy link
Copy Markdown
Contributor Author

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #89118 for commit 7dfdd854a813.

@vllm-bot
vllm-bot merged commit a31ec3a into vllm-project:main Sep 16, 2026
122 of 125 checks passed
@qthequartermasterman

Copy link
Copy Markdown
Contributor

@danisereb Do you plan on adding LoRA support to the vision/audio encoders as well at some point?

@linitra24

Copy link
Copy Markdown
Contributor

@danisereb Do you plan on adding LoRA support to the vision/audio encoders as well at some point?

If needed, I'd be happy to take this on.

@danisereb
danisereb deleted the nemo_vl_lora branch September 28, 2026 07:07
@danisereb

Copy link
Copy Markdown
Contributor Author

@qthequartermasterman
I do not plan to add LoRA support for vision/audio at this time.

@linitra24
It would be great if you take this!

@qthequartermasterman

Copy link
Copy Markdown
Contributor

@danisereb @linitra24 My colleague @Nan2018 actually has just opened a PR for vision/audio support: #58658.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation 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.

6 participants