Agent 工具超时重试已经写过了。这次往回退一层,谈推理服务本身的请求级重放——特指推理网关和 Agent 编排层收到的同一条业务请求被重放时,幂等键该整在什么位置。
先给结论:绝大多数团队的幂等键放在 HTTP 入口,只防住了「同一个 POST 打了两次」。但真正烧钱的重复执行发生在语义层:同一个 Agent 目标走出了两条推理路径,幂等键完全不同,收费却是两倍。这两个问题不是一个机制能解决的。
先分清两种重试意图
tianpan.co 上那篇讲 LLM 流水线幂等的文章把这个区分讲得很清楚:为了瞬时可靠性的重试和为了采样更好答案的重试,需要完全相反的处理。
瞬时重试的前提是「活儿已经干了,只是响应在链路上丢了」。这时要的是从缓存里拿回原结果,绝不能再推理一遍。采样重试的前提是「这次输出不合格,格式错了、被护栏拦了、解析失败了」,这时要的是新样本,重试时必须换有效载荷,通常还得把上次的错误信息回填进 Prompt。
最常见的坑就是把采样重试当成瞬时重试做。一个 Agent 发出工具调用,工具超时,Agent 层判定失败后重放——但第一次调用其实已经执行完,只是回执晚了。结果就是两次副作用和一份乱套的状态机。
放到推理服务内部的对应关系是:前缀缓存命中、连续批处理里的批内复用、网关的结果缓存,这些都能降低算力开销,但它们不是幂等机制。它们没有「这条请求交付过一次」的保证。如果缓存键和幂等键是两套独立系统,重试完全可能绕过缓存,重新排进推理队列。这一点在之前写工具结果缓存那篇时就踩过:三处缓存键不一致,复用直接变成废纸。
键落在 HTTP 入口,只能防一半
腾讯云开发者社区那篇文章给的公式很直白:幂等 = 唯一请求 ID + 存储状态(处理中/已完成)+ 重复判断逻辑。客户端在请求头里带 Idempotency-Key,服务端用 Redis 记状态,INIT、PROCESSING、SUCCESS、FAILED 四个态,PROCESSING 和 SUCCESS 直接拒绝新推理。落地逻辑本身不复杂。
难点在时间参数上。推理耗时从几百毫秒到几十秒不等,如果复用一个很短的幂等状态 TTL,就会出现一种非常恶心的场景:第一次请求还在 GPU 上跑,状态过期了,重试请求穿透过去开始了第二次推理。所以幂等状态的过期时间必须覆盖「最大推理耗时加客户端重试周期」,这里的最大值要按 P999 来找,不能拿平均值拍脑袋。
只落在入口的另一个漏洞是:一个 Agent 编排步骤可能包含五次模型调用和三次工具调用。客户端给每次 HTTP 调用都生成各自的 UUID,那么整条链路重放时,每个子调用的幂等键全都是新的,一个也防不住。健必须整在逻辑操作上——也就是那个会产生外部副作用、会对应一次计费归属的工作单元,而不是某个具体的 HTTP 请求。
请求级重放的落地基线
把上面这些拼起来,我线下能推的一套最小方案是这样的:
- 幂等键由编排层生成,作为业务请求的身份,沿整条调用链透传,禁止下游组件另行生成。
- Redis 存两样东西:请求状态,以及首次推理的结果正文。结果比对错成本更值钱,重试时宁可多占点存储也要存,否则「已经算完但响应丢了」只能靠重算恢复。
- 真正真正执行之前先抢分布式锁,锁键就是幂等键,锁的持有时长取模型最大推理时间,超出就当作异常释放,别把幂等状态当成死锁用。
- 采样重试使用派生键:
原文幂等键 + 重试序号,或者这个带上错误概要的哈希。这样它在语义上是新请求,但同一次网络故障下的重放仍然能找到原结果。这是前面那个「双重重试陷阱」的最小解。 - 不管请求是否被拦,会话历史里这条用户消息只能落一次。多轮场景下重复插入比重复推理更致命,会把后续每一轮的上下文都带偏。
做到这几条,计费和会话基本干净了。但它依然只能覆盖「相同请求的重放」。
更难的那坡:同一意图走了不同路径
Agent 层的现实是,同一个子目标可以用不同的措辞、不同的参数把工具调出来,HTML ID 差一位,字符串差个空格。这时候内容哈希对不上,幂等键就是两把,副作用执行两次。
tianpan.co 那篇给了个三个渐进的漏斗:先字符串精确匹配,再对规范化表示做 Embedding 相似度比对,最后只把模棱两可的样本交给 LLM 判断。阈值上,近乎相同取 0.9 左右,意图等价取 0.85。文章引用的生产区间是真实 Agent 流量上 20% 到 45% 的命中率,这个数字我不建议当基准照搬,因为它的成败很依赖阈值调得对不对,而线上冒烟和压测几乎调不出来:阈值太低会把合法操作拦下,太高又会漏掉仅改了措辞的重复动作。另外它要求查找本身在 50 毫秒级以内,超了就谈不上省钱了。
我对这层的态度偏保守。语义去重只应该用在读多写少、重放成本明确的动作上。真正带副作用的写操作,还是要靠确定性强的幂等键来自保;用相似度来挡付款调用,没人会担这个心。
成本那笔账
为什么值当折腾这一圈,可以用一个保守的算法对齐:重试风暴期间每个未受保护的请求,付的并不是只多一次的钱,它的下游 API 也多了一份。那篇文章自己举的例子大致是一笔五十美元量级的批处理作业,网络抖动重试三次变成两左右,至于「事故期单次成本翻几倍」这类数字,我一直拿来看量级而非当精确值。真正能落地的指标只有一个:各层的幂等命中数。正常情况下它平稳,重试风暴期间它应该跳起来。如果反而掉了,说明有条代码路径根本没接去重层——这比任何仪表盘都直观。
腾讯云那篇文章列出来的收益清单里,我认为只有两条是真需要盯的:重复推理占着 GPU 算力和调度队列(在高并发下比多花的钱更要命,因为它会吃满你的批处理槽位,把后面所有正常请求的 P99 拖进去),以及幂等链路上的错配。其余几条更像是结算和对账业务的指标,不在推理服务的锅界内。
心智模型的切换点是:传统业务里幂等性是单次操作的属性,在 LLM 流水线里它是工作流的属性。核心组件本身是随机的时候,不先定义清楚「什么算同一个操作」,写多少套幂等键都是在自扫门前雪。
转载请注明出处: 皮哈皮阿
本文的链接地址: https://blog.phpat.com/ai-dev/680.html
微信或手机浏览器扫一扫,随时随地随心阅读与分享
-
上下文工程:从 Prompt 到 Context 的工程化实践
客服 Agent 答错时,团队第一反应是换模型。把那次请求的上下文打印出来才发现,模型看到的是一份过期政策、两份互相矛盾的条款,还有一长串无关日志。上下文工程要解决的,就是这类问题。
2026/10/06
-
RAG 的下一站:Agentic Retrieval
用户问“我们去年买的套餐现在还能退吗”,经典 RAG 检索出一段通用退款政策就结束了。可这个问题至少要拆成订单时间、地区、套餐版本三件事。Agentic Retrieval 要解决的,就是这种“一次检索不够用”的场景。
2026/10/12
-
约束解码让 JSON 不再崩,但它会改坏推理
约束解码让 JSON 解析失败率归零,工程师可以删掉一堆重试和修复代码。但它会挤占模型的推理预算:强制格式在部分任务上带来10%以上的准确率下降。文章梳理 OpenAI、Anthropic、Gemini 和其他自托管引擎的现状,以及 schema 设计、两阶段模式与编译缓存几个实操要点。
2026/10/22
-
推理模型输出被截断后怎么接回去
推理模型遇到输出截断,重试整条请求代价高;续写也有隐藏门槛。从识别边界、提示回灌到 prefill 与成本判断,聊聊工程上怎么做才不算亏。
2026/10/25
-
Agent 上下文压缩:四层策略与失败代价
把 Claude Code 的四段分层与 Hermes Agent 的双阈值压缩系统并排看重:200K 窗口下的 50%/85%、legacy 与 lean 尾部的实测差池、未处理到的摘要模型窗口溢出,以及工具对配对边界为什么是能不能跑的问题。
2026/10/23
-
推理模型的并行思维链采样怎么用才不亏
并行思维链采样的成本不是白花的。结合推理模型测试时计算的几条实证结论,梳理best-of-N、束搜索、自洽性投票和自我修订在什么场景下划算、什么场景下只是在烧钱。
2026/10/26
京公网安备11011402053654 
@muffin:链接已更新,分类图像功能...
AI网址导航模版图标库更换指南
作者大大,图标库邀请链接失效了,麻烦更新...
AI网址导航模版图标库更换指南
太好看了,快点更新!
友情链接
@戴墨镜的刘备:哈喽,路过点赞。
vue.js组件之手写签名板vue-signature-simple
太好看了,快点更新!太棒了!👍真的很赞!
vue.js组件之手写签名板vue-signature-simple
你写得非常清晰明了,让我很容易理解你的观...
Emlog插件RSS订阅器发布