| |
| |
| """Unit tests for QuantizationConfigArgs parsing.""" |
|
|
| import pytest |
|
|
| from vllm.config.quantization import ( |
| QUANT_KEY_NAMES, |
| QuantizationConfigArgs, |
| QuantSpec, |
| resolve_quantization_config, |
| ) |
| from vllm.model_executor.layers.quantization.utils.quant_utils import ( |
| kFp8Dynamic128Sym, |
| kFp8DynamicTokenSym, |
| kFp8Static128BlockSym, |
| kFp8StaticTensorSym, |
| kInt8StaticChannelSym, |
| kMxfp8Dynamic, |
| ) |
|
|
| |
|
|
|
|
| def test_quant_spec_resolves_string_to_quant_key(): |
| spec = QuantSpec(weight="mxfp8", activation="fp8_per_token") |
| assert spec.weight == kMxfp8Dynamic |
| assert spec.activation == kFp8DynamicTokenSym |
|
|
|
|
| def test_quant_spec_accepts_quant_key_directly(): |
| spec = QuantSpec(weight=kFp8StaticTensorSym) |
| assert spec.weight is kFp8StaticTensorSym |
| assert spec.activation is None |
|
|
|
|
| def test_quant_spec_rejects_unknown_name(): |
| with pytest.raises(ValueError, match="unknown quantization name"): |
| QuantSpec(weight="not_a_real_format") |
|
|
|
|
| |
|
|
|
|
| def test_args_linear_string_resolves_via_quant_key_names(): |
| |
| args = QuantizationConfigArgs(linear="fp8_per_block_static") |
| assert args.linear == QuantSpec(weight=kFp8Static128BlockSym) |
| assert args.moe is None |
|
|
|
|
| def test_args_moe_string_resolves_via_online_shorthand(): |
| |
| |
| |
| |
| args = QuantizationConfigArgs(moe="fp8_per_block") |
| assert args.moe == QuantSpec(weight=kFp8Static128BlockSym) |
|
|
|
|
| def test_args_string_shorthand_missing_slot_raises(): |
| |
| |
| with pytest.raises(ValueError, match="does not define a linear spec"): |
| QuantizationConfigArgs(linear="int8_per_channel_weight_only") |
|
|
|
|
| def test_args_accepts_dict_form(): |
| args = QuantizationConfigArgs(moe={"activation": "mxfp8"}) |
| assert args.moe == QuantSpec(weight=None, activation=kMxfp8Dynamic) |
|
|
|
|
| |
|
|
|
|
| def test_resolve_shorthand_only_populates_both_slots(): |
| args = resolve_quantization_config("fp8_per_block", None) |
| assert args.linear == QuantSpec(weight=kFp8Static128BlockSym) |
| assert args.moe == QuantSpec(weight=kFp8Static128BlockSym) |
|
|
|
|
| def test_resolve_int8_shorthand_leaves_linear_unset(): |
| |
| |
| args = resolve_quantization_config("int8_per_channel_weight_only", None) |
| assert args.linear is None |
| assert args.moe == QuantSpec(weight=kInt8StaticChannelSym) |
|
|
|
|
| def test_resolve_quantization_config_only(): |
| |
| |
| args = resolve_quantization_config(None, {"moe": {"activation": "mxfp8"}}) |
| assert args.linear is None |
| assert args.moe == QuantSpec(weight=None, activation=kMxfp8Dynamic) |
|
|
|
|
| def test_resolve_merges_explicit_over_shorthand(): |
| |
| |
| args = resolve_quantization_config( |
| "fp8_per_tensor", |
| {"linear": "fp8_per_block"}, |
| ) |
| assert args.linear == QuantSpec(weight=kFp8Static128BlockSym) |
| assert args.moe == QuantSpec(weight=kFp8StaticTensorSym) |
|
|
|
|
| def test_resolve_rejects_quantization_config_with_non_shorthand_quant(): |
| |
| |
| |
| with pytest.raises(ValueError, match="quantization_config is only supported"): |
| resolve_quantization_config("gptq", {"linear": "fp8_per_block"}) |
|
|
|
|
| |
|
|
|
|
| def test_quant_key_names_round_trip(): |
| |
| |
| for name, expected in QUANT_KEY_NAMES.items(): |
| assert QuantSpec(weight=name).weight == expected, name |
| assert QuantSpec(activation=name).activation == expected, name |
|
|
|
|
| def test_static_block_weight_paired_with_dynamic_block_activation(): |
| |
| |
| |
| spec = QuantSpec(weight="fp8_per_block_static", activation="fp8_per_block_dynamic") |
| assert spec.weight == kFp8Static128BlockSym |
| assert spec.activation == kFp8Dynamic128Sym |
|
|