Taylent Labs
返回博客列表
LLM超时处理工具调用系统设计

LLM 应用的工具调用超时处理策略:从外部 API 到数据库查询的完整方案

系统梳理 LLM 工具调用场景下的超时问题根源与分层处理方案,涵盖外部 API、数据库查询、文件操作等典型场景的工程实践

问题的本质:为什么工具调用特别容易超时

LLM 应用中的工具调用(Function Calling / Tool Use)本质是将模型输出的结构化指令翻译成实际的系统调用。这个过程引入了两层不确定性:模型推理耗时本身不可控,工具执行时间又依赖外部系统响应。当两者串联时,总耗时的方差会显著放大。

假设一个客服 Agent 需要调用订单查询 API。即便单次 API 调用通常在 200ms 内返回,模型可能因为理解用户意图不准确而连续调用三次(先查用户信息、再查订单列表、最后查详情),累计耗时加上模型推理就可能突破 10 秒。这种"多跳调用"在复杂任务中很常见,但用户期待的响应时间往往在 3-5 秒以内。

分层超时策略:不同工具类型需要不同处理

外部 API 调用

这是最常见也最脆弱的环节。建议采用三层防护:

  1. 客户端超时:为 HTTP 客户端设置合理的 connect_timeout 和 read_timeout。连接超时通常设 2-3 秒,读取超时根据 API 性质设定——查询类 5 秒,分析类可放宽到 15 秒。
  2. 重试与降级:对幂等操作(GET 请求、查询类接口)可配置指数退避重试,但总重试时间不应超过单次超时的 1.5 倍。非幂等操作(POST/PUT)超时后应返回明确的"操作状态未知"标记,让模型决定是否重新发起。
  3. 熔断器模式:当某个 API 在滑动窗口内失败率超过阈值(如 1 分钟内 50% 请求超时),暂时跳过该工具,避免拖累整个对话流程。

数据库查询

数据库调用的超时需要区分场景:

  • 简单查询(单表、有索引):设 1-2 秒超时,超时即中断查询(statement_timeout)。这类查询如果超时,通常意味着索引缺失或数据量异常,应记录慢查询日志排查。
  • 复杂分析(多表 JOIN、聚合):可放宽到 10 秒,但需在工具描述中明确告知模型"此操作耗时较长",让模型在必要时才调用。同时提供简化版查询工具(如只返回前 100 条)作为替代。

关键是在工具定义的 description 字段中标注预期耗时,帮助模型做更好的规划决策。

文件与计算密集型操作

文档解析、图像处理等本地操作虽然不依赖网络,但计算时间同样不可控。建议:

  • 对输入做预检查,拒绝超大文件(如限制 PDF 不超过 50 页)
  • 使用进程池隔离执行,设置 hard timeout 强制终止
  • 提供流式返回接口,允许模型在部分结果可用时就继续对话

超时后的优雅处理:让模型参与兜底

传统做法是超时后直接向用户返回错误,但在 LLM 应用中可以做得更好。工具执行层应返回结构化的错误信息:

{
  "success": false,
  "error_type": "timeout",
  "partial_result": "已查询到 3 条订单,但完整统计未完成",
  "retry_suggestion": "可缩小时间范围重试"
}

模型收到这个响应后,可以选择:向用户说明情况并提供部分结果、调整参数重试、或切换到备用方案(如改用缓存数据)。这比生硬的"系统超时,请稍后再试"体验好得多。

监控与持续优化

超时问题的根治需要数据驱动:

  • 记录每次工具调用的耗时分布(P50/P95/P99),识别异常慢的操作
  • 追踪"多跳调用"的链路,发现可以合并的场景(如提供批量查询工具)
  • A/B 测试不同超时阈值对任务完成率的影响

假设某个文档问答应用发现 95% 的查询在 3 秒内完成,但剩余 5% 会拖到 20 秒以上,那么可以考虑将超时设为 5 秒,并为慢查询场景设计专门的异步处理流程。


工具调用的超时处理本质是在响应速度与功能完整性之间找平衡。如果你的团队正在构建复杂的 LLM 应用,需要在架构层面系统性解决这类工程问题,欢迎联系 Taylent Labs 探讨定制化方案。