Agent性能优化配置先别调参数,先找出延迟和成本卡在哪
Agent 跑起来之后变慢、变贵,很多时候不是某个参数没调对,而是调用链里有环节在重复劳动。
性能优化配置的第一步不是改数字,而是先量出时间花在哪、token 花在哪,再针对性地改并发、超时、缓存和上下文。
先判断瓶颈在哪一段
一个 Agent 请求通常分成三段:模型推理、工具调用、上下文组装。
三段的开销来源完全不同,混在一起调参数往往越调越乱。
- 模型推理:单次调用延迟高,或一个任务里串行调用了太多次模型。
- 工具调用:外部接口慢、重试次数多、串行执行本可以并行的工具。
- 上下文组装:每轮都把完整历史塞进请求,token 随轮次线性上涨。
判断方法很直接:在请求入口生成一个 trace id,给模型调用和工具执行分别打上开始、结束时间戳,把耗时写进日志。
跑一批真实请求后看统计,哪一段占比最高就先动哪一段。
没有这层数据,配置只能靠猜。
模型调用侧的三项配置
确认瓶颈在模型侧后,优先看这三个配置项。
并发上限。
Agent 内部并行发起多个子任务时,如果不限制并发数,容易触发接口限流,表现为大量 429 和重试,实际吞吐反而下降。
用信号量控制同时进行的模型调用数:
import asyncio
sem = asyncio.Semaphore(4)
async def call_model(prompt):
async with sem:
return await client.chat(prompt)
初始值建议从较小数字开始,比如 3 到 5,观察错误率和平均延迟后再上调。
并发不是越大越好,超过上游限流阈值后总耗时会被重试拖长。
超时时间。
给单次模型调用设置明确的读超时,不要用默认的无限等待。
超时值参考正常调用的 P95 延迟再留一点余量,过长会让失败请求长时间占住并发名额。
结果缓存。
同一任务里重复出现的相同提示(比如固定的系统提示、相同的工具描述)可以缓存组装结果,避免每轮重新拼接。
注意只缓存确定性内容,带时间戳或用户变量的部分不要缓存。
工具执行与上下文裁剪
工具侧最常见的浪费是串行执行本可并行的调用。
多个互不依赖的查询用并发发起,总耗时接近最慢的那一个,而不是全部相加。
有依赖关系的工具仍要按顺序执行,不要为了并行破坏正确性。
上下文方面,每轮把全部历史原样传入是最容易忽略的成本来源。
可以按以下顺序处理:
- 只保留最近若干轮完整对话,更早的内容压缩成摘要。
- 工具返回的大段结果做截断或只保留关键字段,不要整段回填。
- 固定的系统提示放在请求前部,便于缓存命中。
裁剪后要验证效果是否下降。
如果任务正确率明显变差,说明裁掉了必要信息,应放宽保留轮数,而不是继续压缩。
改完怎么验证没有改坏
每次只改一个配置项,用同一批样本请求对比修改前后的平均延迟、P95 延迟、错误率和 token 消耗。
四项里如果延迟下降但错误率上升,说明配置过紧,需要回调。
重点看两个信号:一是 429、超时这类错误是否集中出现,出现就说明并发或超时设置不合理;
二是任务成功率是否稳定,成功率下降往往意味着上下文裁得过多。
几个容易踩的坑
把并发上限设得很高,以为能提升吞吐,结果被上游限流,重试把延迟放大数倍。
只调超时不管重试,超时后立即重试,失败请求成倍增加。
超时和重试次数要一起看。
缓存了带用户变量的提示,导致不同用户拿到别人的结果。
缓存键必须包含所有影响输出的变量。
优化只在开发环境验证,线上流量特征不同,结论不成立。
用线上样本回放或灰度对比更可靠。
Agent 性能优化配置的核心是先有测量再动参数。
把耗时拆到模型、工具、上下文三段,从占比最高的一段入手,每次只改一项并对比关键指标,才能既降延迟又不牺牲任务质量。