tool-calling-model-resident-tool-choice · ZH · 2026-11-02

用 tool_choice 强制只调一个工具:在一把聚合 key 上哪些后端真的照做、哪些只是建议

tool_choice 在聚合 API 上并非处处等价:Claude 与 GPT 系通常能可靠遵循强制单工具约束,部分开源模型后端只把约束当建议。本文解释差异来源、给出逐后端实测方法与提示词兜底方案,并说明如何就在同一把 key 下做选择。

为什么同一个 tool_choice 在不同后端表现不同

在聚合站上,你写的是同一份 OpenAI 兼容请求体,但请求最终落在不同厂商的推理栈上。tool_choice 的语义在 OpenAI 协议里有明确定义:"auto"、"none"、"required"(或 "any")、以及指定具体函数 {"type":"function","function":{"name":"..."}}。不同厂商对这一字段的实现深度并不一致:

  • 有的后端在解码阶段就做约束,强制输出符合指定工具的 JSON schema;
  • 有的只在提示层面注入一条指令,模型“通常”会照做,但可以被上下文带偏;
  • 有的只对 required 生效,对“指定具体某个函数”退化为 auto。

所以在聚合场景下,把 tool_choice 当作硬保证是危险的。更准确的看法是:它是一个意图声明,不同后端的兑现程度不同。

分档看待:硬约束、软约束、仅提示

不必记住逐模型结论,记住分档更实用:

  • 硬约束档:指定具体函数后,后端保证只返回该工具的调用,schema 不合规会被拒绝或修正。Claude 与 GPT 系一般落在这一档,适合对正确性要求高的流程。
  • 软约束档:模型倾向调用指定工具,但在多轮上下文、工具数量多、工具描述重叠时可能改调别的工具,或干脆输出纯文本。部分 DeepSeek、Qwen、GLM 部署在这一档。
  • 仅提示档:tool_choice 被忽略或部分忽略,模型按自身偏好决定是否调用。Kimi 等部分后端在特定版本下更接近这一档。

这些分档会随厂商版本更新变化,不要把它当固定事实,而要当作“先验证、再依赖”的假设。

动手验证:一份最小对照实验

同一个请求体发给不同模型,比较返回:

  1. 构造两个语义相近的工具(例如 searchdocs 与 searchweb),问题故意两边都能答;
  2. 分别发送 toolchoice: "auto"、"required"、指定 searchdocs;
  3. 记录三点:是否返回 tool_calls、调用的是哪个工具、arguments 是否严格符合 schema;
  4. 每个配置重复若干次(温度非零时结果会抖动,单次结果不足以下结论);
  5. 再加一轮“干扰上下文”(历史消息里大量提及另一个工具),看约束是否被破坏。

判据很直接:如果指定具体函数后仍出现别的工具名或纯文本回答,这个后端对你就是软约束。

兜底方案:不依赖后端守规矩

当后端只把 tool_choice 当建议时,用工程手段补强:

  • 收敛工具集:一次请求只挂当前任务需要的工具,别把十几个工具全塞进去。工具越少,误选概率越低;
  • 强化系统提示:明确写出“本轮必须调用 xxx,不得调用其他工具,不得直接回答”;
  • 服务端校验:拿到响应后检查 tool_calls[0].function.name 与 schema,不符就重试一次或降级到硬约束后端;
  • 用 required 兜底:当“必须调工具但调哪个可放宽”时,required 比指定函数更常被后端正确实现;
  • 结构化输出辅助:若任务本质是抽取而非工具调用,考虑用 JSON 模式替代 tool 调用,减少一层不确定性;
  • 路由分流:关键路径固定走硬约束后端,探索性、低风险任务走成本更低的后端。

在一把聚合 key 下做选择

聚合站的价值正在于:上面这些实验和分流,都只需要一个 API key、一套 SDK 配置,改 model 字段即可切换后端,不必为每家单独开户、单独配额度。你可以写一个薄封装:按任务类型选模型,按上面判据校验工具调用,失败则回退到硬约束档。

计费上也要把这个因素算进去:使用方按官方价 ×1.3 扣费,贡献 key 按官方价 ×1.1(优质 ×1.2)返 USDC。也就是说,重试和降级都产生实际成本,把“哪些后端真的守约束”测清楚,本身就是在省钱。充值走 Base 上的 USDC,无 KYC,适合需要快速做多后端对照的团队。

小结

tool_choice 是意图而不是契约。把后端按硬约束、软约束、仅提示三档看待,先用最小对照实验验证,再用服务端校验和路由分流兜底。这样即使某个后端只把约束当建议,你的流程也不会因此崩掉。