技术 · 熟练
「必须调这个工具」这句话,现在没人听了
把约束写进提示词,别写在参数里
过去要让模型一定返回结构化结果,最省事的办法是在 API 参数里强按它的手:指定工具名、或干脆要求「必须调用某个工具」。新一批模型把这个口子关了 —— 这两种写法直接返回 400。这不是「功能少了」,是约束的挂载点被挪了位置:从 API 参数挪回提示词与结构校验。这一页做的是一次迁移核查——先找出你的代码里哪里有「强制选择」,再按新写法换掉(结构约束走严格模式、行为约束走提示词),最后用一条「本来就不该调工具」的任务验证它现在会不会乱调。一句话:声明式约束留在参数里,行为约束回提示词。
方法 · 一图看懂
1
先搜出所有「强制」 — 代码里凡是出现强制工具选择的地方,逐条列出来
2
拆成两类约束 — 结构约束(字段必须这么长)· 行为约束(这轮该不该调)
3
各回各家 — 结构走严格模式与字段校验,行为写进提示词(含「不该调」的判据)
4
补一条反例任务 — 专门跑一条「本来不需要工具」的任务,看它会不会硬调
原理 · 为什么有效
「强制工具选择」被依赖的原因,其实是一个偷懒的等价:把「我要结构化输出」这件事,交给「必须调用这个工具」来保证。两者看着等价,其实不是 —— 前者说的是形状,后者说的是动作。一旦把它们拆开,问题就清楚了:形状该由结构校验(严格模式、字段类型、必填项)来保证,那是确定性的、跟模型无关;动作该由提示词里的判据来引导,因为「这轮该不该调工具」本来就是语义判断,交给模型自己判反而更准。新模型关掉强制选择,等于逼所有人把这两个本来混在一起的东西分开。
适用场景
适合:升级到新一批模型(Claude Opus 5.5 / Fable 5.1 一类)报 400 的人 · 用 LangChain / crewAI 之类框架、升级后突然跑不通的 · 自己在代码里写了「强制调用某工具」来做结构化输出的。
自测 · 5 问
我的代码里,有哪些地方写了「强制工具选择」或「具名强制」?
那些地方要保的到底是「形状」还是「动作」?
形状的部分,我换成严格模式与字段校验了吗?
动作的部分,提示词里写清「什么时候该调」和「什么时候不该调」了吗?
我补了一条「本来不需要工具」的反例任务来验吗?
怎么上手 · 验证步骤
迁移只有两步,但第二步常被跳过:① 打开严格模式、把返回对象的字段类型与必填项定死(这一步是确定性的,跟模型换不换无关)② 在系统提示词里写三句话 —— 「先判断这轮需不需要外部信息」「需要就调哪个工具」「不需要就直接回答,不要为了用工具而用工具」。第二步不做的话,模型会倾向于「有工具就用」,这正是强制选择退场后最常见的新毛病。
换完之后跑三条任务:① 一条明显需要查外部信息的(看它调不调)② 一条明显不需要的(看它会不会硬调)③ 一条边界模糊的(看它会不会解释自己的选择)。三条都符合预期才算迁移完成。另外把「返回 400」这个错误码记进你的监控 —— 强制的写法可能不只在主路径里,插件、脚本、老的 notebook 里都可能有漏网的。