New Features
Quantization
- Add NVFP4 W4A16 weight-only quantization (
w4a16_nvfp4): FP4 weights with group_size=16, BF16 activations, no calibration forward pass required. Usemtq.W4A16_NVFP4_CFGor--qformat w4a16_nvfp4inhf_ptq.py. vLLM deployment support is in progress. - Add
--cast_mxfp4_to_nvfp4flag toexamples/llm_ptq/hf_ptq.pyfor closed-form, bit-exact MXFP4 → NVFP4 weight conversion. Supports the GPT-OSS family (openai/gpt-oss-20b,openai/gpt-oss-120b). See examples/llm_ptq/README.md for usage. - Add
--cast_mxfp4_to_nvfp4flag toexamples/deepseek/deepseek_v4/quantize_to_nvfp4.pyfor closed-form, bit-exact MXFP4 → NVFP4 conversion of DeepSeek V4 routed-expert weights (mirrors the GPT-OSS cast; w1/w3 share one per-tensorscale_2for the fused GEMM1). Activationinput_scalestill comes from--amax_pathcalibration. - DeepSeek PTQ (
examples/deepseek/ptq.py) now defaults to native top-k calibration with post-hoc per-layer peer-max sync of expertinput_quantizer.amax; the all-experts path is preserved behind--calib_all_experts. - Add active-MoE cost accounting for
mtq.auto_quantizeeffective-bits search. Setconstraints={"effective_bits": ..., "cost_model": "active_moe", "cost": {"active_moe_expert_ratio": ...}}to weight routed MoE expert costs by active experts per token while keeping shared experts fully counted. Thehf_ptq.pyAutoQuant path exposes this via--auto_quantize_cost_model active_moeand--auto_quantize_active_moe_expert_ratio. - Add quantized
nn.Embeddingsupport.nn.Embeddingis now registered inQuantModuleRegistryand exposesweight_quantizer(embedding table),output_quantizer(lookup activations), and a permanently disabledinput_quantizerplaceholder — embedding inputs are integer indices and cannot be fake-quantized, so directenable*()calls raise.export_hf_checkpointpacks quantized embedding weights alongside Linear layers. Embedding quantizers are opt-in (parent_class: nn.Embeddingdisabled by default). - Add composable
$importsystem for recipe YAML configs, enabling reusable config snippets referenced via{$import: name}markers. All built-in PTQ recipes converted to use imports with shared snippets undermodelopt_recipes/configs/(numeric formats, quant_cfg building blocks, presets). See composable-imports docs. - The PTQ example scripts
examples/llm_ptq/hf_ptq.py,examples/llm_ptq/multinode_ptq.pyandexamples/megatron_bridge/quantize.pynow derive their--qformat/--kv_cache_qformat(--quant_cfg/--kv_cache_quantfor Megatron-Bridge) CLI vocabularies by discovering the YAML presets undermodelopt_recipes/configs/ptq/presets/{model,kv}/rather than carrying hardcodedQUANT_CFG_CHOICES/KV_QUANT_CFG_CHOICEStables. The discovery helper, alias table and ready-builtQUANT_CFG_CHOICES/KV_QUANT_CFG_CHOICESmappings now live inmodelopt.recipe.presetsand are shared by all three scripts. Presets are loaded eagerly into a plain dict at import. Adding a new preset YAML makes it available on the CLI of all three with no script change — note this means each script now accepts every preset under those directories, not just a previously curated subset. All previously-supported short names (int8_sq,nvfp4_awq,fp8_pb_wo,nvfp4_mse,w4a8_awq,nvfp4_local_hessian,fp8_pc_pt,int8_wo) keep working via a small deprecation alias table; new formats should be exposed as preset YAMLs (or, longer term, as full--reciperecipes). - Add
configs/ptq/presets/kv/fp8_cast.yamlandconfigs/ptq/presets/kv/nvfp4_cast.yaml, promotingfp8_cast/nvfp4_castto first-class KV presets composed from the existingkv_fp8_cast/kv_nvfp4_castunit fragments. The previous runtimeuse_constant_amaxpost-edit inhf_ptq.pyis removed;use_constant_amax: truenow lives in the YAML and is therefore authoritative. Custom (out-of-tree) recipes that target a cast KV format must setuse_constant_amax: truethemselves on the[kv]_bmm_quantizerconfig — in-tree recipes already do via thekv_*_castunits. - Add FP8 KV-cache cast variants for the partial-NVFP4 and weight-only general PTQ recipes:
general/ptq/nvfp4_mlp_only-kv_fp8_cast,general/ptq/nvfp4_experts_only-kv_fp8_cast,general/ptq/nvfp4_omlp_only-kv_fp8_cast, andgeneral/ptq/nvfp4_weight_only-kv_fp8_cast. These compose the same model-quant configs as their-kv_fp8siblings with thekv_fp8_castunit (constant-amax FP8 KV cache, no KV calibration forward pass). - Add Nemotron-3-Super-120B-A12B PTQ recipes
modelopt_recipes/models/Nemotron-3-Super-120B-A12B/super-nvfp4.yaml(MSE-mixed) andsuper-nvfp4-max-calib.yaml(max-calib mixed): NVFP4 W4A4 routed experts + FP8 per-tensor shared experts / Mamba in/out_proj + FP8 KV cache. - Group layerwise calibration options under a nested
LayerwiseConfigand add two knobs:get_qdq_activations_from_prev_layer(correct GPTQ-Hessian vs max-calib activation semantics — defaults to True for GPTQ, False for max/mse/local_hessian) andsave_every(gate per-windownext_inputs.ptactivation-cache writes). Legacy boollayerwiseand flatlayerwise_checkpoint_dirkeys still work; the bool form emits aDeprecationWarning. - Add
examples/alpamayoshowing FP8, NVFP4, and AutoQuantize (mixed-precision) quantization of the Alpamayo (formerly Alpamayo-R1) ~10B vision-language-action model, with a joint VLM + diffusion calibration loop and both fake-quant and--real-quantpacked-checkpoint export. See examples/alpamayo/README.md for details. - Refactor
llm_qatexample with unified YAML-based configuration and flexible dataset blending.ModelOptArgParseradds--configYAML support with CLI overrides and auto-generatesARGUMENTS.mdfrom dataclass definitions. Dataset blending (configs/dataset/blend.yaml) supports HuggingFace datasets, local JSON/JSONL/Parquet files, and weighted multi-source blends. The legacy FSDP1 accelerate config is removed;llm_qatnow documents FSDP2, DeepSpeed, and DDP backends.
Megatron Framework (M-LM / M-Bridge)
- Add quantization examples for the Megatron-Bridge framework (
examples/megatron_bridge/): post-training quantization (quantize.py calibrates an HF model via--quant_cfgalias / full config name or a--recipeYAML, with optional KV-cache quant, weight-only, compression, and MoE expert-ratio calibration, and saves a Megatron checkpoint with tensor / pipeline / expert parallelism), export to a deployable HuggingFace (unified) checkpoint for TensorRT-LLM / vLLM / SGLang (export.py), and Quantization Aware Distillation (extend existing distill.py). See examples/megatron_bridge/README.md for details. - Add Megatron Core export/import mapping for Qwen3-VL (
Qwen3VLForConditionalGeneration) vision-language models. The mapping handles themodel.language_model.weight prefix used by Qwen3-VL. - Add shared Megatron-Core calibration forward loop:
modelopt.torch.utils.plugins.megatron_calibration.get_megatron_calibration_forward_loopproduces theforward_loopcallable expected bymtq.quantize/mtp.prune. Replaces the bespoke calibration loops in Megatron-LM and Megatron-Bridge for quantization and pruning with a single canonical implementation. - Support Megatron-Core checkpoint restore and export for MSE
NVFP4StaticQuantizer. - Add mixed-precision FP8 + NVFP4 export for Megatron-Core: per-layer
quant_algorecorded underquantized_layersinhf_quant_config.json, PP-awarekv_cache_dtypegather, fused-QKV exclude split into per-HF-nameq/k/v_projentries. - Add support for
active_params(for MoE models) andmemory_mbconstraints in Minitron pruning on top of existingparamsconstraint. You can also provide multiple constraints. See examples/pruning/README.md for more details. The underlying utility functionsmcore_param_count,mcore_memory_footprint_mb, andprint_mcore_model_statsinmodelopt.torch.nas.plugins.megatron_model_statsare also available for standalone use to compute parameter counts and memory footprints (weights + KV-cache + Mamba state) for any Megatron-Core model. - Add Minitron pruning support for Megatron-Bridge Gemma3 models.
- Add end-to-end optimization tutorial for Minitron pruning + two-phase distillation (80B @ 8K + 20B @ 32K long-context = 100B tokens) + FP8 PTQ + vLLM deployment for Nemotron-3-Nano-30B-A3B-BF16 (MoE + Mamba-Transformer hybrid) → Pruned 22B/A3.0B active params, along with data blend preparation steps (with tool-calling data) and detailed pruning / data-blend / long-context ablations. See examples/megatron_bridge/tutorials/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16/README.md for details.
Datasets & Calibration
- Add
DATASET_COMBOStomodelopt.torch.utils.dataset_utils— single--datasettokens that fan out to multiple registered datasets; per-entrynum_samplesis split evenly across the members. Initial combos:cnn_nemotron_v2_mix(cnn_dailymail+nemotron-post-training-dataset-v2, used byhf_ptq.pywhen no--datasetis provided) andnemotron-post-training-v3(the sevennvidia/Nemotron-*SFT datasets added in #1498, mirroring the nemotron-post-training-v3 collection). Combo names are listed byget_supported_datasets()and surfaced in--datasethelp.get_dataset_dataloaderrejects inputs that mix a combo with one of its member datasets (e.g.cnn_dailymail,cnn_nemotron_v2_mix) to avoid double-sampling, andget_dataset_samplesrejects combo names so callers route through the dataloader.hf_ptq.pydefault--calib_sizeis bumped from512to1024so the total calibration sample count under the new default combo matches the previous two-dataset fallback. - The
nemotron-sft-agentic-v2registered dataset (added in #1498) now uses only thesearchsplit. The previously configuredinteractive_agentandtool_callingsplits contain content-level defects (heterogeneous schema and a malformed JSON row, respectively) that cause pyarrow's streaming JSON reader to fail deterministically. - Add
pack=Truemode toget_dataset_dataloader(Megatron-LM pretraining-style global-stream document packing): all raw samples concatenated EOS-separated into one token stream, sliced into uniformmax_sample_lengthrows. Used by the shared megatron calibration loop.
Misc
- Add offline DFlash speculative decoding training. Train the draft module from pre-computed base-model hidden states dumped by
examples/speculative_decoding/collect_hidden_states/compute_hidden_states_hf.py; base-model transformer layers are deleted after conversion to save memory. Controlled by the auto-deriveddflash_offlineflag onDFlashConfig(derived fromdata_args.offline_data_path). The dump scripts now sharecollect_hidden_states/common.pyfor aux-layer selection (--aux-layers eagle|dflash|<list>) and optional assistant-tokenloss_maskfor answer-only-loss training. - Add
mtsa.config.SKIP_SOFTMAX_TRITON_CALIBfor skip-softmax attention-sparsity calibration through the fused Tritonattention_calibratekernel (HFmodelopt_tritonbackend), measuring multi-threshold tile-skip statistics the way the Triton inference kernel actually skips tiles for both prefill and decode. Exposed as--sparse_attn_cfg skip_softmax_triton_calibinexamples/llm_sparsity/attention_sparsity/hf_sa.py(with a new--calib_data_dirflag for RULER calibration data). - Add DMD2 distillation for few-step diffusion models in
examples/diffusers/fastgen/: distill Qwen-Image into a 4/8-step student via Distribution Matching Distillation. See examples/diffusers/fastgen/README.md for details. - Make
.agents/skills/the canonical location for agent skills; agent-specific directories (.claude/skills/, etc.) are now relative symlinks into.agents/, so one skill suite serves multiple coding agents (Claude Code, Codex). See.agents/README.md. - Extend Claude Code agent skills for PTQ, deployment, evaluation, monitoring, and baseline-vs-quantized result comparison. Adds evaluation task references for additional benchmarks, stronger PTQ checkpoint validation gates, and session-scoped workspace/job tracking.
- Add SLURM Quality of Service (QoS) support to the ModelOpt launcher. Users can set QoS via
slurm_config.qosorSLURM_QOSand the value is forwarded tonemo_run.SlurmExecutor.
Backward Breaking Changes
KDTrainer/QADTrainerevaluation now reports KD as the primaryeval_lossand CE aseval_ce_loss; the previous secondaryeval_kd_lossmetric is removed.- Reorganize custom CUDA / Triton kernels under
modelopt.torch.kernelsintocommon/attention,quantization/{conv,gemm}, andsparsity/attention. High-level APIs (mtq.quantize,mtsa.sparsify, etc.) are unchanged, but any code importing directly from the kernel subpackages must be updated: there is no backwards-compatibility shim; the old import paths will raiseImportError/ModuleNotFoundError. Migration table:from modelopt.torch.kernels import IS_AVAILABLE, attention, attention_calibrate, register_triton_attention→from modelopt.torch.kernels.common.attention import ...from modelopt.torch.kernels.triton_fa import ...→from modelopt.torch.kernels.common.attention.triton_fa import ...from modelopt.torch.kernels.hf_triton_attention import ...→from modelopt.torch.kernels.common.attention.hf_triton_attention import ...from modelopt.torch.quantization.triton import ...→from modelopt.torch.kernels.quantization.gemm import ...from modelopt.torch.quantization.src.conv.implicit_gemm_cuda import ...→from modelopt.torch.kernels.quantization.conv.implicit_gemm_cuda import ...from modelopt.torch.sparsity.attention_sparsity.kernels import ...→from modelopt.torch.kernels.sparsity.attention import ...
- Deprecated GradNAS pruning algorithm as it is not actively maintained and supports very limited and old models. It is recommended to use Minitron or Puzzletron pruning for LLM models. Also deprecates related
examples/chained_optimizationsdirectory. - Model-specific PTQ
quant_cfgadjustments previously hardcoded inexamples/llm_ptq/(build_quant_cfg/mono_quantize) for gemma, mpt, phi4mm, and Nemotron VL are now opt-in model-specific recipes undermodelopt_recipes/huggingface/<model_type>/ptq/. Any adjustment specific to a model type or instance must live in that model's recipe; the bare--qformatpath produces only the generic numerics. Pass--recipe huggingface/<model_type>/ptq/<recipe>to apply the model's recipe. Covers gemma/mptw4a8_awq(awq_litealpha_step=1), gemmaint8_sq(SmoothQuantalpha=0.5), phi4mm speech/audio/image/vision exclusions, and Nemotron VL vision-branch exclusions. All shipped recipes also enable FP8 KV-cache cast. MTP dynamic layer exclusion andis_nemotron_vldetection remain in Python. - The Step3.5-Flash recipe moved from
modelopt_recipes/models/Step3.5-Flash/nvfp4-mlp-only.yaml(0.44) tomodelopt_recipes/huggingface/step3p5/Step3.5-Flash/ptq/nvfp4-mlp-only.yamlto match thehuggingface/<model_type>/ptq/layout convention. Update--recipepaths accordingly.
Deprecations
- Deprecate the public
QuantizationArgumentsWithConfigname inmodelopt.torch.quantization.plugins.transformers_trainer; it now aliasesQuantizationArgumentsand will be removed in a future release. - Deprecate the
examples/diffusers/evalimage-quality evaluation example (ImageReward / CLIP-IQA / CLIP metrics); it is no longer maintained and will be removed in the next release. - Deprecate
examples/llm_autodeploy. The AutoQuant + TensorRT-LLM AutoDeploy workflow it demonstrates will be removed in a future release; use TensorRT-LLM's AutoDeploy directly together with ModelOpt PTQ inexamples/llm_ptq.
Bug Fixes
- Fix
ShapeInferenceErrorduring ONNX INT8 + FP16 quantization (--high_precision_dtype fp16) of weakly-typed models (e.g. TensorFlow exports) that carry stale rank-0graph.outputshapes or ops such asTopKthat ONNX's static shape inference cannot resolve.clear_stale_value_infonow reconciles stale output shapes via symbolic shape inference (keeping every output's shape field populated), and AutoCast runs ONNX shape inference in strict mode and falls back to schema-based standalone type inference when it fails, so unresolved ops no longer leave tensors untyped. - Always list unquantized MoE routers/gates in the exported
exclude_modules(NVBug 5718750).get_quant_configonly recorded modules that carry a quantizer, but ontransformers>=5.0MoE routers are no longernn.Linear(e.g.TopKRouter) and never receive one, so the BF16 router weight was written to the checkpoint yet omitted fromexclude_modules. vLLM / SGLang then treated it as quantized and failed to load (e.g. Qwen3-30B-A3B NVFP4:AssertionError: Tried to load weights of size [128, 2048] to a parameter of size [128, 1024]). Routers are now detected structurally (an MoE block with anexpertscontainer plus a weight-bearinggate/router/shared_expert_gatesubmodule) and recorded as unquantized regardless of quantizer attachment. - In Megatron-Core only do EP amax sync for routed expert weights if
sync_expert_weight_amax=True. Previously EP amax sync would sync routed expert weights across EP ranks even whensync_expert_weight_amaxwas False. - Fix Megatron-Core HF importer to load fused
TELayerNormColumnParallelLinear.layer_norm_weightfrom HF for GPT-family models (Qwen3 etc.) under--export-default-te-spec. Importer now prefers per-context keysfused_input_layernorm/fused_pre_mlp_layernorm(fallbackfused_normfor Nemotron-H backward compatibility);mcore_qwen.pyprovides the new rules. Without this fix, post-prune MMLU sat at chance. - Fix ONNX AutoCast
keep_io_types=Truesanity-check failure (Unexpected type in I/O tensor ...) when a network input/output is an empty tensor (a dimension of size 0). Such tensors were "fake-cast" (retyped in place) to the low precision type; because the value-info map aliases thegraph.input/graph.outputValueInfoProto, this silently changed the model's I/O type. AutoCast now inserts a realCastfor protected I/O tensors instead. - Fix INT8 entropy calibration of fp16 ONNX models raising
ValueError: Too many bins for data rangeon numpy >= 2.0._collect_valueinmodelopt.onnx.quantization.ort_patchingnow casts the histogram range endpoints to Python float so bin edges are computed in float64, instead of inheriting the fp16 dtype of an activation tensor with a small range (which collapsed the 128-bin linspace under NEP-50 promotion). - Fix the GPT-OSS MXFP4 → NVFP4 PTQ path in
examples/llm_ptq/hf_ptq.py(used with--cast_mxfp4_to_nvfp4).get_modelnow loads native MXFP4 checkpoints (openai/gpt-oss-*) dequantized to BF16GptOssExpertsviaMxfp4Config(dequantize=True)on a sequential device map. This fixes a CUDA illegal-memory access during the multi-GPU dequant load and theNotImplementedErrorfor experts typeMxfp4GptOssExpertsduring unified HF export (the packed-kernel experts wrapper, used when the optionalkernelspackage is installed, is unsupported by export);kernelsis no longer required. The--cast_mxfp4_to_nvfp4step now also resolves a HF Hub ID--pyt_ckpt_pathto its local snapshot directory instead of failing withFileNotFoundError. - Fix
_QuantGptOssExperts/_QuantLlama4TextExpertsstatic-block NVFP4 weight calibration raisingValueError: Input shape has changedduring the calibration forward. These experts quantize their weights transposed (_transposed_quantize);iter_weights_for_calibrationnow yields the same transposed view so weight-only calibration and the forward agree on the block-quant shape (and the export_amaxorientation). - Fix unified HF checkpoint export for Llama4 MoE models. The uncalibrated-experts input-quantizer
amaxfallback in_export_transformers_checkpointspecial-cased onlyQuantGptOssExperts;QuantLlama4TextExpertsuses the same fusedgate_up_proj/down_projlayout and is now handled by the same branch, fixing the export failure. - Fix
NotImplementedError: "max_all_cuda" not implemented for 'Float8_e4m3fn'during quantization calibration of models with natively FP8 (float8_e4m3fn/float8_e5m2) weights, such as DeepSeek-V3. FP8 dtypes implement no reduction (max/amax),abs, or elementwisemaximumkernels, soreduce_amaxnow upcasts FP8 inputs to the default float dtype before reducing; the upcast is lossless and only affects the FP8 path.