【技术跟进】大模型工具调用的瓶颈:现状、根源与可能的出路
工具调用(Tool Use / Function Calling)让大语言模型不再只是“回答问题”,而是开始接触真实系统:查数据库、发请求、读文件、调用业务接口,甚至触发支付、下单、发送邮件等操作。也正因为如此,它成了 AI Agent 能否真正落地的关键能力。
但在实际工程中,工具调用远没有演示视频里那么顺滑。模型可以轻松完成“查天气”“设闹钟”这类单步任务,一旦任务变成长链路、强依赖、带异常的真实流程,失败率就会明显上升。本文想讨论的,正是这背后的瓶颈、成因,以及目前相对可行的改进方向。
1 为什么工具调用是 Agent 的关键问题
过去两年,主流大模型基本都支持了 Function Calling,应用层也出现了 LangChain、AutoGen、CrewAI 等 Agent 框架。表面上看,模型只要按规范生成一段 JSON,系统再执行对应函数,就能把自然语言转成真实动作。
但真正做过落地的人都会遇到类似问题:
- 简单任务表现很好,比如“查一下北京天气”;
- 稍复杂一点的任务开始不稳定,比如“帮我规划一次包含机票、酒店、租车的自驾游”;
- 再往上,如果涉及多轮状态、异常恢复、权限控制、用户确认,系统就很容易卡住或出错。
原因并不只是“模型还不够聪明”。工具调用把 LLM 推到了一个和纯文本生成完全不同的问题域:
- 从“生成内容”变成“执行动作”:调用结果可能产生真实副作用,错一次就是真错;
- 从“单步回答”变成“链式决策”:需要规划顺序、管理依赖、处理失败;
- 从“封闭上下文”变成“开放系统”:工具接口、数据格式、权限边界都很复杂;
- 从“概率输出”变成“工程执行”:模型输出不稳定,而工程系统需要可控、可复现、可审计。
所以,工具调用的难点,本质上是概率模型和确定性系统之间的矛盾。模型擅长理解和生成,但工程系统要求的是稳定、准确、低延迟和可追责。
2 工具调用面临的主要瓶颈
下面从七个方面梳理当前比较常见的问题。
2.1 规划与决策:什么时候调、调什么、怎么调
工具调用看起来是格式问题,实际上首先是规划问题。模型需要判断任务能不能直接回答、是否需要调用工具、该调用哪个工具、多个工具之间如何排序。
常见问题包括:
- 多步任务中的错误累积:模型可能跳过必要步骤,或者把中间结果误当成最终答案。例如还没查距离,就直接估算油耗。
- 无效循环:模型在几个工具之间反复尝试,搜索、修改参数、再次搜索,却迟迟无法收敛。
- 参数歧义:用户说“周五晚上 8 点左右、浦东附近、3 到 4 人”,模型需要把时间、地点、人数都转成接口能接受的参数,这一步很容易出错。
- 上下文参数幻觉:当工具需要当前日期、用户 ID、地区编码等信息时,模型有时会自己“补”一个并不存在的值。
- 不善于反问:信息不足时,模型更倾向于猜一个参数继续调用,而不是停下来问用户。
这类问题很难只靠“多写几个示例”解决,因为它涉及长程依赖、状态追踪和错误归因等更底层的能力。
2.2 延迟与编排:多轮 Ping-Pong 的成本
传统 Tool Calling 1.0 往往是这样的流程:
1 | |
这种模式直观,但代价很高:
- 每次调用都要等工具返回,再让模型继续推理;
- 多个无依赖的工具也常被串行执行;
- 工具返回的大量中间数据会被塞回上下文;
- 模型在多轮中反复生成相同标识符、参数或中间说明。
如果一个任务涉及 3 个工具,实际可能需要 6 到 9 轮模型与工具之间的往返。端到端延迟达到 10 到 30 秒并不罕见,而这对交互式产品来说已经很影响体验。
2.3 准确率:工具选择和参数提取仍不稳定
一次工具调用能否成功,通常取决于三步:识别意图、选择工具、填对参数。任何一步出错,调用就会失败或产生错误结果。
典型问题包括:
- 工具很多时,模型可能选错工具,或者调用根本不需要的工具;
- 自然语言中的参数没有被完整提取,或类型不符合 JSON Schema;
- 嵌套参数、条件参数较多时,模型容易漏掉依赖关系;
- Schema 越复杂,结构化输出越容易出现格式错误,后续还需要重试和修复。
一些公开评测也能说明这个问题。以 Berkeley Function Calling Leaderboard 等测试为例,无结构化示例时,参数准确率可能只有 70% 多;加入结构化示例后,可以提升到 90% 左右。差距很大,也说明“怎么描述工具、怎么给示例”会直接影响调用质量。
2.4 上下文与记忆:长链路中容易丢状态
工具调用一旦变成多轮流程,上下文管理就会成为瓶颈。
- 对话变长后,模型可能忘记之前调用过什么工具、拿到了什么结果;
- 工具返回内容过长时,关键信息可能被截断,或者被淹没在无关文本里;
- 多轮中间结果不断进入上下文,token 成本快速上涨;
- 模型缺乏稳定的外部状态机,很难准确判断“已经完成了哪些步骤、还缺哪些信息”。
一个常见例子是:系统把 20 封邮件的完整元数据全部塞进上下文,只是为了让模型提取其中 3 个 ID。这既浪费 token,也会干扰模型注意力。
2.5 安全与可靠性:真实副作用让风险放大
只要工具会改变外部世界,安全问题就不再是理论问题。
- 提示注入:搜索结果、网页内容、邮件正文中可能夹带恶意指令,诱导模型忽略原规则。
- 权限过大:系统为了省事,给 Agent 开了过宽权限,模型一旦误判,影响范围就会扩大。
- 缺少事务机制:发送邮件、扣费、删除文件这类操作往往不可逆,模型却未必有“先预演、再确认、后提交”的意识。
- 错误传播:工具调用失败后,模型可能把错误信息解释错,甚至声称操作已经成功。
因此,工具调用系统不能只追求“能调通”,还必须关注权限、审计、确认、回滚和降级。
2.6 工具体系:接口太杂,描述也不够标准
现实中的工具形态非常复杂:REST API、GraphQL、数据库、本地脚本、浏览器自动化、GUI 操作都有可能接入。模型通常只看到一段工具名称、描述和参数 Schema,很难理解背后的真实行为。
几个常见难点是:
- 工具描述不清楚,模型不知道什么时候该用;
- 参数说明不完整,模型不知道哪些值合法;
- 返回值格式不稳定,后续解析困难;
- 工具数量从几个扩展到上百个后,全部塞进上下文会非常昂贵,选择准确率也会下降;
- 相似工具之间命名接近,Schema 也接近,模型容易混淆。
换句话说,工具不是“接上就能用”。工具本身也需要被设计成模型容易理解、容易调用、容易纠错的形式。
2.7 评估与调试:出错后很难定位责任
工具调用系统的调试难度往往被低估。最终结果错了,可能有很多原因:
- 用户意图理解错了;
- 模型选错工具;
- 参数填错;
- 工具本身有 bug;
- 工具返回异常;
- 中间结果进入上下文后被模型误读;
- 某一轮非确定性输出导致后续链路偏移。
现有基准如 ToolLLM、API-Bank、BFCL 等能提供参考,但离真实业务场景仍有距离。尤其是长链路、异常恢复、权限控制和人机协作,很难靠单一 benchmark 完整覆盖。
3 问题根源:模型能力和工程架构都不够
这些瓶颈大致可以归为两类:一类是模型自身能力不足,另一类是系统工程设计不成熟。也可以说,这是“后训练”和“Agent 架构”各自要解决的问题。
3.1 后训练:让模型更会用工具
后训练主要包括 SFT(监督微调)和 RL(强化学习)。它解决的是模型“会不会用工具”“用得稳不稳”的问题。
SFT 的作用比较直接:
- 教模型输出符合规范的工具调用格式;
- 覆盖常见单步和简单多步场景;
- 让模型熟悉工具名称、参数结构和调用模式;
- 成本相对可控,是建立基础能力的有效方式。
但 SFT 也有明显局限。它主要是在模仿训练数据中的路径,不擅长探索;训练集中很少包含“失败后如何修正”的轨迹;遇到训练分布之外的长链路任务,表现容易下降。
这时就需要 RL。强化学习可以在模拟环境或真实反馈中,让模型通过“尝试—失败—调整”学习更好的策略。它的价值主要体现在:
- 提升多步任务的规划能力;
- 学会在工具失败后重试、回溯或改换方案;
- 在面对可疑工具返回时更谨慎,降低提示注入风险;
- 通过奖励函数控制调用次数、延迟和成本。
不过 RL 本身也不轻松:训练不稳定、奖励设计复杂,还可能出现模型为了拿奖励而钻规则空子的情况。
比较现实的路线是:先用高质量轨迹做 SFT,让模型掌握基本格式和常见模式;再用 RL 强化长链路、异常恢复和安全策略。简单说,SFT 让模型“会用”,RL 让模型“用得更稳”。
3.2 Agent 架构:用工程把不稳定变得可控
即使模型经过后训练,也不应把所有责任都压在模型身上。工程架构要解决的是模型做不到、做不稳,或者做起来成本太高的问题。
一个可靠的 Agent 系统通常需要:
- 任务分解:把大目标拆成可执行的小步骤,避免一次性规划过长;
- 状态管理:用外部结构化状态记录已完成步骤、工具返回、待确认信息;
- 记忆检索:只把和当前决策有关的信息放回上下文,而不是全量回灌;
- 工具执行器:负责真正调用 API、处理网络错误、解析返回格式;
- 安全边界:通过沙箱、权限控制、人工确认和审计日志限制风险;
- 错误处理:对失败调用进行重试、降级或请求用户补充信息。
这些能力靠模型本身很难稳定保证,但工程系统可以明确实现。
3.3 后训练和 Agent 架构不是二选一
两者解决的问题不同,也不应该互相替代。
| 维度 | 后训练 | Agent 架构 |
|---|---|---|
| 主要目标 | 提升模型自身能力 | 提升系统可控性和可靠性 |
| 擅长解决 | 参数理解、工具选择、多步推理 | 状态管理、权限控制、错误恢复、异构工具接入 |
| 优势 | 能力内化,泛化后可复用 | 可观测、可调试、可逐步迭代 |
| 局限 | 成本高,长尾难覆盖 | 架构复杂,可能增加延迟 |
当前阶段,Agent 架构往往更容易见效。因为模型还没有把工具调用能力完全内化,真实业务又不能等待模型“自然变强”。但如果没有持续后训练,Agent 的上限也会被模型能力锁住。
更健康的路径应该是:强模型作为基础,高质量后训练提升工具调用能力,再用 Agent 架构补齐状态、安全、执行和观测能力。
4 可能的突破方向:从 Tool Calling 1.0 到 2.0
目前业界的改进方向,大致集中在工程、模型和协议生态三个层面。其中一个值得关注的趋势,是从“模型生成 JSON,系统逐步执行”,转向“模型用代码编排工具”。
4.1 工程层:减少往返,管理中间状态
1. 代码化编排
传统方式让模型输出 JSON 参数,然后等待系统执行。新的思路是让模型在受控环境里编写一小段代码,用代码完成循环、分支、过滤和工具组合。
这样做有几个好处:
| 维度 | 传统方式 | 改进方向 | 可能收益 |
|---|---|---|---|
| 交互模式 | 多轮 JSON 往返 | 代码一次性编排 | 减少模型-工具往返 |
| 中间数据 | 全量回灌上下文 | 留在函数环境中处理 | 降低 token 消耗 |
| 工具加载 | 一次性加载全部 Schema | 按需检索工具描述 | 缓解上下文压力 |
| 参数约束 | 依赖模型自觉遵守 | 结合类型检查和结构化示例 | 降低格式错误 |
关键点不是让模型随意执行代码,而是在沙箱和权限控制下,让它用代码处理那些原本需要多轮对话才能完成的编排工作。
2. 异步优先
很多工具调用之间并没有强依赖。比如检索资料、查询价格、拉取用户偏好,可以并行执行,再统一汇总。
1 | |
只要依赖关系划分清楚,异步编排能显著降低端到端延迟。
3. 更细的上下文管理
工具输出不应该未经处理就塞回模型。更合理的方式包括:
- 先摘要,再进入下一轮推理;
- 只保留后续决策需要的字段;
- 对长结果做分块检索,而不是一次性全部输入;
- 对重复中间数据使用外部状态引用,而不是反复复制。
4. 更规范的工具定义
工具描述的质量会直接影响模型表现。一个模糊的工具定义,例如:
1 | |
对模型几乎没有帮助。更好的写法应该明确说明用途、参数和约束:
1 | |
命名最好采用清晰的“动词 + 名词”形式,参数说明要写清楚合法值、必填项、可选项和适用场景。
4.2 模型层:继续强化工具使用能力
模型层的重点仍然是训练和评测。
- 持续积累高质量工具调用轨迹,用于 SFT;
- 在长链路、失败恢复、权限判断和提示注入防御上引入 RL;
- 在 prompt 中加入结构化示例,帮助模型理解参数格式;
- 模型选型时关注工具调用专项能力,而不只看通用聊天效果;
- 用 BFCL、ToolBench 等公开评测做参考,同时建立业务自己的评测集。
不同模型在工具调用上的差距非常明显。选型时不能只看“回答是否聪明”,还要看它是否能稳定选择工具、生成合法参数、处理异常返回。
4.3 协议和生态:让工具更容易被发现和理解
如果每个工具都用不同方式描述、注册和授权,Agent 系统就很难规模化。协议层的价值在于降低接入成本,让工具世界更标准。
值得关注的方向包括:
- MCP(Model Context Protocol):让工具像插件一样注册、发现和调用;
- OpenAPI 等机器可读规范:让模型和框架能更系统地理解接口;
- 工具检索机制:不再把全部工具塞进上下文,而是先搜索、再按需加载;
- 细粒度权限和沙箱:把“模型知道这个工具”和“模型被允许调用这个工具”分开。
5 实践中的优先级
如果要在真实产品里改善工具调用体验,可以按下面的顺序推进。
1 | |
对不同团队来说,侧重点也不同:
- 如果目标是研究模型能力,应重点投入工具调用数据、SFT 和 RL;
- 如果目标是尽快做出可用产品,应优先建设 Agent 架构和工具治理;
- 如果系统已经进入规模化阶段,就必须把评测、审计、安全和成本控制纳入日常工程流程。
6 结语
工具调用不是一个简单的“让模型输出 JSON”的问题。它连接的是两个很不一样的世界:一边是概率性的语言模型,另一边是要求确定性、可控性和安全性的工程系统。
短期看,最有效的办法不是等待模型彻底解决一切,而是用 Agent 架构把流程、状态、权限和错误处理管起来;同时,通过 SFT 和 RL 持续提升模型本身的工具使用能力。
未来一两年,工具调用很可能会从“模型生成参数,系统逐步执行”,走向“模型在受控环境中编写代码,自主编排工具链”。当模型既能理解用户意图,又能在沙箱里可靠地组织工具、处理异常、控制副作用,Agent 的实际可用性才会真正上一个台阶。