项目文件夹

文件
wehub-resource-sync eec33d25b2
Build Wheel / build (3.11) (push) Failing after 1s
Build Wheel / build (3.12) (push) Failing after 0s
pre-commit / pre-commit (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:29:08 +08:00

387 行
13 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Tests for the unified quantization framework."""
import pytest
from torch import nn
pytestmark = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu]
def test_build_quant_config_fp8():
from vllm_omni.quantization import build_quant_config
config = build_quant_config("fp8")
assert config is not None
assert config.get_name() == "fp8"
assert config.activation_scheme == "dynamic"
def test_build_quant_config_none():
from vllm_omni.quantization import build_quant_config
assert build_quant_config(None) is None
def test_build_quant_config_none_string():
from vllm_omni.quantization import build_quant_config
assert build_quant_config("none") is None
def test_build_quant_config_invalid():
from vllm_omni.quantization import build_quant_config
with pytest.raises(ValueError, match="Unknown quantization method"):
build_quant_config("invalid_method")
def test_build_quant_config_dict():
from vllm_omni.quantization import build_quant_config
config = build_quant_config({"method": "fp8", "activation_scheme": "static"})
assert config is not None
assert config.get_name() == "fp8"
assert config.activation_scheme == "static"
def test_build_quant_config_dict_not_mutated():
from vllm_omni.quantization import build_quant_config
original = {"method": "fp8", "activation_scheme": "static"}
copy = original.copy()
build_quant_config(original)
assert original == copy
def test_build_quant_config_modelopt_fp8_config_json():
from vllm.model_executor.layers.quantization.modelopt import ModelOptFp8Config
from vllm_omni.quantization import build_quant_config
config = build_quant_config(
{
"quant_method": "modelopt",
"quant_algo": "FP8",
"ignore": ["proj_out"],
"producer": {"name": "modelopt"},
}
)
assert isinstance(config, ModelOptFp8Config)
assert config.get_name() == "modelopt"
assert config.is_checkpoint_fp8_serialized
def test_build_quant_config_per_component():
from vllm_omni.quantization import ComponentQuantizationConfig, build_quant_config
config = build_quant_config(
{
"transformer": {"method": "fp8"},
"vae": None,
}
)
assert isinstance(config, ComponentQuantizationConfig)
assert config.component_configs["transformer"].get_name() == "fp8"
assert config.component_configs["vae"] is None
def test_build_quant_config_per_component_string():
from vllm_omni.quantization import ComponentQuantizationConfig, build_quant_config
config = build_quant_config({"transformer": "fp8", "vae": None})
assert isinstance(config, ComponentQuantizationConfig)
assert config.component_configs["transformer"].get_name() == "fp8"
def test_build_quant_config_per_component_inner_dict_not_mutated():
"""Inner component dicts should not be mutated by build_quant_config."""
from vllm_omni.quantization import build_quant_config
inner = {"method": "fp8", "activation_scheme": "static"}
original = inner.copy()
build_quant_config({"transformer": inner, "vae": None})
assert inner == original
def test_flat_dict_not_misdetected_as_per_component():
"""A flat config like {"activation_scheme": "static"} must NOT be treated
as a per-component dict — it should raise ValueError for missing 'method'."""
from vllm_omni.quantization import build_quant_config
with pytest.raises(ValueError, match="must have a 'method' or 'quant_method' key"):
build_quant_config({"activation_scheme": "static"})
def test_build_quant_config_passthrough():
from vllm.model_executor.layers.quantization.fp8 import Fp8Config
from vllm_omni.quantization import build_quant_config
fp8 = Fp8Config(is_checkpoint_fp8_serialized=False, activation_scheme="dynamic")
assert build_quant_config(fp8) is fp8
def test_component_config_routing():
from vllm.model_executor.layers.quantization.fp8 import Fp8Config
from vllm_omni.quantization import ComponentQuantizationConfig
fp8 = Fp8Config(is_checkpoint_fp8_serialized=False, activation_scheme="dynamic")
config = ComponentQuantizationConfig(
component_configs={"transformer": fp8, "vae": None},
)
assert config.get_name() == "component"
assert config.resolve("transformer.blocks.0.attn") is fp8
assert config.resolve("vae.encoder.conv_in") is None
assert config.resolve("unknown.layer") is None
def test_component_config_with_default():
from vllm.model_executor.layers.quantization.fp8 import Fp8Config
from vllm_omni.quantization import ComponentQuantizationConfig
fp8 = Fp8Config(is_checkpoint_fp8_serialized=False, activation_scheme="dynamic")
config = ComponentQuantizationConfig(
component_configs={"vae": None},
default_config=fp8,
)
assert config.resolve("transformer.blocks.0") is fp8
assert config.resolve("vae.encoder") is None
def test_integration_string():
from vllm_omni.diffusion.data import OmniDiffusionConfig
config = OmniDiffusionConfig(model="test", quantization_config="fp8")
assert config.quantization_config is not None
assert config.quantization_config.get_name() == "fp8"
def test_integration_dict():
from vllm_omni.diffusion.data import OmniDiffusionConfig
config = OmniDiffusionConfig(
model="test",
quantization_config={"method": "fp8", "activation_scheme": "static"},
)
assert config.quantization_config is not None
assert config.quantization_config.get_name() == "fp8"
assert config.quantization_config.activation_scheme == "static"
def test_integration_no_quant():
from vllm_omni.diffusion.data import OmniDiffusionConfig
config = OmniDiffusionConfig(model="test")
assert config.quantization_config is None
def test_integration_per_component():
"""OmniDiffusionConfig with per-component quantization dict."""
from vllm_omni.diffusion.data import OmniDiffusionConfig
from vllm_omni.quantization import ComponentQuantizationConfig
config = OmniDiffusionConfig(
model="test",
quantization_config={
"transformer": {"method": "fp8"},
"vae": None,
},
)
assert isinstance(config.quantization_config, ComponentQuantizationConfig)
assert config.quantization_config.component_configs["transformer"].get_name() == "fp8"
assert config.quantization_config.component_configs["vae"] is None
def test_transformer_config_auto_detects_modelopt_fp8():
from vllm.model_executor.layers.quantization.modelopt import ModelOptFp8Config
from vllm_omni.diffusion.data import TransformerConfig
config = TransformerConfig.from_dict(
{
"_class_name": "FluxTransformer2DModel",
"quantization_config": {
"quant_method": "modelopt",
"quant_algo": "FP8",
"ignore": ["proj_out"],
},
}
)
assert isinstance(config.quant_config, ModelOptFp8Config)
assert config.quant_method == "modelopt"
def test_supported_methods_includes_vllm():
from vllm_omni.quantization import SUPPORTED_QUANTIZATION_METHODS
for method in ["fp8", "awq", "gptq", "bitsandbytes", "modelopt"]:
assert method in SUPPORTED_QUANTIZATION_METHODS, f"{method} missing"
def test_supported_methods_count():
from vllm_omni.quantization import SUPPORTED_QUANTIZATION_METHODS
assert len(SUPPORTED_QUANTIZATION_METHODS) >= 20
def test_per_component_routing_with_resolve():
"""Verify resolve() routes correctly by prefix."""
from vllm_omni.quantization import ComponentQuantizationConfig, build_quant_config
config = build_quant_config(
{
"transformer": {"method": "fp8"},
"vae": None,
}
)
assert isinstance(config, ComponentQuantizationConfig)
assert config.resolve("transformer.blocks.0.attn.to_q") is not None
assert config.resolve("transformer.blocks.0.attn.to_q").get_name() == "fp8"
assert config.resolve("vae.encoder.conv_in") is None
assert config.resolve("unknown.layer.0.weight") is None
def test_per_component_routing_with_default():
"""Verify default config applies to unmatched prefixes."""
from vllm_omni.quantization import ComponentQuantizationConfig, build_quant_config
config = build_quant_config(
{
"vae": None,
"default": "fp8",
}
)
assert isinstance(config, ComponentQuantizationConfig)
assert config.resolve("vae.decoder.conv") is None
resolved = config.resolve("transformer.blocks.0.attn")
assert resolved is not None
assert resolved.get_name() == "fp8"
@pytest.mark.parametrize("quant_algo", ["FP8"], ids=["modelopt_fp8"])
def test_omni_convertor_thinker_finds_text_config_quant(quant_algo):
"""Thinker stage should discover quantization_config from
thinker_config.text_config for verified modelopt FP8 checkpoints."""
from types import SimpleNamespace
from vllm_omni.config.model import OmniModelArchConfigConvertor
text_config = SimpleNamespace(
quantization_config={
"quant_method": "modelopt",
"quant_algo": quant_algo,
"ignore": ["lm_head", "model.layers.0.mlp.gate"],
},
model_type="qwen3_moe",
)
thinker_config = SimpleNamespace(text_config=text_config)
hf_config = SimpleNamespace(
thinker_config=thinker_config,
talker_config=SimpleNamespace(text_config=SimpleNamespace()),
model_type="qwen3_omni_moe",
)
convertor = OmniModelArchConfigConvertor(hf_config, text_config, stage_config_name="thinker_config")
quant_cfg = convertor.get_quantization_config()
assert quant_cfg is not None
assert quant_cfg["quant_method"] == "modelopt"
assert "lm_head" in quant_cfg["ignore"]
def test_omni_convertor_talker_returns_none():
"""Talker stage should get no quantization config when its text_config
has no quantization_config (talker weights are BF16)."""
from types import SimpleNamespace
from vllm_omni.config.model import OmniModelArchConfigConvertor
talker_text_config = SimpleNamespace(model_type="qwen3_omni_moe_talker")
talker_config = SimpleNamespace(text_config=talker_text_config)
hf_config = SimpleNamespace(
talker_config=talker_config,
model_type="qwen3_omni_moe",
)
convertor = OmniModelArchConfigConvertor(hf_config, talker_text_config, stage_config_name="talker_config")
quant_cfg = convertor.get_quantization_config()
assert quant_cfg is None
def test_omni_convertor_no_stage_name_falls_back():
"""Without stage_config_name, should fall back to base behavior."""
from types import SimpleNamespace
from vllm_omni.config.model import OmniModelArchConfigConvertor
hf_config = SimpleNamespace(model_type="qwen3_omni_moe")
text_config = SimpleNamespace()
convertor = OmniModelArchConfigConvertor(hf_config, text_config)
quant_cfg = convertor.get_quantization_config()
assert quant_cfg is None
def test_multi_component_model_routing():
"""Integration test: walk a multi-component model and verify per-component
quantization routes resolve() correctly for every linear layer."""
from vllm_omni.quantization import ComponentQuantizationConfig, build_quant_config
# Build a mock multi-stage model mimicking Bagel/Qwen3-Omni layout
class MockTransformerBlock(nn.Module):
def __init__(self):
super().__init__()
self.attn_q = nn.Linear(64, 64)
self.attn_k = nn.Linear(64, 64)
self.mlp = nn.Linear(64, 256)
class MockVAEBlock(nn.Module):
def __init__(self):
super().__init__()
self.conv = nn.Linear(64, 64)
class MockMultiStageModel(nn.Module):
def __init__(self):
super().__init__()
self.transformer = nn.ModuleDict(
{
"block_0": MockTransformerBlock(),
"block_1": MockTransformerBlock(),
}
)
self.vae = nn.ModuleDict(
{
"encoder": MockVAEBlock(),
"decoder": MockVAEBlock(),
}
)
model = MockMultiStageModel()
config = build_quant_config(
{
"transformer": {"method": "fp8", "activation_scheme": "dynamic"},
"vae": None,
}
)
assert isinstance(config, ComponentQuantizationConfig)
for name, module in model.named_modules():
if isinstance(module, nn.Linear):
resolved = config.resolve(name)
if name.startswith("transformer"):
assert resolved is not None, f"{name} should be quantized"
assert resolved.get_name() == "fp8"
elif name.startswith("vae"):
assert resolved is None, f"{name} should NOT be quantized"