跳到主要内容

延迟、成本与服务扩展

Agent 服务的延迟与成本来自模型调用、工具执行和排队等待。本文先拆分一次任务的耗时,再说明 Token 费用与缓存的计算方式。最后讨论请求增长后,怎样控制并发、分配配额和降级。

1. 面试核心​

先记住这几条,再读正文
  • 端到端延迟。 Agent 的端到端延迟由关键路径上的模型调用、工具执行和排队等待共同决定。卡 · 延迟的组成
  • 任务成本。 一次任务的费用是各轮输入、缓存和输出费用,以及工具与检索费用之和。卡 · 成本控制
  • 并发与速率。 信号量限制同时执行的调用数,RPM 和 TPM 分别限制每分钟的请求数和 Token 数。卡 · 并发、限流与降级
  • 慢任务归因。 慢任务的追踪记录能区分轮数增加、单轮变慢和等待变长这三类原因。卡 · 延迟的组成
  • 缓存类型。 前缀缓存复用相同输入前缀的计算,结果缓存直接复用已有的业务答案。卡 · 前缀缓存与结果缓存

2. 延迟的组成​

优化延迟前,要先知道时间花在哪一段。链路追踪会记录每轮模型调用和工具调用的起止时间,让你找到决定完成时间的关键路径。

环节观察指标优化方向
首 TokenTTFT、输入量、缓存命中精简输入、复用前缀、减少排队
生成输出长度、生成耗时减少无用输出、评测模型选择
循环轮数、重试和重规划合并固定步骤、限制重复尝试
工具单次耗时和依赖关系缓存、安全并行、超时
排队队列长度、等待时间容量、优先级与背压

首 Token 延迟(TTFT)是发出请求到收到第一个输出 Token 的时间。之后的生成耗时,可以近似看成剩余输出 Token 数乘以每个 Token 的平均耗时。推理模型还会生成内部推理 Token,所以可见回答很短时,等待时间也会很长。

串行步骤需要等上一步完成,因此耗时相加。独立步骤并行后,主要等待最慢的分支完成,还要加上调度与汇总的开销。这就是为什么减少串行轮数,经常比只加快其中一次调用更有效。

根据追踪中的瓶颈,可以分别优化模型轮次、单轮生成、网络、工具和排队:

  • 减少模型轮次:固定的工具顺序由代码编排,同一轮可合并多个判断。无依赖且允许同时执行的工具可以并行,并设置最大步数限制重复尝试。
  • 缩短单轮生成:压缩历史和工具结果,只要求任务需要的输出。比如参数抽取可以返回结构化字段,省去长篇解释。简单步骤可评测更快的模型,减少不必要的推理耗时。
  • 减少输入和网络等待:稳定前缀有助于命中缓存,就近部署可缩短网络往返。TTFT 还包含服务端排队,因此要结合输入量、缓存命中与服务指标判断原因。
  • 缩短工具等待:缓存可复用的工具结果,给下游调用设置超时。工具有数据依赖时,仍需按顺序执行。
  • 控制排队:预留模型配额,按优先级处理请求。背压指下游忙不过来时,让上游放慢或拒绝新工作,避免队列无限增长。

流式返回让用户更早看到文字,改善的是首次可见反馈。完整任务的耗时仍需单独记录。长任务可以先返回任务 ID,再通过 SSE 推送进度,或由客户端轮询查询。SSE 是服务端持续向客户端发送事件的机制,适合单向更新任务进度。

取消与超时应传到后续步骤。这样,用户停止任务后,后台调用也能及时结束,减少继续消耗的预算。

3. 成本控制​

控制费用要先按任务累计各轮用量,再乘以对应单价。未缓存输入、缓存读取与输出分别计费。提供方另有缓存写入、工具或检索费用时,也要一并计入。推理 Token 属于输出用量,按所用模型的计费规则计算。

下面以 OpenAI Responses API 为例,区分用量总数与其中的明细:

Responses 用量字段含义
input_tokens本次处理的输入总量。
input_tokens_details.cached_tokens输入中命中缓存的部分。
output_tokens本次生成的输出总量。
output_tokens_details.reasoning_tokens输出中用于推理的部分。
total_tokens输入量与输出量之和。

缓存命中量已经包含在输入总量中,推理量也已经包含在输出总量中。所以,统计总量时无需再加这两项。计算费用时,则要把用量拆到各个计费类别,分别乘以实际单价。

多轮对话反复处理历史,会让累计输入快速增长。假设第一轮输入为 B,每轮新增固定长度 d,并且每轮重发全部历史。第 k 轮输入约为 B+(k-1)d,n 轮总输入就是 nB+d*n*(n-1)/2。其中后一项随轮数平方增长,解释了长循环为什么容易消耗大量 Token。

压缩和裁剪会减少后续输入量,前缀缓存则减少重复输入的计算与费用。可以按成本来源选择下表中的手段:

