Agent 的 Token 成本怎么控制:从计价模型到每请求成本管理的实战指南
普通 API 按请求计费,Agent 按「token 吞吐」计费——而 Agent 的 token 消耗量,是工程师手里最灵活的旋钮。省 token 不是抠门,是架构能力。
一、先学会算账:Token 成本的真实结构
1.1 计价模型的两个不对称
绝大多数 LLM 服务的定价有两个不对称,直接决定了成本优化的方向:
- 输出比输入贵 3~4 倍(如 GPT-4o 类:输入约 10/M)——少输出比少输入更值钱;
- Agent 的输入会指数膨胀(每轮循环历史累积),而单次输入价格虽低,量大了同样惊人。
1.2 Agent 单请求成本公式
Cost_per_request = Σ_i ( input_tokens_i × P_in + output_tokens_i × P_out )
其中 i 遍历一次请求触发的所有 LLM 调用
一个典型的 RAG Agent 单请求成本拆解(假设调用 4 次 LLM):
| 调用 | 输入 token | 输出 token | 占比 |
|---|---|---|---|
| 规划 | 1,200 | 150 | ~8% |
| 检索后整理 | 8,500(含检索文档) | 400 | ~38% |
| 生成回答 | 6,000(含历史) | 800 | ~40% |
| 校验 | 3,000 | 100 | ~14% |
| 合计 | 18,700 | 1,450 | 100% |
结论: 单请求成本 ≈ 输入 18.7K + 输出 1.45K,其中输入占了大头。所以成本控制的第一战场是「减少输入 token」,第二战场是「减少输出 token」,第三战场是「减少调用次数」。
二、第一战场:减少输入 token
2.1 检索上下文收敛
检索结果通常是输入膨胀的最大来源:
- top-k 收敛:20 个 chunk 压到 5~8 个,配合 Reranker 保证召回质量不降;
- 摘要压缩:
压缩 = 摘要(原始chunk),8K 压到 1.5K,代价是丢失细节(可改为「摘要入上下文 + 原文按需展开」); - 相关性过滤:与 query 无关的 chunk 在入上下文前直接丢弃;
- 按需检索(Contextual Retrieval):先小上下文试答,回答不充分时再补检,而不是一开始就塞满。
2.2 历史消息裁剪
多轮对话与多步循环中,历史是第二号膨胀源:
| 策略 | 做法 | 成本效果 |
|---|---|---|
| 滑动窗口 | 只保留最近 N 轮原文 | 线性截断 |
| 摘要化 | 更早的历史压缩为 1~2 条摘要 | 大幅下降 |
| 去冗余 | 被覆盖的消息(旧检索结果)直接剔除 | 消除无效输入 |
| 引用式存储 | 工具结果落库,上下文只留「摘要 + key」 | 按需展开 |
2.3 Prompt 精简
- 系统提示词瘦身:工具描述用一行话而非一大段;Few-shot 从 5 个压到 1~2 个;
- 动态指令:只有请求涉及的 Agent 能力才注入对应指令,用「按需拼装 prompt」替代「全量固定 prompt」;
- 方言/格式要求后置:把对输出格式的要求放在生成前一刻,避免模型在推理中「重复思考格式」。
三、第二战场:减少输出 token
输出的单价是输入的 3~4 倍,压输出比压输入性价比更高。
3.1 输出格式约束
- 用 JSON Schema / 结构化输出限定输出字段,避免模型「自由发挥」出一大段废话;
- 明确
max_tokens:回答类任务 300500,分类/抽取类任务 50100,截断不是错误,是成本纪律; - 要求简答模式:能一句话答完的不要两段话("请用不超过 3 句话回答")。
3.2 分步输出策略
- 先精后全:先输出结构化骨架(答案 + 置信度),需要时再让用户选择是否展开细节;
- 增量生成:长内容(报告、代码)按章节生成,每一章独立小请求,避免「一次生成超长输出 + 被截断重试」的双重浪费;
- 缓存长输出:已生成的完整内容落库,用户重复请求直接复用,不再二次生成。
3.3 流式输出不省成本,但改变感知
流式(SSE)不减少 token 消耗,但能显著改善用户体验,间接降低「用户没耐心重试」带来的额外成本——属于成本管理的「软手段」。
四、第三战场:减少调用次数
每次 LLM 调用都是一次完整计费,少调用一次 = 省一整次的输入 + 输出。
4.1 缓存:最锋利的成本刀
| 缓存层 | 缓存什么 | 省掉的成本 |
|---|---|---|
| 响应缓存 | 相同问题的完整结果 | 整次请求的输入+输出 |
| 语义缓存 | 相似问题(相似度 > 0.95)结果 | 整次请求 |
| 规划缓存 | 相同任务模板的规划步骤 | 规划的输入+输出 |
| 工具缓存 | 检索结果 / API 返回 | 工具相关的上下文注入 |
| KV Cache / 前缀缓存 | 重复前缀的推理中间态 | 输入的预填充计算(价格侧多由供应商缓存折扣覆盖) |
执行链缓存(Chain Cache) 是进阶玩法:对「意图 + 参数」完全一致的请求,缓存整条 Agent 执行链的结果(含中间步骤),用户请求直接回放——命中一次,省掉全部调用。
4.2 合并与并行
- 并行工具调用:一次请求携带多个工具调用(Function Calling 原生支持),减少「工具结果来回搬运」的额外轮次;
- 合并小任务:能一次调用的多个简单查询合并成一次("查 A 和 B 的天气"),避免拆成两次完整循环;
- 批量 API(Batch API):对非实时任务(日报、数据清洗、批量分类)走异步批量接口,价格通常打 5 折——延迟换成本。
4.3 模型分层:让便宜模型干大部分活
| 环节 | 模型档位 | 成本对比 |
|---|---|---|
| 意图识别 / 路由 | 小模型(7B 或 mini 档) | 便宜 10~50 倍 |
| 分类 / 抽取 | 小模型 | 便宜 10~50 倍 |
| 规划 / 工具选择 | 中模型 | 便宜 3~10 倍 |
| 最终生成 | 大模型 | 全价,仅此一环 |
关键原则: 让 70% 的调用落在小模型上,大模型只做「最终交付」。多数场景下,分层后的总成本可以下降 40%~60%,且质量几乎不降。
五、利用供应商的计价机制「合法省钱」
不改变任何提示词,单纯理解定价条款就能省下可观的成本:
- Prompt Caching(提示缓存):Anthropic / OpenAI 等对重复前缀的缓存 token 按输入价的 10%~25% 计费。把系统提示词、工具定义、Few-shot 固定为稳定前缀,多轮对话中每轮都能命中缓存折扣——这几乎是零成本的省钱手段;
- Batch API:非实时任务走批量接口,普遍 5 折;
- 长上下文模式切换:部分供应商对超长上下文有单独计价档位,评估「长上下文是否真的必要」;
- 流式不额外计费:SSE 不产生额外费用,放心用。
注意:Prompt Caching 依赖前缀字节级一致——即使只有一个空格的差异也会 miss。因此系统提示词、工具描述必须拼接顺序固定、内容不改动。
六、成本可观测:管不住的成本都在黑盒里
6.1 全链路 token 计量
每次 LLM 调用的响应里都带 usage 字段,必须逐调用记录并聚合:
指标维度:
- 按 Agent 类型:每个 Agent 的每请求平均 token / 成本
- 按环节:规划 / 检索整理 / 生成 / 校验 各自的占比
- 按模型:各档位模型的成本分布
- 按用户:Top 高消耗用户(防滥用 + 找优化对象)
6.2 关键指标与预算
| 指标 | 含义 | 建议 |
|---|---|---|
| 每请求 token 消耗 | 成本的第一性指标 | 建基准线,随版本追踪 |
| 输入/输出比 | 输入是否膨胀 | 输入占比过高 → 查上下文 |
| 缓存命中率 | 缓存体系是否有效 | 语义缓存命中 <10% 需检查 |
| 每请求成本 | 折算成钱 | 按 Agent 类型设预算 |
| 成本/P95 延迟 | 成本与体验的平衡 | 降级方案的成本收益对比 |
6.3 预算与配额
- 按用户 / 按 Agent 类型设置每日预算,超限自动降级(缓存优先 → 小模型 → 拒绝);
- 成本告警:单 Agent 成本周环比上升 >20% 即告警——模型更新或 Prompt 改动常在这里暴露;
- 成本回归测试:把「每请求 token 消耗」纳入 CI,Prompt 变更导致 token 上升超过阈值时阻止合并。
七、落地路线图:按 ROI 排序
成本优化手段多,收益差异大,按投入产出排序推进:
第一步(零改动,先记账):
- 全链路 token 计量 + 按 Agent 类型成本看板,找到「钱都花在哪」;
第二步(低成本高收益):
- 固定前缀 + 启用 Prompt Caching(零代码改动);
- 系统提示词瘦身、max_tokens 收紧、简答模式;
- 非实时任务切 Batch API(5 折);
第三步(架构级收益):
- 模型分层(小模型承担 70% 调用);
- 检索 top-k 收敛 + 摘要压缩 + 历史裁剪;
- 响应缓存 + 语义缓存 + 工具缓存 + 执行链缓存;
第四步(持续治理):
- 成本预算 + 配额 + 告警 + CI 成本回归;
- 每季度复盘「每请求 token」基准线,持续下探。
八、关键结论
- 成本的三个战场按优先级排:减少输入 > 减少输出 > 减少调用次数——但「少调用一次」的绝对收益最大,是质变手段。
- 缓存是最锋利的刀:语义缓存 + 执行链缓存命中一次,省掉整次请求的全部 token。
- 输出比输入贵 3~4 倍:压输出的性价比高于压输入,格式约束 + max_tokens 纪律立竿见影。
- 模型分层是总成本最大的杠杆:让 70% 的调用落在便宜模型上,总成本降 40%~60%。
- 理解计价机制就是省钱:Prompt Caching、Batch API 是零代码的成本折扣。
- 成本必须可观测:没有「每请求 token」指标,所有优化都是盲人摸象;把成本回归纳入 CI,防止优化回退。
省 token 的本质不是抠门,而是让每一分算力都花在「用户真正需要的那部分输出」上——输入只留必要的,输出只给有用的,调用只发值得的。