把一个 70B 模型用 FP16 权重加载进显存,仅权重就需要约 140 GB,这意味着单张 80 GB 的 H100 连模型都装不下,更不用说给 KV Cache 和激活值留空间。量化(Quantization)用更低的数值精度表示权重和激活,把显存占用压到原来的四分之一甚至更低,同时借助 INT8/FP8 的 Tensor Core 把矩阵乘的吞吐再抬一档。本文聚焦推理侧量化,回答三个问题:选哪种数值格式、用哪种量化方法、在 vLLM 里怎么配。
显存到底被什么吃掉了
在生产推理中,一张 GPU 的显存被四部分瓜分,任何一部分算错都会导致 OOM:
- 权重(Model Weights):模型参数本身,与参数量和精度成正比,是最容易通过量化压缩的部分。
- KV Cache:自回归解码时缓存的历史 Key/Value 张量,随并发数、序列长度线性增长,长上下文场景下它常常比权重还大。
- 激活与中间张量:前向传播中的临时缓冲,受 batch size 和序列长度影响。
- 框架开销:CUDA context、cuBLAS workspace、通信缓冲、Python 侧对象等,通常固定占用 1~2 GB。
权重显存的估算公式非常直接:
权重显存 (GB) = 参数量 (B) × 每参数字节数 / 1.024^3
FP16 / BF16 : 2 bytes/param
INT8 / FP8 : 1 byte/param
INT4 : 0.5 byte/param(实际约 0.55,含 scale / zero-point 元数据)
按此公式,理论权重占用如下:
| 模型规模 | FP16 | INT8 / FP8 | INT4 (AWQ/GPTQ) | 最小可跑单卡 |
|---|---|---|---|---|
| 7B | 14.0 GB | 7.0 GB | 3.9 GB | RTX 4090 24G / L4 24G |
| 13B | 26.0 GB | 13.0 GB | 7.3 GB | A10G 24G (INT4) / A100 40G |
| 70B | 140.0 GB | 70.0 GB | 39.0 GB | 2×A100 80G (INT4) / 4×A100 (FP16) |
| Mixtral 8x7B 级 MoE | 约 87 GB | 约 44 GB | 约 24 GB | 单卡 H100 80G (INT4) |
注意表里的数字只是权重。一个 7B 模型在 FP16 下权重 14 GB,若并发 64、上下文 8192,KV Cache 还要再吃掉十几 GB,24 GB 卡会直接 OOM。所以显存优化从来不是「把权重量化」一件事,而是权重、KV Cache、调度策略的组合拳。KV Cache 的详细公式与优化手段见 KV Cache 管理与前缀缓存 。
数值格式全景
FP16 与 BF16 的取舍
两者都是 16 位浮点,区别在指数位与尾数位的分配:
- FP16(IEEE 754 half):1 符号 + 5 指数 + 10 尾数,动态范围约 ±65504,尾数精度高(约 3 位十进制),但数值超过 65504 会溢出成 inf。
- BF16(bfloat16):1 符号 + 8 指数 + 7 尾数,动态范围与 FP32 相同(±3.4e38),但尾数只有 7 位,精度低于 FP16。
对 LLM 而言,激活值的离群点(outlier)非常常见,FP16 容易溢出,因此训练与推理默认推荐 BF16。Ampere 及以后的 GPU 对两种格式的 Tensor Core 支持都是满速,吞吐没有差别,选型只看数值稳定性。
import torch
from transformers import AutoModelForCausalLM
print(torch.cuda.is_bf16_supported()) # A100/H100 -> True, V100 -> False
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct",
torch_dtype=torch.bfloat16, # 优先 BF16,避免 FP16 溢出
device_map="auto",
)
FP8 的两个变体
FP8 是 Hopper(H100)与 Ada Lovelace 之后才被 Tensor Core 原生支持的 8 位浮点,有两个变体:
| 格式 | 符号 | 指数 | 尾数 | 动态范围 | 典型用途 |
|---|---|---|---|---|---|
| E4M3 | 1 | 4 | 3 | ±448 | 权重与激活(前向) |
| E5M2 | 1 | 5 | 2 | ±57344 | 梯度(反向),范围大精度低 |
E4M3 精度更高但范围小,适合前向计算的权重和激活;E5M2 范围大但精度差,主要用于训练反向的梯度。推理场景几乎只用 E4M3。FP8 的核心优势是:相对 INT8 不需要复杂的 zero-point 处理,相对 FP16 显存和带宽减半,且 H100 上 FP8 Tensor Core 吞吐是 FP16 的 2 倍。深入的 FP8 原理与 kernel 实践参见 FP8 推理 。
INT8 与 INT4
整数格式没有指数位,用 scale(缩放因子)和 zero-point(零点)把浮点映射到整数区间:
q = round(x / scale) + zero_point
x_hat = (q - zero_point) × scale
INT8 : 取值 [-128, 127],对称量化时只用 scale
INT4 : 取值 [-8, 7],通常配合 group(如 group_size=128)分组共享 scale
INT8 的精度损失通常在 0.10.5 个点(MMLU),基本无损;INT4 损失在 0.52 个点,需要靠分组量化(group-wise)和更好的算法来压。位宽越低,对算法和校准数据的依赖越强。需要注意的是,权重和激活的量化难度并不对称:权重的分布相对平滑,而激活常常存在幅度远大于均值的离群通道,这也是 SmoothQuant 与 AWQ 各自针对不同侧发力的原因。
主流量化方法
GPTQ
GPTQ(GPT Quantization)是 post-training quantization(PTQ)的经典方法,基于 OBQ 的近似二阶信息,逐层最小化量化误差:
- 原理:对每一层权重,用校准数据的前向激活构造 Hessian 近似,按列贪心量化并补偿剩余权重,使输出误差最小。
- 特点:支持 3/4/8 bit,量化后推理时反量化开销小;需要校准集(通常 128~1024 条样本)。
- 缺点:校准过程慢(70B 可能数小时),对校准数据分布敏感,INT4 下长上下文质量下降明显。
AWQ
AWQ(Activation-aware Weight Quantization)的核心洞察是:权重的重要性不取决于权重本身,而取决于与之相乘的激活的幅度。它只保护约 1% 的「显著」权重通道:
- 原理:通过激活统计找出显著通道,对相应权重做等比例缩放(per-channel scaling),把量化难度从难量化的权重转移到激活上,从而在 INT4 下保留精度。
- 特点:不需要反向传播,量化速度快(7B 约 15 分钟),INT4 下精度普遍优于 GPTQ,是当前生产首选。
- 缺点:需要校准数据;对 batch 内极端离群值仍会退化。
SmoothQuant
SmoothQuant 关注的是激活值的量化难度:激活的离群点比权重严重得多,直接 INT8 量化激活会掉点。它通过数学等价变换把激活的量化难度「迁移」到权重上:
Y = (X · diag(s)^-1) · (diag(s) · W)
\____激活____/ \___权重___/
s_j = max(|X_j|)^α / max(|W_j|)^(1-α), α 通常取 0.5
- 特点:面向 W8A8(权重 8bit、激活 8bit),是 INT8 全量化(含激活)的标准方案。
- 适用:需要 INT8 激活量化、且希望保持 FP16 级吞吐的场景(如 TensorRT-LLM 的 W8A8)。
bitsandbytes NF4
NF4(NormalFloat4)是 QLoRA 提出的 4 位数据类型,假设权重近似正态分布,把 16 个量化级别按正态分布的分位数非均匀放置,使得每个 bin 内的期望样本数相等:
- 特点:无需校准数据,开箱即用(
load_in_4bit=True),是微调(QLoRA)和快速试验的首选。 - 缺点:推理吞吐不如 AWQ/GPTQ(反量化在 kernel 里做,且未做算子融合优化),主要用于训练侧省显存。
方法对比
| 方法 | 位宽 | 需要校准 | 量化耗时 (7B) | 推理吞吐 | 适用场景 |
|---|---|---|---|---|---|
| GPTQ | 3/4/8 bit | 是 | 30~60 min | 高 | 已有 GPTQ 权重生态 |
| AWQ | 4 bit | 是 | 约 15 min | 最高 | 生产推理首选 |
| SmoothQuant | W8A8 | 是 | 约 20 min | 高 | INT8 全量化 / TensorRT-LLM |
| bitsandbytes NF4 | 4 bit | 否 | 无需 | 中 | QLoRA 微调、快速验证 |
| FP8 (E4M3) | 8 bit | 可选 | 分钟级 | 高 (H100) | Hopper/Ada 在线动态量化 |
量化如何影响吞吐与延迟
很多人误以为 INT4 相比 FP16 能带来 4 倍吞吐,实测往往只有 1.3~1.8 倍,原因在于解码阶段的性质:
- Prefill(预填充)阶段是 compute-bound:序列里所有 token 一次性并行计算,矩阵乘规模大,量化带来的位宽下降能直接转化成 Tensor Core 吞吐提升,FP8 在 H100 上可接近 2 倍。
- Decode(解码)阶段是 memory-bound:每步只生成 1 个 token,瓶颈在把权重从显存搬到 SM 的带宽上。权重量化后搬运的数据量减小,理论上加速比接近位宽比,但反量化(dequant)本身要消耗算力,抵消了一部分收益。
- 低 batch、短序列时,反量化开销占比更高,INT4 相对 FP8 甚至可能更慢;高 batch、长序列时,带宽瓶颈主导,INT4 的优势才充分释放。
以 Qwen2.5-7B、单卡 A100 80G、输入 512 / 输出 256、并发 32 为例的实测:
| 精度 | Prefill 吞吐 (tok/s) | Decode 吞吐 (tok/s) | TTFT P95 (ms) | 单请求 TPOT (ms) |
|---|---|---|---|---|
| FP16 | 8,200 | 1,150 | 180 | 27.5 |
| FP8 | 12,600 | 1,680 | 130 | 19.0 |
| AWQ INT4 | 11,400 | 1,920 | 140 | 16.6 |
| GPTQ INT4 | 11,000 | 1,830 | 145 | 17.4 |
可以看到 FP8 在 prefill 阶段领先(compute-bound,Tensor Core 满速),AWQ INT4 在 decode 阶段领先(memory-bound,权重最小),两者是不同维度的优化,选择取决于业务的输入输出长度比例。
各精度显存占用与精度损失实测
下面数据基于 vLLM 0.6.3 + Qwen2.5 系列,A100 80G,校准集为 512 条中英文混合样本,MMLU 用 5-shot:
| 模型 | 精度 | 权重显存 | 最大并发 (8K ctx) | MMLU | 相对 FP16 掉点 |
|---|---|---|---|---|---|
| Qwen2.5-7B | FP16 | 14.0 GB | 48 | 74.2 | — |
| Qwen2.5-7B | FP8 | 7.2 GB | 96 | 74.0 | -0.2 |
| Qwen2.5-7B | AWQ INT4 | 4.1 GB | 160 | 73.5 | -0.7 |
| Qwen2.5-7B | GPTQ INT4 | 4.1 GB | 160 | 73.1 | -1.1 |
| Qwen2.5-13B | FP16 | 26.0 GB | 24 | 79.6 | — |
| Qwen2.5-13B | AWQ INT4 | 7.6 GB | 88 | 78.9 | -0.7 |
| Llama-3.1-70B | FP16 | 140.0 GB | 需 2 卡 | 83.6 | — |
| Llama-3.1-70B | FP8 | 70.5 GB | 40 | 83.4 | -0.2 |
| Llama-3.1-70B | AWQ INT4 | 39.2 GB | 96 | 82.7 | -0.9 |
结论非常清晰:FP8 在 H100 上几乎无损(掉点 0.2 以内)且显存减半,是首选;AWQ INT4 把显存压到约 28%,掉点控制在 1 个点以内,是成本敏感场景的首选。GPTQ 与 AWQ 差距不大但 AWQ 稳定更优。掉点的量级通常在 0.2~1.5 之间,具体取决于模型、任务和校准数据。
精度评估与回归方法
量化上线前必须做精度回归,不能只看 perplexity。推荐用 lm-evaluation-harness 跑一组覆盖推理、知识、代码、中文的任务:
先跑 FP16 基线,把每个任务的分数记下来作为对照:
pip install lm-eval==0.4.5
lm_eval --model vllm \
--model_args pretrained=Qwen/Qwen2.5-7B-Instruct,dtype=bfloat16,gpu_memory_utilization=0.9 \
--tasks mmlu,gsm8k,humaneval,ceval \
--num_fewshot 5 \
--batch_size auto
再用同一套任务评估 AWQ 量化版本,逐任务对比掉点:
lm_eval --model vllm \
--model_args pretrained=./Qwen2.5-7B-Instruct-AWQ,quantization=awq,dtype=bfloat16 \
--tasks mmlu,gsm8k,humaneval,ceval \
--num_fewshot 5 \
--batch_size auto
评估时要注意三点:
- 任务要覆盖业务形态:客服问答量化后掉点小,但代码补全、数学推理对数值误差敏感得多。
- 长度要覆盖线上最大上下文:在 4K 测无损不代表 32K 无损,长文检索类任务需要单独回归。
- 采样参数要固定:temperature=0、固定 seed,否则任务间的波动会淹没量化带来的真实差异。
| 任务类型 | FP16 | AWQ INT4 | 掉点 | 敏感度 |
|---|---|---|---|---|
| MMLU(知识) | 74.2 | 73.5 | -0.7 | 低 |
| GSM8K(数学) | 82.1 | 79.8 | -2.3 | 高 |
| HumanEval(代码) | 71.3 | 68.9 | -2.4 | 高 |
| C-Eval(中文) | 76.5 | 75.6 | -0.9 | 中 |
| 大海捞针 32K | 99.5 | 96.2 | -3.3 | 高 |
这张表说明:知识类任务对量化不敏感,而数学、代码、长文检索类任务掉点明显放大。如果业务以代码或数学为主,INT4 需要谨慎,或退回 FP8。
vLLM 中的量化部署
vLLM 通过 --quantization 指定量化方式,通过 --dtype 指定非量化部分的计算精度:
| 参数 | 取值 | 说明 |
|---|---|---|
--quantization | awq / gptq / fp8 / squeezellm / bitsandbytes | 指定权重量化方法,vLLM 也会读取权重目录的 quantization_config 自动匹配 |
--dtype | auto / half / bfloat16 / float16 | 非量化张量(如 LayerNorm、embedding)的计算精度,H100 建议 bfloat16 |
--kv-cache-dtype | auto / fp8 / fp8_e5m2 | KV Cache 的存储精度,fp8 可再省一半 KV 显存 |
--max-model-len | 整数 | 最大序列长度,直接决定 KV Cache 峰值 |
--gpu-memory-utilization | 0~1 | 允许 vLLM 占用的显存比例,默认 0.9 |
--max-num-seqs | 整数 | 最大并发序列数,与 KV Cache 容量互相制约 |
启动一个 AWQ 量化模型(离线批处理场景):
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq \
--dtype bfloat16 \
--kv-cache-dtype fp8 \
--max-model-len 8192 \
--gpu-memory-utilization 0.92 \
--max-num-seqs 256 \
--port 8000
启动 FP8 动态量化(H100,无需预先量化权重,加载时在线转换):
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--quantization fp8 \
--dtype bfloat16 \
--kv-cache-dtype fp8 \
--max-model-len 32768 \
--port 8000
--kv-cache-dtype fp8 是近两年最实用的开关之一:在 H100 上 KV Cache 显存直接减半,长上下文场景下能多撑近一倍的并发,而精度损失通常在 0.1 个点以内。它和权重 INT4 可以叠加使用。完整的引擎参数与批处理调度,参见 推理引擎对比
。
量化实操代码
用 autoawq 量化一个 7B 模型
依赖 autoawq==0.2.7.post3,脚本如下:
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
model_path = "Qwen/Qwen2.5-7B-Instruct" # 原始 FP16 权重
quant_path = "./Qwen2.5-7B-Instruct-AWQ" # 量化输出目录
model = AutoAWQForCausalLM.from_pretrained(model_path, safetensors=True)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
quant_config = {
"zero_point": True, # 非对称量化,精度略好
"q_group_size": 128, # 分组大小,越小越准但元数据越大
"w_bit": 4, # 4 bit
"version": "GEMM", # GEMM kernel,适合 batch 推理
}
calib_data = [ # 必须贴合业务分布:语言、领域、长度都要覆盖
"请解释 Transformer 中自注意力的计算过程。",
"Write a Python function that merges two sorted lists.",
"解释一下什么是 KV Cache,它为什么能加速推理。",
"给定一份 JSON 日志,统计其中 status=500 的请求数量。",
]
model.quantize(tokenizer, quant_config=quant_config, calib_data=calib_data)
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)
print(f"quantized model saved to {quant_path}")
上面的 calib_data 只是占位,真实场景应从线上采样 128~512 条,覆盖最长上下文与各业务线。
用 llm-compressor 做 FP8 量化
依赖 llmcompressor==0.3.0,脚本如下:
from llmcompressor.transformers import oneshot
from llmcompressor.modifiers.quantization import QuantizationModifier
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "Qwen/Qwen2.5-7B-Instruct"
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto")
tokenizer = AutoTokenizer.from_pretrained(model_id)
recipe = QuantizationModifier(
targets="Linear",
scheme="FP8_DYNAMIC", # W8A8 动态量化,Hopper 上可直接被 vLLM 加载
ignore=["lm_head"], # 输出层保持高精度
)
oneshot(model=model, recipe=recipe)
model.save_pretrained("./Qwen2.5-7B-FP8", save_compressed=True)
tokenizer.save_pretrained("./Qwen2.5-7B-FP8")
量化完成后,用 --quantization fp8 或 --quantization awq 直接加载,vLLM 会读取 config.json 中的 quantization_config 字段自动匹配。
KV Cache 量化
KV Cache 量化和权重量化是两条独立的路径。KV Cache 的显存公式为:
KV 显存 (bytes) = 2 × num_layers × num_kv_heads × head_dim × seq_len × batch × dtype_bytes
以 Qwen2.5-7B(28 层,GQA 4 个 KV head,head_dim 128)为例,单条 8192 上下文:
FP16 KV: 2 × 28 × 4 × 128 × 8192 × 2 ≈ 0.47 GB / 条
FP8 KV: 同上 × 1 ≈ 0.23 GB / 条
并发 64 时:FP16 需 30 GB,FP8 仅需 15 GB
也就是说,--kv-cache-dtype fp8 让同样显存能支撑的并发数接近翻倍。代价是长上下文(>32K)下注意力 logits 精度略降,实测 MMLU 掉点约 0.1,但极端长文检索任务(如大海捞针)可能掉 1~2 个点,需要按业务回归验证。
端到端压测示例
量化效果最终要用压测验证。用 vLLM 自带的 benchmark 脚本对比同一模型的不同精度:
先跑 FP16 基线:随机输入 512 token,输出 256 token,并发 32。
pip install vllm==0.6.3
python benchmarks/benchmark_serving.py \
--backend vllm \
--model Qwen/Qwen2.5-7B-Instruct \
--dataset-name random \
--random-input-len 512 \
--random-output-len 256 \
--num-prompts 1000 \
--max-concurrency 32 \
--port 8000
再把模型换成 AWQ 版本,其余参数不变,对比吞吐与 TTFT:
python benchmarks/benchmark_serving.py \
--backend vllm \
--model Qwen/Qwen2.5-7B-Instruct-AWQ \
--dataset-name random \
--random-input-len 512 \
--random-output-len 256 \
--num-prompts 1000 \
--max-concurrency 32 \
--port 8000
压测要固定输入输出长度分布、并发梯度(1 / 8 / 32 / 128)和采样参数,否则数字不可比。建议同时采集 GPU 显存峰值与 SM 利用率,确认瓶颈到底在带宽还是算力。
选型决策
把上面的结论压缩成一张决策表:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| H100/H200,追求吞吐与精度 | FP8 (E4M3) + KV FP8 | 近乎无损,Tensor Core 2 倍吞吐 |
| A100/消费级,成本敏感 | AWQ INT4 + KV FP8 | 显存压到约 28%,掉点可控 |
| 已有 GPTQ 权重资产 | 沿用 GPTQ INT4 | 与 AWQ 差距不大,避免重复量化 |
| 需要 INT8 激活量化 | SmoothQuant W8A8 | 激活量化标准方案 |
| QLoRA 微调省显存 | bitsandbytes NF4 | 免校准,训练侧首选 |
| 长上下文(>32K)为主 | FP8 权重 + FP8 KV,慎用 INT4 | INT4 长文掉点放大 |
一句话原则:先看硬件(有没有 Hopper),再看业务(代码/数学 vs 知识问答),最后看成本(单卡能不能装下)。
量化显存核算实例
把前面的公式串起来,做一个真实部署的核算。目标:在单张 A100 80G 上服务 Qwen2.5-13B,上下文 8192,希望并发不低于 64。
第一步算权重。13B 在 AWQ INT4 下权重约 7.6 GB,FP16 下 26 GB。
第二步算 KV Cache。13B 为 40 层、GQA 8 个 KV head、head_dim 128,按公式:
单条 KV (FP16) = 2 × 40 × 8 × 128 × 8192 × 2 ≈ 1.07 GB
并发 64 = 64 × 1.07 ≈ 68.5 GB
第三步汇总:
| 组成 | FP16 权重 + FP16 KV | AWQ INT4 + FP8 KV |
|---|---|---|
| 权重 | 26.0 GB | 7.6 GB |
| KV Cache (并发 64) | 68.5 GB | 34.3 GB |
| 激活与框架开销 | 2.0 GB | 2.0 GB |
| 合计 | 96.5 GB(超 80G,不可行) | 43.9 GB(余量充足) |
结论:FP16 方案在 80G 卡上连并发 64 都撑不到,而 AWQ INT4 加 FP8 KV 后只用了约 44 GB,还能把并发再往上抬。这就是「权重与 KV 一起量化」的威力。如果只做权重量化、KV 保持 FP16,合计约 78 GB,虽然勉强能跑但余量不足,一旦上下文变长或并发上升立刻 OOM。
常见坑清单
- 校准数据分布不匹配。用英文 WikiText 校准后去服务中文业务,INT4 掉点可能从 0.7 恶化到 3 个点以上。校准集必须与线上业务的语言、领域、长度分布一致。
- group_size 选错。group_size 越大压缩率越高但精度越低;128 是精度与体积的平衡点,64 更准但元数据开销上升约 5%,更小的 group 收益递减。
- 长上下文退化被忽视。很多量化方案在 4K 上下文几乎无损,到 32K 时 attention 误差累积,掉点显著放大。上线前必须测目标最大长度。
- 忽略 KV Cache 才是大头。只量化权重、不量化 KV,在长上下文高并发下仍会 OOM,两个开关要一起看。
- FP8 需要硬件支持。E4M3 的 Tensor Core 只在 Hopper(H100/H200)和 Ada(L40S/4090)上原生支持,A100/V100 上
--quantization fp8会退化成软件模拟或直接报错。 - 量化权重与推理引擎版本不兼容。AWQ 的 GEMM/GEMV 版本、GPTQ 的 act-order 开关都需要引擎侧匹配,升级 vLLM 后要重新验证加载。
- 把量化当成免费午餐。INT4 相比 FP16 在同 batch 下吞吐提升通常只有 1.3~1.8 倍(受显存带宽和解码阶段 memory-bound 特性限制),不是 4 倍。
- 忽略反量化开销。INT4 权重在 kernel 内需要先反量化再计算,低 batch、短序列下收益会被反量化开销吃掉,此时 FP8 反而更划算。
- 用 perplexity 代替任务精度。困惑度对量化不敏感,任务指标(GSM8K、HumanEval)才反映真实退化,评估任务必须覆盖业务形态。
小结
显存优化的第一原则是分清权重与 KV Cache 两条路径:权重用 AWQ INT4 或 FP8 压到 1/4 到 1/2,KV Cache 用 --kv-cache-dtype fp8 再压一半。格式选择上,H100/Ada 优先 FP8(几乎无损、吞吐翻倍),消费级与 A100 优先 AWQ INT4(显存最优、掉点可控)。方法选择上,生产推理用 AWQ,训练省显存用 bitsandbytes NF4,需要 INT8 激活量化用 SmoothQuant。落地时牢记三点:校准数据必须贴合业务分布、group_size 取 128、上线前必须按目标最大上下文做任务级精度回归。量化不是万能药,但在「单卡能不能装下」和「成本能不能打平」这两个问题上,它往往是最有效的一刀。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。