这道题其实问的是,我们怎么让大模型突破纯文本生成的天花板,去操作外部系统。我理解它的核心就是让模型学会判断“什么时候该用工具、用哪个工具、参数怎么填”,然后拿到结果再回给用户。
具体说一下工作流,分四步。第一步是工具注册,就是提前把每个工具的接口定义成一份 schema,包括名称、描述、参数格式,比如 JSON Schema。第二步是意图识别,模型根据用户的问题判断要不要调工具。第三步是参数生成,模型按 schema 输出结构化的参数。第四步是执行和回填,外部系统跑完工具,结果拿回来,模型再生成最终回复。
实现方式上,主要有三种。Prompt-based 最简单,把工具描述塞进 system prompt,靠模型遵循指令输出固定格式,适合快速验证。Native Fine-tuned 是专门训练模型识别特殊 token,像 GPT-4 和 Claude 用的就是这种,输出更稳定。还有一种 [[ReAct]] 模式,Thought 到 Action 到 Observation 循环,适合复杂多跳任务。实际落地时,我一般会把 Prompt-based 和 ReAct 结合起来用:简单工具靠 prompt 搞定,复杂场景走 ReAct 做多步推理。
这里有个坑,就是参数合法性。模型生成的参数可能不符合 schema,比如类型不对、缺字段。所以我会用 JSON Schema 加采样约束,比如 outlines 库,在生成时就限制输出格式。另外错误处理也很关键,工具调用可能超时或失败,我会设计 fallback 逻辑,要么重试一次,要么告诉用户暂时查不到。还有一个常见场景是并行调用,模型一次想查天气和股价,我会在 prompt 里明确支持同时输出多个 tool call。
讲个真实业务场景。比如电商客服系统,用户问“帮我查一下订单 12345 的物流状态,顺便看看这个商品现在有没有优惠”。模型需要同时调订单查询和价格查询两个工具。如果只靠 prompt 去推,很容易参数搞错,比如把订单号传给价格接口。所以我会在 schema 里把参数校验写严,并且让模型先确认订单号格式再传参。如果调用失败,比如物流接口超时,我就 fallback 到返回已知的部分信息,而不是直接报错。
所以我的判断是,tool calling 落地的前提是工具 schema 设计得足够清晰,而且要有完善的错误处理。常见失败场景是工具太多、描述模糊,模型选错工具或参数乱填。上线我会特别关注调用成功率和参数合法率,低的话就调整描述或加 few-shot 示例。
还有一种更激进的玩法,就是让模型自己决定要不要组合多个工具,比如先查天气再推荐穿搭。这个就涉及到 [[Toolformer]] 那类自监督训练的思路,模型学会在文本里插入工具调用 token。但它的风险是可能会滥用工具,推理成本也高,我目前更倾向用 ReAct 加人工设计的工具链。
整体上,我更倾向把 tool calling 看成模型能力的扩展,而不是替代。它擅长解决实时信息获取和精确计算这类问题,但前提是工具接口稳定、schema 设计合理。如果这两点不满足,模型再强也容易翻车。