Skip to content

Q71 · Agent 链路耗时很长时,如何定位性能瓶颈? ​

客服 Agent 收到“查订单 A123 到哪了,并解释‘运输中’”。用户等了将近 9 秒才看到完整回答。只看聊天框,会以为“模型生成太慢”;但请求可能先在队列里等,接着由模型决定调用什么,查资料,再访问订单工具,最后由模型组织答案。要定位瓶颈,先为同一次请求画出各步开始和结束的时间线,再看哪些等待真的延长了用户看到答案的时间。

本文的订单 A123、时间和所有测量值都是假设示例,用于说明定位方法,并非任何模型、框架或线上系统的实测性能。假设订单查询只读,另有一份配送说明可供检索;需要两者才能完整回答用户的两个问题。

术语解释:先说明测量对象 ​

**Agent(智能体)**是让模型在给出最终答复前,按任务选择工具、读取结果并可能继续下一步的应用。链路是用户发出请求到拿到回答的整个过程。它可以包含多个模型调用、检索、外部工具和等待,所以“模型 API 耗时”只覆盖其中一段。

术语在这道题里的含义A123 例子
端到端时延约定的起点到终点所经过的时间用户点击发送到完整回答呈现,假设 8.8 秒
首 token 时间 / TTFT从约定起点到第一段可见答案出现的时间;token 是模型生成文字的基本单位最终回答第一段在第 6.3 秒出现
总完成时间最后一段答案到达并完成渲染的时间第 8.8 秒才完整显示
trace / 链路追踪将同一请求的各步记录关联成一条路径A123 这次请求的完整轨迹
span / 片段记录trace 中一次具体工作的开始、结束、名称和属性一次检索或一次订单工具尝试
trace ID给同一条请求路径的关联编号网关、Agent 和订单服务共享的追踪号
网关接收外部请求并转给 Agent 服务的入口客服请求先经过的服务入口
排队时间工作已到达系统、还未拿到执行资源时的等待Agent 工作槽位忙,等 0.4 秒
重试 / 退避失败后再次调用 / 两次调用间有意等待订单工具先失败,等 0.5 秒再试
幂等同一业务意图重复执行也不会多产生一次副作用退款重试不能多退一笔;本例订单查询只读
串行 / 并行前一步结束才开始后一步 / 独立工作在同一段时间进行资料检索和订单查询能否同时启动
关键路径哪些步骤的完成时间真正决定最终结束时间本例的串行五段都在关键路径上
p95将同一类请求按耗时排序,约 95% 的请求不超过的值观察慢用户群,而不只看平均值
p50同类请求耗时的中位数,约一半请求不超过它观察典型请求,配合 p95 看慢尾部

**起点和终点必须先约定。**如果后端只从收到 HTTP 请求计到写出最后一字节,它漏掉浏览器到网关的网络与前端渲染;前端点击到完整显示又包含这些时间。比较前后版本时必须使用同一口径。TTFT 也要注明是“模型 API 的首 token”还是“用户真正看到的第一段答案”:前面的排队、规划模型和工具等待会让两者相差数秒。规划模型即使先生成了内部决策内容,也不等于用户已看到答案。

OpenTelemetry 把 trace 视为一次请求穿过应用的路径,span 记录每项工作的起止时间、父子关系和属性;跨进程传递 trace ID 才能把网关、Agent 与工具服务接起来。若只看到 Agent 的调用时间,却没看到订单服务内部,不能把空白处算成“模型慢”。OpenTelemetry:Traces · OpenTelemetry Trace API

把 8.8 秒展开成时间线 ​

假设这次请求的时间线如下。所有时间都相对“用户点击发送的第 0 秒”;表中相邻步骤先后执行,因此跨度可以相加。工具失败只是这一例的现象,不能据此推断生产环境的常态。

阶段开始~结束用时trace 里应看到什么
网关到 Agent 的排队0.0~0.4 秒0.4 秒到达时间、领取执行槽位时间、当时在途量
规划模型0.4~2.0 秒1.6 秒一次模型调用、所用模型、输入/输出 token 数
配送资料检索2.0~3.1 秒1.1 秒查询、检索服务等待、返回的片段数
订单工具3.1~5.3 秒2.2 秒第一次失败 0.8 秒、退避 0.5 秒、第二次成功 0.9 秒
最终回答模型5.3~8.8 秒3.5 秒首段输出在 6.3 秒;其后 2.5 秒完成剩余输出

