文章

LLM 权重量化上线生产实战:用校准集指纹、Kernel 兼容矩阵与双轨回放守住质量和吞吐

深入拆解 LLM 权重量化从实验到生产落地的完整链路,涵盖 AWQ/GPTQ 算法对比、校准集指纹构建、四层兼容模型、Kernel 兼容矩阵、质量与吞吐双轨回放及灰度发布回滚策略。

为什么量化模型”能跑”仍然可能上线失败

大模型权重量化经常从一个看似简单的目标开始:把 BF16 或 FP16 权重压缩为 INT8、INT4 或 FP8,让更大的模型装入更少的 GPU,并获得更高吞吐。

真正进入生产环境后,问题通常不在”量化命令能否执行”,而在以下四个错位:

  1. 模型文件变小,但服务显存没有按比例下降。 权重之外还有 KV Cache、激活、CUDA Graph、通信缓冲区和运行时工作区。
  2. 模型能够加载,但没有命中高效 Kernel。 相同的”INT4”可能对应不同打包布局、group size、zero-point 规则和后端实现。
  3. 通用基准变化很小,但业务任务明显退化。 代码、数学、长文本、结构化抽取和多语言任务对量化误差的敏感度不同。
  4. 同名模型无法复现。 基座 revision、Tokenizer、校准集、量化工具版本或权重打包方式发生变化后,生成的新制品并不是原来的模型。

因此,生产量化不应被当作启动参数,而应被视为一条独立的模型制品派生、验证和发布流水线

先明确量化边界:本文讨论的是权重,不是 KV Cache

量化对象不同,风险与收益也不同。

量化对象常见形式主要收益主要风险
权重W8A16、W4A16降低模型常驻显存和权重读取带宽精度退化、打包格式与 Kernel 不兼容
权重与激活W8A8、W4A8进一步降低计算和带宽成本激活离群值更难处理,硬件要求更强
KV CacheFP8、INT8、INT4降低长上下文和高并发时的缓存占用长上下文质量与注意力误差

本文聚焦权重量化上线。它与近期常见的 KV Cache Quantization 不是同一问题:前者生成一个长期保存、需要版本治理的模型制品;后者主要改变每次请求执行期间的缓存表示。

AWQ 与 GPTQ 的核心差异

AWQ:用激活统计识别敏感通道

**AWQ(Activation-aware Weight Quantization)**的关键并不是简单地把所有权重映射到 4 bit,而是借助代表性输入采集激活统计,识别对输出更敏感的通道,并通过等价缩放降低这些通道的量化误差。

这意味着 AWQ 制品至少依赖:

  • 基座模型和精确 revision;
  • Tokenizer 与 Chat Template;
  • 校准样本及其预处理方式;
  • bits、group size、zero point 和打包版本;
  • 量化工具及其版本。

GPTQ:按层控制权重重构误差

GPTQ 属于训练后量化方法,利用校准输入产生的统计信息,逐层寻找低比特权重,使量化层输出尽量接近原始层输出。工程实现通常还会绑定特定的权重布局和融合反量化 Kernel。

GPTQ 的生产风险不只来自算法本身,也来自:

  • 校准数据是否覆盖真实输入分布;
  • 量化工具是否支持当前模型结构;
  • 保存格式是否被目标推理引擎完整识别;
  • GPU 架构是否存在匹配的高效 Kernel。

不要把 AWQ 与 GPTQ 当成静态标签

同样标记为 AWQ 的两个模型,可能拥有不同 group size、打包格式和 Kernel 路径;同样标记为 GPTQ 的模型,也可能由不同工具链产生。生产系统真正需要识别的是完整量化配置指纹,而不是一个字符串标签。

量化上线的四层兼容模型

建议把一次量化部署拆成四层:

第一层:算法层

记录 AWQ、GPTQ、SmoothQuant 或其他方法,以及位宽、分组方式、对称或非对称量化、是否使用 zero point。

第二层:制品格式层

记录权重分片、Tensor 名称、scale 与 zero-point 的存储方式、packing layout、配置文件和模型类。算法相同不代表格式兼容。

第三层:Kernel 层

记录实际执行的 GEMM、融合反量化实现和后端,例如通用实现、Marlin 类 Kernel 或引擎自有 Kernel。模型能加载只证明存在一条执行路径,不证明该路径足够快。

第四层:硬件与运行环境层

记录 GPU 架构、驱动、CUDA、PyTorch、推理引擎和容器镜像。vLLM 的量化支持矩阵会按 Volta、Turing、Ampere、Ada、Hopper、AMD GPU、Intel GPU 和 CPU 区分;TensorRT-LLM 也按模型与硬件维护不同量化配方的支持范围。

工程落地:把量化模型建设成可追溯制品

1. 冻结未量化基线

