Taylent Labs
返回博客列表
LLM工具调用架构设计AI应用

LLM 应用的工具调用链路设计:从单工具到多工具协同的架构方案

从单工具调用到复杂多工具协同,梳理 LLM 应用中工具链路设计的核心模式、错误处理与性能优化实践

工具调用(Function Calling / Tool Use)让 LLM 能够突破纯文本生成的边界,调用外部 API、查询数据库、执行代码。但从单个天气查询到复杂的多步骤业务流程,工具链路的设计复杂度会呈指数级上升。本文梳理从简单到复杂场景下的架构选择与工程实践。

单工具调用:最小可行链路

最简单的场景是一次对话只涉及一个工具。假设用户问"北京今天天气",LLM 识别意图后调用 get_weather(city: "北京"),拿到结果后组织成自然语言回复。

这个链路的核心是工具定义的清晰度。工具的 schema 需要明确参数类型、必填项、枚举值范围。参数命名要语义化,避免 LLM 混淆——比如 location 比 loc 更不容易被误解为"本地/远程"的标志。

错误处理在这一层就要考虑:工具返回失败时(API 超时、参数非法),是让 LLM 重试、换个工具,还是直接告知用户?建议在工具返回中包含结构化的错误信息(error_code + message),让 LLM 能基于错误类型决定下一步——这比把异常栈直接扔给模型要可控得多。

顺序多工具:链式依赖的编排

当一个任务需要多个工具按顺序执行时,架构开始分化。假设用户要求"查北京天气,如果下雨就帮我订明天的室内活动",这涉及 get_weather → 判断 → book_activity 的链式调用。

方案一:让 LLM 自主编排。每次工具返回后,把结果追加到对话历史,LLM 基于上下文决定下一个工具。这种方式灵活,但 token 消耗随步骤线性增长,且 LLM 可能在中间环节"忘记"最初目标。适合步骤少(3 步以内)、分支简单的场景。

方案二:预定义工作流。在应用层用状态机或 DAG 描述工具依赖关系,LLM 只负责填参数,执行顺序由代码控制。这降低了模型出错的概率,但牺牲了灵活性——用户需求稍有变化就要改代码。适合业务流程相对固定的场景,比如客服工单处理。

混合方案是在关键决策点让 LLM 介入,其余用硬编码。比如"是否下雨"的判断交给 LLM 解析天气数据,但订票流程走固定的三步校验。

并行多工具:性能与一致性的权衡

当多个工具之间没有依赖关系时,并行执行能显著降低延迟。假设用户问"对比北京、上海、深圳三地的天气和酒店价格",6 个 API 调用如果串行执行可能要 10 秒,并行可以压缩到 2 秒以内。

但并行带来两个问题:

  1. 部分失败的处理。6 个调用中有 2 个超时,是等全部完成再让 LLM 总结,还是先返回部分结果?前者用户体验差,后者可能导致 LLM 给出片面结论。工程上可以设置 partial_results_threshold,比如"至少 4 个成功才继续"。

  2. 工具间的隐式依赖。看似独立的工具可能共享底层资源(同一个数据库连接池、同一个 API 配额),并发可能触发限流。需要在工具层做好速率控制,或者在调度层感知依赖关系。

多轮对话中的工具状态管理

复杂应用往往跨多轮对话。用户可能先问"帮我找附近的餐厅",LLM 调用 search_restaurants(location: "当前位置"),然后用户追问"第一家的评分多少",这时需要引用上一轮的结果。

方案一:全量上下文。把所有工具调用的输入输出都保留在对话历史中,LLM 自行索引。这在旗舰档模型(128K+ 上下文窗口)上可行,但 token 成本会随对话轮次快速上涨。

方案二:结构化缓存。在应用层维护一个 tool_results 字典,key 是工具调用的 ID,value 是结果摘要。只把摘要传给 LLM,完整数据存在后端。当 LLM 需要细节时,通过类似 get_tool_result(call_id: "abc123") 的元工具按需获取。这降低了常驻 token,但增加了工程复杂度。

轻量档模型上下文窗口较小,更适合方案二;旗舰档模型可以先用方案一快速验证,成本敏感后再优化。

错误恢复与可观测性

工具调用链路越长,某个环节出错的概率越高。建议在每个工具执行前后埋点记录:

  • 工具名称、参数、执行时长
  • 返回状态(成功/失败/部分成功)
  • 如果失败,记录错误类型与是否触发重试

这些日志不仅用于排查问题,还能训练出"哪些工具组合容易出错"的经验。比如发现 search + filter 的组合在某个参数范围下成功率低于 60%,可以考虑合并成一个工具或者调整 schema。

对于关键业务,可以在工具层实现幂等性与补偿机制。假设订单提交工具因为网络抖动执行了两次,幂等设计能保证只创建一个订单;如果用户中途取消,补偿机制能回滚已执行的步骤。

小结

工具调用链路设计没有银弹。单工具场景优先保证 schema 清晰与错误可读;顺序多工具在灵活性与可控性之间权衡;并行多工具关注部分失败与资源竞争;多轮对话需要在上下文完整性与成本之间找平衡。

所有方案的共同点是:把确定性逻辑交给代码,把语义理解与决策交给 LLM。边界划分得越清晰,系统越稳定。

如果你的团队正在构建复杂的 LLM 工具调用系统,或者需要在成本与性能之间做架构优化,欢迎与 Taylent Labs 交流——我们在 AI 应用架构与 API 网关层有深度实践积累。