Prhub

#21593 Fix tool call constrained decoding and parsing for models with native formats

原始 PR 作者 JustinTong0323 合并时间 2026-04-11 11:37 文件变更 9 提交数 19 评论 33 代码增减 +306 / -61

执行摘要

修复工具调用约束解码与解析,确保原生格式模型在 required 模式下正确使用 structural_tag 并强制至少一个调用。

根据PR body描述,当模型配置了特定--tool-call-parser(如kimi_k2deepseekv3qwen25)时,tool_choice="required"此前强制使用通用JSON模式约束,与模型的原生工具调用格式(如特殊标记<|tool_calls_section_begin|>)冲突,并尝试将模型输出解析为纯JSON,导致解析失败并返回tool_calls: null

该PR值得精读,特别是function_call_parser.py中的get_structure_constraint()方法设计,展示了如何权衡模型原生格式与OpenAI协议要求。关注at_least_one标志的引入和supports_structural_tag()检查的逻辑,这对理解约束解码机制有重要价值。

讨论亮点

Review中核心讨论来自AgainstEntropy,建议在非流式_process_tool_calls方法中显式检查supports_structural_tag(),以与流式路径保持一致。JustinTong0323采纳该建议,修改代码添加守卫,确保逻辑一致性。讨论焦点在于正确性,未解决其他重大疑虑。

实现拆解

实现拆解为以下模块:

1) 协议层(protocol.py):添加at_least_one: bool = False字段到LegacyStructuralTagResponseFormat,支持强制工具调用。
2) 文法后端(xgrammar_backend.py):传递at_least_one字段到xgrammar的StructuralTag API。
3) 功能调用解析器(function_call_parser.py):修改get_structure_constraint()方法,为required或命名工具选择使用structural_tag约束并设置at_least_one=True;同时添加supports_structural_tag()检查。
4) 服务层(serving_chat.py):更新非流式工具调用处理逻辑,镜像流式路径,使用supports_structural_tag()守卫以确保正确解析。
5) 检测器修复(base_format_detector.pydeepseekv3_detector.py):修复流式解析中的空参数处理和deepseekv3格式前缀。
6) 测试更新:添加单元测试和集成测试覆盖新逻辑。

文件 模块 状态 重要度
python/sglang/srt/function_call/function_call_parser.py function call parsing modified 9.0
python/sglang/srt/entrypoints/openai/serving_chat.py OpenAI serving modified 8.0
python/sglang/srt/constrained/xgrammar_backend.py constrained decoding modified 6.0
python/sglang/srt/entrypoints/openai/protocol.py protocol definitions modified 5.0
test/registered/unit/function_call/test_function_call_parser.py testing modified 7.0

关键符号

get_structure_constraint _process_tool_calls parse_streaming_increment structure_info

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

检查 supports_structural_tag() 在非流式路径 正确性

AgainstEntropy 建议在非流式 _serving_chat.py 的 _process_tool_calls 方法中显式检查 supports_structural_tag(),以与流式路径保持一致。

结论:JustinTong0323 采纳建议并修改代码添加守卫,确保逻辑一致性。 · 已解决

风险与影响

技术风险包括:

1) 回归风险:修改核心解析逻辑(serving_chat.py)可能影响现有工具调用功能,需通过测试覆盖验证。
2) 兼容性风险:对多种模型原生格式的支持需确保所有检测器正确处理at_least_one标志,特别是那些不支持structural_tag的模型(如lfm2)。
3) 性能风险:添加额外检查和解析步骤可能轻微影响性能,但预计可忽略。
4) 安全风险:无显著安全风险,但解析错误可能导致数据不一致。

影响范围:

1) 用户影响:修复了使用原生格式模型(如DeepSeek、Kimi、Qwen等)时tool_choice="required"失败的问题,提升工具调用可靠性和用户体验。
2) 系统影响:改进解析准确性和OpenAI协议合规性,确保strictrequired标志正确交互。
3) 团队影响:代码更一致,测试覆盖增加,便于未来维护和扩展。

核心解析路径变更 跨模型兼容性风险 测试覆盖依赖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论