量化会破坏 LLM 工具调用能力吗?在4GB笔记本GPU上的实测报告
"Q4 对工具调用安全吗?"这个问题在本地 LLM 圈子中反复被提起,而答案几乎都是基于个例——在某一个模型上跑了几百个 agent 小时,然后推广到所有情况。我想要一个基准测试,其中每个降级声明都来自对配对逐种子的差异本身进行 bootstrap 推断,而不是凭肉眼判断两个置信区间是否恰好重叠。所以我构建了一个:QuantCall。
没有使用云 GPU——以下所有内容都在我自己的硬件上运行,一台搭载 RTX 3050 Laptop、4096 MiB VRAM 的笔记本,这也正是为什么下面的模型选择(0.6B–1.7B)看起来不大。这正是重点:这些是人们实际上在这类硬件上运行的模型。
实验设置:BFCL v4(T1 简单/多轮调用 + T6 无关检测,n=200/seed,3 个种子,greedy 解码,temperature=0)。指标:Schema 有效性比率(SVR)、工具选择准确率(TSA)、参数正确性(AC)、弃权准确率,以及函数调用可靠性(FCR——它们的加权聚合)。
核心结论:模型家族比模型大小更能预测表现
| 模型 | 量化 | SVR | AC | FCR(95% CI) | 显著降级? |
|---|---|---|---|---|---|
| Qwen3-0.6B | fp16 | 0.877 | 0.605 | 0.822 [0.797, 0.847] | — |
| Qwen3-0.6B | Q8_0 | 0.878 | 0.610 | 0.826 [0.804, 0.850] | 否 |
| Qwen3-0.6B | Q5_K_M | 0.878 | 0.609 | 0.820 [0.797, 0.852] | 否 |
| Qwen3-0.6B | Q4_K_M | 0.873 | 0.575 | 0.798 [0.779, 0.827] | AC 和 FCR 是(AC Δ 95% CI: [+2.6%, +7.3%] 相对) |
| Qwen3-1.7B | Q8_0(基线*) | 0.880 | 0.681 | 0.842 [0.805, 0.873] | — |
| Qwen3-1.7B | Q4_K_M | 0.883 | 0.686 | 0.844 [0.814, 0.875] | 否 |
| Llama-3.2-1B | fp16 | 0.327 | 0.188 | 0.301 [0.277, 0.327] | — |
| Llama-3.2-1B | Q8_0 | 0.305 | 0.176 | 0.284 [0.266, 0.302] | SVR、AC 和 FCR 是 |
| Llama-3.2-1B | Q4_K_M | 0.280 | 0.174 | 0.283 [0.258, 0.305] | SVR、AC 和 FCR 是(SVR Δ 95% CI: [+0.040, +0.055] 绝对) |
* Qwen3-1.7B 的真实 fp16 权重在 4GB 显卡上无法装下可用的上下文长度——在 n_ctx=4096 和 2048 下都会 CUDA OOM,只能在 512 下加载,而这对于 BFCL 的工具 schema prompt 来说太小了。Q8_0 是其公开说明的回退基线,不是隐藏的替代品。
有两件事值得深思:
- Qwen3-0.6B 一直到 Q4_K_M 都撑住了——schema 有效性从未显著下降;只有 AC 和 FCR 下降,而且只在测试的最严苛量化级别下。
- Llama-3.2-1B 的 schema 有效性在每个量化级别都很脆弱,包括 Q8_0——那个人们通常认为几乎无损的级别。它的绝对 AC 也全面偏低;它倾向于输出字符串化的数字("10"而不是 10),这会被正确的 JSON-schema 验证拒绝。
一个 1B 的 Llama 和一个 0.6B 的 Qwen3 在纸面上看起来是难度相当的部署选择。但在量化面前,它们的表现截然不同。
更困难的任务会拉大差距,而非缩小
T1+T6 是 BFCL 中最简单的层级(一次调用,或无需调用)。作为广度检查,我们也在 fp16 和 Q4_K_M 下运行了 T2(并行工具调用)+ T3(ToolACE,真实目录):
| 模型 | 量化 | SVR | ΔSVR(95% CI) |
|---|---|---|---|
| Llama-3.2-1B | fp16 | 0.572 | — |
| Llama-3.2-1B | Q4_K_M | 0.338 | +0.233 abs, CI [+0.205, +0.265] — 约为 T1+T6 降幅的 5 倍 |
| Qwen3-0.6B | fp16 | 0.687 | — |
| Qwen3-0.6B | Q4_K_M | 0.692 | 不显著(与 T1+T6 一致) |
Llama 在 Q4_K_M 下的 schema 有效性崩溃大约是并行/ToolACE 类任务上的 5 倍于简单单次调用任务。如果你只评测简单层级,你会严重低估对 agent 来说最重要的失效模式。
两个负面结果,如实报告
约束解码(GBNF)并没有挽救什么。在修复了一个实际阻塞了正确弃权的 grammar bug 之后,通过 grammar 约束强制 schema 有效输出并没有显著改善 Qwen3 的 SVR 或 AC——而且每个实例的 wall-clock 时间增加了 6–86%。这是一个真实且公开的成本,在这个基准测试中没有测量到任何收益。
服务后端本身不会独立于量化而影响结果。在相同精度下,Qwen3-0.6B 的 SVR/AC/FCR 在 llama-cpp(GGUF)和 transformers(bf16,非 GGUF)之间统计上不可区分——所以上述降级是量化效应,而非服务引擎的选择性偏差。
复现方法
每个结果文件都嵌入了 manifest:git commit SHA、配置哈希、数据集样本哈希和硬件指纹(GPU/驱动/CUDA)。这里没有任何挑选性——约束解码和后端检查都是负面结果,并如实报告。
pip install uv
git clone https://github.com/Happynood/quant-toolcall-bench
cd quant-toolcall-bench
uv sync
make verify # no GPU needed
quantcall run --config configs/smoke.yaml --output results/smoke.json
- 代码:github.com/Happynood/quant-toolcall-bench
- 实时排行榜 + Pareto 图:huggingface.co/spaces/happynood/quantcall-leaderboard
- 原始逐种子结果:huggingface.co/datasets/happynood/quantcall-results
目前涵盖 Qwen3(0.6B/1.7B)和 Llama-3.2-1B,跨越 llama-cpp、transformers 和 openai 兼容后端;vLLM 已经实现了针对真实 LLM.chat() API 的接口,但尚未经过 GPU 验证——这需要超过 4GB 的 VRAM 才能正确测试。如果你有更大的显卡并想扩展模型或硬件覆盖范围,PR 流程在 CONTRIBUTING.md 中有文档说明。
如果你正在为 agent 部署选择 Q4 和 Q6 之间犹豫不决,从这些数据出发的诚实答案是:取决于你运行的是哪个模型家族,并且要看困难任务的数据,而不仅仅是简单层级的结果。这不如一条简单的经验法则令人满意,但这正是数字实际告诉我们的信息。