这条 trace 的算术是 0.4 + 1.6 + 1.1 + 2.2 + 3.5 = 8.8 秒。最终模型单段最长(3.5 秒),但订单工具的 2.2 秒包含可定位的失败与重试,两项读取还被安排为串行。看到最长方块后仍要问:哪一部分可以安全减少、减少后会不会让另一段变成新的瓶颈?

一次客服 Agent 请求的排队、规划、资料检索、订单工具重试和回答生成顺序时间线

图里的红色订单工具表示“失败后重试”的具体线索,不表示它比最终回答模型耗时更长。图只画这次请求的串行路径;并行工作和其他慢请求要再打开对应 trace 查看。第一段用户可见答案在 6.3 秒出现,因为前 5.3 秒没有最终答复,最终模型又用 1.0 秒产出首段。若界面等整段生成完才显示,用户感受到的“首次可见答复”会接近 8.8 秒。OpenAI:Latency optimization

沿着 trace 排查,而不是靠猜 ​

**先确认慢在哪里发生。**把同一时间窗的成功、超时、取消请求都纳入,按接口、租户(使用同一服务的一个客户组织)、模型版本、工具名、是否重试和高峰/低峰分组。先看端到端时延的分布与 p95,再点开落在慢尾部的几条具体 trace;一条 8.8 秒样本不足以代表全体。p95 可理解为把 100 条同类请求从快到慢排列后接近第 95 条的位置;实际监控常通过直方图估计,统计窗口、分桶及样本数都会影响结果。不能把每个阶段各自的 p95 直接相加当作整条链路的 p95:各阶段最慢的请求未必是同一批,阶段还可能重叠。Prometheus:Histograms and summaries

再看时间轴的空白和重叠。本例从 2.0 到 5.3 秒,资料检索先做完才开始查订单。两项只读且在规划阶段已经知道所需参数,理论上可同一时刻启动,等两者都完成再生成答案。如果保持工具失败重试情况不变,检索 1.1 秒与订单工具 2.2 秒重叠后,这段的完成时间由较慢的 2.2 秒决定,而不是两者相加 3.3 秒;单次请求的理论完成时间会从 8.8 秒变成 7.7 秒。只有相互独立、无顺序或一致性约束的动作才能这样改;退款、取消订单等写操作不能看到“可并行”就并发。OpenAI 延迟指南:并行化

**然后展开最可疑的内部阶段。**订单工具的 2.2 秒不是“一次网络调用慢”——它由失败 0.8 秒、退避 0.5 秒和重试成功 0.9 秒组成。应继续看第一跳为何失败:超时、限流、连接池(可复用的数据库连接集合)耗尽、DNS(域名解析)/网络还是订单服务内部查询慢;分别记录错误码、尝试次数、队列等待和服务端处理时间。如果只给外层 order_tool(订单工具整段工作的记录名称)一个 span,就看不到重试,优化方向容易跑偏。对于只读查询,可在有总时间预算的前提下调整超时与有限重试;对于有副作用的工具,先解决幂等和结果确认,不能为了降低平均耗时随意重试。

**最后看模型自身的两段等待。**规划模型 1.6 秒和最终回答模型 3.5 秒要分别记录模型名、请求数、输入/输出 token 数、模型 API 首 token 与总完成时间。若最终模型首 token 1.0 秒、后续生成 2.5 秒,而输出很长,可测试减少重复说明或压缩最终回答,同时核对是否丢失用户需要的订单位置与“运输中”解释;若首 token 很慢,继续查模型服务排队、输入规模、路由和网络。若规划阶段为一个简单固定查询却反复调用模型,可评估合并步骤或用确定性代码,但要先确保功能正确。OpenAI 官方延迟指南把减少请求、并行、减少输出 token 与用户可见的流式呈现列为不同手段;流式显示改善首段可见时间,本身不能证明后台总工作已减少。OpenAI:Latency optimization

