Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Changelog
- Add ``layerwise.export_dir``: layerwise calibration writes each decoder layer to its own quantized checkpoint shard as it finishes, so no separate ``export_hf_checkpoint()`` pass is needed and, with ``layerwise.checkpoint_dir``, an interrupted run resumes without redoing finished layers. Calibration writes the layer shards; ``finalize()`` on the exporter left on the model adds the tail shard, the index and the config artifacts, and the checkpoint does not load until it runs. ``examples/hf_ptq`` does this for you. Supports FP8 and NVFP4 on single-process models, resident or offloaded, including multimodal models and models with MTP layers; other formats and placements raise ``NotImplementedError`` before calibration starts.
- Add support for quantizing and calibrating enabled operators outside the transformer layers, such as ``lm_head``, when using layerwise calibration.
- Add an end-to-end BEVFormer ONNX PTQ example with temporal calibration data generation, INT8 and FP8 quantization, TensorRT engine building, and nuScenes accuracy evaluation. See `examples/onnx_ptq/bevformer/README.md <https://github.com/NVIDIA/Model-Optimizer/tree/main/examples/onnx_ptq/bevformer>`_ for details.
- Add a reusable local-Hessian NVFP4 PTQ recipe and a Qwen3.8-27B checkpoint recipe that reproduces its 5.5-bit AutoQuantize NVFP4/FP8 assignment.

*Misc*

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# PTQ recipe wrapping the shipped NVFP4 W4A4 local-Hessian preset.

imports:
preset: configs/ptq/presets/model/nvfp4_w4a4_weight_local_hessian

metadata:
recipe_type: ptq
description: >-
Applies NVFP4 W4A4 with static weight scales, dynamic inputs, KV quantizers disabled, and
local-Hessian weight calibration with an FP8-scale sweep.
quantize:
$import: preset
Comment thread
realAsma marked this conversation as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BB: Rename this file to nvfp4_w4a4_mlp_fp8_attn_local_hessian.yaml

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

🐝 On it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

Blocked for now: the live PR branch was force-updated and the canonical checkout has divergent history. I preserved the checkout and artifacts and asked privately for approval to realign it before applying this rename. The PR monitor remains active.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

Blocked for now: the canonical checkout is on dd602fb7ce, while the verified PR head was force-updated to 07bddc6fb6 with divergent history. I preserved the checkout and artifacts without changing source. The rename to nvfp4_w4a4_mlp_fp8_attn_local_hessian.yaml remains pending safe synchronization.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# modelopt-schema: modelopt.recipe.config.ModelOptPTQRecipe
imports:
base: models/Qwen/Qwen3.8-27B/ptq/max_nvfp4_w4a4_mlp_fp8_attn

metadata:
recipe_type: ptq
description: >-
Qwen3.8-27B local-Hessian PTQ using the NVFP4 W4A4 and FP8 W8A8 assignment exported by
the 5.5-bit NVFP4-max AutoQuantize sweep.

quantize:
$import: base
algorithm:
method: local_hessian
fp8_scale_sweep: true
layerwise:
enable: true
get_qdq_activations_from_prev_layer: true
Comment thread
realAsma marked this conversation as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BB: Rename this file to nvfp4_w4a4_mlp_fp8_attn_max.yaml

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

🐝 On it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

🐝 Got it — I’ll rename the recipe file and update its references.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

Blocked for now: the live PR branch was force-updated and the canonical checkout has divergent history. I preserved the checkout and artifacts and asked privately for approval to realign it before applying this rename. The PR monitor remains active.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Bot comment.

Blocked for now: the canonical checkout is on dd602fb7ce, while the verified PR head was force-updated to 07bddc6fb6 with divergent history. I preserved the checkout and artifacts without changing source. The rename to nvfp4_w4a4_mlp_fp8_attn_max.yaml remains pending safe synchronization.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# QuantizeConfig for the precision assignment exported by a 5.5-bit NVFP4-max AutoQuantize sweep.

# modelopt-schema: modelopt.torch.quantization.config.QuantizeConfig
imports:
base_disable_all: configs/ptq/units/base_disable_all
fp8: configs/numerics/fp8
nvfp4: configs/numerics/nvfp4
nvfp4_static: configs/numerics/nvfp4_static

algorithm: max
quant_cfg:
- $import: base_disable_all

- quantizer_name: '*language_model.layers.*.mlp.*.weight_quantizer'
cfg: {$import: nvfp4_static}
- quantizer_name: '*language_model.layers.*.mlp.*.input_quantizer'
cfg: {$import: nvfp4}

