本节摘要:智能体应用的性能看两个指标:延迟与成本。本节讲清延迟的构成(模型、工具、循环)与优化手段(模型选择、并行、缓存),成本的构成(token)与控制方法(上下文管理、模型路由),以及并发与资源管理。
阅读完本节,你应当能够:
"智能体太慢、太贵"——两个痛点,一套解法:先量化,再优化。延迟大头通常在模型调用,成本大头在上下文 token。搞清楚"慢在哪、贵在哪",优化就有的放矢。
先量化是什么意思?不要凭感觉说"智能体好慢",而是用追踪数据回答三个问题:一次运行平均几次模型调用?每次调用平均多久?上下文平均多少 token?这三个数字决定了优化的方向——如果平均 5 次模型调用,那降低延迟的关键是减少轮次,而不是给模型"加速"。
| 手段 | 说明 | 收益 |
|---|---|---|
| 换快模型 | 简单任务用小模型 | 大幅降延迟 |
| 并行工具 | 独立工具同时调 | 一次少一轮 |
| 减少循环 | 精简流程与指令 | 少几次模型调用 |
| 结果缓存 | 重复问题免模型 | 延迟归零 |
💡 关键直觉:延迟优化先看模型——模型调用通常占 80% 以上的时间。换模型、减轮次,比优化其他环节收益大得多。
from agents import Agent, Runner, function_tool from agents.model_settings import ModelSettings @function_tool def get_price(code: str) -> str: """查询股票价格。""" return "12.5" @function_tool def get_volume(code: str) -> str: """查询成交量。""" return "1.2 亿" agent = Agent( name="行情助手", instructions="查询行情时尽量并行获取价格与成交量。", tools=[get_price, get_volume], model_settings=ModelSettings(parallel_tool_calls=True), ) result = Runner.run_sync(agent, "查一下某股票的价格和成交量") print(result.final_output)
parallel_tool_calls=True 让模型在一次响应里声明多个工具调用,Runner 并行执行——原本"查价格 → 等结果 → 再查成交量"的两轮循环,变成一轮完成。
一 上下文管理:历史滚动窗口 + 摘要 二 模型路由:简单用小模型,复杂用大模型 三 缓存:重复查询命中缓存
成本 = token 单价 × 用量。单价靠模型路由控制,用量靠上下文管理和缓存控制。三个杠杆都按下,成本通常能降 50% 以上。
| 类型 | 可否缓存 | 说明 |
|---|---|---|
| 无状态查询 | 可以 | 相同输入相同输出 |
| 时间敏感 | 短缓存 | 行情、天气设有效期 |
| 用户相关 | 按用户缓存 | 不能跨用户共享 |
⚠️ 常见坑:缓存带上下文的回答。会话相关的回答不能全局缓存——缓存错对象,轻则答非所问,重则泄露他人信息。缓存键必须包含"影响输出的所有因素"。
并发:异步处理多个请求(await Runner.run) 限流:保护模型 API 配额(令牌桶) 队列:高峰削峰填谷 监控:延迟与错误率
智能体服务的资源管理与普通 Web 服务不同的地方:每个请求会占用"模型 API 配额"和"上下文计算",这两样都是真金白银。并发开太高,模型限流会先帮你"刹车";所以要主动限流、排队,而不是等配额耗尽再被动失败。
优化前:记录 P50/P95 延迟、单次成本、成功率 优化后:同一组指标对比 目标:延迟降幅、成本降幅、成功率不变或上升
性能优化的验收标准是"指标对比",不是"感觉快了"。每次优化只改一个变量,跑同一组压测数据,用数字说话。
| 瓶颈信号 | 常见根因 | 首选对策 |
|---|---|---|
| P95 延迟高 | 模型调用轮次多 | 减循环、并行工具 |
| 单次成本高 | 上下文太长 | 滚动窗口、摘要 |
| 高峰超时 | 并发超配额 | 限流、排队、水平扩展 |
| 响应不稳定 | 工具外部依赖慢 | 工具缓存、超时控制 |
把现象对号入座,直接命中对策,比盲目优化高效得多。
跑得快了,最后一节上线——部署与扩展。