工具重试 | Middleware 中间件 | 产品经理学Langchian | 第16篇

内容纲要

概述

在前面的章节中,我们讨论了如何通过工具选择器降低token消耗。现在我们要解决一个很实际的问题:当工具调用失败时,怎么办?有时候失败是临时性的(比如网络波动、API限流),如果直接报错,用户体验会很差。

想象一下,用户让AI智能体查询天气,但因为网络波动失败了,用户看到错误信息会很困惑。但如果系统能自动重试几次,很可能就成功了,用户完全感觉不到刚才的失败。

Tool retry中间件会在工具调用失败时,使用指数退避策略自动重试,处理临时性错误,提升AI智能体的可靠性和容错能力。这样,即使遇到网络波动、API限流等临时问题,也能自动恢复,用户几乎感觉不到。

使用场景

处理临时性错误

网络波动、API限流、服务临时不可用等临时性错误,通过重试可以自动恢复。这些错误通常是暂时的,重试后很可能就成功了。

提升网络依赖工具的可靠性

依赖外部API的工具(如搜索、数据库查询),在网络不稳定时通过重试可以提升成功率。特别是在移动网络环境下,网络波动更常见。

构建容错AI智能体

在不确定的外部环境中,通过重试机制优雅处理临时错误,避免因单次失败导致整个任务失败。这样AI智能体就更健壮了。

核心功能需求

重试策略:指数退避

指数退避是一种很常用的重试策略,它的特点是延迟时间按指数增长:第一次重试等待1秒,第二次等待2秒,第三次等待4秒,以此类推。

为什么使用指数退避?

避免雪崩效应

  • 如果所有失败的请求都立即重试,可能对刚刚恢复的服务造成压力,导致再次崩溃
  • 指数退避让重试分散开,给服务恢复的时间

节省资源

  • 临时性错误通常在短时间内恢复,较短的初始延迟可以快速恢复
  • 较长的后续延迟避免过度重试

平衡等待与响应

  • 在等待时间与重试次数之间取得平衡
  • 既不过度等待,也不过度重试

产品建议:指数退避是经过实践验证的策略,建议默认使用。可以根据实际情况调整退避因子和初始延迟。

重试配置

我们需要配置几个关键参数来控制重试行为。

最大重试次数

  • max_retries参数:设置最多重试多少次
  • 总调用次数:总调用次数 = 1(初始)+ max_retries(重试)
  • 建议值:网络工具建议3-5次,本地工具建议1-2次

退避因子

  • backoff_factor参数:每次重试的延迟时间 = initial_delay * (backoff_factor ^ 重试次数)
  • 建议值:通常设置为2.0(标准指数退避)

初始延迟

  • initial_delay参数:第一次重试前的等待时间(秒)
  • 建议值:快速工具0.5-1.0秒,慢速工具1.0-2.0秒

异常类型判断

不是所有错误都应该重试。有些错误是永久性的(比如404资源不存在、401认证失败),重试也没用。

可重试的异常

  • 网络超时:TimeoutError
  • 连接错误:ConnectionError
  • 5xx服务器错误:服务器临时问题
  • 429限流错误:API限流,稍后重试可能成功

不可重试的异常

  • 4xx客户端错误:401认证失败、404资源不存在等
  • 参数验证错误:参数格式错误等
  • 这些是永久性错误,重试也无法解决

产品建议:在PRD中明确区分可重试和不可重试的异常,只有临时性错误才重试。

失败处理策略

如果所有重试都失败了,我们需要决定如何处理。

返回错误消息(推荐)

  • on_failure='return_message':返回包含错误详情的消息给LLM
  • 优点:允许LLM根据错误信息调整策略或告知用户,用户体验更好
  • 适用场景:大多数生产场景

抛出异常

  • on_failure='raise':直接抛出异常,停止执行
  • 优点:便于测试和调试
  • 适用场景:关键工具失败必须终止的场景

自定义处理

  • 自定义函数:返回友好的错误消息,便于LLM理解和处理

产品建议:生产环境建议使用返回错误消息,给用户更好的体验;开发测试环境可以使用抛出异常,便于发现问题。

PRD需求描述

功能需求

FR-1: 自动重试机制

  • 描述:工具调用失败时,自动使用指数退避策略重试
  • 重试策略:支持配置最大重试次数、退避因子、初始延迟
  • 优先级:P0(核心功能)

