常驻服务已迁移到
unsloth/Qwen3.6-27B-NVFP4 + vLLM 0.23.0,并正式关闭 MTP 推测解码。
原因:MTP 会随机打坏工具调用的 XML,导致 Hermes Agent / 定时任务出错——对一个要跑 Agent 的常驻服务来说这是硬伤。
本文下半部分(推荐 MTP=3 的调优历程)保留作为历史记录,最终决策与最新基准见文末
「MTP 与工具调用的冲突」一节。
背景与目标
需要在本地单卡上部署一个 27B 参数量的常驻 LLM 服务,承载图库管理、语音助手、个人知识库问答、Hermes Agent 工具调用等多种日常 AI 任务。对模型的核心要求:
- 单卡可跑:NVFP4 量化,27B 权重约 16-20 GB 显存
- 长上下文:支持 256K token,个人知识库场景需大窗口
- 多模态:原生视觉能力,处理图库管理任务
- Agent 能力:内置思考链 + 工具调用(function calling)
- 解码速度:单请求 100+ tok/s,多并发下线性扩展
候选模型:Qwen3.6-27B-LNARIZE-AEON-NVFP4(带 MTP 推测解码)和 Huihui-Qwen3.6-27B-abliterated-NVFP4-MTP(去审查版本)。两者均基于 Qwen3.6-27B 架构,NVFP4 量化 + MTP 推测解码头。
硬件环境
推理栈:vLLM (latest) + CUDA 12.x + PyTorch + FP8 KV Cache
量化:NVFP4(NVIDIA 4-bit 浮点),权重 ~20 GB
推测解码:MTP(Multi-Token Prediction),模型内置 drafter head
调优历程
1. GPU 显存利用率
--gpu-memory-utilization 控制 vLLM 可用的显存比例。设得太高会 OOM,太低浪费 KV Cache 容量。调优路径:
0.88 (保守) → 0.55 (激进) → 0.60 (最优)
关键发现:该参数直接决定 KV Cache 大小,进而决定能同时处理多少长上下文请求、前缀缓存能保留多少条目。
2. KV Cache 容量测算
通过多组实测数据拟合出 KV Cache 容量与 gpu-memory-utilization 的线性关系:
其中 multiplier 表示可容纳多少个 256K 上下文的等价容量。
| gpu_util | KV 倍率 | 可容纳 256K 请求数 | 场景 |
|---|---|---|---|
| 0.50 | 2.74× | ~2.5 | 不够 3 并发 256K |
| 0.55 | 3.25× | ~3.0(紧张) | 3 并发勉强,cache 命中率低 |
| 0.60 | 3.76× | ~3.5(充裕) | 3 并发 256K + 90%+ 缓存命中 |
| 0.88 | 6.61× | ~6.5 | 浪费,且挤占其他 GPU 任务 |
实测验证:gpu_util=0.55 时 3×222K 前缀缓存命中率仅 65.7%;提升到 0.60 后达到 98.6%。原因是每个请求的 KV cache 需要独立存储(唯一前缀导致无法共享),加上 MTP 额外 6.25% 开销和 block 对齐 ~5% 浪费。
3. MTP 推测解码
Qwen3.6-27B 内置 MTP(Multi-Token Prediction)drafter head,无需额外小模型。一次前向传播生成 num_speculative_tokens 个候选 token,由主模型验证。
| 指标 | 实测值 |
|---|---|
| 总体接受率 | 52-57% |
| 位置 0 接受率 | 78% |
| 位置 1 接受率 | 55% |
| 位置 2 接受率 | 37% |
| 平均每步有效 token | 2.56-2.70 |
MTP=4 不被 LNARIZE drafter 支持;MTP=2 损失加速空间。MTP=3 是最优平衡点。
4. 前缀缓存命中率优化
Agent 场景中系统提示词 + 历史对话高度重复,前缀缓存可以跳过 prefill 阶段直接进入 decode。实际使用中缓存命中率通常 >80%,此时 decode 成为端到端延迟的主控因素。
对于 3 个并发 256K 请求(最恶劣情况),gpu_util=0.60 保证缓存容量有 20% 余量,命中率 >98%。
5. Agent 功能配置
为支持完整的 Agent 工作流,服务端需要如下配置:
| 参数 | 值 | 作用 |
|---|---|---|
--reasoning-parser | qwen3 | 正确分离思考链 (thinking) 和输出内容 (content) |
--enable-auto-tool-choice | — | 自动识别 function call 意图 |
--tool-call-parser | qwen3_coder | 解析工具调用的 JSON 结构 |
--mm-processor-cache-type | shm | 共享内存缓存多模态处理器,减少重复加载 |
Qwen3.6 chat template 默认enable_thinking=true。没有--reasoning-parser qwen3时,thinking 内容会混入 content 字段,导致 API 返回结构异常。
6. 多模态图片配置
Qwen3.6-27B 原生支持视觉输入。模型默认 max_dynamic_patch=12(每张图最多拆分为 12 个 patch 输入),当前部署保持默认值 12,不做裁剪,保证图库管理精度。
服务端通过 --limit-mm-per-prompt '{"image": 32}' 限制单请求最多 32 张图片,避免极端请求耗尽 KV cache。--mm-processor-cache-type shm 将多模态处理器缓存到共享内存,减少重复加载开销。
基准测试
阶梯测试 (10K-222K)
单并发、变输入长度(10K / 50K / 100K / 150K / 180K / 222K),固定输出 3000 token(ignore_eos), 每档加唯一前缀绕开 prefix cache,测真实冷启动性能。
| 档位 | 输入 tok | TTFT (s) | Prefill (tok/s) | Decode (tok/s) | Total (s) |
|---|---|---|---|---|---|
| 10K | 9,963 | 0.80 | 12,494 | 120.5 | 25.7 |
| 50K | 49,866 | 6.40 | 7,797 | 118.8 | 31.6 |
| 100K | 99,958 | 18.82 | 5,311 | 110.9 | 45.9 |
| 150K | 150,049 | 37.44 | 4,008 | 110.3 | 64.6 |
| 180K | 180,047 | 51.74 | 3,480 | 103.3 | 80.8 |
| 222K | 221,931 | 73.25 | 3,030 | 104.0 | 102.1 |
规律解读:
- Prefill 速率随上下文线性下降:Attention 的 O(N²) 复杂度使得每 token 计算量与序列长度成正比。10K 时 12.5K tok/s → 222K 时 3.0K tok/s。
- Decode 速率几乎不受上下文长度影响:从 10K 的 120 tok/s 到 222K 的 104 tok/s 仅下降 13%,说明 decode 阶段主要瓶颈是权重读取带宽而非 KV cache attention 开销。
并发吞吐测试
3 个并发请求,每个 200K input / 5K output。测试混合 prefill + decode 场景下的总吞吐。
混合场景受 prefill 串行影响:vLLM chunked prefill 会将并发请求的 prefill 阶段交叉执行,3×222K 需要 ~230s 串行 prefill 时间。
纯解码隔离测试
用两阶段法隔离纯 decode 吞吐:Phase 1 串行发 max_tokens=1 填充 prefix cache;Phase 2 同时发 3 个 5K output 请求,prefix cache 命中后直接进入 decode。
Decode 是 memory-bandwidth bound(非 compute bound)——模型权重只读一次就服务所有请求。 多并发下每个请求的 decode 速率降低(55→33 tok/s),但聚合吞吐近似线性叠加。
模型对比:LNARIZE-AEON vs Huihui
两个模型使用完全相同的 serve 参数(gpu-mem=0.60, MTP=3, fp8 KV cache),跑相同的阶梯 benchmark。
| 档位 | TTFT (s) | Prefill (tok/s) | Decode (tok/s) | Total (s) | ||||
|---|---|---|---|---|---|---|---|---|
| L | H | L | H | L | H | L | H | |
| 10K | 0.80 | 0.81 | 12,494 | 12,239 | 120.5 | 123.6 | 25.7 | 25.1 |
| 50K | 6.40 | 6.47 | 7,797 | 7,712 | 118.8 | 120.9 | 31.6 | 31.3 |
| 100K | 18.82 | 19.10 | 5,311 | 5,233 | 110.9 | 112.8 | 45.9 | 45.7 |
| 150K | 37.44 | 37.88 | 4,008 | 3,961 | 110.3 | 110.0 | 64.6 | 65.2 |
| 180K | 51.74 | 52.25 | 3,480 | 3,446 | 103.3 | 101.6 | 80.8 | 81.8 |
| 222K | 73.25 | — | 3,030 | — | 104.0 | — | 102.1 | — |
L = LNARIZE-AEON H = Huihui 绿色 = 该档位较优值(差异均 <2%)
这符合预期——两者架构相同、量化方式相同(NVFP4-MTP),Huihui 仅做了 abliteration(去审查微调),不影响推理计算图。 选择依据应为输出质量和审查策略,而非速度。
最终配置
exec uv run vllm serve \
"${MODEL_DIR}" \
--host 0.0.0.0 \
--port 8000 \
--served-model-name Qwen3.6-27B-MTP \
--gpu-memory-utilization 0.60 \
--kv-cache-dtype fp8_e4m3 \
--max-num-seqs 32 \
--max-num-batched-tokens 10240 \
--enable-prefix-caching \
--enable-chunked-prefill \
--mm-processor-cache-type shm \
--limit-mm-per-prompt '{"image": 32}' \
--trust-remote-code \
--reasoning-parser qwen3 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder \
--tensor-parallel-size 1 \
--speculative-config '{"method":"mtp","num_speculative_tokens":3}'
关键参数决策汇总:
| 参数 | 值 | 决策理由 |
|---|---|---|
| gpu-memory-utilization | 0.60 | 3 并发 256K prefix cache >98% 命中,且留 40% 给其他 GPU 任务 |
| kv-cache-dtype | fp8_e4m3 | KV cache 量化,容量翻倍,精度损失可忽略 |
| max-num-seqs | 32 | Agent 场景仅需 ~3 并发,32 主要服务批量识图等短输入高并发任务 |
| MTP tokens | 3 | 接受率 56%,平均每步 2.7 有效 token,最优平衡点 |
| enable-prefix-caching | on | Agent 场景系统提示复用率极高 |
| enable-chunked-prefill | on | 长输入不阻塞其他请求的 decode |
| reasoning-parser | qwen3 | 正确分离 thinking / content 字段 |
| tool-call-parser | qwen3_coder | Agent function calling 支持 |
常驻服务用途
多模态视觉理解
默认 12 patches 高精度
单请求最多 32 张图
ASR→LLM→TTS 管道
短输入低延迟
TTFT <1s @10K
RAG + 长上下文
256K 窗口
prefix cache 加速
思考链 + 工具调用
auto tool choice
qwen3_coder parser
⚠️ MTP 与工具调用的冲突(2026-06-21 更新)
上文把 MTP=3 当作纯收益(decode 翻倍)来推荐。但常驻服务的核心负载之一是 Hermes Agent 的工具调用和定时任务(cron), 实际运行一段时间后发现:开 MTP 会随机打坏工具调用的 XML,付出的代价远超那点解码加速。最终决策是关闭 MTP。
问题:MTP 在精确 token 上猜错,打坏 tool_call XML
Qwen3.6 用 XML 格式输出工具调用(<tool_call><function=terminal><parameter=command>…</parameter></function></tool_call>)。
MTP 推测解码在这种精确结构化输出上一旦猜错、verify 回滚失步,XML 就残缺(mismatched tag / not well-formed),
vLLM qwen3_xml parser 解析失败 → arguments 退化成 null → Hermes 工具收到 command=None 直接报错。
普通自然语言输出从不受影响,只砸结构化的工具调用,且随机间歇——典型的投机解码”猜错才崩”特征。
qwen3xml_tool_parser:303 报错):
| 配置 | 样本 | XML 解析报错 |
|---|---|---|
| MTP off | 10 轮 | 0 |
| MTP on (mtp/3) | 30 轮 | 6 |
关掉 0 报错、打开就有——正常使用下 MTP 是工具调用 XML 崩坏的来源。与早先定时任务大面积失败、关 MTP 后归零的现象一致。
注意:这不是“换 chat 模板”或”关思考链”能解决的——那些治的是另一类失败(工具调用混进 think 块)。
MTP 打坏的是 token 本身。要既保 MTP 加速又不崩工具调用,唯一正交解法是 grammar-constrained 解码(xgrammar 强制每个 token 合法),与 MTP 是否开启无关;但当前 Agent 走 tool_choice=auto 自由生成路径,吃不到这条,所以最稳的选择就是关 MTP。
代价:关 MTP 后的解码速度(unsloth NVFP4,单流阶梯)
关 MTP 后 decode 从 ~100+ tok/s 降到 ~50 tok/s(少了投机加速),但 prefill 反而更快(Blackwell 原生 FP4 GEMM)。对 Agent 场景,工具调用的可靠性 > 解码峰值速度,这个取舍是值得的。
| 档位 | 输入 tok | TTFT (s) | Prefill (tok/s) | Decode (tok/s) |
|---|---|---|---|---|
| 10K | 9,963 | 0.96 | 10,377 | 58.05 |
| 50K | 49,866 | 7.21 | 6,916 | 55.50 |
| 100K | 99,958 | 20.34 | 4,915 | 52.64 |
| 150K | 150,049 | 39.37 | 3,811 | 49.95 |
| 180K | 180,047 | 53.70 | 3,353 | 48.49 |
对比文首 MTP-on 的 180K 档(decode 103 tok/s / prefill 3,480):关 MTP 后 decode 降到 48.49(MTP 加速消失),但 prefill 3,353 与之相当、TTFT 持平。
更新后的最终配置(MTP off)
exec vllm serve /path/to/Qwen3.6-27B-NVFP4 \
--host 0.0.0.0 --port 8000 \
--served-model-name Qwen3.6-27B-MTP \
--dtype bfloat16 \
--gpu-memory-utilization 0.55 \
--kv-cache-dtype fp8_e4m3 \
--max-num-seqs 32 \
--max-num-batched-tokens 16384 \
--enable-prefix-caching \
--enable-chunked-prefill \
--mm-processor-cache-type shm \
--limit-mm-per-prompt '{"image": 32}' \
--trust-remote-code \
--reasoning-parser qwen3 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_xml \
--tensor-parallel-size 1
# 不加 --speculative-config:MTP 关闭,保证工具调用 XML 不被打坏
关键结论
- 跑 Agent 的常驻服务必须关 MTP(2026-06-21 修订)——MTP 随机打坏工具调用 XML(受控实测 off 0/10、on 6/30),代价远超解码加速。要兼得需 grammar-constrained 解码,而非关思考或换模板。
- gpu-memory-utilization 是最关键的调优参数——目标是在最低显存占用下跑满 3 个 256K 并发请求并维持足够的 KV cache 供 prefix cache 命中。0.60 恰好满足该条件,是当前工况的最优平衡点。
- MTP=3 提供稳定的 ~2.7× 每步加速,接受率 56%,是 drafter 支持范围内的最优值。(但见上:因打坏工具调用 XML,常驻 Agent 服务最终关闭 MTP——加速诱人,可靠性优先。)
- Decode 是 memory-bandwidth bound——单请求未饱和显存带宽,多并发下聚合吞吐近线性增长。
- Prefill 速率随上下文长度线性下降(Attention O(N²)),但在 Agent 场景中 prefix cache 可以基本跳过重复的 prefill。
- NVFP4 量化模型之间速度无差异——同架构同量化方案,abliteration 等微调不影响推理速度,选型应基于输出质量。
测试环境:RTX PRO 6000 Blackwell / AMD Ryzen 9 7950X / Ubuntu 24.04 / vLLM 0.23.0 / CUDA 13.x (torch cu130)
初版 2026-05-23(Qwen3.6-27B-LNARIZE-AEON / Huihui NVFP4-MTP)
更新 2026-06-21(unsloth/Qwen3.6-27B-NVFP4,关闭 MTP)