量化前先冻结一个能够复现的基线:

  • 模型仓库与 commit/revision;
  • 权重文件 SHA-256;
  • Tokenizer 和 Chat Template 指纹;
  • 推理引擎、驱动、CUDA 和 GPU 型号;
  • 生成参数与停止条件;
  • 质量评测集和性能压测集版本。

如果基线本身在变化,后续无法判断差异来自量化、模型升级还是推理环境。

2. 建立校准集指纹

校准集不需要无限大,但必须代表线上输入。至少按以下维度分层采样:

  • 短、中、长输入;
  • 中文、英文及主要业务语言;
  • 普通问答、代码、数学、抽取、分类等任务;
  • System Prompt、工具 Schema 和业务模板;
  • 真实字符分布、特殊符号与结构化片段。

校准集与最终质量评测集必须隔离,避免把”适合校准样本”误判为”整体质量稳定”。

下面的示例用于生成校准集与配置的稳定指纹:

import hashlib
import json
from pathlib import Path
from typing import Any

def sha256_file(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as file:
        for chunk in iter(lambda: file.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()

def stable_hash(value: Any) -> str:
    payload = json.dumps(
        value,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
    ).encode("utf-8")
    return hashlib.sha256(payload).hexdigest()

manifest = {
    "base_model_revision": "<immutable-revision>",
    "tokenizer_hash": "<sha256>",
    "chat_template_hash": "<sha256>",
    "calibration_file_hash": sha256_file(Path("calibration.jsonl")),
    "quantization": {
        "method": "awq",
        "bits": 4,
        "group_size": 128,
        "zero_point": True,
    },
    "toolchain": {
        "quantizer": "<name-and-version>",
        "transformers": "<version>",
        "torch": "<version>",
    },
}

print(stable_hash(manifest))

不要在指纹中使用浮动标签,例如 mainlatest 或未固定版本的容器镜像。

3. 为量化制品保存完整 Manifest

artifact_id: llama-example-awq-w4a16-r3
base_model:
  repository: <model-repository>
  revision: <immutable-revision>
  weights_sha256: <sha256>
tokenizer:
  revision: <immutable-revision>
  fingerprint: <sha256>
calibration:
  dataset_id: production-calibration-2026-07
  fingerprint: <sha256>
  preprocessing_revision: <git-commit>
quantization:
  method: awq
  weight_bits: 4
  activation_dtype: bf16
  group_size: 128
  zero_point: true
  packing_format: <format-version>
runtime:
  engine: <engine-and-version>
  kernel_backend: <backend>
  gpu_architecture: <architecture>
  cuda: <version>
validation:
  quality_report: <report-id>
  performance_report: <report-id>
approval: <release-record>

这个 Manifest 应与权重一起发布,不能只存在于构建日志中。

双轨回放:质量门禁与性能门禁必须同时通过

质量轨

至少包含三类评测:

  1. 通用能力评测:用于识别大范围能力坍塌,但不能替代业务评测。
  2. 业务黄金集:使用真实任务指标,例如字段级 F1、执行通过率、分类准确率、人工偏好或规则校验成功率。
  3. 敏感切片:长输入、少数语言、代码、数学、边界格式及高价值客户场景。

不要只比较平均分。量化退化可能集中在一个低频但高风险切片中。

对于开放式生成,可组合以下方法:

  • 确定性任务优先使用精确指标;
  • 代码任务执行测试;
  • 抽取任务使用 Schema 和字段级校验;
  • 生成任务使用固定回放集、人工抽检和版本化评价规则;
  • 同时观察拒答率、截断率和格式失败率。

性能轨

性能测试必须覆盖真实请求分布,而不是只测试一个短 Prompt:

指标需要回答的问题
模型加载时间量化制品是否降低或增加启动成本
常驻显存权重节省是否被其他工作区抵消
TTFTPrefill 是否受反量化与 Kernel 影响
TPOTDecode 阶段是否真正获得加速
吞吐不同并发和输入输出长度下是否稳定
P95/P99 延迟是否出现少量请求严重变慢
GPU 利用率与带宽瓶颈是否从显存容量转为计算或内存带宽
错误与回退计数是否发生 Kernel fallback、OOM 或不支持算子

量化常常在内存带宽受限场景更有价值,但并不保证所有 GPU、批次和长度组合都更快。

Kernel 兼容矩阵:上线前必须做启动预检

推荐把下面这些字段做成机器可判定的准入规则:

  • GPU compute capability;
  • 驱动与 CUDA 版本;
  • 推理引擎版本;
  • 模型架构与层类型;
  • quant method、bits、group size、zero point;
  • packing format;
  • 目标 Kernel 是否可用;
  • 不支持时是否允许 fallback;
  • fallback 后的显存和延迟上限。

启动预检应返回明确结果:

  • PASS:optimized kernel selected
  • WARN:compatible fallback selected;canary only
  • FAIL:artifact/runtime combination unsupported

不要让不支持的组合进入流量后才通过 P99 延迟或 OOM 被动发现。

灰度发布与回滚

量化模型应与原始模型保持独立路由目标,并采用以下步骤:

  1. 离线回放:同一输入分别运行基线和量化模型,生成质量与性能差异报告。
  2. 影子流量:量化结果不返回用户,只记录差异和资源消耗。
  3. 低比例灰度:优先选择可容错、可自动校验的任务。
  4. 按切片扩大:按语言、任务、输入长度和租户逐步扩大,而不是只看总流量比例。
  5. 自动回滚:任一关键质量门禁、错误率或尾延迟越界时切回基线制品。

回滚单位必须是完整的 artifact_id + runtime profile。只把 quantization=awq 改回 none,可能仍然使用不同模型 revision、Tokenizer 或引擎版本,无法形成真正的基线回滚。

适用场景

权重量化通常适合:

  • 模型权重是 GPU 容量或内存带宽主要瓶颈;
  • 需要在固定 GPU 预算中部署更大模型或更多副本;
  • 请求量足以摊薄模型加载和编译成本;
  • 业务拥有可重复的质量评测集;
  • 推理引擎对目标模型、格式和 GPU 有成熟 Kernel 支持。

以下场景应谨慎:

  • 小模型本身已完全驻留且计算成为主要瓶颈;
  • 目标硬件只有通用反量化路径;
  • 业务缺少可验证的质量指标;
  • 极低比特设置用于高敏感代码、数学或精确抽取;
  • 模型、Tokenizer 和工具链频繁漂移,却没有制品版本治理。

常见误区

误区一:INT4 权重一定带来四倍端到端收益

权重位宽只是成本的一部分。scale、zero point、对齐填充、非量化层、KV Cache、激活和运行时工作区都会占用资源。端到端速度还取决于 Kernel 和负载形态。

误区二:模型能加载,就说明格式兼容

能加载可能只代表推理引擎找到了降级路径。必须确认实际 Kernel、是否发生在线转换、是否反复反量化,以及吞吐是否达到预期。

误区三:校准集越大越好

校准集的代表性通常比盲目扩大规模更重要。大量重复的普通问答,不能替代代码、长文本、特定语言或业务模板覆盖。

误区四:只看困惑度或一个通用榜单

量化误差可能对不同能力产生不均匀影响。生产判断必须加入业务黄金集、敏感切片和端到端规则校验。

误区五:量化制品可以跨硬件直接复制

权重数值可能可移植,但打包布局、融合 Kernel、支持矩阵和性能结论通常不能直接跨 GPU 架构复用。每个目标运行矩阵都要重新验证。

上线检查清单

制品与数据

  • 基座模型使用不可变 revision。
  • 权重、Tokenizer、Chat Template 均有 SHA-256 指纹。
  • 校准集已去重、分层并固定预处理版本。
  • 校准集与最终评测集相互隔离。
  • 量化配置和 packing format 已写入 Manifest。

兼容与性能

  • 已验证目标 GPU、驱动、CUDA 和推理引擎组合。
  • 已确认实际命中的 Kernel,而不是仅确认加载成功。
  • 已覆盖主要输入长度、输出长度和并发档位。
  • 已比较显存、TTFT、TPOT、吞吐和 P99。
  • 已记录 Kernel fallback、OOM 和不支持算子。

质量与发布

  • 通用评测、业务黄金集和敏感切片均通过门禁。
  • 已完成基线与量化模型的双轨回放。
  • 影子流量不向用户返回量化结果。
  • 灰度指标可以按模型、制品、Kernel、GPU 和任务切片。
  • 自动回滚可以恢复完整基线制品与运行配置。

参考资料

  1. vLLM Quantization Documentation
  2. Hugging Face Transformers — AWQ
  3. Hugging Face Transformers — GPTQ
  4. NVIDIA TensorRT-LLM — Quantization
  5. AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
  6. GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers
  7. Evaluating Quantized Large Language Models

常见问题

AWQ 和 GPTQ 哪一种更适合生产环境?
没有脱离模型、硬件和推理引擎的统一答案。应在相同基座模型、校准数据、GPU、并发和请求长度分布下,同时比较业务质量、显存、吞吐与尾延迟。
量化模型能够成功加载,是否代表已经获得性能收益?
不代表。推理引擎可能使用兼容但非最优的 Kernel,甚至发生反量化或后端回退。必须通过启动日志、Profiler 和同负载基准测试确认真实执行路径。
量化上线最重要的回滚单位是什么?
应回滚完整量化制品,而不是只切换一个 quantization 参数。完整制品包括基座版本、Tokenizer、校准集指纹、量化配置、权重文件、打包格式、Kernel 后端和运行环境。