FR-2: 异常类型判断

  • 描述:能够区分可重试和不可重试的异常
  • 可重试异常:网络超时、连接错误、5xx服务器错误、429限流错误
  • 不可重试异常:4xx客户端错误、参数验证错误
  • 优先级:P0(核心功能)

FR-3: 选择性重试

  • 描述:可以指定哪些工具需要重试,哪些不需要
  • 工具选择:支持工具白名单/黑名单机制
  • 优先级:P1

FR-4: 失败处理策略

  • 描述:所有重试失败后的处理策略
  • 策略类型:返回错误消息、抛出异常、自定义处理
  • 优先级:P0(核心功能)

非功能需求

NFR-1: 性能要求

  • 延迟累积:重试会增加总执行时间,需要在PRD中明确最大延迟容忍度
  • 超时设置:建议为工具调用设置超时时间,避免单次调用等待过久
  • 延迟控制:单次工具调用最多等待时间建议不超过30秒

NFR-2: 资源消耗

  • 重试次数监控:监控工具重试率,避免因重试导致成本激增
  • 资源限制:设置合理的重试次数,避免无限重试

NFR-3: 监控与告警

  • 重试率监控:监控工具重试率(重试次数/总调用次数)
  • 告警机制:如果重试率过高(>10%),可能表明工具或网络存在问题,需要告警
  • 失败原因记录:记录每次重试的失败原因,便于分析问题

产品设计要点

重试次数与延迟配置

max_retries设置

  • 网络工具建议3-5次
  • 本地工具建议1-2次
  • 避免过度重试导致延迟累积

backoff_factor设置

  • 建议设置为2.0(标准指数退避)
  • 如果需要更快恢复,可以设置为1.5
  • 如果需要更保守,可以设置为2.5

initial_delay设置

  • 快速工具建议0.5-1.0秒
  • 慢速工具建议1.0-2.0秒

产品建议:根据工具特性设置合理的重试参数,在可靠性和响应时间之间取得平衡。

工具选择策略

全工具重试

  • 默认对所有工具生效,适用于大多数场景

选择性重试

  • 仅对特定工具重试(如仅对网络工具重试)
  • 适用于有本地工具和网络工具混合的场景

排除特定工具

  • 某些工具(如支付工具)不应重试,避免重复扣款
  • 需要在PRD中明确排除列表

产品建议:建议在PRD中明确哪些工具需要重试,哪些不需要。特别是涉及资金、支付等操作的工具,需要特别注意。

异常类型判断

可重试异常

  • 网络超时、连接错误、5xx服务器错误、429限流错误
  • 这些都是临时性错误,重试可能成功

不可重试异常

  • 4xx客户端错误(如401认证失败、404资源不存在)
  • 参数验证错误
  • 这些是永久性错误,重试也无法解决

自定义判断函数

  • 可以实现retry_on函数,根据异常类型和HTTP状态码精确判断
  • 提供更灵活的控制

产品建议:建议在PRD中明确异常类型判断规则,避免对永久性错误进行无效重试。

使用建议

什么时候应该使用

  1. 网络依赖工具:工具依赖外部API,可能遇到网络问题
  2. 临时性错误场景:容易遇到临时性错误(限流、超时等)
  3. 容错要求高:需要构建健壮的AI智能体,不能因为临时错误就失败

配置建议

  1. 重试次数:根据工具特性设置,网络工具3-5次,本地工具1-2次
  2. 退避策略:默认使用指数退避,退避因子2.0
  3. 异常判断:明确区分可重试和不可重试的异常

注意事项

  1. 避免过度重试:设置合理的重试次数,避免延迟累积
  2. 排除敏感工具:支付、扣款等敏感工具不应该重试
  3. 监控重试率:如果重试率过高,需要检查工具或网络是否存在问题

与其他中间件的配合

工具重试可以与其他中间件配合使用:

  • 与ToolCallLimitMiddleware配合:重试次数不计入工具调用限制,避免因重试导致误触发限制
  • 与ModelFallbackMiddleware配合:工具失败后,如果LLM收到错误消息,可能触发模型回退或调整策略
  • 执行顺序:ToolRetryMiddleware应在其他工具控制中间件之前执行,确保重试逻辑优先

后续优化方向

  1. 智能重试:根据错误类型和历史数据,智能决定是否重试和重试次数
  2. 自适应退避:根据网络状况动态调整退避策略
  3. 重试预测:基于历史数据预测工具可能失败的情况,提前准备
  4. 降级策略:重试失败后,可以考虑使用备用工具或降级方案
滚动至顶部