[Bug]: [structured outputs] speculative decoding + `VLLM_ENFORCE_STRICT_TOOL_CALLING=1` failed to advance FSM

该报错发生在 vLLM 开启结构化输出(structured outputs / JSON schema)并同时启用 speculative decoding(MTP)与 VLLM_ENFORCE_STRICT_TOOL_CALLING=1 时,导致 FSM(有限状态机)无法推进。优先确认 vLLM

快速结论:该报错发生在 vLLM 开启结构化输出(structured outputs / JSON schema)并同时启用 speculative decoding(MTP)与 VLLM_ENFORCE_STRICT_TOOL_CALLING=1 时,导致 FSM(有限状态机)无法推进。优先确认 vLLM 版本并应用修复 PR #44297,同时检查是否使用了 MTP 投机解码与异步调度组合。

适用环境:Ubuntu 24.04.4、Python 3.12.3、PyTorch 2.11.0+cu130 / 2.13.0+cu130、CUDA 13.0、NVIDIA H100 80GB 或 RTX 5090(多卡 TP=2),vLLM 0.28.0 及更新版本,默认 xgrammar 结构化输出后端。模型包括 Qwen3.5-35B-A3B + MTP(k=1) 与 Inferact/Qwen3.8-27B-NVFP4。

最快修复方案:升级到包含 PR #44297 修复的 vLLM 版本(即 v0.28.0 及以上)。该修复已合入主线,在 2×H20 环境下 50 次测试中失败次数从 29/50 降至 0/50。

注意事项:即使包含修复的 v0.28.0,在特定组合下(MTP + --reasoning-parser qwen3 + --async-scheduling)仍可能出现 HTTP 200 但内容静默退化为空白字符的问题,此时日志仍报 Failed to advance FSM。这是尚未完全解决的衍生问题。

问题场景

在 vLLM 服务中使用 response_format={"type": "json_schema"} 请求结构化 JSON 输出,同时启用 speculative decoding(MTP 模式),并设置 VLLM_ENFORCE_STRICT_TOOL_CALLING=1。运行场景包括通过 serve 命令部署 Qwen3 系列模型,开启 --enable-auto-tool-choice--tool-call-parser qwen3_coder。约三分之一请求返回 HTTP 200 但 finish_reason="length",内容在 JSON 数组字段冒号后停止,后续输出大量空白字符直到 max_tokens 耗尽。

报错原文

ERROR [backend_xgrammar.py:167] Failed to advance FSM for request chatcmpl-… for tokens 71093. Please file an issue.
ERROR [backend_xgrammar.py:167] Failed to advance FSM for request chatcmpl-… for tokens 2164. Please file an issue.
ERROR [backend_xgrammar.py:167] Failed to advance FSM for request chatcmpl-… for tokens 271. Please file an issue.

[Bug]: [structured outputs] speculative decoding + `VLLM_ENFORCE_STRICT_TOOL_CALLING=1` failed to advance FSM

原因分析

这是 结构化输出(xgrammar FSM 引导)与投机解码(MTP)之间的交互缺陷。MTP drafter(草稿模型)在生成候选 token 时未严格遵循 FSM 约束,产生 FSM 无法接受的 token(例如尝试在 JSON 前插入 markdown 围栏 ```json 或在字符串值内放入原始换行)。在 VLLM_ENFORCE_STRICT_TOOL_CALLING=1 强制工具调用约束时,这种不匹配导致 FSM 无法推进。后续评论补充:即使在修复后(v0.28.0),MTP + --reasoning-parser qwen3 + --async-scheduling 的组合仍可能导致模型输出静默退化为空白(只有空格、制表符或引号换行对),这可能是 FSM 与 MTP drafter 对空白 token 的处理仍有边缘缺陷。同一问题还伴随 vLLM_ENFORCE_STRICT_TOOL_CALLING=1 强制工具调用时的 FSM 不推进。

环境排查

  • vLLM 版本:确认是否为 0.28.0 及以上(修复合并时间点)。旧版本必现此问题。
  • 投机解码配置:检查 --speculative-config 是否使用 "method": "mtp"
  • 调度模式:是否启用了 --async-scheduling(与静默退化问题相关)。
  • 推理解析器--reasoning-parser 是否设置为 qwen3
  • 结构化输出后端:确认是否为默认 xgrammar(跳过 structured_outputs={"grammar": …} 自定义语法时现象有差异)。
  • 模型与驱动:确认模型是否 Qwen3 系列(报告涉及 Qwen3.5-35B-A3B、Inferact/Qwen3.8-27B-NVFP4),GPU 驱动版本(H100 使用 580.159.03,RTX 5090 使用 595.71.05)。

解决步骤

  1. 首要操作:升级 vLLM 到包含 PR #44297 的版本(v0.28.0 或更新)。该修复已合入主线,可解决 VLLM_ENFORCE_STRICT_TOOL_CALLING=1 下 FSM 完全无法推进的问题。
  2. 如升级后仍遇到空白退化:可优先尝试 移除 --async-scheduling 标志,改为默认同步调度。
  3. 如仍有问题:尝试关闭 --reasoning-parser qwen3,或改用不带 MTP 的模型(如 --speculative-config '{"method": "ngram"}' 或其他非 MTP 草稿策略)。
  4. 若必须使用 MTP:可尝试降低 num_speculative_tokens(原配置为 5),观察是否减少退化频率。
  5. 对关键业务请求,可在客户端校验 JSON 合法性并检测空白退化(如 finish_reason="length" 且内容以大量空白结尾),触发重试。

验证方法

用同一组历史失败提示词(约 50 个样本)反复请求:

  • 确认不再出现 Failed to advance FSM 的服务端错误日志。
  • 确认所有请求返回合法 JSON,finish_reasonstop 而非 length,内容尾部无大量空白字符。
  • 对比修复前后失败比例:主分支 29/50 失败,应用修复后 0/50(H20 环境)。若用 v0.28.0 仍观察到空白退化,需继续执行第 2、3 步调整。

参考来源

vllm-project/vllm #44006

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 21593

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注