# PR #48785 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Bugfix] Fix activation quantization dispatch for WNA4Int/WNA8Int
- 合并时间：2026-07-17 05:13
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/48785

---

# 执行摘要

- 一句话：修复 Humming WNA4Int/WNA8Int 激活量化调度 bug
- 推荐动作：值得精读。虽然改动量小，但揭示了 Humming 量化路径中 schema 分发设计的隐蔽 bug，对理解量化配置的工厂方法与继承路由有参考价值。建议在后续 PR 中补充 vllm 内的单元测试，覆盖 `BaseInputSchema.from_config` 的分发逻辑。

# 功能与动机

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 激活量化实际未生效。

# 实现拆解

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.py` 和 `compressed_tensors_wNa8.py` 的 `_build_input_quant_config`**：将 `format` 字段从 `self.quant_format`（可能含 `pack-quantized`）硬编码为 `"int-quantized"`，因为 `CompressedTensorsInputSchema` 的断言只接受 `int-quantized` 或 `nvfp4-pack-quantized`。此变更避免了向上游依赖（humming 库）打补丁的等待时间。

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

关键文件：
- `vllm/model_executor/layers/quantization/utils/humming_utils.py`（模块 量化工具；类别 source；类型 data-contract；符号 prepare_humming_layer）: 核心修复文件：将 `HummingInputSchema.from_config` 替换为 `BaseInputSchema.from_config`，并新增 `input_schema.convert_humming` 调用，确保输入量化配置能正确路由到 `CompressedTensorsInputSchema`。
- `vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa4.py`（模块 量化方案；类别 source；类型 data-contract；符号 _build_input_quant_config）: 修改 `_build_input_quant_config` 返回的 `format` 字段从 `self.quant_format` 改为硬编码 `"int-quantized"`，以兼容 `CompressedTensorsInputSchema` 的格式断言。
- `vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa8.py`（模块 量化方案；类别 source；类型 data-contract；符号 _build_input_quant_config）: 与 compressed_tensors_wNa4.py 完全相同的问题和修复，需要保持对称。

关键符号：prepare_humming_layer, _build_input_quant_config

## 关键源码片段

### `vllm/model_executor/layers/quantization/utils/humming_utils.py`

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

```python
# vllm/model_executor/layers/quantization/utils/humming_utils.py

def 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`

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

```python
# vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa4.py

def _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",
    }

```

# 评论区精华

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

- 暂无高价值评论线程

# 风险与影响

- 风险：风险较低。变更仅涉及三个源文件，改动量小（+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 分发逻辑变更 , 缺少测试覆盖

# 关联脉络

- 暂无明显关联 PR