Prhub

#48785 [Bugfix] Fix activation quantization dispatch for WNA4Int/WNA8Int

原始 PR 作者 HDCharles 合并时间 2026-07-17 05:13 文件变更 3 提交数 1 评论 1 代码增减 +13 / -6

执行摘要

修复 Humming WNA4Int/WNA8Int 激活量化调度 bug

PR body 明确指出两个问题:

1) HummingInputSchema.from_config 被子类调用时不会进入 BaseInputSchema.from_config 的分发分支,导致 CompressedTensorsInputSchema 不被使用,a_dtype 静默回退为 bfloat16
2) 修复后报错,因为 CompressedTensorsInputSchema 不接受 pack-quantized 格式,而 humming 路径传递了 self.quant_format(包含 pack-quantized)。根本原因是量化格式检查不匹配,导致 WNA4Int/WNA8Int 激活量化实际未生效。

值得精读。虽然改动量小,但揭示了 Humming 量化路径中 schema 分发设计的隐蔽 bug,对理解量化配置的工厂方法与继承路由有参考价值。建议在后续 PR 中补充 vllm 内的单元测试,覆盖 BaseInputSchema.from_config 的分发逻辑。

讨论亮点

讨论较少,核心决策由 PR 作者 HDCharles 在 body 中详细解释。mgoin 直接批准(状态 APPROVED),无 review 评论交互。

实现拆解

  1. 修改 humming_utils.py:prepare_humming_layer:将 HummingInputSchema.from_config(input_quant_config) 改为 BaseInputSchema.from_config(input_quant_config),确保输入量化配置能通过基类的 quant_method 分发正确路由到 CompressedTensorsInputSchema。同时新增对 input_schema.convert_humming 的调用,使输入 schema 也经过标准化转换(与权重 schema 流程对称)。

  2. 修改 compressed_tensors_wNa4.pycompressed_tensors_wNa8.py_build_input_quant_config:将 format 字段从 self.quant_format(可能含 pack-quantized)硬编码为 "int-quantized",因为 CompressedTensorsInputSchema 的断言只接受 int-quantizednvfp4-pack-quantized。此变更避免了向上游依赖(humming 库)打补丁的等待时间。

  3. 无测试文件变更:本次修复依赖外部 e2e 测试(llm-compressor PR#2821)验证效果,未在 vllm 仓库内新增单元测试。

文件 模块 状态 重要度
vllm/model_executor/layers/quantization/utils/humming_utils.py 量化工具 modified 6.27
vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa4.py 量化方案 modified 5.28
vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa8.py 量化方案 modified 5.28

关键符号

prepare_humming_layer _build_input_quant_config

关键源码片段

vllm/model_executor/layers/quantization/utils/humming_utils.py data-contract

核心修复文件:将 `HummingInputSchema.from_config` 替换为 `BaseInputSchema.from_config`,并新增 `input_schema.convert_humming` 调用,确保输入量化配置能正确路由到 `CompressedTensorsInputSchema`。

# vllm/model_executor/layers/quantization/utils/humming_utils.pydef prepare_humming_layer(
    layer: LinearBase,
    quant_config: dict,
    input_quant_config: dict | None = None,
):
    from vllm.utils.humming import (
        BaseInputSchema, # 新增导入:基类负责根据 quant_method 分发到正确的子类
        BaseWeightSchema,
        HummingInputSchema,
        HummingMethod,
    )
​
    weight_schema = BaseWeightSchema.from_config(quant_config)
    if input_quant_config is not None:
        # 修复前:HummingInputSchema.from_config(input_quant_config)
        # 原代码会绕过基类的 quant_method 分发,导致压缩张量配置静默失败
        # 修复后:使用 BaseInputSchema.from_config 确保路由到 CompressedTensorsInputSchema
        input_schema = BaseInputSchema.from_config(input_quant_config)
    else:
        input_schema = HummingInputSchema()
​
    # ... shape 计算省略 ...
​
    # Step 1: 转换权重和输入 schema 到 humming 标准格式
    weight_schema, tensors = weight_schema.convert_humming(
        tensors=dict(layer.named_parameters()),
        shape_n_stacks=shape_n_stacks,
        shape_k_stacks=shape_k_stacks,
        param_dtype=layer.params_dtype,
    )
    # 新增:输入 schema 也需要调用 convert_humming 以完成标准化
    # 这是因为 BaseInputSchema 的分发并未携带转换逻辑,需要显式执行
    input_schema, _ = input_schema.convert_humming(
        tensors={},
        shape_n_stacks=shape_n_stacks,
        shape_k_stacks=shape_k_stacks,
        param_dtype=layer.params_dtype,
    )
​
    layer.weight_schema = weight_schema
    # ... 后续处理保持不变 ...
vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa4.py data-contract

修改 `_build_input_quant_config` 返回的 `format` 字段从 `self.quant_format` 改为硬编码 `"int-quantized"`,以兼容 `CompressedTensorsInputSchema` 的格式断言。

# vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa4.pydef _build_input_quant_config(self) -> dict | None:
    """Build the config dict that BaseInputSchema.from_config expects."""
    if self.input_quant is None:
        return None
    iq = self.input_quant
    type_val = iq.type.value if hasattr(iq.type, "value") else iq.type
    strategy_val = (
        iq.strategy.value if hasattr(iq.strategy, "value") else iq.strategy
    )
    return {
        "num_bits": iq.num_bits,
        "type": type_val,
        "strategy": strategy_val,
        "symmetric": iq.symmetric,
        "dynamic": iq.dynamic,
        "group_size": iq.group_size or 0,
        "quant_method": "compressed-tensors",
        # 修复前使用 self.quant_format,可能包含 "pack-quantized"
        # CompressedTensorsInputSchema 不接受该格式,导致断言失败
        # 修复后硬编码为 "int-quantized",因为所有非 nvfp4 格式在此上下文中等价
        "format": "int-quantized",
    }

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险较低。变更仅涉及三个源文件,改动量小(+13/-6)。主要风险在于:

  • BaseInputSchema.from_config 的默认行为可能与 HummingInputSchema.from_config 不完全一致,但 PR 中已通过新增 convert_humming 调用弥补了缺失的转换步骤。
  • 硬编码 format"int-quantized" 假定了所有非 nvfp4 格式等价,若未来 humming 库新增其他格式判断逻辑,可能引入新兼容性问题。
  • 缺乏 vllm 仓库内的单元测试覆盖,回归风险依赖外部测试。

影响范围较小,仅影响使用 Humming 量化路径且带有激活量化(WNA4Int/WNA8Int)的模型加载。修复前这些模型静默退化为 WNA16 行为,导致激活量化未生效;修复后正确应用 4-bit 或 8-bit 激活量化。对仅用权重量化(WNA16)的模型无影响。

schema 分发逻辑变更 缺少测试覆盖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论