实战
AI Agent 成本优化实战:Token 计费、缓存与省钱策略
很多团队的第一版 Agent Demo 很惊艳,一算账单却傻眼:单个用户每月跑出几百块,规模一上来直接亏本。LLM 成本不像传统算力那样线性可控,它由"模型单价 × Token 量 × 调用次数"共同决定,且充满隐性陷阱。本教程给你一套能立刻上手的降本打法。
💰 本教程适合:正在为 Agent 账单发愁的创业者、需要控制 AI 预算的团队负责人、以及准备把 Agent 从"尝鲜"推向"规模化"的技术/运营同学。
一、成本到底从哪来?
想省钱,先搞清钱花在哪。LLM 计费有三个直接维度 + 一类隐性成本:
| 成本项 | 说明 | 常见浪费点 |
|---|---|---|
| 输入 Token | 每次请求带上全部上下文 | System Prompt 又长又不变,反复计费 |
| 输出 Token | 模型生成的每个字 | 没限制长度,啰嗦输出 |
| 模型差价 | 旗舰模型贵 10-50 倍 | 简单任务也用最贵的模型 |
| 隐性成本 | 重试/循环/失败重算 | Agent 陷入调用死循环 |
核心认知:成本优化不是"选最便宜的模型"这么简单,而是在每一个环节减少不必要的 Token 和调用。下面六个手段叠加,通常能把账单砍掉 50%-80%,而用户体验几乎不变。
Step 1:提示词瘦身
1 删掉"废话",只留指令
# 优化前:System Prompt 800 字,充满解释和例子
"你好!我是你的助手,很高兴为你服务。下面我会
详细告诉你应该怎么做……(一大段铺垫)"
# 优化后:180 字,纯指令
"你是客服分类器。输入用户消息,仅输出以下之一:
[咨询][投诉][售后][其他]。
规则:含'坏/烂/差'判[投诉];含'退/换'判[售后]。
不要任何解释。"
💡 实操要点:System Prompt 每次请求都会作为"输入 Token"重复计费。把它从 800 字压到 200 字,等于每个请求永久省 600 输入 Token——乘以日均调用量,是一笔持续的大头节省。把示例/说明放进 few-shot 缓存(见 Step 2)而非常驻 Prompt。
Step 2:上下文缓存
2 不变的内容,别反复付费
很多厂商(OpenAI/Anthropic/Google)支持 Prompt Caching:命中缓存的部分按 1/10 甚至更低价格计费。把不变的"系统指令 + 长文档"标记为可缓存前缀。
# 以 Anthropic 为例,给稳定前缀打 cache_control
messages = [
{"role":"system","content": SYSTEM_PROMPT,
"cache_control": {"type":"ephemeral"}}, # 缓存系统指令
{"role":"user","content": LONG_DOC,
"cache_control": {"type":"ephemeral"}}, # 缓存长文档
{"role":"user","content": user_question} # 只有这句每次都全价
]
🚀 进阶玩法:RAG 场景里"检索到的知识片段"每次不同、不适合缓存;但"系统指令"和"产品手册全文"是稳定的,标记缓存后,同一会话/同批请求只首传全价、后续命中折扣价。长文档类应用靠这一步能省下 70% 以上的输入成本。
Step 3:模型分层(Routing)
3 简单任务别用旗舰模型
# 用一个小模型先做路由判断,决定调哪个大模型
def route(task):
kind = small_model_classify(task) # 用 7B 小模型,几乎免费
if kind in ("分类","抽取","改写"):
return cheap_model(task) # 小模型/便宜模型直接出
elif kind == "复杂推理":
return flagship_model(task) # 只有难的才上贵模型
else:
return mid_model(task)
📊 经验参考:实测中,Agent 流量里 60%-80% 是"分类/抽取/简单问答"这类轻任务,本可以用便宜 10 倍的小模型完成。加一层路由,把旗舰模型留给真正需要推理的 20%,整体成本立刻腰斩,用户几乎无感。
Step 4:减少无效调用
4 堵住"烧钱黑洞"
# 1) 去重:相同问题直接返回缓存答案
if question in answer_cache: return answer_cache[question]
# 2) 合并:把 N 个独立小问合并成一次批量请求
batch = [q1, q2, q3]; reply = model(batch)
# 3) 限长:给输出设上限,杜绝"写小说"
gen(max_tokens=300)
# 4) 防循环:Agent 单轮最多调 8 次工具,超限强制收尾
if tool_calls >= 8: force_final_answer()
最贵的 bug 是"调用循环":Agent 因逻辑缺陷或模型幻觉,可能在几秒内调用上百次工具/模型。必须设硬性上限(单轮次数、单会话预算、单用户日额度),否则一次线上故障就是天价账单。这是成本优化里优先级最高的一条。
Step 5:批量与异步
5 不着急的任务,打折跑
# OpenAI Batch API:离线批量,价格约 5 折,24h 内返回
client.batches.create(
input_file_id=file_id,
endpoint="/v1/chat/completions",
completion_window="24h"
)
# 适合:日报生成、批量文档摘要、离线数据 enrichment
🔑 关键认知:不是所有调用都要"实时"。把"明早 9 点前出就行"的任务(日报、批量打标、历史数据补全)丢进 Batch/异步队列,用时间换 50% 折扣。把实时额度留给真正需要即时响应的用户交互。
Step 6:量化与自托管
6 把一部分流量"搬回本地"
当调用量足够大,本地部署小模型(参见本中心《本地部署开源大模型》教程)能把"按量付费"变成"一次硬件投入、调用免费"。
# 分层策略落地:高频轻任务走本地,敏感/高难走云端
if task.is_high_volume_and_simple:
return local_ollama(task) # 免费、隐私、低延迟
elif task.needs_reasoning:
return cloud_flagship(task) # 仅这部分付费
💡 适用判断:本地模型单次边际成本为 0,但前期有显卡投入。粗略经验——当月云端账单稳定超过硬件成本(约一两张中端显卡)的 1/3 时,自托管开始划算。中小团队先用云端 + 缓存 + 路由三板斧,往往就够了。
七、成本自检清单
上线前,逐条过一遍:
| 检查项 | 做了吗 |
|---|---|
| System Prompt 是否压到最短? | ☐ |
| 稳定前缀是否启用了缓存? | ☐ |
| 是否按任务难度做了模型分层? | ☐ |
| 是否设了输出长度上限? | ☐ |
| 是否有单轮/单用户调用上限防循环? | ☐ |
| 非实时任务是否走了 Batch/异步? | ☐ |
| 是否建立了按功能/用户的成本看板? | ☐ |