Deployment note / Tool calling

Qwen3x 工具调用:XML 默认,双格式解析才是解法

Qwen3x 会生成工具调用,不等于服务端能稳定解析工具调用。真正决定流式工具是否可用的,是模型格式、chat template 和后端增量 parser 三者是否一致。

2026-08-30生产取舍记录
当前决定 30001 继续使用 XML 作为唯一生产格式:Froggeric 模板默认 XML,vLLM 使用 qwen3_xml。OpenAI 和 Anthropic 客户端仍发送标准 tools,前端不需要理解模型生成的 XML。

观察到了什么

社区长轮次测试给出的现象很一致:Qwen3x 天然更偏向 XML 工具调用。无论 OpenAI 或 Anthropic 请求外形、流式或非流式,模型都更容易稳定保持 XML。JSON 在非流式下尚有较高成功率,但温度高于 0.3 后,流式调用更容易发生格式漂移、参数截断或无法进入工具执行。

换到 v22 chat template 不能消除这个差异。模板能强化输出格式,却不能替代模型后训练,也不能让一个 XML-only parser 自动理解 JSON。

问题不在前端

客户端看到的应该始终是标准 API 事件。以 OpenAI-compatible API 为例,客户端提交 tools 和消息;chat template 把它渲染成模型熟悉的格式;模型生成 XML;vLLM 再把 XML 增量转换为标准 tool_calls delta。Anthropic 路径同理。

OpenAI / Anthropic tools
        ↓
chat template 渲染模型提示
        ↓
Qwen3x 生成 XML
        ↓
vLLM qwen3_xml 增量解析
        ↓
标准 tool_calls / tool_use 事件

因此前端助手不应增加 Qwen 专用 XML 逻辑。把模型私有格式泄漏到客户端,只会让每一个前端都重复处理半截标签、转义和重试。

模板支持 JSON,不代表服务支持双格式

30001 固定的 Froggeric 模板已经包含 tool_call_format=json 分支,也能按 XML 或 JSON 重放历史工具调用。但当前启动参数是 --tool-call-parser=qwen3_xml,运行时 parser 只识别 XML 的 <function=...> 和 <parameter=...> 结构。

路径模板生成后端增量解析当前结论
XML支持,且为默认qwen3_xml 支持生产使用
JSON支持当前 parser 不支持不得启用
网关事后提取 JSON无关需要等待完整响应不是真流式

如果现在强制 tool_call_format=json,模型可能生成看似正确的 JSON,但服务端可能把它留在普通文本里,或者无法提取为 API 工具调用。这是 parser 能力缺口,不是再加一句提示词就能解决的问题。

真正的双格式方案

后端需要一个按请求维护状态的双格式增量 parser。在每个 <tool_call> 内,看到 <function= 就进入 XML 状态机,看到 { 就进入 JSON 状态机;两条路径都要尽早发出函数名,并持续发送 arguments delta,而不是等整个工具调用闭合以后再解析。

温度不是修复开关

降低 temperature 可以减少格式漂移,所以 JSON 在低温下看起来更稳定;它不能弥补 parser 不认识 JSON,也不能保证长参数、write/edit 或多工具流式调用正确。生产指标必须同时覆盖格式提取、参数正确性、工具执行、自动重试和最终回答完成,不能只统计“模型输出过一个 tool_call”。

如何验证生产级

社区结果声称:覆盖长短文本、主要工具类型和 200 轮以上 agent loop,重复五轮后,包含参数错误自动重试的整体成功率不低于 99.6%。这个数字可以作为目标,但不能直接算作我们的结果。复现时必须固定模型 revision、模板、parser、采样参数、工具集合、重试策略和测试语料。

  1. XML/JSON × 流式/非流式 × OpenAI/Anthropic 四个维度全部覆盖;
  2. 分别测试 temperature 0、0.3 和 1.0;
  3. 重点覆盖 write/edit 的长参数、换行、引号、Unicode 和嵌套 JSON;
  4. 至少 200 轮连续执行,记录格式失败、参数失败、重试恢复和异常停止;
  5. 重复五轮,按完整工具执行成功率计算,而不是按 parser 命中率计算。

现阶段保留:XML-only、qwen3_xml、标准客户端协议。下一阶段:实现 vLLM 双格式流式 parser 后再开放 JSON,并用上述矩阵独立复现成功率。