
peg-native: lazy grammar fails to prevent malformed tool-call XML (duplicate </parameter>) on Qwen3.6-35B-A3B; parser then drops the whole tool call and
快速结论:该报错发生在使用 llama-server 通过 peg-native 自动生成惰性语法(lazy grammar)进行 XML 工具调用时,模型偶尔会生成重复的 </parameter> 闭合标签。优先排查 llama.cpp 版本是否为 b9728 之前(尤其是 b9608 之后),并尝试升级到包含修复补丁的版本(如 b9728+ 或 #24839 后的构建)。
问题场景
用户在 llama-server(多模型路由预设)中加载 unsloth/Qwen3.6-35B-A3B(推理型 MoE 模型,UD-Q8_K_XL 量化),通过外部 --chat-template-file(社区修复的 Qwen3.6 家族模板,XML 工具调用方言)并设置 --jinja 和 --chat-template-kwargs '{"preserve_thinking": false}' 启动服务。客户端(如 VS Code Copilot 风格)使用 tool_choice: "auto" 进行流式工具调用时触发。问题在推理型模型上出现概率约 1/128 次请求,在非推理型模型上未重现。
报错原文
common_chat_peg_parse: unparsed peg-native output: <tool_call>
<function=read_file>
<parameter=filePath>
/Users/.../pallium-finish-done.story
</parameter>
</parameter> <!-- stray duplicate close tag (model slip) -->
<parameter=startLine>
1
</parameter>
<parameter=endLine>
50
</parameter>
</function>
</tool_call>
srv stop: cancel task, id_task = 3431
客户端进一步报错:
The model produced output that does not match the expected peg-native format
原因分析
这是两个问题叠加的后果:
- 生成阶段:自动生成的惰性语法未能有效约束模型输出。在
tool_choice: "auto"下,peg-native 路径设置grammar_lazy=true,以<tool_call>作为触发器。但触发器被触发后,语法理论上应只允许<parameter=或</function>,然而模型仍然采样了重复的</parameter>。这可能是因为语法定义中 parameter 的闭合被定义为Until('\n</parameter>\n'),在惰性模式下边界处理不够严密。 - 解析阶段(更关键):解析器在遇到无法解析的语法块时,没有降级处理(如 best-effort 恢复已解析的参数),而是直接丢弃整个
<tool_call>块并终止流。这导致即使模型在重复闭合标签之外生成了有效的参数(如startLine、endLine),也无法被利用。
在 b9608 之前的版本中该问题未出现,因此可能是在 b9608 至 b9728 之间的某个提交引入了解析或语法生成的变化。
环境排查
- llama.cpp 版本:确认是否在 b9608 之后、b9728 之前(问题于 b9722 首次报告)。升级到包含 #24839 修复的分支或晚于 2026-06-21 的构建。
- 模型:Qwen3.6-35B-A3B(推理型 MoE)——仅在推理型模型上观察到,非推理型模型(如 Qwen3.6 27B)不受影响?实测 27B 也遇到。
- 客户端行为:VS Code Copilot 风格的客户端可能不发送回 reasoning traces,但这并非根因。即使在自定义推理应用且启用了 reasoning traces 的配置下也可能复现。
- 工具定义(次要):检查工具函数的参数中是否缺少必填字段。某些案例显示当模型省略了必填
content参数时也可能触发类似报错(但表现为无重复标签的单个</function>直接结束)。
解决步骤
- 升级 llama.cpp 版本:首先尝试升级到包含 #24839 修复的构建(预计在 b9728+)。该修复专门针对重复的
</parameter>标签问题。如果无法立即升级,可降级到 b9608 或更早版本。 - 验证语法修复(若使用自定义构建):检查修改了 peg-native 语法生成逻辑的提交 #24839。该提交应确保惰性语法正确禁止在已闭合的
<parameter>后生成重复标签。 - 临时降级方案:如果不便升级,可将模型切换为非推理型模型(如 Qwen3.6 27B 的某些变体),或禁用
grammar_lazy=true特性(如果服务器配置允许)。 - 客户端配置(可优先尝试):如果使用 VS Code Copilot 客户端,确保发送推理痕迹(reasoning traces)给服务器。虽然不是根本原因,但某些客户端配置差异可能影响模型行为(社区报告该问题在
b9608下正常,因此客户端作用有限)。 - 工具定义检查(仅针对 “missing mandatory parameter” 模式):如果报错中没有重复
</parameter>而是直接闭合</function>,请检查工具函数的required字段是否完整。模型可能省略了必填参数,导致解析器因不匹配直接取消流。
验证方法
升级后,使用相同的工作负载(多轮代理工具调用,特别是涉及 read_file 等返回文件内容的调用)进行测试。如果问题不再出现(重复 </parameter> 标签消失,所有 <tool_call> 块均被正确解析),则修复成功。也可以通过触发边缘情况(如在工具调用中故意包含复杂嵌套内容)来验证语法约束的健壮性。



