Skip to content

Commit 7b5e4c8

Browse files
fix(quantization): accept QuantizeAlgorithmConfig in get_modelike_from_algo_cfg
get_modelike_from_algo_cfg raised ValueError for a QuantizeAlgorithmConfig instance even though QuantizeAlgoCfgType lists it as a valid type. Since ModeloptBaseConfig is a Mapping, widen the type cascade's dict check to Mapping and materialize the resolved config with dict(). Add unit and end-to-end regression tests plus a CHANGELOG entry. Fixes #201 Signed-off-by: javierdejesusda <javier.dejesusj9@gmail.com>
1 parent a5bc6f8 commit 7b5e4c8

4 files changed

Lines changed: 41 additions & 4 deletions

File tree

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Changelog
3131
**Bug Fixes**
3232

3333
- Fix Megatron-Core HF importer to load fused ``TELayerNormColumnParallelLinear.layer_norm_weight`` from HF for GPT-family models (Qwen3 etc.) under ``--export-default-te-spec``. Importer now prefers per-context keys ``fused_input_layernorm`` / ``fused_pre_mlp_layernorm`` (fallback ``fused_norm`` for Nemotron-H backward compatibility); ``mcore_qwen.py`` provides the new rules. Without this fix, post-prune MMLU sat at chance.
34+
- Fix ``QuantizeAlgorithmConfig`` instances being rejected with ``ValueError`` when passed as the ``algorithm`` in a quantization config (e.g. ``cfg["algorithm"] = mtq.MaxCalibConfig(...)``). Such instances are now accepted, consistent with the ``algorithm`` field's type annotation.
3435

3536
0.44 (2026-05-14)
3637
^^^^^^^^^^^^^^^^^

modelopt/torch/quantization/mode.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"""This module contains the mode descriptor for the quantization mode."""
1717

1818
from abc import abstractmethod
19-
from collections.abc import Callable
19+
from collections.abc import Callable, Mapping
2020

2121
from modelopt.torch.opt.config import ModeloptBaseConfig
2222
from modelopt.torch.opt.conversion import ModelLikeModule
@@ -374,7 +374,9 @@ def get_modelike_from_algo_cfg(algo_cfg: QuantizeAlgoCfgType) -> ModeConfigList:
374374
return [get_modelike_from_algo_cfg(c)[0] for c in algo_cfg]
375375
if algo_cfg is None or isinstance(algo_cfg, str):
376376
algo_name, algo_cfg = algo_cfg, {}
377-
elif isinstance(algo_cfg, dict):
377+
elif isinstance(algo_cfg, Mapping):
378+
# Normalize any mapping (incl. ModeloptBaseConfig instances) to a plain dict.
379+
algo_cfg = dict(algo_cfg)
378380
algo_name = algo_cfg["method"]
379381
else:
380382
raise ValueError(f"Invalid config type: {type(algo_cfg)}")

tests/unit/torch/quantization/test_mode.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@
1919

2020
from modelopt.torch.opt.config import ModeloptField
2121
from modelopt.torch.opt.mode import _ModeRegistryCls
22-
from modelopt.torch.quantization.config import QuantizeAlgorithmConfig
22+
from modelopt.torch.quantization.config import (
23+
MaxCalibConfig,
24+
QuantizeAlgorithmConfig,
25+
SmoothQuantCalibConfig,
26+
)
2327
from modelopt.torch.quantization.mode import (
2428
BaseCalibrateModeDescriptor,
2529
CalibrateModeRegistry,
2630
QuantizeModeRegistry,
31+
get_modelike_from_algo_cfg,
2732
)
2833

2934

@@ -60,3 +65,20 @@ def config_class(self) -> QuantizeAlgorithmConfig:
6065
@CalibrateModeRegistry.register_mode
6166
class TestIncorrectCalibrateModeDescriptor:
6267
pass
68+
69+
70+
def test_get_modelike_from_algo_cfg_accepts_config_instance():
71+
"""Regression test for GitHub issue #201.
72+
73+
A ``QuantizeAlgorithmConfig`` instance passed as the ``algorithm`` config is
74+
normalized to a dict and accepted, instead of raising ``ValueError``.
75+
"""
76+
mode_name, algo_cfg = get_modelike_from_algo_cfg(MaxCalibConfig(distributed_sync=False))[0]
77+
assert mode_name == "max_calibrate"
78+
assert isinstance(algo_cfg, dict)
79+
assert algo_cfg["distributed_sync"] is False
80+
MaxCalibConfig(**algo_cfg)
81+
82+
modes = get_modelike_from_algo_cfg([MaxCalibConfig(), SmoothQuantCalibConfig()])
83+
assert [name for name, _ in modes] == ["max_calibrate", "smoothquant_calibrate"]
84+
assert all(isinstance(cfg, dict) for _, cfg in modes)

tests/unit/torch/quantization/test_quantize_cpu.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import modelopt.torch.opt as mto
3333
import modelopt.torch.quantization as mtq
3434
from modelopt.torch.quantization.calib import MaxCalibrator
35-
from modelopt.torch.quantization.config import QuantizerAttributeConfig
35+
from modelopt.torch.quantization.config import MaxCalibConfig, QuantizerAttributeConfig
3636
from modelopt.torch.quantization.conversion import set_quantizer_attributes_full
3737
from modelopt.torch.quantization.nn.modules.tensor_quantizer import (
3838
SequentialQuantizer,
@@ -167,6 +167,18 @@ def forward_loop():
167167
mtq.quantize(model, mtq.INT8_DEFAULT_CFG, forward_loop=forward_loop)
168168

169169

170+
def test_quantize_accepts_algo_config_instance_end_to_end():
171+
"""Regression test for GitHub issue #201.
172+
173+
A ``QuantizeAlgorithmConfig`` instance set as ``config["algorithm"]`` must not
174+
raise ``ValueError`` through the full quantize/calibrate flow.
175+
"""
176+
quant_config = copy.deepcopy(mtq.INT8_DEFAULT_CFG)
177+
quant_config["algorithm"] = MaxCalibConfig(distributed_sync=False)
178+
model = SimpleLinear()
179+
quantize_model_and_forward(model, quant_config, [model.get_input() for _ in range(2)])
180+
181+
170182
def test_custom_calib_config():
171183
model_ref = SimpleLinear()
172184
model_ref = mtq.quantize(

0 commit comments

Comments
 (0)