概述
在前面的章节中,我们讨论了如何通过工具选择器降低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中明确异常类型判断规则,避免对永久性错误进行无效重试。
使用建议
什么时候应该使用
- 网络依赖工具:工具依赖外部API,可能遇到网络问题
- 临时性错误场景:容易遇到临时性错误(限流、超时等)
- 容错要求高:需要构建健壮的AI智能体,不能因为临时错误就失败
配置建议
- 重试次数:根据工具特性设置,网络工具3-5次,本地工具1-2次
- 退避策略:默认使用指数退避,退避因子2.0
- 异常判断:明确区分可重试和不可重试的异常
注意事项
- 避免过度重试:设置合理的重试次数,避免延迟累积
- 排除敏感工具:支付、扣款等敏感工具不应该重试
- 监控重试率:如果重试率过高,需要检查工具或网络是否存在问题
与其他中间件的配合
工具重试可以与其他中间件配合使用:
- 与ToolCallLimitMiddleware配合:重试次数不计入工具调用限制,避免因重试导致误触发限制
- 与ModelFallbackMiddleware配合:工具失败后,如果LLM收到错误消息,可能触发模型回退或调整策略
- 执行顺序:ToolRetryMiddleware应在其他工具控制中间件之前执行,确保重试逻辑优先
后续优化方向
- 智能重试:根据错误类型和历史数据,智能决定是否重试和重试次数
- 自适应退避:根据网络状况动态调整退避策略
- 重试预测:基于历史数据预测工具可能失败的情况,提前准备
- 降级策略:重试失败后,可以考虑使用备用工具或降级方案