New Features
Quantization
-
ONNX quantization with Autotune now benchmarks placements in the requested runtime precision and retains calibrated INT8/FP8 Q/DQ only when it meets the configured TensorRT speedup threshold (1.02x by default); otherwise it saves the high-precision no-Q/DQ model.
-
Add a Muse Glimmer AutoQuantize recipe that searches language-model MLP projections, self-attention projections, and
lm_headover W4A16 NVFP4 Four-Over-Six, FP8, and BF16 fallback at 5.5 effective bits while leaving the vision tower unquantized. -
Add
examples/alpamayo/qad.py, which runs quantization-aware distillation on the quantized Alpamayo checkpoint produced byexamples/alpamayo/quantize.py. It distills the quantized VLM against the original FP16 VLM withQADTrainer, supports FSDP2 for multi-GPU runs, and--exportreassembles the trained VLM into a full AlpamayoR1 checkpoint thatAlpamayoR1.from_pretrainedcan reload. -
Add a calibration-free streaming Kimi-K3 converter and checkpoint-mirror recipe for NVFP4 routed experts with
input_scale=1.0and 128x128 block-FP8 KDA/MLA attention weights. The converter operates shard-by-shard on the source checkpoint's packed MXFP4 experts instead of loading the 2.8T model through the in-memoryhf_ptq.pypath. -
Add end-to-end PETRv1 and PETRv2 ONNX PTQ examples covering calibration, INT8 and FP8 VoVNet backbone quantization, TensorRT deployment, and accuracy evaluation.
-
Add opt-in FP8 Vision Encoder recipes under the
qwen3_vlandqwen3_5model types. The vision-only recipe keeps the language model and KV cache in high precision; the joint recipe quantizes Vision Encoder and language-model Linears and uses FP8 KV-cache cast. Both quantize primary and deepstack merger Linears where present, while leaving patch embedding and vision-attention BMMs in high precision. Exported checkpoints require an inference runtime that supports quantized Vision Encoder Linears. -
Add
mtq.temporarily_fold_weightsfor repeated frozen-weight inference andmtq.preserve_quantizer_attributes_contextfor restoring temporary quantizer property and type changes. Temporary folding snapshots affected fake-quant weights on a configurable device and restores them with their quantizer state; retained pre-quant scales are inactive, while shared weights, shared quantizers, andSequentialQuantizerweights are unsupported. -
Add the
nvfp4_act_headroomcalibration algorithm for NVFP4 activation global scales. Instead of setting the global scale from the largest per-block amax seen during calibration (plainmax, which leaves no room above it so any larger activation saturates), it anchors the scale to a low percentile of the per-block amax distribution, leaving the rest of the FP8 block-scale range as headroom:amax = max(rho * anchor, upper), whereanchorandupperare the per-block amaxes atanchor_percentile(default 1) andupper_percentile(default 99.99; set to 100 to never clip calibration data), andrho(default 16384) is the headroom factor. Applies only to NVFP4 dynamic-block input quantizers;SequentialQuantizeractivation quantizers raise. Weight scales are an orthogonal axis selected by a nestedweight_scale_algorithm(maxby default, ormse/local_hessian), so one recipe can combine a weight calibration with this activation policy in a single pass. Shipsmodelopt_recipes/general/ptq/nvfp4_act_headroom-kv_fp8_cast.yaml, which mirrorsnvfp4_default-kv_fp8_castwith only the calibration algorithm swapped and exports a standard NVFP4 checkpoint. -
Add PTQ support for Step-3.7 (
stepfun-ai/Step-3.7-Flash), whose routed experts were previously left unquantized. Quantize with the newhuggingface/step3p7/ptq/nvfp4_experts_only-kv_fp8_castorhuggingface/step3p7/ptq/nvfp4_mlp_only-kv_fp8recipes rather than the general ones, which select experts by module names Step does not use.
Megatron Framework (M-LM / M-Bridge)
- Add
clamp_kv_cache_scalestoexport_mcore_gpt_to_hf. Set it toFalsewhen exporting a QAT Megatron-Core model to preserve its learned FP8 KV-cache scales; the default retains the existing minimum scale of 1.0. - Add SFT-masked data support to
examples/megatron_bridge/distill.py:--sft --sft_dataset_root <dir>distills on raw prompt-completion JSONL ({"input", "output"}records) with the loss masked to the response tokens, using Megatron-Bridge'sFinetuningDatasetConfigand the model's own HuggingFace tokenizer instead of the pretrainingGPTDatasetandNullTokenizer. - Add per-expert weight quantization for Transformer Engine
TEGroupedLinear(fused MoE experts): each expert now has its ownweight_quantizer(aGroupedQuantizerholding oneTensorQuantizerper expert) with an independentamax, instead of a single sharedamaxacross all experts. Applies tomtq.quantizecalibration, HF / Megatron export, and QAD. - Add opt-in
torch.compileexecution for Transformer Engine grouped-linear per-expert weight quantizers while preserving their native checkpoint amax shapes. SetMODELOPT_TEGROUPED_COMPILE_WEIGHT_LOOP=1before quantized-module conversion; the default path remains eager. - Add HuggingFace unified export of quantized Qwen3-VL and Qwen3.5-VL checkpoints (PTQ or QAD) via
examples/megatron_bridge/export_quantized_megatron_to_hf.py, Qwen3.5-VL additionally covering GatedDeltaNet linear-attention layers and MoE shared experts. Only the language model is quantized; the vision tower is copied from the source HuggingFace checkpoint. - Megatron-Bridge scripts now choose the MoE expert layout automatically from the model config: the faster fused
TEGroupedMLP(grouped GEMM) unless the architecture cannot export it to HuggingFace, in which caseSequentialMLPkeeps the checkpoint exportable and--no_moe_grouped_gemmforces it explicitly. For the affected architectures this changes MoE activation scales from one shared scale to per-expert.
Misc
- Add
modelopt.torch.utils.mlflow.MlflowRunLoggerfor recording a script run on an MLflow tracking server: the invocation, the ModelOpt version, the run log (captured by teeingstdout/stderr) and any caller-supplied artifacts, with configuration as searchable params.mlflowis an optional dependency, imported only when tracking is enabled. - Add
--mlflow <tracking-uri>toexamples/hf_ptq/hf_ptq.py(MLflow's ownMLFLOW_TRACKING_URIis honoured too). A tracked run records the invocation, the resolved recipe ($imports expanded), the run log and the quantization summaries, with every command-line argument as a searchable param; failed runs are recorded with their traceback. The experiment defaults to$USER/hf_ptq/<checkpoint basename>-<recipe name or --qformat>and can be overridden with--mlflow_experiment/--mlflow_run_name. - Add
--mlflow <tracking-uri>toexamples/vllm_serve/vllm_serve_fakequant.py(MLflow's ownMLFLOW_TRACKING_URIis honoured too), so a fake-quant serve records what it quantized and an evaluation of that endpoint can be traced back to a recipe. A tracked run uploads the launcher command, the resolvedRECIPE_PATH(or the mergedQUANT_CFG/KV_QUANT_CFGwhen presets are used), the worker log and the quantizer summary; the experiment defaults to$USER/vllm_serve_fakequant/<model basename>-<recipe name or quantization config>and can be overridden with--mlflow-experiment/--mlflow-run-name.
Backward Breaking Changes
- Migrate the FAR3D ONNX PTQ example to the shared evaluator and ModelOpt containers and
quantize_vovnet.py. Only the encoder supports INT8 and FP8; decoder calibration, quantization, and related CLI flags are removed, and the decoder remains in its exported mixed FP16/FP32 precision. - Image-text calibration with
--calib_with_imagesnow forwards multimodal batches through the complete VLM for all VLM families, so existing non-Nemotron commands may produce different language-model activation ranges and output scales. Recipe-based VLM PTQ also targets the complete VLM: vision modules stay in high precision by default and are quantized only when a model-specific recipe enables them, so custom recipes must explicitly exclude vision modules when required. - Move the checkpoint-mirror recipe tier from
huggingface/models/<org>/<checkpoint>/to the top-levelmodels/<org>/<model_id>/, keyed by each recipe's canonical Hugging Face Hub id — so the Step 3.5 Flash recipe moves tomodels/stepfun-ai/Step-3.5-Flash/ptq/and the NVIDIA Nemotron recipes gain theNVIDIA-prefix (e.g.models/nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-BF16/ptq/nvfp4-mse). Update any saved--recipepaths for these checkpoint recipes accordingly; the per-model_typerecipes underhuggingface/are unchanged. - Move the Mistral Medium 3.5 checkpoint-mirror recipe from
huggingface/models/nvidia/Mistral-Medium-3.5-128B-NVFP4/ptq/nvfp4-max-calibtomodels/mistralai/Mistral-Medium-3.5-128B/ptq/nvfp4-max-calib, keying it by the canonical Hugging Face base model. Update any saved--recipepaths to the new location. - Remove the
--auto_quantize_bits,--auto_quantize_method,--auto_quantize_score_size,--auto_quantize_cost_modeland--auto_quantize_active_moe_expert_ratioflags fromexamples/hf_ptq(deprecated in 0.46). Use an AutoQuantize--recipefrommodelopt_recipes/general/auto_quantize/instead. Those recipes now also splice in the shared basecost_excluded_layersunit, which the removed CLI applied unconditionally, so a VL model keeps its vision tower and MTP layers out of the effective-bits denominator. On a VL model this changes the per-layer cost weights, so an existing--auto_quantize_checkpointfrom an earlier release is rejected with "Use a different checkpoint path"; delete or repoint it to re-run the search. - Remove the
examples/llm_ptqsymlink and theexamples/vlm_ptqforwarder (both deprecated in 0.46). Useexamples/hf_ptq, passing--vlmfor vision-language models. - Remove the backward-compat
--qformat/--quant_cfgshort namesint8_sq,int8_wo,w4a8_awq,nvfp4_awq,nvfp4_mse,nvfp4_local_hessian,fp8_pb_woandfp8_pc_pt(deprecated in 0.45). Use the preset basename undermodelopt_recipes/configs/ptq/presets/model/instead:int8_smoothquant,int8_weight_only,w4a8_awq_beta,nvfp4_awq_lite,nvfp4_w4a4_weight_mse_fp8_sweep,nvfp4_w4a4_weight_local_hessian,fp8_2d_blockwise_weight_onlyandfp8_per_channel_per_token. Themodelopt.recipe.presets.QFORMAT_ALIASEStable and thealiasesargument ofload_quant_cfg_choices()are removed along with them. - Remove the legacy
layerwisebool form, itsuse_sequentialalias, and the top-levellayerwise_checkpoint_dirkey from calibration algorithm configs (deprecated in 0.45). Use the nested form, e.g.layerwise: {enable: true, checkpoint_dir: /path}. A pre-0.45modelopt_statecarrying either legacy key now fails validation on restore instead of being migrated; re-save it with a 0.45/0.46 release first. - Remove in-trainer quantization via
QuantizationArguments.quant_cfg/--quant_cfg(deprecated in 0.45); use--recipe. New recipesgeneral/ptq/mxfp4_mlp_weight_onlyandgeneral/ptq/nvfp4_mlp_weight_onlyreplaceMXFP4_MLP_WEIGHT_ONLY_CFG/NVFP4_MLP_WEIGHT_ONLY_CFGin theexamples/gpt-ossQAT flow. - Remove the
QuantizationArgumentsWithConfigalias inmodelopt.torch.quantization.plugins.transformers_trainer(deprecated in 0.45). UseQuantizationArguments. - Transformer Engine
TEGroupedLinear(fused MoE experts) now uses per-expert weight quantization (oneamaxper expert) instead of a single sharedamax, so ModelOpt checkpoints containing quantizedTEGroupedLinearmodules saved before 0.47 are not compatible with 0.47. Re-run PTQ to regenerate compatible checkpoints. mtq.quantizenow raises when a config asks for weight quantization but none of its weight-quantizer patterns match the model, instead of calibrating and exporting a silently unquantized checkpoint ("quant_algo": null). Configs that quantize activations or the KV cache only are unaffected, as are patterns that match and are then disabled by a later entry. If this fires, use the recipe for that architecture undermodelopt_recipes/huggingface/<model_type>/or fix the module patterns. SetMODELOPT_SKIP_WEIGHT_QUANT_CHECK=1to disable the check process-wide, e.g. for a pipeline-parallel rank whose local stage legitimately has none of the targeted modules.
Deprecations
- Remove
examples/llm_eval/lm_eval_tensorrt_llm.py(thetrt-llmmodel) in favor of the TensorRT-LLM backend shipped by lm-evaluation-harness itself (registered astrtllm, also supportsloglikelihood_rollingand pipeline parallelism);lm_evalis pinned to>=0.4.12,<0.5. Replacepython lm_eval_tensorrt_llm.py --model trt-llm --model_args tokenizer=<tok>,checkpoint_dir=<ckpt>withpython lm_eval_trtllm.py --model trtllm --model_args model=<ckpt>,tokenizer=<tok>, and settensor_parallel_sizeandmax_input_lenexplicitly — they default to 1 and 2048, and longer prompts are silently truncated. Uselm_eval_trtllm.pyrather than the plainlm_evalCLI: it patches an off-by-one in the backend's_parse_logprobsthat otherwise raisesKeyErroron every loglikelihood task. Loglikelihood tasks additionally require TensorRT-LLM >= 1.3.0rc11; generative tasks are unaffected.examples/hf_ptq/scripts/huggingface_example.shgains--input(BUILD_MAX_INPUT_LEN, default 4096) to size the evaluation engine's context, and honours a presetLM_EVAL_TPto override the tensor-parallel size. - Bump minimum container requirement to
nemo:26.08for the Megatron-Bridge / Megatron-LM optimization features. Megatron-LM quantization still works onnemo:26.06but will be dropped in a future release.
Bug Fixes
- Fix shared ONNX export metadata and Diffusers attention policy: every
NVFP4QuantExporterpost-process now upgrades the default-domain opset to at least 23, all FP8 custom-op exports re-run ONNX shape/type inference after setting output metadata, and quantized SDPA derives FP8 MHA enablement from the live Q/K/V quantizers instead of honoring a caller-set_disable_fp8_mhaattribute. - Fix ONNX FP16 conversion failing to preserve public output types when type inference changes a graph output declaration before output casts are inserted.
- Fix HuggingFace checkpoint export failing with
activation scaling factor 0.0 not positivewhen a dynamic-block quantizer (such as an NVFP4 input quantizer) ends calibration with an amax of zero because the calibration data never activated that layer or expert. Such a quantizer now exports a positive fallback scale and warns instead of crashing, matching what static quantizers already did; if you see the warning, check whether the layer is expected to be inactive and consider a larger calibration size. - Fix ONNX AutoCast failing on models with external initializers larger than 2 GiB.
- Avoid querying CUDA/Blackwell capability when
NVFP4QTensor.quantizeuses its CPU path or has the optional TensorRT-LLM fast path disabled. - Fix NVFP4 ONNX export to quantize FP4 weights with the published FP8 block scales, matching eager ModelOpt packed weights. Block scales below
2**-9are now clamped to that minimum, and non-finite or negative scales raise an error. - Fix FP8 ONNX export of BF16 models during real-weight compression.
- Fix Megatron-Bridge Quantization Aware Distillation of a vision-language model silently discarding the ModelOpt state, so the distilled checkpoint restored no quantizers and exported as an unquantized model. Re-run QAD to regenerate any affected checkpoint.
- Fix Megatron-Core HuggingFace export silently omitting fused (grouped GEMM) MoE experts for architectures without an
experts.linear_fc1rule (e.g.Qwen3MoeForCausalLM), which produced a valid-looking checkpoint containing no expert weights. The exporter now raises instead of writing that checkpoint; the scripts also avoid the situation by selectingSequentialMLPfor those architectures. - Fix GatedDeltaNet (Qwen3.5) quantizer exclusions on Megatron-Core: the recipe patterns name the HuggingFace
linear_attnmodule, so theconv1dwas calibrated and the alpha / beta gate projections were exported in FP8.conv1dnow has aself_attentionalias in the default disabled-quantizer units, and the alpha / beta projections are exported in BF16 (they share Megatron's fusedin_projquantizer and cannot be disabled by name). - Fix quantizing a Megatron-Core GPT
output_layer(HuggingFacelm_head) failing to checkpoint: megatron-core dropsoutput_layer._extra_state, where ModelOpt keeps quantizer state, so saving raised and loading silently restored the layer unquantized. ModelOpt now retains that entry for every Megatron model, and disables the workaround once megatron-core keeps it itself. - Fix Megatron-Core HuggingFace export writing Qwen3.5 / Qwen3.6 MoE routed experts as one packed tensor per layer, which vLLM cannot load (
Layer ... has no parameter 'w2_weight_weight_scale_2'). Quantized exports now write one entry per expert withgate_proj/up_projsplit, matching the released NVFP4 checkpoints. - Megatron-Core HuggingFace export now names unquantized grouped-GEMM MoE experts in
exclude_modulesinstead of omitting them, so a mixed-precision checkpoint tells the runtime what is not quantized. This adds onehf_quant_config.jsonentry per expert per layer for grouped-expert architectures such asNemotronHForCausalLM; the served numerics are unchanged. - Remove
--moe_calib_experts_ratiofromexamples/megatron_bridge/quantize.py. It was accepted but had no effect there: the option is implemented only for HuggingFace MoE modules, so Megatron models silently ignored it. It remains available inexamples/hf_ptq/hf_ptq.py, where it works. - Fix image-text (VLM) calibration hanging on multi-GPU: the per-subset sample budget used truncating division, so the stream supplied fewer samples than requested (1023 for
--calib_num_samples 1024over 3 subsets) and the strided data-parallel sharder left the trailing rank one sample short, deadlocking calibration until a 30-minute NCCL/gloo timeout. Subset budgets now sum exactly, and the sharder truncates every rank to the same count. - Fix Megatron-Core quantized KV-cache scales being dropped when a Qwen checkpoint is exported to HuggingFace:
k_scale/v_scalewere omitted andkv_cache_quant_algoleft unset for every Qwen architecture, so a checkpoint calibrated with an FP8 or NVFP4 KV cache silently served an unquantized one. - Megatron-Core HuggingFace export now verifies its own output: if the exported checkpoint is missing tensors the source checkpoint has (an architecture whose module has no export rule), it raises instead of writing a valid-looking checkpoint. Depth-pruned models and tied embeddings are accounted for.
- Loading a Megatron checkpoint that holds quantizer tensors but no restorable ModelOpt state now raises instead of silently loading the model unquantized.
- Fix image-text calibration for non-Nemotron VLMs by forwarding multimodal batches through the complete VLM.
- Update HuggingFace checkpoint export to use name-based tied-weight deduplication instead of the previous address-based approach. The address-based deduplication could incorrectly drop an untied weight that happened to share memory with a tied one, producing an incomplete checkpoint (observed as a false positive on MiniMax-M2.7).
- Fix EAGLE-3 training with context parallelism (
--cp_size > 1inexamples/speculative_decoding), which failed to start onaccelerate >= 1.13and then raisedgot mixed torch.Tensor and DTensor. - Polygraphy minimum dependency upgraded to
0.53.4to solve ONNX AutoCast failures when marking optional graph outputs. - Fix
--kv_cache_free_gpu_memory_fractionhaving no effect on thelm_evaltask ofexamples/hf_ptq/scripts/huggingface_example.sh, where the KV cache always took TensorRT-LLM's default 90% of free GPU memory and evaluation could run out of memory.examples/llm_eval/lm_eval_trtllm.pynow takeskv_cache_free_gpu_memory_fractionin--model_args, defaulting to 0.8.