手段做法
压缩保留目标、约束、当前证据和产物引用
按需加载工具与技能只展开相关部分
模型路由按任务评测选择能力与成本组合
结果缓存对满足身份和新鲜度条件的结果复用
批处理用于可延后完成的离线任务
预算限制单任务、用户和租户的累计开销

具体应用时,要结合成本来源选择压缩、加载、路由、缓存、批处理与预算控制:

  • 上下文压缩保留目标、约束和结论的来源,工具原始结果可改为摘要与引用。具体取舍见上下文压缩。
  • 按需加载先提供工具或技能摘要,需要执行时再展开,减少每轮重复的固定输入。加载方式见 Agent Skills。
  • 模型路由可以把意图识别、参数抽取、记忆整理和压缩交给小模型,把复杂推理交给能力更强的模型。这些任务调用频繁,小模型达标时就能减少累计费用与延迟。
  • 结果缓存需要设置过期时间,并按身份和数据版本判断结果是否仍然有效。语义检索阈值只负责筛出候选,具体边界见下一节。
  • 批处理把可延后的离线任务交给提供方的批量接口,适合时效要求低的工作。
  • 预算上限同时约束任务、用户和租户的 Token 与调用次数。达到上限后停止继续调用,并明确返回已经完成的结果。

模型选型要用同一份评测集,比较成功率、延迟和每个成功任务的总成本。单价低的模型若需要更多轮次或重试,总费用反而会增加。输入和输出谁占大头,也取决于数量、单价与缓存命中,应该根据实际用量判断。

3.1 前缀缓存与结果缓存​

两种缓存复用的对象不同,所以命中条件也不同。前缀缓存复用相同输入前缀的计算,模型仍会为本次请求生成结果。

组装输入时,把稳定规则和工具定义放在前面,有助于保持共同前缀。修改某处后,从该处开始的计算需要更新,前方满足条件的部分仍可命中。缓存命中还受模型、最小长度和保留时间等条件影响,要通过 API 的缓存用量字段验证。

前缀缓存省去的是重复输入的预填充计算,原理见大语言模型基础。

具体组装顺序见上下文管理。

结果缓存直接返回已有的业务答案,因此要确认答案仍适用于当前请求。缓存键应包含请求参数、租户、权限范围和相关数据版本。语义相似度可以帮助找到候选,但仍要核对身份、实体和时效。比如两个人都问“我的订单到哪了”,所需答案属于不同用户。

支付、删除等操作会改变外部业务状态,这类变化称为副作用。结果缓存无法保证副作用只发生一次,需要由业务幂等机制处理重复请求。

4. 并发、限流与降级​

请求增长后,要同时保护模型配额与工具下游。并发数表示同一时刻正在执行的调用数,速率表示一段时间内发出了多少请求。

提供方按每分钟请求数(RPM)和每分钟 Token 数(TPM)限制用量。即使同时只运行少量请求,短请求快速完成后,仍会耗尽 RPM。TPM 则还与输入量、输出预算有关。信号量通过固定数量的许可限制同时执行的调用数,所以还需要单独控制请求速率。

服务需要处理以下三类容量风险:

  • 模型配额耗尽:超过速率限制会收到 429 响应。立即大量重试会继续占用配额,让失败进一步增加。
  • 下游容量耗尽:数据库、内部接口和浏览器都有容量上限。多 Agent 或批量任务并行调用时,会把压力集中到同一个下游。
  • 循环持续占用资源:失控任务反复调用工具与模型,会挤占其他用户的配额。

可以把保护措施放在以下五个位置:

  1. 请求入口按用户、租户和接口分配配额,用令牌桶等方式限制请求速率。
  2. 任务队列由固定数量的工作进程消费,并限制队列长度和最大等待时间。根据积压决定扩容、延后或拒绝任务。
  3. 调用入口为每个模型和工具设置独立的信号量,并累计速率用量。比如 100 个任务最多同时执行 3 个。收到 429 后有界退避,响应提供 Retry-After 时按它等待。
  4. 降级流程使用经过评测的备用模型,或关闭反思、重排序等非核心步骤。也可以返回只基于检索的简化结果,最终转人工或稍后恢复。
  5. 业务隔离让不同业务和优先级使用独立的队列与配额,减少相互影响。

重试需要计入原任务的预算和总截止时间。备用模型与简化流程也要满足最低验收要求,持续失败时应保存进度并停止接收超出容量的新工作。

多模型或多提供方的应用还可以使用模型网关,即应用与模型服务之间的统一调用层。LiteLLM 或自研网关可以集中管理以下能力:

  • 转换接口格式,并在程序侧管理调用凭据。
  • 按任务选择模型,执行重试与故障切换。
  • 统计用量,并统一实施限流。

5 · 面试题卡片​

本页题目与参考回答

5.1 一个 Agent 推理链路包含 3 个工具,请求频率也高,整体延迟较高,你会怎样优化?​

考察重点

  • 能把延迟拆到每轮模型调用、每个工具和排队等待,找到关键路径。
  • 能根据依赖关系选择并行与缓存,并解释流式返回改善哪一段体验。

