Skip to content

Commit e4e13cd

Browse files
kamran-nvidiaclaude
andcommitted
refactor(model): build MiMo from a builder-backed model config
MimoBridge extends the Qwen2 builder kwargs with its attention settings and MTP depth (mtp_num_layers, mtp_loss_scaling_factor) instead of overriding provider_bridge(). It inherits the Qwen2 conversion flag, so MiMo checkpoints convert through the ModelBuilder as well. Signed-off-by: Kamran Jafari <kjafarisadeg@nvidia.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent ea88b54 commit e4e13cd

2 files changed

Lines changed: 42 additions & 9 deletions

File tree

‎src/megatron/bridge/models/mimo/mimo_bridge.py‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import Mapping
15+
from typing import Any, Mapping
1616

1717
import torch
1818
from megatron.core.models.gpt.gpt_model import GPTModel
19+
from transformers import PretrainedConfig
1920

2021
from megatron.bridge.models.conversion.mapping_registry import MegatronMappingRegistry
2122
from megatron.bridge.models.conversion.model_bridge import MegatronModelBridge, WeightConversionTask
@@ -31,20 +32,18 @@
3132
class MimoBridge(Qwen2Bridge):
3233
"""Megatron Bridge for MiMo Causal LM."""
3334

34-
def provider_bridge(self, hf_pretrained):
35-
provider = super().provider_bridge(hf_pretrained)
36-
hf_config = hf_pretrained.config
35+
def hf_config_to_model_config_kwargs(self, hf_config: PretrainedConfig) -> dict[str, Any]:
36+
"""Convert a Hugging Face MiMo config to builder config kwargs."""
37+
config_kwargs = super().hf_config_to_model_config_kwargs(hf_config)
3738

3839
# MiMo follows Qwen2 attention behavior and adds MTP on top.
39-
provider.qk_layernorm = False
40-
provider.add_qkv_bias = True
40+
config_kwargs.update(qk_layernorm=False, add_qkv_bias=True)
4141

4242
num_mtp_layers = getattr(hf_config, "num_nextn_predict_layers", 0)
4343
if num_mtp_layers > 0:
44-
provider.mtp_num_layers = num_mtp_layers
45-
provider.mtp_loss_scaling_factor = 0.1
44+
config_kwargs.update(mtp_num_layers=num_mtp_layers, mtp_loss_scaling_factor=0.1)
4645

47-
return provider
46+
return config_kwargs
4847

4948
def mapping_registry(self) -> MegatronMappingRegistry:
5049
mapping_list = list(super().mapping_registry().mappings)

‎tests/unit_tests/models/mimo/test_mimo_bridge.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,37 @@ def test_mtp_input_proj_swap_on_hf_export(self):
126126

127127
expected = torch.cat((weight[:, 4:], weight[:, :4]), dim=1)
128128
assert torch.equal(modified["model.mtp_layers.0.input_proj.weight"], expected)
129+
130+
def test_provider_bridge_is_inherited_compatibility_only(self):
131+
"""MiMo builds both paths from its builder-config kwargs."""
132+
assert "provider_bridge" not in MimoBridge.__dict__
133+
134+
def test_conversion_uses_builder_config(self):
135+
assert MimoBridge.USE_MODEL_CONFIG_FOR_CONVERSION is True
136+
137+
def test_model_config_maps_mtp_config(self, mock_pretrained_mimo):
138+
from megatron.bridge.models.gpt.model_config import BridgeGPTModelConfig
139+
140+
model_config = MimoBridge().hf_config_to_model_config(mock_pretrained_mimo.config)
141+
142+
assert isinstance(model_config, BridgeGPTModelConfig)
143+
assert model_config.qk_layernorm is False
144+
assert model_config.add_qkv_bias is True
145+
assert model_config.mtp_num_layers == mock_pretrained_mimo.config.num_nextn_predict_layers
146+
assert model_config.mtp_loss_scaling_factor == 0.1
147+
assert model_config.position_embedding_type == "rope"
148+
assert model_config.normalization == "RMSNorm"
149+
150+
def test_model_config_matches_provider_runtime_config(self, mock_pretrained_mimo):
151+
from dataclasses import fields
152+
153+
bridge = MimoBridge()
154+
model_config = bridge.hf_config_to_model_config(mock_pretrained_mimo.config)
155+
with pytest.warns(FutureWarning, match=r"deprecated.*get_model_config.*get_model"):
156+
provider = bridge.provider_bridge(mock_pretrained_mimo)
157+
158+
provider_fields = {field.name for field in fields(provider)}
159+
model_config_fields = {field.name for field in fields(model_config)}
160+
model_config_fields.update(field.name for field in fields(model_config.transformer))
161+
for field_name in sorted((provider_fields & model_config_fields) - {"transformer_layer_spec"}):
162+
assert getattr(model_config, field_name) == getattr(provider, field_name), field_name

0 commit comments

Comments
 (0)