给每个阶段留足定位证据 ​

最少要在接收请求的入口建立一条根 span,覆盖进入系统至返回的过程;若排队发生在网关,就从网关开始记录,别让根 span 只从 Agent 真正开工时才计时。再给排队、规划模型、检索、每次工具尝试、退避、最终模型分别留可关联的时间记录。根 span 与子 span 共享 trace ID;跨网络调用时把追踪上下文传过去。记录入口、模型与工具版本、结果状态、错误类别、重试次数、token 用量、资料返回数量及是否命中缓存(复用之前保存的结果)。若工具服务也有 trace,继续拆成连接池等待、数据库查询和远端 API,而非止步于“工具 2.2 秒”。OpenTelemetry 的 span 属性和事件正是承载这些结构化信息的机制。OpenTelemetry:Traces

同时明确隐私边界:追踪号、阶段名称和耗时通常足够定位性能;订单号、用户资料、完整提示词、检索片段及模型输出可能包含敏感信息,应按权限、脱敏与保留期限处理。为性能统计记录“工具名称 + 耗时 + 错误码”通常比无差别保存用户原文更稳妥。采样导致部分请求没有完整 trace 时,用全量聚合指标观察整体 p95,再用采样 trace 解释代表性慢请求;不要把缺失的子 span 误当成零耗时。

优化后怎样证明真的变快 ​

按本例,先修订单工具第一次失败的原因,并只在确认互不依赖后并行两项读取。如果订单工具稳定为单次 0.9 秒,检索仍需 1.1 秒,那么两者并行的查询段至少要等 1.1 秒;在其余阶段完全不变的假设下,单次时间可算作 0.4 + 1.6 + 1.1 + 3.5 = 6.6 秒。这个 6.6 是时间线推演,不是部署后的承诺值:并发也可能增加后端排队,模型与工具时延会波动。

真正验证要固定请求集合、模型版本、输出要求、用户权限和负载条件,比较改动前后端到端 p50/p95、用户可见首段时间、每阶段耗时、错误/超时/重试率、答案正确性与成本。例如在同一测试环境各跑 100 次,本例若观察到 p95 从 12.4 秒降到 9.6 秒、首段可见时间从 8.0 秒降到 6.4 秒,而且答案和引用检查没有退步,才有证据说改动对这组负载有效;这组数仍是假设示范,不能推广到真实流量。上线后继续按高峰流量监控,因为测试环境可能没有生产队列。若平均值下降却 p95 升高,要重点查并行后后端过载、排队和超时重试是否增加。

面试时可以这样回答 ​

Agent 慢时,我先定清楚用户点击到首段答案、到完整答案分别花多久,再给同一次请求建立 trace,把排队、每次模型调用、检索、工具尝试和重试拆成有起止时间的 span。先按接口和高峰时段看端到端 p95,再打开慢请求的时间线找关键路径;并行段看最晚完成者,串行段看是否存在无谓等待。本例 8.8 秒里最终模型占 3.5 秒,订单工具 2.2 秒含失败和重试,两次独立读取还被串行了。我会先查工具失败原因,再评估安全并行,随后才根据 token 和首 token 数据处理模型阶段。优化后用同一请求集和负载复测 p95、首段时间、错误率、答案质量及成本,避免只把等待从一个环节挪到另一个环节。

若追问“最大的 span 就是瓶颈吗”,回答是要结合关键路径和可优化部分:并行的最长子任务决定汇合时间,等待在非关键路径的工作加速后未必能改变总时长;本例最终模型单段最长,但工具重试和无谓串行也值得先排查。若追问“流式输出算优化吗”,回答是它让用户更早看到可见内容,但仍要单独记录最终完成时间与实际工作量。若追问“为什么看 p95”,回答是平均值可能遮住一小批严重慢的用户,p95 要按可比较的请求群体和时间窗计算。

参考资料 ​

最后更新2026-09-26
难度P1
频率medium
阅读18 min
主题agent / latency / observability
觉得有帮助?把这个链接转给正在求职的朋友 · 用 Ctrl + K 全站搜索其它题