相关内容:延迟的组成、组装顺序与前缀缓存。

参考回答

应根据关键路径减少串行等待,再优化单轮调用和高频请求中的重复工作。

先比较每轮模型调用、三个工具和排队的耗时,并单独记录重试。工具顺序固定时,可以由代码编排,省去每步让模型决策的等待。三个工具相互独立时,让模型一次提出多个调用,再安全并行执行。

随后按测量结果优化单轮耗时、重复调用和首次反馈:

  • 压缩历史与工具结果,限制无用输出,并用稳定前缀提高缓存命中。
  • 按请求参数、身份和数据版本缓存工具结果,设置过期时间。
  • 把路由和参数抽取等简单步骤交给经过评测的小模型。
  • 使用流式返回改善首次反馈,长任务异步执行并推送进度。

每次修改都比较完整延迟和任务通过率,确认提速后仍能完成原任务。

5.2 在 Token 消耗上做过哪些成本控制?模型选型时怎样权衡能力和成本?​

考察重点

  • 能根据实际用量判断成本来源,解释多轮重发历史的累计开销。
  • 能解释压缩、缓存、模型路由和预算的作用,并用评测比较每个成功任务的成本。

相关内容:成本控制、Token 与上下文窗口。

参考回答

压缩重复输入、复用缓存并限制调用预算,可以减少任务的累计费用。

先按任务记录未缓存输入、缓存用量、输出与工具费用,判断主要开销。多轮重发历史时,精简历史和工具结果的收益更大。工具与技能可先给摘要,按需展开;时效要求低的离线任务则可评估批处理。

意图识别、参数抽取、记忆整理和压缩,可以尝试交给小模型。是否采用要用同一份评测集比较成功率、耗时和每个成功任务的总成本。小模型若增加重试与轮次,单价优势就会被抵消。

只能使用一个模型时,可以改进检索,精简输入,并用结构化输出和程序校验提高成功率。任务与租户预算则限制反复尝试的累计费用,超限后返回已完成的结果。

5.3 为什么要限制 Agent 的并发?LLM 服务并发太高、很多用户同时使用时怎样限流和降级?​

考察重点

  • 能说明提供方配额、下游容量和失控循环为什么需要分别限制。
  • 能说明入口、队列和调用层各保护什么,以及故障时如何降级与隔离。

相关内容:并发、限流与降级、限流算法。

参考回答

限制并发可以保护下游容量,再配合速率与预算限制,避免模型配额被耗尽。

模型服务按 RPM 和 TPM 限速,工具访问的数据库与内部接口也有容量上限。失控循环还会持续挤占其他用户资源。因此,入口要按用户、租户和接口限流,长任务进入有界队列。

模型与工具各用信号量限制同时执行的调用数,例如 100 个任务最多同时运行 3 个。队列长度和等待时间用于判断扩容或拒绝,429 则采用有界退避并遵循 Retry-After。

高峰或故障时,可使用经过评测的备用模型,或关闭非核心的反思与重排序。无法完成的任务保存进度,返回部分结果或转人工。不同业务和优先级应使用独立配额与队列,减少故障扩散。

5.4 一个长任务平时 5 分钟结束,这次运行了 15—20 分钟,你会怎样分析原因?​

考察重点

  • 与正常任务对比,把差异拆到轮数、单轮耗时、工具和排队。
  • 区分“做了更多步”和“每一步更慢”两类原因。

相关内容:延迟的组成、失败归因与可观测性。

参考回答

应先对比正常任务与慢任务的追踪记录,判断是步数增加,还是单步耗时与等待时间增加。

可以沿以下三类差异定位原因:

  1. 步数增加:检查重复工具调用、失败重试和反复重规划,再比较任务的数据规模。工具返回错误或空结果、压缩丢失进度,以及提示或模型版本变化,都值得核对。
  2. 单轮变慢:比较输入量、输出长度和工具耗时。TTFT 变长时,还要检查前缀缓存、服务端排队和内部推理,结合指标定位瓶颈。
  3. 等待增加:单独统计队列等待、429 和退避时间,避免把它们归入模型生成耗时。

确认原因后,修复对应环节,并设置最大步数与总时长预算。同一工具连续失败时提前停止,关键指标超过基线时告警,最后把这次任务加入回归集。

5.5 前缀缓存与结果缓存有什么区别,语义相似的请求能直接复用答案吗?​

考察重点:能区分计算复用与答案复用,并说明身份、实体和时效怎样影响缓存有效性。

相关内容:前缀缓存与结果缓存。

参考回答

前缀缓存复用输入计算,结果缓存复用业务答案;语义相似的请求仍需验证答案能否共享。

前缀命中后,模型还会生成当前请求的结果。结果缓存则直接返回旧答案,因此要匹配用户身份、目标实体和数据版本。比如两个用户都查询“我的订单”,问题相似,授权范围却不同。权限变化或数据过期时,应使缓存失效或重新计算。

6. 参考资料​