详解尾延迟控制:可靠智能体工作流反直觉工程
在企业内部跑一个 LLM 工作流的时候,几乎所有失败都是廉价的:重试、回退,甚至直接忽略都行。可一旦把这个工作流挂到客户的 API 或 MCP 服务器后面,容错空间就瞬间归零。此时唯一重要的事情是:客户拿到正确、可用的结果了吗?他们的流程依赖于你交付的结果。由他们——而不是你——来决定什么算“交付”
要交付正确结果,比看上去难得多,因为 LLM 出了名地不可靠。它们经常以四种方式失败:无效回答(空、无法解析或干脆错误)、硬错误、完全没有回答、或者回答来得太迟。而且整个流程的成功依赖每一个步骤都不出错,所以你串联的步骤越多,其中某个步骤失败的概率就越大。即使每个步骤都表现出色,整个工作流也可能像一个抛硬币似的——成功概率五五开。
这说的是什么——以及不是什么:工作流,而非自由推理智能体
先做一个区分,因为它改变了一切。这里讨论的是**智能体工作流(agentic workflow)**:一个已知的处理流程,内部包含由 LLM 驱动的步骤,并由一个确定性编排器执行。它不是**推理智能体(reasoning agent)**——那种在运行时自行决定下一步行动的智能体。对于相同的任务,工作流显然更快:它已经知道计划,跳过思考过程,并并行运行所有独立步骤,因此能在几分之一的时间和成本内得到相同答案。两者各有其用(推理智能体灵活得多),但失败方式不同,修复方法也不同。推理智能体的问题是决定做什么;工作流的问题(客户能感受到的)是在规定时间内,以质量保证交付它已经知道怎么做的事情。本文讨论的是后者。我们的系统是如何构建的
下面的发现来自我们的架构,而且应该具有普适性。这些是普通的、直接的 API 调用。不过,了解我们的设置有助于你与自己的系统做比较。 我们运行一个自定义编排器,该编排器调度受管理的第三方 API(本数据集中不包含自托管模型),并且同时通过模型提供商自己的接口(OpenAI、Anthropic 等)和托管平台(Bedrock、Databricks 等)运行旗舰模型。因此,顶级模型有多个提供商。这让我们能够比较服务路径,并在它们之间转移工作负载。 我们的工作负载是混合的:简单的智能体调用、深度推理、提取、JSON 和自由文本输出。对于很大一部分调用,我们综合一个大型事实库来生成答案,因此输入大、输出中等偏小。本文中的分析在桶内保持输入和输出大小不变(参见附录)。 我们遇到的长尾很大程度上是瞬态的。请注意:如果你的架构是自托管或使用专用容量,尾部表现可能不同,需要采用另一种方法。其次,运行多个提供商正是使“路由到一个独立预算作为对冲”变得可行的原因。对于单个提供商,这些策略的选择会少很多。论点,以及证据
那么,这里有一个听起来反直觉的操作:**我们会在一个步骤执行到 20-30 秒时将其截断,尽管我们知道它如果再等一会儿可能会给出完美的答案——而这反而使系统更可靠,而不是更不可靠。** 这不是猜测。它在理论上成立——重尾分布下重试的数学计算是明确的——而且数据也支持:我们扫描了超过一百万个近期生产环境中的 LLM 调用,来自企业工作负载的真实客户流量。这些数据首先告诉你的是,单次调用的时间分布有多奇怪。典型的较长输出调用大约在十几秒内返回。但每 100 次调用中就有 1 次需要 30 秒,有时甚至超过一分钟——而原因与它做了多少工作毫无关系。为什么时间限制毫不留情
工作流不是以其平均值来评判的。它是在截止时间之前被评判的。平均而言,我们的流程可以轻松完成;但在长尾中的异常运行却无法完成。那些尾部运行本身并没有坏掉。它们只是稍晚一点返回完美答案;在内部运行时,它们会被算作成功。但在客户端,每一次这样的运行都是失败。延迟分布中整个长尾,无论答案正确与否,都会变成你失败率的一部分。 这就是为什么这里重要的数字不是平均延迟,而是方差。如果你的尾部很长,一个快速的中间值毫无意义。 第二个挤压因素是**沉没成本**。工作流执行得越深,你已经投入的就越多:时间、金钱和你的 TPM 配额。第 9 步的失败远比第 2 步的失败代价更高。你丢失了工作流构建的所有东西,并且你剩下的时间来调整策略的时间更少。我们从不自己重启整个工作流,但客户会。如果我们失败了,他们几乎肯定会重试,从头开始重新运行整个流程。这会在我们的系统上加剧问题。它消耗更多的成本、更多的 token 预算,以及 SLA 的错误预算。而且,由于导致运行失败的条件通常没有改变,重试同样可能失败。更糟糕的是,它往往发生在高 TPM 窗口期间。在最坏的时间将额外负载堆积到已经紧张的系统上,而且正是失败概率最高的时候。 还有第二个乘数效应,很容易被忽略。第一个是开篇提到的:可靠性是复合的,所以即使每个步骤都表现出色,整个链仍可能像抛硬币一样不可靠。但那种失败通常被描述为正确性的故事:拿到了错误答案。 你几乎从未听说的是:**完全相同的时间复合效应也在时钟上发生。** 每个步骤都会增加其落入慢尾的小概率,而且这些概率会累积。因此,你串联的步骤越多,至少有一个步骤超过截止时间的可能性就越大——即使每个步骤单独来看都很快。这正是本文要讨论的乘数效应,也是文献中很少提及的。所以,让我们来看看具体数字。LLM 回答时间的真实面貌
上图里典型时间集中在一个相当窄的区间内:每个模型在八到二十秒之间完成一次典型调用。而尾部则非常分散。一个模型的第 99 百分位调用在 30 秒左右,另一个则超过 80 秒。中位数相似,最坏情况却天差地远。告诉客户你的中位数,你就是在欺骗那 1/20 和 1/100 的尾部调用——而一个多步工作流会频繁命中这些尾部。**一个快速的典型时间并不等于可预测性。** 一个明显反驳是:慢调用只是在做更多的工作:更大的提示、更长的答案。但它们不是。即使固定提示大小和响应长度,尾部几乎没有变化:在同一个大小桶内(工作固定),第 99 百分位仍然是中位数的 **2 到 7 倍**(图 4)。慢的原因与调用需要做多少工作无关——在我们的流量中,它主要是瞬态的(排队、调度、流内争用、提供商故障),这正使其值得打断。一个慢步骤拖垮整个运行
你可能会认为工作流错过截止时间是因为很多步骤都稍微有点慢。但几乎从不这样。当一个链条超出预算时,通常只有一个步骤进入了它的尾巴区域,而其他所有步骤都表现正常。从数学上看,一个链条的超时主要由其最差的单个步骤决定,而不是由多个轻微慢步骤的累积。**总时间表现得像最大值,而不是总和。** 这是个好消息。你不需要每个步骤都快。你需要的是阻止任何一个步骤失控。这就是截断的意义。附注 — 简要的数学原理(不喜欢数学可以跳过)
- 复合效应。 独立步骤的简单算术:每个步骤成功概率为 p,n 个步骤端到端成功概率为 pⁿ。当 p = 0.95 时,10 步 ≈ 60%,20 步 ≈ 36%——纯乘法,无需建模。相同的复合效应也影响时钟:每增加一个步骤,就是一次独立的延迟尾部抽取(我们测得的每个调用 p99/p50 在 2-7 倍),因此至少有一个步骤超出预算的概率只会随着链条长度增加而上升。独立假设是一个简化——共享容量会使真实步骤相关——但这是一个保守的例证。
- 单一大幅跳跃。 LLM 延迟是重尾分布(类似对数正态),而对数正态属于次指数类。对于独立的次指数步骤,和的尾部渐近等于单个尾部的和:`P(ΣX_i > t) ≈ ΣP(X_i > t) ≈ P(max_i X_i > t)` 当 t 很大时。换句话说:链条超时是因为一个步骤命中它的尾部,而不是因为许多步骤都轻微慢。
- 对冲,以及它为什么对任何类型的失败都有效。 启动 n 个独立尝试,取第一个好的结果:如果单个尝试失败的概率是 q,那么所有 n 个都失败的概率是 qⁿ。这个算术不关心“失败”的含义——是一个超时、硬错误还是错误答案——它都以同样的方式减少,这就是为什么相同的重试/竞争/回退策略适用于各种失败。对于特定的时间维度,它还缩小了波动范围:由于独立步骤的方差相加,`Var(ΣX_i) = Σ Var(X_i)`,限制每个步骤的尾部会缩小整个链条的方差。所有这些都建立在尝试相互独立的基础上(新的抽取、新的队列)——这正是并行重绘能够摆脱瞬态尾部(或不幸的错误答案)的原因,而对于确定性尾部则无能为力。
策略:尽早截断,然后并行竞争
如果一个步骤进入它的尾部,等待是最糟糕的选择——你正在用你最稀缺的资源换取最不可能得到的回报。所以尽早放弃,然后并行地再次尝试:发起一个新尝试,取最先返回的那个。新尝试很少会掉进同一个坑里,因此两个尝试一起消耗的时间可能比一个卡住的调用还要短——而且两者都慢的概率微乎其微(如果单个慢的概率是 q,两个都慢的概率是 q²)。基于正确的信号进行截断
一个回答时间实际上分为两个阶段:等待**首个 token** 主要是排队和调度;后续逐 token 的**生成**是剩下的部分。哪个阶段承载了尾部决定了你截断的条件。而这取决于步骤写多少内容。 对于本文讨论的较长步骤(那些逼近截止时间的),尾部存在于**生成**阶段,而不是首个 token 等待。慢队列在 40 秒调用中只占一小部分;超支预算的波动在 token 中。因此,对于这些步骤,按**总耗时**来截断,或者根据你剩余时间与已生成的 token 数来截断,而不是根据 time-to-first-token(对于短步骤则相反:生成很少,首个 token 等待占据大部分调用,此时 time-to-first-token 成为更清晰的截断信号。测量你自己的步骤来看你属于哪一边)。 无论如何,有两个信号值得接入: - **超过截断时间仍未收到首个 token?** 那就是卡住,不是慢。放弃并对冲。一个新的并行尝试会重新调度,几乎总能成功。 - **token 正在流,但会超出预算?** 不要重新运行它。你只是以同样的速度重新生成同样的长度。降级到更快的模型。 还有一种时钟抓不到的失败:步骤按时返回但返回了垃圾(例如,内容为空、被截断或无法解析)。延迟截断会直接跨过去;只有下游的质量检查才能发现。对于任何应该返回特定形状的步骤,最便宜的质量检查就是在调用之后立即进行严格的验证。将结果按预期 schema 或对象解析,并把验证失败视为任何其他失败一样:截断并回退(重绘,或升级到更强大的模型)。它能在错误结果到达下一步之前抓住很大一部分。尽早截断为你赢得可预测性,而不是正确性。请将这两项工作分开。陷阱:对冲花费的是你最紧缺的预算
竞争有一个尴尬的特性:尾部最严重的时候正是系统最忙的时候。而“忙”恰恰意味着你的每分钟 token 预算剩余最少。因此,修复尾部的那个操作,偏偏在最难获得 token 的时候想花钱。如果盲目去做,就会产生叠加效应:慢调用触发对冲,对冲增加负载,负载使一切变慢,更多调用跨过截断线。一个延迟问题变成了速率限制问题。 有两个事实使这个问题比看起来更棘手。成本在发出第二个调用的瞬间就确定了。取消失败的调用会释放你的连接,但提供商会继续生成并计费那个被放弃的尝试。没有追回的可能,所以所有控制必须发生在决定对冲的时刻,而不是之后。而且你通常无法看到还剩下多少预算。估计它是可能的但很复杂,所以任何“当配额快要满时放松对冲”的方案在实践中都很难运行。 在实践中,更粗放但更结构化的方法有效: - **将对冲请求发送到拥有独立预算的位置。** Token 限制是每个模型和每个提供商独立的,而我们大多数人运行了不止一个提供商(如“我们的系统是如何构建的”中所述)。将重试路由到不同的模型或提供商可以获得独立的配额和独立的抽取。同一操作既能逃避阻塞,又能避免两次消耗稀缺预算。 - **通过对冲发起条件本身来将对冲控制在罕见情况。** 这正是预先计算的截断阈值的效果:如果将阈值设在每个步骤测量的 p95,那么对冲只在慢的少数情况下触发,额外消耗保持很小,无需任何运行时记账。(与下一节相同的截断值,不需要新机制。) - **对你实际能收到的信号做出反应。** 你可能读不到剩余配额,但你能读到 429 错误和延迟上升。把这些信号解读为减少对冲、推迟截断,而不是加大。 - **在真正饱和时,停止对冲。** 一旦提供商已经开始返回速率限制错误,更多尝试只会加深困境。降级到更小、更便宜的模型,或者直接丢弃工作。 有一个我们还没构建的杠杆,只作为方向提供:一个显式的全局上限,将对冲调用限制在总流量的一小部分,独立于每步决策。这是“大规模尾部”工作指向的原则性后盾;我们目前设置保守的截断值,还没用到它,但在更高的对冲率下,那会是我们下一步的方向。附注 — 你先做的低成本策略
截断和对冲是保险。如果工作流本身构建得好,你买的保险就更少。以下是在每次请求上默认执行的基础策略,在任何反应式技巧之前:
- **并行性设计。** 将流程布局为依赖图,一旦某个步骤的输入存在就立即运行它。更进一步——设计消除依赖。依赖越少,意味着更多的步骤是叶子节点,一个叶子节点失败时不会拖垮图的其余部分,代价更低。
- **不需要模型的时候就不要调用模型。** 最可靠的调用是你不需要进行的调用——只要工作不需要模型,就使用代码、查找和验证器。
- **按步骤混用模型,而不是按工作流。** 在够用时用快速便宜的;不够用时用能力强的。
- **缓存确定性部分。** 不要为不会变化的答案两次支付 LLM 费用。
要点:先花你的可靠性预算在结构上,这样时钟部分要修复的东西就少了。你什么时候真正触发截断?
截断是一个旋钮,不是一个常数。你拧多紧取决于关于每个步骤的三个简单问题: 1. **这个步骤的答案有多关键?** 可有可无:就让它失败。必须要有:保护它。 2. **有多少步骤在等待它?** 如果没有东西依赖它,就让它跑到截止时间。如果一半工作流队列在它后面,就尽快完成它,并且确保它正确,因为一个错误答案会毒害下游的一切。 3. **还剩多少时间?** 还多:从容重试。快没了:快速截断并回退。 一个步骤越是“必须要有”、“承载关键”、时间紧迫,你就越早启动备份,并且为它花费更多来对冲。一个可选的、终端的、时序靠前的步骤则不需要这些。(“在流程中是早还是晚”从来不是真正的轴;它只是有多少东西仍然依赖这个步骤的袋里变量。) 而且你不靠猜数。你要多次运行工作流,测量每个步骤的延迟曲线(P95),并据此设置截断值。低于该步骤的最坏情况,并用上述三个问题加权。一个通常 20 秒回答的步骤在 30 秒时截断,即使它可能在 60 秒时成功。为什么几乎没有人这么做
这并不难。只是需要细致入微,而且大多数团队没有相应的引擎。 流行的工流工具,比如 Airflow 和 Temporal,设计目标是让管道持久化:重试、恢复、不丢失状态——它们在这方面非常擅长。它们的超时建议遵循这个目标:设置一个比最慢运行还长的每步超时,然后重试直到成功。当目标是最终完成时,这是正确的本能——但当任务是要在时间内完成时,**这完全是错误的建议**。你的工作流引擎会高兴地多次重试一个步骤;它没有关于一个步骤测量到的典型时间及对下游影响的任何概念,因此它不可能尽早截断并切换模型。这不是缺陷。这是设计如此。 分布式系统的基础原理已经站在我们这边:从一个截止时间预算出发工作,将每个超时与测量到的延迟匹配。我们并没有在反驳这一点。我们是在将其应用到一个这些工具没有假设的场景:一个短暂、不可恢复的预算,在这里正确的操作是在截断后选择更快的替代方案,而不是再次调用同一个。同样的原理,方向相反。核心要点
只记住一点:**可预测的完成时间胜过有长尾的快速度。** 低方差胜过低延迟。你不能向客户承诺一个中位数,只能承诺一个边界。这里的一切都是为了那个边界。尽早截断、对冲、竞争、设计消除依赖:每一项都是用一点点平均速度来换取大幅减少方差。你放弃右尾来买左尾。 在面向客户的智能体工作流中,可靠性就是产品。真正的技艺不是拥有一个重试和回退的袋子——那是门槛。而是为每个步骤判断是否要对冲、何时放弃,基于约束和你自己系统的测量行为。附录
关于作者
Frank Wittkampf 是 Databook 的应用 AI 工程主管。他的团队架构、构建并运营一个完全自定义的 AI 栈,包括深度推理、智能体工作流引擎、AI 资产生成、智能体框架、知识库与上下文图谱、AI 预处理、多租户 AI 配置管理等。这个 AI 基础设施为微软、Salesforce、亚马逊、Databricks 等顶级企业的 GTM 团队提供动力。
关于数据的说明
本文中的延迟数据来自近期(2026 年 6 月)匿名化的企业客户工作负载生产流量——大约在 30 天窗口内的 120 万次 LLM 调用,并非合成基准测试或公开追踪。如“我们的系统是如何构建的”所述,这些是直接调用受管理的第三方 API,这也是慢尾在很大程度上是瞬态的部分原因。文中的数字描述了较长的调用(输出 ≥ 600 token),因为那些才是真正逼近截止时间的调用;较短的调用更快且变异性更小。在整个过程中,“尾部比”(p99/p50)在桶内保持调用大小固定,除非另有说明。模型仅按族和服务路径标记;可预测性取决于服务路径(例如,托管 API 与直接 API),而不仅仅是模型本身,因此这些故意不是模型排名。持续时间被分桶到 1 秒桶;90 秒硬上限仅截断了较长调用的最后约 0.2%,所以你看到的尾部是真实的,不是上限造成的伪影。
尾部难道不就是更大的调用吗?
对图 4 的一个合理反驳:每一行是一个 token 桶,而不是固定的 token 数,所以一个桶内的慢调用可能只是更大的那些——更多需要预填充,更多需要生成——而尾部只是工作量,不是任何瞬态因素。
并不是,而且数据本身的形状说明了原因。如果工作量驱动了桶内的尾部,那么两件事应该成立:尾部比会随着工作量的增加而增长,并且最紧密约束的桶几乎不会有尾部。两者都不成立。
从这张图可以读出两点。首先,尾部比在每个输出大小列上大致平坦在 2-4 倍——它不会随着工作量的增加而增加,因此尾部不与工作量成比例。其次,也是决定性的,看最左边那列:那些调用最多输出 **50 个 token**,所以生成时间物理上不可能变化超过大约一秒——但那里的尾部仍然约为 **3.5 倍**。没有足够大的工作量变量能产生这个差异。剩余的波动是瞬态的(排队、调度、短暂的提供商故障),这正是新尝试能逃离的。
为什么这些数字看起来比之前引用的 2-7 倍小:这里的列数值是跨许多桶的按量加权平均值,平滑了扩散,而正文中的 2-7 倍是每次调用的包络——个别桶实际跨度的范围。同一数据,两种不同的切分:平均值显示尾部不与工作量成比例;包络显示任何给定调用时的尾部有多宽。
注与脚注
注:所有图片由作者创建。
1: 10 个步骤各 95% 成功率 ≈ 60% 端到端;20 个 ≈ 36%(假设独立)。
2: 对数正态分布在次指数类中,其中独立项的和的尾部渐近地等于各个尾部的和:当 t → ∞ 时,`P(S_n > t) ∼ Σ_i P(X_i > t) ∼ P(max_i X_i > t)`——即“单一大幅跳跃”原理(Foss, Korshunov & Zachary, An Introduction to Hea vy-Tailed and Subexponential Distributions, Springer, 2nd ed. 2013, eqs. 1.3 & 1.6)。这是一个渐近陈述,并假设独立性,请将其视为“一个慢步骤占主导”的直觉,而不是一个可代入公式。
3: 如果每个独立尝试慢的概率是 q,则两个并行尝试都慢的概率是 q²;n 个尝试,qⁿ。经典的对冲请求结果(Dean & Barroso, “The Tail at Scale,” CACM 2013);在智能体环境中,Winston 等人(arXiv:2605.21470, ICML 2026)根据测量到的延迟曲线在串行、并行和竞争执行之间做选择。在我们的生产数据上,对较长步骤进行两个并行竞争使 p99 减半(约 60 秒 → 25 秒),而顺序重绘在总时间上没有效果。
4: 这种拆分在推理工作中是标准的:“首个 token 时间”(队列+预填充)与逐 token 生成。例如,Agrawal 等人,Taming the Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve(arXiv:2403.02310, 2024)。在我们的生产流量中,较长调用的尾部位于生成阶段,而不是首个 token 等待——这就是为什么我们对较长的步骤按总耗时而并非 time-to-first-token 截断。
5: Temporal 的活动超时被设计为最终完成,包括重试——因此 Start-To-Close 设置得比慢尾长。
6: Google SRE、gRPC 截止时间和 Spanner 都建议传播一个总预算并丢弃不再能帮助调用者的工作。我们将同一个原则扩展到同步、不可恢复的客户预算。
你是一名 AI 行业编辑,请围绕下面这条热点输出一份资讯解读:
热点:详解尾延迟控制:可靠智能体工作流反直觉工程要求:
1. 先用一句话解释这条热点在讲什么
2. 再总结它为什么重要
3. 说明会影响哪些 AI 产品或内容方向
4. 最后给出 3 个适合资讯站使用的标题
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
相关热点AI数据分析工具正在深刻改变团队的决策方式,而Metrixon便是其中一款值得关注的产品。它不再仅仅是一个数据仪表盘,而是围绕“角色”这一核心——根据你在团队中的具体职能、目标与责任,提供量身定制的洞察和建议。简单来说,它将商业数据、市场趋势和AI能力整合在一起,帮助团队更快、更聪明地做出决策,最终
市面上的浏览器插件琳琅满目,但能通过自然语言直接指挥浏览器完成任务的,Do Browser 堪称AI领域的革新者。今天介绍的这款 Do Browser,将人工智能深度集成到Chrome扩展中,只需说出指令或输入文字,即可轻松操控浏览器。 什么是Do Browser AI Chrome扩展程序 插件?
近期,埃隆·马斯克旗下的太空探索公司SpaceX,向内部投资者与利益相关方展示了一款AI设备原型。据透露,该设备外形比iPhone更纤薄,设计风格介于小型触屏手机与Rabbit R1之间。消息传出,外界纷纷猜测:一家以火箭发射闻名的公司,是否真要切入消费电子领域?尽管马斯克随后在公开场合澄清该报道“
生物科技领域日新月异,然而面对海量、复杂且常常残缺不全的实验数据,研究人员往往感到力不从心。传统分析工具在理想条件下表现尚可,但一旦遭遇真实科研中的“一团乱麻”——数据不完整、背景信息模糊、各类干扰并存——就容易失灵。如何破局?OpenAI 近日推出了一套全新的基准测试——GeneBench-Pro
- 日榜
- 周榜
- 月榜
热点快看
