You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Implement canonical ModelOpt quantized HF export through Megatron Bridge #4804
Wire Megatron-Bridge topology reconstruction and HF naming to ModelOpt functional export so quantized Megatron models can be emitted in the canonical ModelOpt HF schema for native vLLM deployment and refit.
Megatron-Bridge scope
Reconstruct logical HF weights across TP, ETP, EP, and PP.
Apply fused QKV, gate/up, and expert topology transforms while carrying opaque ModelOpt export state.
Call ModelOpt-owned packing and config APIs and expose the resulting canonical tensors and sidecars.
changed the title [-]Natively support quantized megatron to HF export for vLLM deployment (retires ModelOpt custom logic)[/-][+]Implement canonical ModelOpt quantized HF export through Megatron Bridge[/+]on Aug 24, 2026
Re-evaluated this against current main of both repos (2026-09-30) and the open PRs, with the goal of fully deprecating ModelOpt's custom Megatron↔HF logic (unified_export_megatron.py, plugins/mcore_*.py, plugins/megatron_importer.py) in favor of the bridge. Below is the current state and the proposed split of remaining work.
Where things stand
MBridge main is essentially unchanged since July. export_hf_weights_modelopt:
supports NVFP4 / W4A16-NVFP4 only and rejects static NVFP4;
writes no quantization_config and has no save-to-dir wrapper;
drops KV-cache quantizers;
renames fused experts to vLLM-internal w13_weight / w2_weight.
It has no callers outside unit tests. examples/quantization/export.py still calls ModelOpt's mtex.export_mcore_gpt_to_hf.
ModelOpt: format, packing and quantization_config.
MBridge: topology and HF names.
feat(export): add functional quantized weight export NVIDIA/Model-Optimizer#2251 covers FP8, FP8_PC_PT, FP8_PB_WO, MXFP8, NVFP4 (dynamic and static), W4A16/W4A8 NVFP4, MXFP4 and mixed precision. That is a superset of what the custom Megatron exporter writes a quant config for, except IQ. The custom exporter already rejects AWQ/SmoothQuant, so this is no regression. Both PRs have been drafts since 2026-09-10.
The custom exporter is TP=1 only; it shards through PP. The bridge gathers across TP / EP / ETP / PP.
Only the inline config.jsonquantization_config is needed; drop hf_quant_config.json.
vLLM prefers the inline config. It falls back to the file only for ModelOpt ≤0.29 checkpoints, or mixed precision without quantized_layers (config.py#L921-L933, weight_utils.py#L224-L265).
ModelOpt will unify the pair's amax after calibration, so QAT numerics match what gets deployed. The bridge only needs a generic check (see below). Longer term, MCore's mla_down_proj_fusion gives the pair a single quantizer natively.
Drop ModelOpt's HF→Megatron import path (import_mcore_gpt_from_hf / megatron_importer.py). BF16 HF→Megatron import is already covered by AutoBridge. The remaining users are Megatron-LM's examples/post_training/modelopt (convert_model.py, quantize.py, prune.py; export.py uses the exporter). Those examples get migrated to AutoBridge or retired together with the exporter.
Testing-first. Implementation is expected to be the small part. Every PR lands with Megatron-Bridge CI tests that let us merge confidently (see "Test plan").
Test plan (Megatron-Bridge CI, with every PR)
Parallelism parity against the current ModelOpt export.
Quantize a small model per architecture once, then export the same Megatron checkpoint two ways:
new: bridge native export at TP2, PP2, EP2 and ETP2 (fits the existing 2-GPU H100 / GB200 runners), with larger combinations such as TP2×EP2×PP2 in the nightly tier.
Assert that everything vLLM reads is identical:
every tensor, bitwise (names, dtypes, shapes, values);
config.json, including quantization_config (quant_algo, quantized_layers, exclude list, KV scheme);
generation config, tokenizer and processor config.
How tensors are split across safetensors files may differ. Any intentional difference (e.g. MLA scale unification) is listed explicitly and treated as having no baseline.
Also export a checkpoint quantized at TP/EP > 1, so amax resharding on load is covered.
Once the ModelOpt exporter is removed, the bridge TP1/PP1 export becomes the reference for parallelism invariance, plus small checked-in golden hashes.
fused sibling groups (q/k/v, gate/up, q_a/kv_a) share weight_scale_2 / input_scale;
exclude_modules covers exactly the unquantized linears;
no source-checkpoint quantization_config or *_scale_inv leaks through.
vLLM runs only where there is no identical baseline. If the bridge export is identical to a vLLM-validated checkpoint from the ModelOpt exporter, a vLLM run adds no information. vLLM (Blackwell for NVFP4) is needed only for:
architectures and formats the ModelOpt exporter doesn't cover, e.g. Qwen3-VL-MoE, Gemma3-VL, MXFP8, FP8 per-channel;
intentional differences from the old export.
Even there it is a one-time load plus known-answer prompts, not a full eval.
Pilot: Qwen3.6-35B-A3B W4A4 NVFP4 from the ModelOpt tutorial (examples/megatron_bridge/tutorials/Qwen3.6-35B-A3B). One vLLM load-and-generate, only to confirm the parity harness compares everything vLLM reads.
KV-cache export: k_scale / v_scale from k_bmm / v_bmm quantizers, plus kv_cache_quant_algo. It is hard-set to NONE today.
MLA q_down / kv_down amax unification: static NVFP4 via SharedWeightGlobalAmaxState patterns; dynamic NVFP4 / FP8 per-tensor via a post-calibration step.
Find a home for the other users of unified_export_megatron.py before deleting it:
vLLM fake-quant export (export_mcore_gpt_to_hf_vllm_fq, used by Megatron-LM export.py): port to the bridge's BF16 export of folded weights plus a quantizer-state sidecar;
Switch examples/megatron_bridge and the Megatron-LM post_training/modelopt examples to the bridge. Deprecate export_mcore_gpt_to_hf / import_mcore_gpt_from_hf for one release, then remove them together with the mcore_* rule tables.
Offline save API (save_hf_pretrained-style) that consumes the export plan and writes the packed tensors plus the inline quantization_config. It should also strip any source-checkpoint quantization_config and *_scale_inv companions.
Per-expert canonical names also for transpose_on_export experts.
exclude_modules derived from disabled quantizers, plus a per-HF-output "export unquantized" override for HF weights that MCore fuses into one quantized linear (below).
Post-export check: equal weight_scale_2 / input_scale across fused sibling groups.
Parity and format tests from the test plan.
MBridge, per bridge
Needed
Bridges
Nothing (standard mappings only)
Llama, Mistral/Ministral3 (LM), Gemma 1–3, Qwen2/3/3-MoE, Qwen2.5-VL (LM), OLMoE, MiniMax, Ernie-4.5; MLA models (DeepSeek V2/V3, Kimi K2, GLM-4.7-Flash, GLM-5) once ModelOpt unifies the pair
This breaks the checklist above into 8 PRs. Every PR lands with its CI tests from the test plan: bitwise parity against ModelOpt's PP-only export at TP2 / PP2 / EP2 / ETP2, plus structural checks. Implementation is expected to be quick. Most of the time goes into tests, so each PR can be merged with confidence.
KV-cache export (k_scale / v_scale from k_bmm / v_bmm quantizers, plus kv_cache_quant_algo) and MLA linear_q_down_proj / linear_kv_down_proj amax unification after calibration (static NVFP4 via SharedWeightGlobalAmaxState patterns; dynamic NVFP4 / FP8 per-tensor via a post-calibration step)
1
3
Megatron-Bridge
Quantized export core:#5812 rebased onto main (incl. #6074with_megatron_names), plus:
offline save API (packed tensors plus the inline quantization_config; drops source quant metadata);
parity harness and fused-sibling scale check;
exclude_modules from disabled quantizers;
switch examples/quantization/export.py to the bridge.
Parity tests on small Llama / Qwen3 / Qwen3-MoE models (NVFP4, FP8, mixed)
1
4
Megatron-Bridge
Pilot: GDN mapping support (GDNLinearMappingSeparate), per-HF-output unquantized override for in_proj_a/b, KV-cache config. Parity tests on a small Qwen3.5/3.6-MoE model
2, 3
Pilot exit criteria:
The Qwen3.6-35B-A3B checkpoint exported through the bridge at EP=8 is identical to the ModelOpt PP-only export. That means every tensor bitwise, plus config.json / quantization_config, the tokenizer and the processor config.
One vLLM load-and-generate on Blackwell, only to confirm the harness compares everything vLLM reads.
Remaining PRs
#
Repo
PR
Depends on
5
Megatron-Bridge
Architecture coverage, each family with its own parity tests:
row-split / re-grouping mappings, by deriving row indices from each mapping's own megatron_to_hf: MambaInProjMapping, Nemotron-H MTP flattening, QKVG / ConcatenatedQKV / asymmetric QKV (Nemotron-H +MTP);
MLA models (DeepSeek-style, GLM-5);
per-expert canonical names for transpose_on_export experts (Qwen3-VL-MoE);
GPT-OSS fused 3D experts. Split this into its own PR if checking vLLM's ModelOpt NVFP4 GPT-OSS support delays it.
2, 3
6
Model-Optimizer
Migration + deprecation:
switch examples/megatron_bridge and its tutorials to the bridge;
port the other users of unified_export_megatron.py: vLLM fake-quant export via the bridge's BF16 export (folded weights plus quantizer-state sidecar), IQ formats via the functional API;
deprecation warnings on export_mcore_gpt_to_hf / import_mcore_gpt_from_hf.
4, 5
7
NVIDIA/Megatron-LM
Move examples/post_training/modelopt (convert_model.py, quantize.py, prune.py, export.py) to AutoBridge, or retire them
6
8
Model-Optimizer
Remove unified_export_megatron.py, the plugins/mcore_*.py rule tables and megatron_importer.py one release after the deprecation
6, 7
vLLM testing: needed only where no identical ModelOpt-exported baseline exists. That means architectures and formats the old exporter doesn't cover (e.g. Qwen3-VL-MoE, Gemma3-VL, MXFP8, FP8 per-channel) and intentional differences (e.g. MLA scale unification). Even there it is a one-time load plus known-answer prompts.
Activity
[-]Natively support quantized megatron to HF export for vLLM deployment (retires ModelOpt custom logic)[/-][+]Implement canonical ModelOpt quantized HF export through Megatron Bridge[/+]kevalmorabia97 commentedon Sep 30, 2026
Re-evaluated this against current
mainof both repos (2026-09-30) and the open PRs, with the goal of fully deprecating ModelOpt's custom Megatron↔HF logic (unified_export_megatron.py,plugins/mcore_*.py,plugins/megatron_importer.py) in favor of the bridge. Below is the current state and the proposed split of remaining work.Where things stand
MBridge
mainis essentially unchanged since July.export_hf_weights_modelopt:quantization_configand has no save-to-dir wrapper;w13_weight/w2_weight.It has no callers outside unit tests.
examples/quantization/export.pystill calls ModelOpt'smtex.export_mcore_gpt_to_hf.feat(export): add functional quantized weight export NVIDIA/Model-Optimizer#2251 + refactor(modelopt): delegate real-quant export to ModelOpt #5812 implement the ownership split in this issue:
quantization_config.feat(export): add functional quantized weight export NVIDIA/Model-Optimizer#2251 covers FP8, FP8_PC_PT, FP8_PB_WO, MXFP8, NVFP4 (dynamic and static), W4A16/W4A8 NVFP4, MXFP4 and mixed precision. That is a superset of what the custom Megatron exporter writes a quant config for, except IQ. The custom exporter already rejects AWQ/SmoothQuant, so this is no regression. Both PRs have been drafts since 2026-09-10.
The custom exporter is TP=1 only; it shards through PP. The bridge gathers across TP / EP / ETP / PP.
The custom path keeps growing: ~59 commits since June, and GLM-5.x alone is +1.1k LoC ([3/3] Add GLM-5.3-Flash support to Megatron-Bridge PTQ and HF export NVIDIA/Model-Optimizer#2539). So the migration is worth prioritizing.
Decisions
config.jsonquantization_configis needed; drophf_quant_config.json.quantized_layers(config.py#L921-L933, weight_utils.py#L224-L265).fused_qkv_a_proj) and TRT-LLM (fused_a) fuseq_a_proj+kv_a_proj_with_mqainto one GEMM.weight_scale_2differ.input_scale(modeling_deepseekv3.py#L471).mla_down_proj_fusiongives the pair a single quantizer natively.import_mcore_gpt_from_hf/megatron_importer.py). BF16 HF→Megatron import is already covered by AutoBridge. The remaining users are Megatron-LM'sexamples/post_training/modelopt(convert_model.py,quantize.py,prune.py;export.pyuses the exporter). Those examples get migrated to AutoBridge or retired together with the exporter.Test plan (Megatron-Bridge CI, with every PR)
Parallelism parity against the current ModelOpt export.
Quantize a small model per architecture once, then export the same Megatron checkpoint two ways:
export_mcore_gpt_to_hf(TP=1, PP=1/2);Assert that everything vLLM reads is identical:
config.json, includingquantization_config(quant_algo,quantized_layers, exclude list, KV scheme);How tensors are split across safetensors files may differ. Any intentional difference (e.g. MLA scale unification) is listed explicitly and treated as having no baseline.
Also export a checkpoint quantized at TP/EP > 1, so amax resharding on load is covered.
Once the ModelOpt exporter is removed, the bridge TP1/PP1 export becomes the reference for parallelism invariance, plus small checked-in golden hashes.
Format × architecture matrix: NVFP4, W4A16 NVFP4, FP8 (per-tensor / per-channel / 128×128 block), MXFP8, mixed precision, KV FP8.
Structural checks on every export:
weight_scale_2/input_scale;exclude_modulescovers exactly the unquantized linears;quantization_configor*_scale_invleaks through.vLLM runs only where there is no identical baseline. If the bridge export is identical to a vLLM-validated checkpoint from the ModelOpt exporter, a vLLM run adds no information. vLLM (Blackwell for NVFP4) is needed only for:
Even there it is a one-time load plus known-answer prompts, not a full eval.
Pilot: Qwen3.6-35B-A3B W4A4 NVFP4 from the ModelOpt tutorial (
examples/megatron_bridge/tutorials/Qwen3.6-35B-A3B). One vLLM load-and-generate, only to confirm the parity harness compares everything vLLM reads.Remaining work
ModelOpt
k_scale/v_scalefromk_bmm/v_bmmquantizers, pluskv_cache_quant_algo. It is hard-set to NONE today.SharedWeightGlobalAmaxStatepatterns; dynamic NVFP4 / FP8 per-tensor via a post-calibration step.unified_export_megatron.pybefore deleting it:export_mcore_gpt_to_hf_vllm_fq, used by Megatron-LMexport.py): port to the bridge's BF16 export of folded weights plus a quantizer-state sidecar;export_extra_modules): decide separately.examples/megatron_bridgeand the Megatron-LMpost_training/modeloptexamples to the bridge. Deprecateexport_mcore_gpt_to_hf/import_mcore_gpt_from_hffor one release, then remove them together with themcore_*rule tables.MBridge, generic (details in #5812)
with_megatron_names.save_hf_pretrained-style) that consumes the export plan and writes the packed tensors plus the inlinequantization_config. It should also strip any source-checkpointquantization_configand*_scale_invcompanions.transpose_on_exportexperts.exclude_modulesderived from disabled quantizers, plus a per-HF-output "export unquantized" override for HF weights that MCore fuses into one quantized linear (below).weight_scale_2/input_scaleacross fused sibling groups.MBridge, per bridge
MambaInProjMapping(Nemotron-H, Falcon-H1), Nemotron-H MTP flattening, QKVG / ConcatenatedQKV / asymmetric QKV (Step, MiMo, Bailing, …)in_proj_a/in_proj_b(inside the fusedin_proj)shared_expert_gate, routers, Gemma4 per-layer-embedding projections, vision towers, MTP (Qwen3.5)cc @cuichenx @mxinO
kevalmorabia97 commentedon Sep 30, 2026
Execution plan: pilot, then remaining PRs
This breaks the checklist above into 8 PRs. Every PR lands with its CI tests from the test plan: bitwise parity against ModelOpt's PP-only export at TP2 / PP2 / EP2 / ETP2, plus structural checks. Implementation is expected to be quick. Most of the time goes into tests, so each PR can be merged with confidence.
Pilot: Qwen3.6-35B-A3B W4A4 NVFP4 (PRs 1–4, target ~2 weeks)
The reference is the checkpoint from ModelOpt's tutorial (
examples/megatron_bridge/tutorials/Qwen3.6-35B-A3B). It is mixed precision:lm_head;conv1d, GDNin_proj_a/band the vision tower.That makes it a good first target: it covers grouped experts, mixed precision, the attention output gate, GDN and a VLM wrapper.
k_scale/v_scalefromk_bmm/v_bmmquantizers, pluskv_cache_quant_algo) and MLAlinear_q_down_proj/linear_kv_down_projamax unification after calibration (static NVFP4 viaSharedWeightGlobalAmaxStatepatterns; dynamic NVFP4 / FP8 per-tensor via a post-calibration step)main(incl. #6074with_megatron_names), plus:- offline save API (packed tensors plus the inline
- parity harness and fused-sibling scale check;
- switch
Parity tests on small Llama / Qwen3 / Qwen3-MoE models (NVFP4, FP8, mixed)quantization_config; drops source quant metadata);exclude_modulesfrom disabled quantizers;examples/quantization/export.pyto the bridge.GDNLinearMappingSeparate), per-HF-output unquantized override forin_proj_a/b, KV-cache config. Parity tests on a small Qwen3.5/3.6-MoE modelPilot exit criteria:
config.json/quantization_config, the tokenizer and the processor config.Remaining PRs
megatron_to_hf:MambaInProjMapping, Nemotron-H MTP flattening, QKVG / ConcatenatedQKV / asymmetric QKV (Nemotron-H +MTP);transpose_on_exportexperts (Qwen3-VL-MoE);examples/megatron_bridgeand its tutorials to the bridge;unified_export_megatron.py: vLLM fake-quant export via the bridge's BF16 export (folded weights plus quantizer-state sidecar), IQ formats via the functional API;export_mcore_gpt_to_hf/import_mcore_gpt_from_hf.examples/post_training/modelopt(convert_model.py,quantize.py,prune.py,export.py) to AutoBridge, or retire themunified_export_megatron.py, theplugins/mcore_*.pyrule tables andmegatron_importer.pyone release after the deprecationvLLM testing: needed only where no identical ModelOpt-exported baseline exists. That means architectures and formats the old exporter doesn't cover (e.g. Qwen3-VL-MoE, Gemma3-VL, MXFP8, FP8 per-channel) and intentional differences (e.g. MLA scale unification). Even there it is a one-time load plus known-answer prompts.
Out of scope for this deprecation:
export_extra_modules): decided separately;main.Rough timeline: pilot ~2 weeks; everything through PR 7 ~5–6 engineer-weeks. The calendar depends mostly on reviews and releases:
cc @cuichenx @mxinO
kevalmorabia97 commentedon Oct 14, 2026
Status 2026-10-14
feat(export): add functional quantized weight export NVIDIA/Model-Optimizer#2251: approved, CI green; waiting on a second code-owner approval. KV-cache export and MLA unification (PR 2) not started.
refactor(modelopt): delegate real-quant export to ModelOpt #5812: ready for review. Still needs:
importorskipfix for CI;It lands together with feat(modelopt): add format-general real-quant vLLM rollout RL#3945.
vLLM fake-quant (moved ahead of PR 6): [2/5] Export Megatron fakequant quantizer state and YAML NVIDIA/Model-Optimizer#2627 through [5/5] Preserve source config in HF fakequant export NVIDIA/Model-Optimizer#2630 set the sidecar format to
quantizer_state.pth+quant_recipe.yaml, which vLLM detects automatically. The bridge side needs two changes:modelopt_weights.pt;ENABLE_BRIDGE_QUANT_MAPPINGshould be on by default, or unmapped quantizer buffers skipped. Without it, saving a quantized model crashes.