错误恢复与终止熔断
恢复手段按什么顺序分级升级?
- 排序依据: 对用户透明的程度——能用低级别解决就不升级;
| 级别 | 手段 | 关键细节 |
|---|---|---|
| 1. 静默重试 | 可重试错误的默认动作 | 指数退避叠加随机抖动,避免大量客户端同步重试造成二次拥塞;尊重服务端返回的等待时长提示 |
| 2. 降级与接续 | 改变请求本身再试 | 输出触顶时先提升输出上限重发,仍不够再追加元指令从断点接续;主模型过载时降级到备用模型;高成本模式被限流时回落到标准模式 |
| 3. 暴露给用户 | 所有自动手段用尽后呈现错误 | 必须附上已尝试过的恢复动作 |
- 前后台区分: 主循环请求失败要重试,标题生成、输入建议这类后台辅助调用失败则直接放弃,否则后台重试会挤占主链路配额,形成“重试放大”;
- 备用模型注意点: 切换前需剥离旧模型私有的格式块,否则新模型无法解析历史消息;
工具层错误为什么要变成模型的输入?
- 原则: 不终止会话,把错误变成模型的输入;
- 表现一: 幻觉调用收到“工具不存在”的结构化错误结果;
- 表现二: 参数校验失败收到附带输入约束提示的错误;
- 表现三: 畸形参数(本该是对象却输出字符串)在执行前先经程序化修复;
- 机制: 这些错误以普通工具结果的身份进入上下文,由模型下一轮自行纠正;
- 依据: 喂回的错误越具体,模型自我纠正成功率越高——即“反馈越结构化越好”;
恢复循环的边界原则是什么?
- 原则: 错误处理的边界不是单次请求,而是整个恢复循环;
- 要求: 在确认无法恢复之前,中间错误不应暴露给消费者(用户或订阅事件的下游系统);
- 效果: 恢复期间扣留错误消息,恢复成功则消费者毫无感知,所有手段失败后才统一呈现错误;
跨厂商接管时哪些内容带不走?
中立轨迹
├─ 思考:可移植的文字 + 厂商签发的不可移植凭证
├─ 工具调用:只记录名称与参数
└─ 标识符:渲染成具体请求时按目标厂商重新生成
- 真障碍: 不是接口地址不同,而是轨迹里有一部分只属于原厂商;
- 可移植部分: 工具调用与结果各家结构不同但语义一致,重新渲染即可;思考中的可读文字换一家仍读得懂;
- 不可移植部分: 厂商附在思考上的凭证用来证明这段思考出自它自己,换一家即失效;
- 原则: 跨厂商接管能带走的是文字,带不走的是凭证;
- 厂商差异: 宽松端不校验,严格端拒绝一切非自己签发的凭证;凭证还可能附在工具调用而非思考上,因此“把思考删干净”反而通不过;
- 设计: 按最严格的一端设计,并准备退路——把历史工具调用改写成文字叙述,模型不再当作真正调用过的工具,但至少能接着跑;
- 中立格式要求: 轨迹不按任何一家接口格式存储;切换时凭证一律丢弃,文字以普通内容身份带入,而非塞回目标厂商放思考的位置;
- 附带收益: 厂商返回的思考摘要本就是为这种场合准备的可移植副本,保留即可,不必再调模型压缩;中立轨迹还可用于评估重放、训练样本构造与经验提取;
跨厂商接管的实验结论是什么?
- 对照三做法: 直传(原厂商消息原样搬入新厂商结构)、剥离(删掉全部思考与凭证)、中立(丢凭证、带文字、标识符重渲染);
- 硬性要求: 中立做法在全部厂商组合上都不出现接口错误;直传的失败必须是厂商真实返回的错误,不得用模拟错误代替;
- 观测项: 任务完成率、切换后重复调用同一工具的次数(按“工具名 + 参数”指纹计)、切换后到完成所需的额外轮数与 token;
- 诚实记录: 若中立做法在重复调用上并未优于剥离,同样如实记录;
输出到一半断掉之后如何接续?
- 三类断点: 思考中途、正文中途、工具调用参数中途;
- 三种恢复: 丢弃半截整轮重发;把半截内容作为末尾 assistant 消息要求接着写(部分厂商原生支持,有的需显式标注待续写,没有接口的退回下一种);追加一条元指令说明从断点继续;
- 工具调用特殊处理: 半截工具调用无法以原生结构回传,需先转成文字让模型补完,拼接后重新解析校验;
- 副作用防护: 若半截输出里已有工具因流式提前执行,续写前按调用指纹去重,避免重复副作用;
- 观测项: 各方式的恢复成功率、相对整轮重发节省的输出 token、补完后参数的合法率与语义正确率(拼接处易多出空白或重复字符,合法不等于正确)、重复副作用次数;
- 诚实记录: 哪些断点在部分厂商上无法复现,以及降级路径是否可用;
每条恢复路径为什么必须有熔断上限?
- 前提: 恢复机制本身也会失效,因此每条路径都必须有明确上限;
- 示例: 上下文压缩连续失败若干次就放弃压缩、权限分类连续失败就回退到人工询问、输出接续最多尝试固定轮数;
- 阈值来源: 生产数据而非拍脑袋;
- 实证: 压缩熔断的“连续 3 次”来自真实会话统计——曾有一个会话在这条路径上连续失败三千余次,这类无效重试每天在全球造成约 25 万次 API 调用浪费,逾千个会话出现过 50 次以上连续失败;
- 拐点含义: 3 次是“绝大多数故障此前已恢复”与“继续重试基本无望”之间的经验分界;
死亡螺旋如何形成与打断?
- 连锁案例: Agent 因上下文溢出而停止 → 触发“结束时自动提交代码”的停止钩子 → 钩子调用 LLM 生成 commit message → 再次上下文溢出 → 又一次触发钩子;
- 防护一: 在错误路径上禁用一切会再次调用模型的副作用逻辑,宁可丢掉一次辅助功能(如自动记忆提取);
- 防护二: 用递归深度计数器检测并打断残余连锁;
全局终止与升级条件有哪些?
- 终止上限: 最大迭代轮数、会话预算上限;
- 升级条件: 连续失败超过阈值时升级到人工干预;
- 定位: 所有自动化机制之上仍需这层全局兜底;
- 分类与检测的入口: 见 故障分类与检测;