- quantizer_name: '*language_model.layers.*.self_attn.*_proj.weight_quantizer'
cfg: {$import: fp8}
- quantizer_name: '*language_model.layers.*.self_attn.*_proj.input_quantizer'
cfg: {$import: fp8}
- quantizer_name: '*language_model.layers.*.linear_attn.*_proj*.weight_quantizer'
cfg: {$import: fp8}
- quantizer_name: '*language_model.layers.*.linear_attn.*_proj*.input_quantizer'
cfg: {$import: fp8}

- quantizer_name: '*lm_head.weight_quantizer'
cfg: {$import: nvfp4_static}
- quantizer_name: '*lm_head.input_quantizer'
cfg: {$import: nvfp4}

# These projections were excluded from the AutoQuantize search but match the
# broad linear-attention patterns above, so disable them last.
- quantizer_name: '*linear_attn.in_proj_a*'
enable: false
- quantizer_name: '*linear_attn.in_proj_b*'
enable: false
14 changes: 13 additions & 1 deletion modelopt_recipes/ptq.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ supported combinations.
### The shipped recipes

<details>
<summary>All 25 <code>general/ptq/</code> recipes (click to expand)</summary>
<summary>All 26 <code>general/ptq/</code> recipes (click to expand)</summary>

| Recipe | Model body | KV cache | Calibration |
|--------|-----------|----------|-------------|
Expand All @@ -38,6 +38,7 @@ supported combinations.
| `nvfp4_default-kv_fp8_cast` | NVFP4 W4A4, all linears | FP8 (constant amax) | max |
| `nvfp4_act_headroom-kv_fp8_cast` | NVFP4 W4A4, all linears | FP8 (constant amax) | nvfp4_act_headroom |
| `nvfp4_default-kv_nvfp4_cast` | NVFP4 W4A4, all linears | NVFP4 (constant amax) | max |
| `nvfp4_default-kv_none-local_hessian` | NVFP4 W4A4 (static W), all linears | none | local Hessian + FP8 sweep |
| `nvfp4_default-kv_none-gptq` | NVFP4 W4A4 (static W), all linears | none | GPTQ (layerwise) |
| `nvfp4_mlp_only-kv_fp8` | NVFP4 W4A4, MLP + MoE experts | FP8 (calibrated) | max |
| `nvfp4_mlp_only-novit-kv_fp8` | NVFP4 W4A4, MLP + MoE experts (VL vision tower excluded) | FP8 (calibrated) | max |
Expand Down Expand Up @@ -171,6 +172,11 @@ How the quantization scales are searched. The default (no suffix) is `max`.
(amax) calibrated as in the default recipes. Costs more calibration time but
recovers accuracy NVFP4 W4A4 can lose under plain max. Reach for it when a
`max` recipe regresses.
- **`local_hessian`** (`nvfp4_default-kv_none-local_hessian`) — searches static
NVFP4 weight scales by minimizing output reconstruction error using a local
Hessian approximation, with an FP8-scale sweep. It can recover accuracy when
plain max calibration regresses, but currently supports only single-rank
calibration.
- **`input_scale1`** (`nvfp4_experts_only_input_scale1-kv_fp8_cast`) — pins the
expert **activation** per-tensor amax to a constant `2688.0`
(= E2M1_MAX × E4M3_MAX = 6 × 448) via `constant_amax`, so the exported NVFP4
Expand Down Expand Up @@ -393,6 +399,12 @@ checkpoint's** quant config verbatim:
`nvidia/Mistral-Medium-3.5-128B-NVFP4`: decoder MLP layers 4–86 use NVFP4
W4A4, edge MLP layers 0–3 and 87 use FP8 W8A8, and all attention projections
and the KV cache use FP8. It uses max calibration.
- **`models/Qwen/Qwen3.8-27B/ptq/local_hessian_nvfp4_w4a4_mlp_fp8_attn`**
reproduces NVFP4 W4A4 mixed precision quantization recipe used for `Qwen/Qwen3.8-27B`:
MLP projections and `lm_head` use NVFP4 W4A4, self-attention and the large
linear-attention projections use FP8 W8A8, and the vision tower, MTP layers,
KV cache, and `linear_attn.in_proj_a/b` remain unquantized. Static NVFP4 weight
scales are calibrated with local-Hessian algorithm.
- **`models/nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-BF16/ptq/nvfp4-mse`** mirrors
`nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4` exactly — a hybrid
**Mamba-MoE** with a hand-mapped, **per-component** precision scheme:
Expand Down