在大屏或电脑上体验更佳——动画和操作区域更宽敞。
输入

错误恢复

错误恢复层先识别模型调用为什么失败,再选择等待、压缩输入、调整输出预算或使用兼容备用模型。原因没有变化就重试,常会得到同样结果。

搬沙发过门时,门暂时卡住与沙发本身太宽需要不同处理;地址错误则要先改目标。重试策略也必须区分暂态问题、请求问题和需要停止修正的问题。

错误恢复如何工作

本课把恢复分为改变时间、改变请求、停止自动尝试三类。

等待能处理的错误

示例的 529 overloaded 代表暂时的服务压力,真实的 429 rate_limit 也常如此。等待后重发同一请求,环境可能已经恢复。真实 429 也可能是额度或其他限制,不能只看状态码就断言稍等即可;要结合错误详情与服务端建议。

必须重建请求的错误

400 context_length_exceeded 表示本例的输入加预留输出超过窗口,等待不会缩短输入。应压缩旧消息、保留所需近况,再检查新请求大小。

成功响应中的 stop_reason: max_tokens 表示生成触及输出预算,本例把它视为未完成并增加 max_tokens。真实处理还应检查任务是否完整,增加预算也不能超过模型输出上限或输入加输出的总限制。

反复 529 可以触发切换到获准、兼容的备用模型。这是恢复策略,不证明原模型选错或永远不会恢复。备用模型的工具与请求格式也必须兼容。

停止后再修正的错误

本例 400 invalid_request_error 是无效工具 JSON Schema。等待、压缩、盲目切换模型都不修复 schema,因此第一次就停止并报告。修正请求后可以再试;“不自动重试”不等于错误永远无法修。

从哪里识别错误

classify(response) 要读取不同层:HTTP 状态如 429、529、400;错误体判别字段,如本课 Anthropic 风格的 error.type,含 rate_limit_error、overloaded_error、invalid_request_error;成功响应中的停止原因,如 stop_reason: "max_tokens"。不同 API 的字段并不完全相同。

业务成功由 harness 判断,不能只看 HTTP。 截断可以伴随 HTTP 200。只捕获异常会漏掉这种未完成结果。

错误恢复逐步演示

默认请求过长,策略先分类再重试,共八步。

  1. 组装请求。 模型 primary,输入 203,800 token,max_tokens = 4,096,34 条消息,窗口 200,000。
  2. 第一次尝试。 提交 203,800-token 输入。
  3. 拒绝。 400 context_length_exceeded。本例检查 203,800 + 4,096 = 207,896 > 200,000,输入本身已经超限。没有生成、超时或过载;原样发送仍不满足限制。
  4. 分类。 得到 context_too_long,需要改变请求,不能靠等待。
  5. 压缩。 最旧 28 条消息共 172,300 token,换成 1,450-token 摘要;最近 6 条共 18,900 原样保留;system 与工具定义 12,600 在本策略中不改。新输入 32,950 token、7 条消息,约减少 84%。任务和近况保留,旧消息摘要仍有损。
  6. 第二次尝试。 模型与 max_tokens 不变,提示内容及消息数改变。
  7. 成功。 32,950 + 4,096 = 37,046,处于窗口内。
  8. 账目。 2 次尝试,等待 0.0 秒,提交输入合计 236,750 token。这是提交量,不是实际计费;确定性超限先修请求,无需先退避。

切换 blind,每次都发送 203,800,失败后等待 1、2、4、8、16 秒。共 5 次尝试、31 秒退避、1,019,000 token 提交量,没有答案。最后失败后还等 16 秒才退出,是这段朴素循环故意保留的问题。

盲目重试的成本差异

暂态过载中,两策略都在等 1 秒后第二次成功,共提交 49,200 token,分类没有改变这个结果。差异来自不能靠时间改变的失败。

上下文超限时,blind 提交量约为 classify 的 4.3 倍,额外等 31 秒仍失败。无效请求则由 classify 用 1 次、0 秒结束,blind 用 5 次、31 秒结束;前者尝试数与提交量为五分之一,但不能据此称真实速度或价格恰好改善五倍。

压缩本身也有成本。读取 172,300-token 旧历史生成摘要,是额外模型工作,本账本未计。把这个输入加回,分类路径约为 409,000 输入 token 暴露量,和 blind 的提交量比约 2.5 倍,不再是 4.3 倍。这仍不是账单:被拒请求是否计费、缓存、摘要输出与不同模型费率都会改变价格。修复调用也应纳入实际预算。

暂时与持续的 529 初次响应相同。示例先等 1 秒、2 秒,第三次仍失败后切备用模型,第四次成功。重试预算定义“何时换路”,不证明主模型无法恢复。这里不统计真实错误频率,也不能把示例类别当成所有失败的比例。

边界情况

  • 压缩还不够。 保留尾部已超窗时,一次摘要无法解决。应缩小保留范围、分块或明确失败,不能无限重复同一修复。
  • 备用也不可用。 切换不保证成功,仍需总预算与结束条件。
  • 重复副作用。 若先前操作已扣款或发消息,重试可能重复执行。接收方支持并落实幂等键时可复用稳定键,否则需要去重或对账恢复。仅附一个被忽略的键没有保证。
  • 输出再次截断。 加倍预算受输出上限和总窗口约束;到上限应缩小任务或分段完成。
  • 没有 jitter。 所有客户端按 1、2、4、8、16 同时醒来,可能再次形成请求峰值。真实退避通常加入随机性并遵守服务端建议。

常见错误

  • 把失败当一个布尔值。 一个 except 加 sleep 会对无需等待的错误也延迟。读取具体错误类型与响应状态。
  • 修好确定性问题后还先等。 压缩后无故等待四秒不再修复任何东西。若服务端另有流量限制,则需按该独立限制处理。
  • 最后失败后仍 sleep。 blind 的最后 16 秒不通向新尝试,只增加等待。
  • 只捕获异常。 HTTP 200 也可能未完成,应检查停止原因与任务所需完整性。
  • 把所有 400 当成同类。 无效 schema 应先修 schema,本课的上下文超限也用 400,却可以压缩后再试。不能只按状态码决定。
  • 备用掩盖故障。 每次都悄悄切备用会遮住主模型长期异常,应在日志里记录切换原因、次数和结果。

模型的简化

请求大小、压缩比例、故障序列都是预设,由确定性 harness 计算,没有调用模型,也不是模型录制。等待秒数是示例策略,不是生产默认值。

账本把修复成本计为零:没有摘要模型的 token、输出与延迟,也没计备用路径的冷启动。引用比值时必须保留这些范围,且提交 token 不等于收费 token。

真实恢复还包括 jitter、retry-after、中断流恢复、受支持的幂等机制、熔断、分错误类型的预算,以及客户端令牌桶限流。分类与修复思路可复用,数值只用于核算本课示例。