Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
72f9f7d
[OmniML-3853] Backfill checkpoint aliases for Kimi-K2.7-Code and the …
shengliangxu Oct 8, 2026
4c1ffaa
fix(export): Don't re-apply a reverse rename to a key that already ca…
juhi10071998 Oct 8, 2026
37e9123
fix(gpt-oss): pin trl<1.15 and trackio>=0.41 for the example (#2718)
Fridah-nv Oct 8, 2026
f8b93e7
[OMNIML-3817] Move model-specific PTQ modeling into modelopt/torch/mo…
shengliangxu Oct 9, 2026
752b51b
[OMNIML-3817] Move model-specific PTQ modeling into modelopt/torch/mo…
shengliangxu Oct 9, 2026
836a223
Fix the GLM-5.1 alias: it is not the input_scale1 recipe (#2711)
shengliangxu Oct 9, 2026
e70cbfa
Fix the FSDP2 export deadlock at world > 1 (#2731)
cjluo-nv Oct 12, 2026
59c8668
Fix megatron_preprocess_data multi-worker segfault: use forkserver in…
shengliangxu Oct 13, 2026
13589a1
[https://nvbugspro.nvidia.com/bug/6886263] Fix FlashInfer sparse atte…
yingguo-trt Oct 13, 2026
903a235
[NVBugs 6914520, 6914493] Right-pad labeled calibration for finite at…
meenchen Oct 13, 2026
2ceb733
Add freeze_mtp to Megatron distillation to keep the MTP head fixed (#…
yueshen2016 Oct 13, 2026
5ca3b5b
fix(quantization): isolate optional Megatron imports (#2719)
joe-nv Oct 14, 2026
51cbc97
[6915406] Fix TensorRT 11 plugin registry enumeration (#2796)
ajrasane Oct 14, 2026
62f0409
[6919103] Fix custom-op plugin compilation with TensorRT 11 (#2801)
ajrasane Oct 14, 2026
7fbdeb4
[NVBug 6914119] Fix native NemotronH export config mappings (#2794)
meenchen Oct 14, 2026
c587049
[NVBugs 6918092] Fix FP8 fake quant zeroing a small nonzero amax (sta…
cjluo-nv Oct 14, 2026
c353ad5
[1/4] [6466805] Make quantization carriers safe for CPU export captur…
ajrasane Oct 14, 2026
925ce34
[NVBugs 6918319] Keep INT8 real-quant scales in FP32 so small FP16 ch…
cjluo-nv Oct 15, 2026
4afeac1
[1/2] Add a chat JSONL output mode to prepare_megatron_data_blend (#2…
yueshen2016 Oct 15, 2026
8689869
docs(dms): fix broken link to the small-budget training script (#2792)
ColinM-sys Oct 15, 2026
6c89743
[NVBug -6914213] fix(export): drop reverse renames that invent names …
juhi10071998 Oct 15, 2026
04ac0d5
Speed up CPU unit tests to stay under the 20 min CI limit (#2823)
kevalmorabia97 Oct 15, 2026
04d057a
[1/2] Unified export: quantized-weight state capture (#2777)
mxinO Oct 16, 2026
0af87c1
Sync GPTQ Hessians across data-parallel ranks (#2773)
kevalmorabia97 Oct 16, 2026
eed13bb
[6933164] fix: preserve Diffusers pipeline settings in component expo…
yingguo-trt Oct 16, 2026
76825c9
Fix post-merge unit CI and the gpu_megatron nightly timeout (#2832)
kevalmorabia97 Oct 16, 2026
5b48000
[6915426] Fix ONNX AutoTune benchmark initialization on TensorRT 11 (…
ajrasane Oct 16, 2026
4b51168
[3/4] [6466805] Normalize canonical Dynamo quantized weight paths (#2…
ajrasane Oct 16, 2026
7ea7a97
[6914448] Keep Qwen vision blocks in high precision for vLLM (#2822)
ajrasane Oct 16, 2026
725cb77
Fix concat elimination crashing when a Concat input is a constant (#2…
gcunhase Oct 16, 2026
7cdde51
Fix fused-experts export for W4A8 AWQ (SequentialQuantizer) weight qu…
Fridah-nv Oct 16, 2026
2f1f957
[https://nvbugspro.nvidia.com/bug/6918844] Fix LSQ FP8 block-scale lo…
yingguo-trt Oct 16, 2026
a95a86a
Load distributed object payloads with weights_only (#2837)
kevalmorabia97 Oct 16, 2026
2a52aa9
Fix scale-aware PTQ for native FP8 experts (#2820)
chadvoegele Oct 16, 2026
ab34c9f
Backport the fold_weight validation hook from #2656 for #2820
rohansjoshi Oct 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ jobs:
env:
COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml
COVERAGE_FILE: ${{ github.workspace }}/.coverage
run: pip install nox uv && nox -s "unit-3.12(torch_214, tf_latest)"
# Everything but PRs also runs the slow tests marked ``manual`` (e.g. AutoNAS).
PYTEST_EXTRA: ${{ github.event_name != 'pull_request' && '--run-manual' || '' }}
run: pip install nox uv && nox -s "unit-3.12(torch_214, tf_latest)" -- $PYTEST_EXTRA
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v7
with:
Expand Down
26 changes: 26 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ Changelog

*Quantization*

- Add metadata-only export specifications and non-mutating per-weight quantizer-state capture.
- HF export records canonical activation schemes, group/block sizes and weight-only MXFP4 metadata; mixed-format exports retain unquantized-layer exclusions, and non-square FP8 block layouts are rejected.
- Add Q8_0 weight-only quantization with 32-value GGML blocks, packed unified HF and Megatron export, and a built-in ``q8_0`` PTQ recipe.
- Add Hugging Face PTQ calibration and export support for Nemotron-H MTP modules, preserving calibrated expert input scales.
- Backfill checkpoint aliases for three more published NVFP4 releases: ``moonshotai/Kimi-K2.7-Code``, ``google/gemma-4-26B-A4B-it`` and ``google/diffusiongemma-26B-A4B-it``. Each imports an existing general recipe wholesale rather than copying its body.
- Backfill checkpoint aliases for nine more published NVFP4 releases, so each is reachable from its source model's hub path: ``zai-org/GLM-5.1`` and ``GLM-5.2``, ``MiniMaxAI/MiniMax-M2.5`` and ``MiniMax-M3``, ``deepseek-ai/DeepSeek-V3.1`` and ``DeepSeek-V3.2``, ``Qwen/Qwen3-235B-A22B-Instruct-2507`` and ``-Thinking-2507``, and ``Qwen/Qwen3.6-27B``. Each imports an existing general or architecture recipe wholesale rather than copying its body.
- Add composed Hugging Face AutoQuantize recipes that run fixed PTQ or weight AutoQuantize before
a separate KV-cache AutoQuantize stage, with independent resumable checkpoints for the weight and
Expand Down Expand Up @@ -47,6 +50,8 @@ Changelog

*Megatron Framework (M-LM / M-Bridge)*

- Add ``freeze_mtp`` to the Megatron ``DistillationConfig`` (``--freeze_mtp`` in ``examples/megatron_bridge/distill.py``): the student's MTP head keeps its input weights and its loss is skipped, so distillation trains the rest of the model on the distillation loss alone.
- Add ``output_format: chat_jsonl`` to ``prepare_megatron_data_blend``: it writes a weighted blend as ``train.jsonl`` / ``validation.jsonl`` chat data for ``distill.py --sft --sft_hf_dataset``, so the distillation loss can be restricted to assistant tokens. See the `Megatron data preparation guide <https://github.com/NVIDIA/Model-Optimizer/tree/main/examples/dataset/MEGATRON_DATA_PREP.md#chat-jsonl-blends-for-assistant-only-loss>`_.
- Add optional Top-P (nucleus) truncation to the Megatron top-k logits KD loss (now ``TopLogitsKLLoss``) via ``logit_kl_top_p`` and ``logit_kl_top_p_min_k`` in ``DistillationConfig``: after the global Top-K selection, only the smallest prefix whose cumulative teacher probability reaches ``top_p`` (with a floor of ``min_k`` entries) contributes to the KL, mirroring ``--logits-save-top-p`` / ``--logits-save-top-p-min-k`` in Megatron-LM's logits saver.
- Add an end-to-end W4A4 NVFP4 PTQ and QAD tutorial for Qwen3.6-35B-A3B also covering evaluation and vLLM throughput benchmarking. See `examples/megatron_bridge/tutorials/Qwen3.6-35B-A3B/README.md <https://github.com/NVIDIA/Model-Optimizer/tree/main/examples/megatron_bridge/tutorials/Qwen3.6-35B-A3B/>`_ for details.
- Add ``--mlflow <tracking-uri>`` to the ``examples/megatron_bridge`` scripts that write a checkpoint -- ``prune_minitron.py``, ``quantize.py``, ``distill.py``, ``export_quantized_megatron_to_hf.py`` and ``export_distilled_megatron_to_hf.py`` (MLflow's own ``MLFLOW_TRACKING_URI`` is honoured too). Each run records the invocation, its arguments as searchable params and its log -- a distillation records its training metrics instead of the rank-0 log -- and writes ``.experiment.json`` into the checkpoint it produced, so a pruning, a quantization, the distillation that refines its checkpoint and the export that deploys it can be traced to one another; uploading the checkpoints themselves stays off unless ``--mlflow_log_checkpoints`` is passed.
Expand All @@ -63,6 +68,7 @@ Changelog

**Backward Breaking Changes**

- ``modelopt.torch.utils.distributed.broadcast``/``allgather`` now reject objects of unregistered custom classes. Register them with ``torch.serialization.add_safe_globals``.
- Bump minimum transformers version to ``5.5`` instead of ``4.57``; transformers 4.x is no longer supported. Upgrade with ``pip install -U "nvidia-modelopt[hf]"``.
- ``modelopt.torch.distill.plugins.megatron.TopKLogitsKLLoss`` (``logit_kl_topk`` in ``DistillationConfig``) is renamed to ``TopLogitsKLLoss``, keeping the old name as a deprecated alias. It now normalizes both distributions over the full vocabulary instead of re-normalizing over the Top-K entries, and always appends a "ghost" token holding the probability mass outside the Top-K to both student and teacher (matching Megatron-LM's offline cached-logits KD loss). Loss values change for existing ``logit_kl_topk`` runs.
- ``LogitsAndIntermediatesLossBalancer`` (Megatron distillation plugin) no longer rescales the distillation loss to the magnitude of the LM loss when the LM loss is included. The total is now the fixed convex combination ``(1 - alpha) * lm_loss + alpha * kd_loss`` with ``DistillationConfig.kd_loss_alpha`` (in [0, 1]), matching Megatron-LM's offline cached-logits KD. The default ``kd_loss_alpha=1.0`` skips the LM loss, as before. ``DistillationConfig.skip_lm_loss`` and ``kd_loss_scale`` are removed and raise ``ValueError`` if passed; set ``kd_loss_alpha`` instead. In ``examples/megatron_bridge/distill.py``, ``--kd_loss_alpha`` replaces ``--no_skip_lm_loss`` and ``--kd_loss_scale``.
Expand Down Expand Up @@ -124,7 +130,16 @@ Changelog

**Bug Fixes**

- Harden the distributed object broadcast/allgather helpers and the Megatron expert-parallel export gather so a compromised peer rank can no longer execute code through a crafted pickle payload: payloads load with ``weights_only=True`` and the export gathers raw bytes instead of pickled objects.
- Fix LSQ clamping small, representable FP8 block scales too aggressively, which could zero quantized values and suppress scale gradients.
- Fix ONNX AutoTune benchmark initialization with TensorRT 11 while preserving strongly typed networks on TensorRT 10.
- Keep vision-block Linears in high precision in the ``qwen3_vl`` and ``qwen3_5`` FP8 vision recipes so exported checkpoints avoid a vLLM vision-attention shape failure. The recipes still quantize primary and deepstack merger Linears; re-quantize affected checkpoints before deployment.
- Fix unified HF export writing a weight name the source checkpoint does not use when a model declares a backwards-compatibility *load* rename as a reversible ``WeightRenaming``. Reversing such a rule rewrote the canonical name to a legacy spelling, and a deployment runtime keyed on the canonical name then failed to load the quantized checkpoint. Each exported name is now resolved against the names the source checkpoint actually carries, for both the exported tensors and the quantization config's module references.
- Fix exports using the built-in Transformers NemotronH implementation retaining incompatible legacy remote-code config and model mappings. Re-export affected checkpoints before deployment.
- Fix ``export_hf_checkpoint`` dropping Diffusers pipeline settings, such as Wan 2.2 ``boundary_ratio``, from ``model_index.json`` when ``components`` is given. Re-export affected checkpoints to a new directory, since component exports do not overwrite an existing ``model_index.json``.
- Fix INT8 real quantization (``mtq.compress``) of FP16 weights zeroing or clipping channels with a small amax: their scales underflowed in FP16. Scales of newly compressed INT8 weights are now stored in FP32.
- Fix Hugging Face exports classifying registered Qwen VLM parameters as unplaced source weights, which overwrote quantized tensors with original weights and incorrectly excluded their modules from quantization. Re-export affected checkpoints.
- Right-pad labeled calibration samples to avoid fully masked causal rows that can produce non-finite cuDNN attention gradients during AutoQuantize. Generation previews remove padding before decoding.
- Fix calibration silently dropping samples when an out-of-memory error forces the batch to be
split and a smaller working batch size is already known: the slices stopped tiling the batch,
so the rows between the old and the new width never reached the model and the collected
Expand All @@ -137,10 +152,17 @@ Changelog
- Fix ``hf_ptq`` overwriting a model's existing ``pad_token`` with ``eos_token`` when the model already has a valid padding token. The exported tokenizer now preserves the source model's padding configuration.
- Fix Hugging Face exports dropping off-index safetensors such as GLM-4.7's ``mtp.safetensors``.
- Fix Megatron-Core checkpoint saving for quantized grouped MoE experts when tensor and expert parallelism are both enabled.
- Fix FP8 fake quantization treating a positive amax at or below 2**-24 as zero, which silently zeroed such tensors and channels and every block of a static NVFP4 weight (``NVFP4StaticQuantizer``, including LSQ) with a global amax below ~3.6e-7. Fake quantization now matches the exported checkpoint.
- Fix ``megatron_preprocess_data`` with ``workers > 1`` segfaulting when run in a process that has already initialized CUDA or other native threads (for example in-process after GPU work): the tokenization worker pool now uses the ``forkserver`` start method instead of ``fork``.
- Fix unified HuggingFace export of RADIO-based VLMs retaining post-conversion vision and
projector names instead of restoring the hub layout; deployment loaders could skip those weights.
Streaming, offload, FSDP2, and layerwise export now reject reverse conversions that regroup
tensors; use resident export for those models.
- Fix that same reverse rename double-prefixing tensors copied from the source checkpoint rather
than loaded by the model, when a conversion mapping renames a module to a suffix of its original
name. Those tensors already carry the hub name, so C-RADIO towers exported
``vision_model.radio_model.radio_model.input_conditioner.norm_mean``. Re-export affected
checkpoints.
- Fix shared ONNX export metadata and Diffusers attention policy: every ``NVFP4QuantExporter`` post-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_mha`` attribute.
- Fix ONNX FP16 conversion failing to preserve public output types when type inference changes a graph output declaration before output casts are inserted.
- Fix ``examples/hf_ptq/hf_ptq.py`` discarding a completed PTQ run (no checkpoint exported) when the optional post-quantization sanity-check ``generate()`` call raised, for example because ``device_map="auto"`` placed part of the model on CPU. That failure is now caught and only skips the sanity check; export proceeds regardless.
Expand All @@ -158,6 +180,10 @@ Changelog
- Fix two issues in the vLLM offline hidden-state dump (``examples/speculative_decoding/collect_hidden_states/compute_hidden_states_vllm.py``) that only surface on large runs. **Resume:** the filter that skips conversations whose ``.pt`` already exists now runs with ``load_from_cache_file=False``. It depends on on-disk state, which is not part of the fingerprint ``datasets`` computes from the function and the dataset, so with a persistent HF cache reused across a resumed or requeued run the cached "keep everything" result from an earlier run was replayed and the dump re-generated and overwrote conversations it had already finished (observed: tens of thousands of ``.pt`` rewritten while the output count stayed flat). **Staging:** generation is now chunked (``--save-chunk-size``, default 256), so each chunk is saved and its staged hidden states freed before the next chunk is generated. Previously the whole dataset was generated before anything was saved, which kept every conversation staged in the connector's ``shared_storage_path`` (``/dev/shm``, i.e. RAM, by default) at once and exhausted it partway through large dumps. Chunking also makes the dump incrementally durable, so an interrupted run keeps its finished conversations and resumes from them. The save path now also frees each conversation's staged hidden states in a ``finally``, so a conversation skipped mid-loop (e.g. a short ``loss_mask``) can no longer leak its staging file, and conversation ids are validated as plain filenames before being used to build output paths.
- Fix YAML config I/O decoding with the locale codepage instead of UTF-8, which made a config containing any non-ASCII byte fail to load on a machine whose locale is not UTF-8 (notably Windows, where the default is cp1252). ``modelopt/recipe/loader.py``, the two ONNX autotune state files, the two transformers config readers, the distill config and the puzzletron profile now pass ``encoding="utf-8"`` explicitly. Only the YAML config paths are covered: these are the files most likely to carry non-ASCII text in comments, model names or paths, and the only ones read inside a user's process.
- Hybrid (e.g. Nemotron-H) checkpoints saved by the ``examples/megatron_bridge`` scripts now record their layer spec in ``run_config.yaml`` in a form that reloads, so they can be converted to HuggingFace; a checkpoint saved by an earlier release still needs its ``model.hybrid_stack_spec`` block replaced by hand.
- Fix ONNX preprocessing with custom TensorRT plugin libraries on TensorRT 11.
- Fix GPTQ with Megatron data parallelism: each data-parallel replica of a module now builds its Hessian from the whole calibration set instead of only its own shard, so all replicas reach the same quantized weights.
- Fix ONNX quantization with the default ``concat_elimination`` pass crashing in calibration with ``KeyError: '<tensor>_ReduceMin'`` when a ``Concat`` input is a constant, such as the class token of a ViT.
- Fix PTQ of native Transformers FP8 experts to apply source weight scales during calibration and export. Re-quantize affected checkpoints from the original FP8 source.

0.47.0 (2026-09-23)
^^^^^^^^^^^^^^^^^^^
Expand Down
10 changes: 10 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,16 @@ nox -s "unit-3.12(torch_211, tf_latest)"
keeping CI/CD fast and lean. Default to one test per behavior: use `@pytest.mark.parametrize` instead of
near-duplicate test functions, and don't add a per-branch test for a helper that a higher-level test already
exercises. More tests is not better coverage — every checked-in test is CI time and maintenance forever.
Before adding a test, check whether an existing unit, GPU, or example test already exercises the path; if so,
extend it instead. Do not add tests that only restate the implementation, assert on mocks, pin log/warning
wording, or re-cover a branch of a helper whose caller is tested. A PR that adds many tests should be able to
say what regression each one catches.
- **Keep `tests/unit` fast — the `linux` job has a hard 20-minute limit** and runs the whole suite serially.
A unit test should take well under 5s (check with `pytest --durations=20`). Tests that spawn processes or
subprocesses (`spawn_multiprocess_job`, `subprocess.run` importing torch), train for many steps, or build
real-size models belong in `tests/gpu*`; batch several cases into one spawn rather than one spawn per case,
or reuse the session-scoped `cpu_dist_workers` fixture for multi-rank CPU tests.
Slow tests for features without active maintenance (e.g. AutoNAS) should be `@pytest.mark.manual` or nightly-only.
- **Exercise the behavior a test claims to validate.** Mocks are useful for focused interface and wiring coverage, but
replacing the implementation under test does not validate its real behavior. Include an end-to-end test that runs
the actual implementation whenever the test claims backend or runtime behavior. For example, a test of
Expand Down
5 changes: 1 addition & 4 deletions docs/source/guides/9_autotune.rst
Original file line number Diff line number Diff line change
Expand Up @@ -569,10 +569,7 @@ Using TensorRT Python API
# Create builder and logger
logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
network = builder.create_network(
1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
| 1 << int(trt.NetworkDefinitionCreationFlag.STRONGLY_TYPED)
)
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.STRONGLY_TYPED))
parser = trt.OnnxParser(network, logger)

# Parse optimized ONNX model
Expand Down
Loading
Loading