fix(quant): resolve hyphenated registry methods and disk-dict from_config in quant factory

_normalize_method_name canonicalizes dashes to underscores for _OVERRIDES
lookup, but vLLM's QUANTIZATION_METHODS keeps historical spellings
('compressed-tensors'), so both --quantization compressed-tensors and
checkpoint auto-detection raised 'Unknown quantization method'. Resolve
the normalized name back to the registry spelling, and fall back to
from_config for registry configs whose __init__ does not take the
serialized schema (compressed-tensors config_groups/format/ignore).
This commit is contained in:
admin committed 2026-10-08 07:00:05 -04:00
1 parent 3e705fcdb1
commit 2f8363c5fc
2 files changed
+98 -6

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
"""Tests for the quantization config factory's method-name and disk-dict resolution."""
from __future__ import annotations
import pytest
from vllm.model_executor.layers.quantization.compressed_tensors.compressed_tensors import (
CompressedTensorsConfig,
)
from vllm_omni.quantization import build_quant_config, resolve_component_quant_config
from vllm_omni.quantization.component_config import (
ComponentQuantizationConfig,
resolve_encoder_quant_config,
)
from vllm_omni.quantization.factory import SUPPORTED_QUANTIZATION_METHODS, _build_single
def _int8_weight_only_disk_config() -> dict:
"""Serialized compressed-tensors int8 weight-only metadata as it appears on disk."""
weights = {
"num_bits": 8,
"type": "int",
"symmetric": True,
"strategy": "channel",
"dynamic": False,
"observer": "minmax",
}
return {
"quant_method": "compressed-tensors",
"format": "pack-quantized",
"config_groups": {"group_0": {"targets": ["Linear"], "weights": weights}},
"ignore": ["img_in"],
"quantization_status": "frozen",
}
def test_hyphenated_registry_method_builds_from_str() -> None:
config = _build_single("compressed-tensors")
assert isinstance(config, CompressedTensorsConfig)
assert config.get_name() == "compressed-tensors"
@pytest.mark.parametrize("spelling", ["compressed-tensors", "compressed_tensors"])
def test_disk_dict_builds_via_from_config(spelling: str) -> None:
disk = _int8_weight_only_disk_config()
disk["quant_method"] = spelling
config = build_quant_config(disk)
assert isinstance(config, CompressedTensorsConfig)
def test_per_component_dict_routes_transformer_only() -> None:
disk = {"transformer": _int8_weight_only_disk_config()}
config = build_quant_config(disk)
assert isinstance(config, ComponentQuantizationConfig)
assert isinstance(
resolve_component_quant_config(config, "transformer"), CompressedTensorsConfig
)
encoder = resolve_encoder_quant_config(
resolve_component_quant_config(config, "text_encoder")
)
assert encoder is None
def test_unknown_method_still_raises() -> None:
with pytest.raises(ValueError, match="Unknown quantization method"):
_build_single("not-a-real-method")
def test_supported_list_advertises_hyphenated_registry_names() -> None:
assert "compressed-tensors" in SUPPORTED_QUANTIZATION_METHODS
+26 -6
View File
@@ -326,20 +326,36 @@ def _build_from_method_and_config(method: str, config: Mapping[str, Any]) -> Qua
return _build_single(method, **config)
def _resolve_registry_method_name(method: str) -> str | None:
"""Resolve a normalized (underscore) method name to vLLM's registry spelling.
vLLM's ``QUANTIZATION_METHODS`` keeps canonical names with their historical
spelling — including hyphenated ones such as ``compressed-tensors`` — while
``_normalize_method_name`` canonicalizes dashes to underscores for the
``_OVERRIDES`` lookup. Try both spellings so hyphenated registry entries
remain reachable.
"""
for candidate in (method, method.replace("_", "-")):
if candidate in QUANTIZATION_METHODS:
return candidate
return None
def _build_single(method: str, **kwargs: Any) -> QuantizationConfig:
"""Build a single QuantizationConfig by method name.
Resolution: _OVERRIDES first, then vLLM registry via from_config().
"""
method = _normalize_method_name(method)
normalized = _normalize_method_name(method)
if method in _OVERRIDES:
return _OVERRIDES[method](**kwargs)
if normalized in _OVERRIDES:
return _OVERRIDES[normalized](**kwargs)
if method not in QUANTIZATION_METHODS:
registry_method = _resolve_registry_method_name(normalized)
if registry_method is None:
raise ValueError(f"Unknown quantization method: {method!r}. Supported: {SUPPORTED_QUANTIZATION_METHODS}")
config_cls = get_quantization_config(method)
config_cls = get_quantization_config(registry_method)
from vllm.config.quantization import resolve_quantization_config
from vllm.model_executor.layers.quantization.online.base import OnlineQuantizationConfig
@@ -347,7 +363,7 @@ def _build_single(method: str, **kwargs: Any) -> QuantizationConfig:
if config_cls is OnlineQuantizationConfig:
if "args" in kwargs:
return config_cls(**kwargs)
args = resolve_quantization_config(method, kwargs or None)
args = resolve_quantization_config(registry_method, kwargs or None)
if args is None:
raise ValueError("Online quantization requires quantization config arguments")
return config_cls(args)
@@ -355,6 +371,10 @@ def _build_single(method: str, **kwargs: Any) -> QuantizationConfig:
try:
return config_cls(**kwargs)
except TypeError:
# Registry configs built from checkpoint metadata (e.g. compressed-tensors)
# take the serialized schema through from_config rather than __init__.
if kwargs and hasattr(config_cls, "from_config"):
return config_cls.from_config(dict(kwargs))
sig = inspect.signature(config_cls.__init__)
raise TypeError(
f"Cannot instantiate {config_cls.__name__} with kwargs {kwargs}. Expected signature: {sig}"