Prhub

#20208 Remove maxItems=1 restriction when tool_choice is specified

原始 PR 作者 kpham-sgl 合并时间 2026-04-03 10:35 文件变更 6 提交数 4 评论 8 代码增减 +83 / -17

执行摘要

修复函数调用 JSON 模式中 maxItems=1 限制导致的模型停滞问题。

修复 Issue #17998 中描述的 bug,其中当 tool_choice 指定函数时,JSON 模式中的 maxItems:1 约束导致模型在提示暗示多次调用时停滞生成空白字符。PR body 明确引用该 Issue 作为动机。

该 PR 值得精读,特别是设计决策如何通过 parallel_tool_calls 参数平衡灵活性与控制,以及 JSON 模式生成的修改方式,展示了 API 兼容性与功能修复的结合。

讨论亮点

review 讨论中仅 JustinTong0323 批准 PR,评论为空;但 Issue 评论显示关键讨论:hnyls2002 报告集成测试失败,指出 parallel_tool_calls 默认值应为 True,kpham-sgl 纠正了先前假设,并通过后续提交更新实现和测试。这表明对 API 默认行为的澄清和测试验证。

实现拆解

核心改动包括:

  1. python/sglang/srt/function_call/utils.pyget_json_schema_constraint 函数中,移除无条件 maxItems=1,添加 parallel_tool_calls 参数,仅在 parallel_tool_calls=False 时设置 maxItems=1。
  2. python/sglang/srt/function_call/function_call_parser.pyget_structure_constraint 函数中,添加 parallel_tool_calls 参数并传递给 JSON 模式生成函数。
  3. python/sglang/srt/entrypoints/openai/protocol.pyChatCompletionRequest 类中添加 parallel_tool_calls: bool = True 字段,与 OpenAI API 兼容。
  4. python/sglang/srt/entrypoints/openai/serving_chat.py 中传递 parallel_tool_calls 参数到函数调用解析器。
  5. 更新测试:移除不稳定集成测试,添加单元测试验证 parallel_tool_calls=True 和 False 的行为。
文件 模块 状态 重要度
python/sglang/srt/function_call/utils.py function_call modified 8.0
python/sglang/srt/function_call/function_call_parser.py function_call modified 6.0
python/sglang/srt/entrypoints/openai/protocol.py openai API modified 5.0
python/sglang/srt/entrypoints/openai/serving_chat.py openai serving modified 5.0
test/registered/unit/function_call/test_json_schema_constraint.py testing modified 4.0

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

关键符号

get_json_schema_constraint get_structure_constraint

评论区精华

测试失败与 parallel_tool_calls 默认值纠正 测试

hnyls2002 报告集成测试失败,指出 parallel_tool_calls 默认值应为 True;kpham-sgl 纠正了先前假设,并通过提交更新实现。

结论:默认值设为 True 以保持与 OpenAI API 兼容,测试通过验证。 · 已解决

风险与影响

风险包括:

  1. 新增 parallel_tool_calls 参数默认值设为 True,以保持向后兼容性,但可能影响依赖旧行为的代码,不过旧行为是 bug,因此风险较低。
  2. 修改 JSON 模式生成逻辑可能导致回归错误,但已有单元测试覆盖,且移除了不稳定集成测试。
  3. 新参数需在 API 文档中说明,否则用户可能不了解其功能。

影响范围:

  • 对用户:修复模型停滞问题,支持并行工具调用,提升函数调用可靠性和灵活性。
  • 对系统:扩展 OpenAI API 兼容性,添加新字段,无性能影响。
  • 对团队:变更集中在函数调用模块,需确保新参数在文档和测试中正确集成。
参数默认值调整 JSON 模式变更 测试覆盖不足

关联 Issue

#17998 [Bug] tool_choice with specific function causes model to stall on multi-call prompts

完整报告

执行摘要

该 PR 修复了函数调用 JSON 模式中 maxItems=1 限制导致的模型停滞问题,通过引入 parallel_tool_calls 参数控制是否限制单次调用,默认允许并行调用,与 OpenAI API 兼容,修复了 Issue #17998 中的 bug,提升函数调用可靠性。

功能与动机

修复 Issue #17998 中描述的 bug:当 tool_choice 指定函数时,JSON 模式强制 maxItems: 1,导致模型在提示暗示多次调用时停滞生成空白字符。PR body 明确引用此 Issue 作为动机,旨在解除不必要的限制,支持并行工具调用场景。

实现拆解

关键改动点按模块梳理:

  • function_call 模块:在 get_json_schema_constraint 函数中移除无条件 maxItems: 1,添加 parallel_tool_calls 参数,仅在 False 时设置限制;在 get_structure_constraint 函数中传递该参数。
  • openai API 模块:在 ChatCompletionRequest 类添加 parallel_tool_calls: bool = True 字段,扩展 API 兼容性;在 serving_chat.py 中处理参数传递。
  • 测试模块:移除不稳定集成测试 test_specific_function_multi_call_no_stall,添加单元测试覆盖 parallel_tool_calls=TrueFalse 的行为,验证 JSON 模式正确性。

评论区精华

review 讨论中仅 JustinTong0323 批准 PR;但 Issue 评论揭示关键交锋:hnyls2002 报告集成测试失败,指出 parallel_tool_calls 默认值问题,导致 kpham-sgl 纠正假设并更新实现。引用 hnyls2002 原话:“test_specific_function_multi_call_no_stall failed...”,以及 kpham-sgl 回应:“oh I assumed parallel_tool_calls is already default to True... Good catch!”,体现了测试驱动修复的过程。

风险与影响

风险:新增参数默认值可能影响现有行为,但设为 True 保持向后兼容;JSON 模式修改需确保无回归错误,已有单元测试覆盖;新参数需文档说明以避免用户混淆。
影响:修复 bug 提升用户函数调用体验,支持并行调用扩展功能;系统层面 API 对齐 OpenAI 标准,无性能影响;团队需注意新参数的集成和测试维护。

关联脉络

从历史 PR 分析,近期 PR 如 #21570(支持 LoRA)和 #19163(Transformers 后端)涉及模型功能扩展,但本 PR 专注于函数调用 JSON 模式修复,属于独立 bugfix。与 Issue #17998 直接关联,展示了针对具体问题的快速响应和设计权衡(通过参数控制限制)。整体看,SGLang 在持续优化 API 兼容性和功能可靠性。

参与讨论