Skip to content

Commit 7e9dcd6

Browse files
authored
feat(nemotron): native HF 5.19 Super VL conversion support (#6471)
Signed-off-by: Chen Cui <chcui@nvidia.com>
1 parent e2f2496 commit 7e9dcd6

16 files changed

Lines changed: 650 additions & 51 deletions

File tree

‎docs/fern/versions/nightly/pages/models/minimax/minimax-m3.mdx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
[MiniMax-M3](https://huggingface.co/MiniMaxAI/MiniMax-M3) is a natively multimodal sparse MoE model from MiniMaxAI (428B total, ~23B active parameters). `MiniMaxM3Bridge` converts the vision tower, both multimodal projector stages, and sparse-MoE text backbone into a `MiniMaxM3VLModel`.
44

5+
## Transformers vision RoPE compatibility
6+
7+
Bridge applies its full partial-3D vision RoPE correction only on Transformers
8+
5.17.0. Transformers 5.18+ includes the geometry fix from
9+
[HF PR #49164](https://github.com/huggingface/transformers/pull/49164), so Bridge
10+
leaves those versions unpatched.
11+
12+
The native 5.18/5.19 implementation stores inverse frequencies in buffers.
13+
Explicit `.half()` or `.bfloat16()` casts can round these buffers, producing
14+
different results from the earlier FP32-per-forward calculation. Bridge accepts
15+
this precision difference and does not promise bitwise equality across these
16+
versions after dtype conversion. The three-axis geometry and partial rotation
17+
remain required and tested.
18+
519
{/* BEGIN GENERATED VERIFIED CONFIGURATIONS */}
620

721
## Verified configurations

‎docs/fern/versions/nightly/pages/models/nemotron/nemotron3.5-super-vl.mdx‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,47 @@ The records below contain refreshed conversion, inference, and training verifica
1212

1313
For language-only conversion and training without media components, see [the text-only companion guide](nemotron3.5-super-vl-text-only.md).
1414

15+
## Native Hugging Face processor compatibility
16+
17+
With Transformers 5.19.0, `AutoBridge.from_hf_pretrained(..., trust_remote_code=False)`
18+
uses a Bridge-local processor loading adapter for Super VL. It removes a legacy
19+
read-only video configuration field in memory and does not require an audio feature
20+
extractor for this audio-free model. The source checkpoint and installed Transformers
21+
code are not modified; image/video processing and token expansion use the native HF
22+
implementation. Remote-code loading remains available on older supported HF versions.
23+
24+
The adapter is version-guarded to Transformers 5.19.0. Processor artifacts can be saved
25+
and reloaded through Bridge, but ordinary `AutoProcessor.from_pretrained` outside
26+
Bridge still encounters the native 5.19.0 audio-component requirement. This workaround
27+
does not imply standalone HF processor compatibility or full model forward parity.
28+
The wrapper's `hf_pretrained.model` accessor selects `AutoModelForImageTextToText`
29+
for native Super VL and retains `AutoModelForCausalLM` for legacy remote-code
30+
loading. Ordinary text checkpoints continue to use `AutoModelForCausalLM`.
31+
Filtered text-only conversion views are not directly loadable for HF inference;
32+
load their standalone text exports instead. Full native forward parity remains
33+
a separate verification requirement.
34+
35+
Known native HF 5.19.0 runtime limitations for this checkpoint:
36+
37+
- The installed `mamba-ssm` execution path produced non-finite text logits in
38+
verification. With that package unavailable to the HF process, the native
39+
PyTorch fallback produced bitwise-identical source/export logits and identical
40+
16-token greedy continuations on three prompts. This is a diagnostic runtime
41+
condition, not an automatic Bridge workaround; do not remove dependencies
42+
from a shared Megatron training environment.
43+
- Image/video inputs can be prepared with the Bridge processor adapter and
44+
passed to the native HF model. This is **not** standalone HF processor support.
45+
Native video forward currently fails because it concatenates an already-tensor
46+
`pooler_output` as though it were a sequence. Video inference is not verified.
47+
- Native HF does not consume the source checkpoint's
48+
`vision_projector.vision_final_layernorm` keys. The tested Base checkpoint has
49+
identity affine values, but this does not validate loading non-identity values
50+
from a fine-tuned checkpoint. Bridge preserves these source weights during
51+
conversion; native HF visual reload remains a separate compatibility gap.
52+
53+
These limitations and checks do not update or supersede the historical
54+
verification-card results below.
55+
1556
{/* BEGIN GENERATED VERIFIED CONFIGURATIONS */}
1657

1758
## Verified configurations

‎docs/models/minimax/minimax-m3.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
[MiniMax-M3](https://huggingface.co/MiniMaxAI/MiniMax-M3) is a natively multimodal sparse MoE model from MiniMaxAI (428B total, ~23B active parameters). `MiniMaxM3Bridge` converts the vision tower, both multimodal projector stages, and sparse-MoE text backbone into a `MiniMaxM3VLModel`.
44

5+
## Transformers vision RoPE compatibility
6+
7+
Bridge applies its full partial-3D vision RoPE correction only on Transformers
8+
5.17.0. Transformers 5.18+ includes the geometry fix from
9+
[HF PR #49164](https://github.com/huggingface/transformers/pull/49164), so Bridge
10+
leaves those versions unpatched.
11+
12+
The native 5.18/5.19 implementation stores inverse frequencies in buffers.
13+
Explicit `.half()` or `.bfloat16()` casts can round these buffers, producing
14+
different results from the earlier FP32-per-forward calculation. Bridge accepts
15+
this precision difference and does not promise bitwise equality across these
16+
versions after dtype conversion. The three-axis geometry and partial rotation
17+
remain required and tested.
18+
519
<!-- BEGIN GENERATED VERIFIED CONFIGURATIONS -->
620

721
## Verified configurations

‎docs/models/nemotron/nemotron3.5-super-vl.md‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,47 @@ The records below contain refreshed conversion, inference, and training verifica
1212

1313
For language-only conversion and training without media components, see [the text-only companion guide](nemotron3.5-super-vl-text-only.md).
1414

15+
## Native Hugging Face processor compatibility
16+
17+
With Transformers 5.19.0, `AutoBridge.from_hf_pretrained(..., trust_remote_code=False)`
18+
uses a Bridge-local processor loading adapter for Super VL. It removes a legacy
19+
read-only video configuration field in memory and does not require an audio feature
20+
extractor for this audio-free model. The source checkpoint and installed Transformers
21+
code are not modified; image/video processing and token expansion use the native HF
22+
implementation. Remote-code loading remains available on older supported HF versions.
23+
24+
The adapter is version-guarded to Transformers 5.19.0. Processor artifacts can be saved
25+
and reloaded through Bridge, but ordinary `AutoProcessor.from_pretrained` outside
26+
Bridge still encounters the native 5.19.0 audio-component requirement. This workaround
27+
does not imply standalone HF processor compatibility or full model forward parity.
28+
The wrapper's `hf_pretrained.model` accessor selects `AutoModelForImageTextToText`
29+
for native Super VL and retains `AutoModelForCausalLM` for legacy remote-code
30+
loading. Ordinary text checkpoints continue to use `AutoModelForCausalLM`.
31+
Filtered text-only conversion views are not directly loadable for HF inference;
32+
load their standalone text exports instead. Full native forward parity remains
33+
a separate verification requirement.
34+
35+
Known native HF 5.19.0 runtime limitations for this checkpoint:
36+
37+
- The installed `mamba-ssm` execution path produced non-finite text logits in
38+
verification. With that package unavailable to the HF process, the native
39+
PyTorch fallback produced bitwise-identical source/export logits and identical
40+
16-token greedy continuations on three prompts. This is a diagnostic runtime
41+
condition, not an automatic Bridge workaround; do not remove dependencies
42+
from a shared Megatron training environment.
43+
- Image/video inputs can be prepared with the Bridge processor adapter and
44+
passed to the native HF model. This is **not** standalone HF processor support.
45+
Native video forward currently fails because it concatenates an already-tensor
46+
`pooler_output` as though it were a sequence. Video inference is not verified.
47+
- Native HF does not consume the source checkpoint's
48+
`vision_projector.vision_final_layernorm` keys. The tested Base checkpoint has
49+
identity affine values, but this does not validate loading non-identity values
50+
from a fine-tuned checkpoint. Bridge preserves these source weights during
51+
conversion; native HF visual reload remains a separate compatibility gap.
52+
53+
These limitations and checks do not update or supersede the historical
54+
verification-card results below.
55+
1556
<!-- BEGIN GENERATED VERIFIED CONFIGURATIONS -->
1657

1758
## Verified configurations

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ classifiers = [
7171
"Topic :: Utilities",
7272
]
7373
dependencies = [
74-
"transformers>=5.15,<5.18",
74+
"transformers>=5.15,<5.20",
7575
"mistral-common>=1.10.0",
7676
"peft>=0.20.0,<=0.21.0",
7777
"datasets>=2.20.0",

‎src/megatron/bridge/models/conversion/auto_bridge.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ class instead of raising, silently loading the wrong architecture. Remaining
281281
supported architectures use :class:`PreTrainedCausalLM`.
282282
"""
283283
architectures = getattr(config, "architectures", None) or []
284+
if "NemotronH_Omni_Reasoning_V3" in architectures:
285+
from megatron.bridge.models.nemotron_omni.hf_pretrained import Nemotron35VLPretrained
286+
287+
return Nemotron35VLPretrained
284288
if any(arch.endswith("ForTokenClassification") for arch in architectures):
285289
return PreTrainedTokenClassification
286290
if any(arch.endswith("ForMaskedLM") for arch in architectures):
@@ -1259,7 +1263,12 @@ def _save_artifacts():
12591263
.hf_pretrained
12601264
)
12611265
else:
1262-
artifact_source = PreTrainedCausalLM.from_pretrained(artifact_source_path, **artifact_kwargs)
1266+
artifact_cls = _resolve_pretrained_wrapper_cls(self.hf_pretrained)
1267+
# Preserve specialized causal-family processor loaders without
1268+
# changing the artifact contract for non-causal model heads.
1269+
if not issubclass(artifact_cls, PreTrainedCausalLM):
1270+
artifact_cls = PreTrainedCausalLM
1271+
artifact_source = artifact_cls.from_pretrained(artifact_source_path, **artifact_kwargs)
12631272
artifact_source.config = self.hf_pretrained
12641273
additional_files = getattr(model_bridge_instance, "ADDITIONAL_FILE_PATTERNS", None) or None
12651274
artifact_source.save_artifacts(

‎src/megatron/bridge/models/hf_pretrained/causal_lm.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ def __init__(
153153
if model_name_or_path and trust_remote_code:
154154
self._original_source_path = model_name_or_path
155155

156+
def _get_auto_model_class(self) -> type:
157+
"""Select the HF loader without changing shared lazy-loading behavior."""
158+
return AutoModelForCausalLM
159+
156160
def _load_model(self) -> CausalLMType:
157161
"""Load the model."""
158162
if self._text_only:
@@ -172,7 +176,7 @@ def _load_model(self) -> CausalLMType:
172176
if config is not None:
173177
model_kwargs["config"] = config
174178

175-
model = AutoModelForCausalLM.from_pretrained(self.model_name_or_path, **model_kwargs)
179+
model = self._get_auto_model_class().from_pretrained(self.model_name_or_path, **model_kwargs)
176180
model = model.to(self.device)
177181

178182
generation_config = getattr(self, "_generation_config", None)

‎src/megatron/bridge/models/minimax_m3/transformers_compat.py‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,18 @@ def forward(self, x: torch.Tensor, position_ids: torch.Tensor) -> tuple[torch.Te
5454

5555

5656
def patch_minimax_m3_vision_rope() -> bool:
57-
"""Restore 3D vision RoPE for new HF MiniMax models on Transformers 5.17.0.
57+
"""Restore partial 3D vision RoPE on Transformers 5.17.0 only.
5858
5959
Transformers PR #48105 changed the frequency ladder to 2D and dropped the
6060
width coordinate from the T/H/W position IDs. Keep the released checkpoint's
61-
partial 3D rotation until an upstream fixed release is available. Replacing
62-
the class affects new MiniMax models only. Import Bridge before constructing
63-
HF MiniMax models; existing instances retain their old numerical behavior
64-
and should be reconstructed before serialization.
61+
partial 3D rotation on 5.17.0. Transformers PR #49164 restores the geometry
62+
in 5.18+. Leave those releases unpatched: their native buffer-based frequency
63+
calculation can differ after model.half()/bfloat16() from the FP32-per-forward
64+
calculation used here. That precision difference is accepted; it is not the
65+
missing-axis/incorrect-geometry bug this compatibility patch addresses.
66+
Replacing the class affects new MiniMax models only. Import Bridge before
67+
constructing HF MiniMax models; existing instances retain their old numerical
68+
behavior and should be reconstructed before serialization.
6569
"""
6670
if transformers.__version__ != "5.17.0":
6771
return False
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Native HF processor compatibility for the audio-free Super-VL checkpoint."""
16+
17+
import transformers
18+
from packaging.version import Version
19+
from transformers import AutoModelForImageTextToText, AutoProcessor, ProcessorMixin
20+
21+
from megatron.bridge.models.hf_pretrained.causal_lm import PreTrainedCausalLM
22+
23+
24+
class Nemotron35VLPretrained(PreTrainedCausalLM):
25+
"""Keep native processor compatibility separate from legacy remote-code loading."""
26+
27+
def _uses_remote_model(self) -> bool:
28+
"""Check the checkpoint registration, not only permission to execute it."""
29+
return self.trust_remote_code and bool(
30+
(getattr(self.config, "auto_map", None) or {}).get("AutoModelForCausalLM")
31+
)
32+
33+
def _get_auto_model_class(self) -> type:
34+
"""Use native VL registration while retaining the remote CausalLM mapping."""
35+
if self._text_only:
36+
return super()._get_auto_model_class()
37+
# Permission to execute remote code does not imply that the checkpoint
38+
# uses it: native exports have no remote CausalLM registration.
39+
if self._uses_remote_model():
40+
return super()._get_auto_model_class()
41+
if Version(transformers.__version__) < Version("5.19.0"):
42+
raise ValueError("Native Super-VL requires Transformers >=5.19.0; use trust_remote_code=True otherwise.")
43+
return AutoModelForImageTextToText
44+
45+
def _load_processor(self) -> ProcessorMixin | None:
46+
if self.model_name_or_path is None or self._uses_remote_model():
47+
return super()._load_processor()
48+
49+
version = Version(transformers.__version__)
50+
if version < Version("5.19.0"):
51+
raise ValueError("Native Super-VL requires Transformers >=5.19.0; use trust_remote_code=True otherwise.")
52+
53+
processor_cls = AutoProcessor
54+
# Bound the workaround to the release whose loading behavior we tested.
55+
# Future releases use their own loader and surface errors rather than
56+
# silently dropping a required VLM artifact during conversion/export.
57+
if version.base_version == "5.19.0" and getattr(self.config, "audio_config", None) is None:
58+
from megatron.bridge.models.nemotron_omni.processing_super_vl import Nemotron35VLProcessor
59+
60+
processor_cls = Nemotron35VLProcessor
61+
return processor_cls.from_pretrained(self.model_name_or_path, trust_remote_code=False, **self.init_kwargs)

0 commit comments

Comments
 (0)