LLM API 越来越贵,别让 token 像自来水一样哗哗流

Posted on 五 08 5月 2026 in Journal

Abstract LLM API 越来越贵,别让 token 像自来水一样哗哗流
Authors Walter Fan
Category Journal
Status v1.0
Updated 2026-05-10
License CC-BY-NC-ND 4.0

短大纲

展开看看 - **核心观点**:省 token 不是少用 LLM,而是把 LLM 当成昂贵的计算资源来调度。 - **第一个动作**:先把 token 用量打点,别凭感觉优化。 - **模型分级**:小模型做分类、抽取、改写,大模型做推理、设计、复杂判断。 - **Prompt 瘦身**:固定规则放前面,变量放后面,删掉礼貌废话和重复上下文。 - **上下文控制**:RAG 不要把整本书塞给模型,只给当前问题真正需要的材料。 - **成本工具箱**:prompt caching、response cache、Batch API、输出长度限制、预算告警。 - **模式与反模式**:模型路由、预算盒、上下文漏斗是好模式;一把梭、自来水、资料倾倒是反模式。 - **落地清单**:一张能直接抄走的 token 成本自查表。

正文

有一种账单,平时安安静静,月底突然跳出来给你一巴掌。

LLM API 就是这种账单。

刚开始大家都挺开心:"这个需求让 AI 写吧","这批文档让 AI 总结吧","这个工单让 AI 分类吧"。跑 Demo 的时候一切美好,效果不错,老板点头,同事鼓掌,连你自己都觉得生产力革命已经到门口了。

然后月底账单来了。你盯着那串数字,心里只剩一句话:这哪是 AI 助手,这是会说话的碎钞机。

问题不在于 LLM 不能用。恰恰相反,我觉得 LLM 该用,而且要用得更深。但它不是免费的魔法,也不是随便开的自来水。token 是一种工程资源,和 CPU、内存、带宽一样,需要度量、预算和治理。

一句话:不要为了省钱少用 AI,要为了做成事聪明地用 AI。

先弄清楚:token 到底花在哪里

很多团队一说降本,第一反应是换便宜模型。有用,但经常不是第一步。第一步该看账。

LLM API 的成本一般来自这几个地方:

成本来源 常见浪费
Input tokens system prompt 太长,历史消息无限追加,RAG 塞太多上下文
Output tokens 没限制回答长度,模型写成小作文
Reasoning tokens 简单任务用了强推理模型,杀鸡用牛刀
Embedding tokens 文档重复索引,chunk 切太碎,增量更新没做好
Retry tokens 超时重试、解析失败重试、Agent 循环调用
Tool call tokens 工具列表太多,每次都传完整 schema

没有这些拆分,优化就是玄学。玄学降本的常见姿势是:今天换模型,明天改 prompt,后天禁止大家用。最后成本好像下来了,效果也一起下去了。

这就像看病不验血,直接让病人少吃饭。体重是降了,人也快没了。

第一步:给 token 上仪表盘

省 token 之前,先把 token 量出来。每次调用至少记录这些字段:

request_id
user_id / tenant_id
feature_name
model
prompt_tokens
completion_tokens
cached_tokens
reasoning_tokens
latency_ms
success / failure
retry_count
estimated_cost
created_at

然后按几个维度看:

按功能看:哪个 feature 最烧钱?
按用户看:是否有少数用户占了大头?
按模型看:大模型是否被滥用?
按失败看:失败重试吃掉了多少 token?
按时间看:批处理任务是否在高峰期挤占预算?

如果你用 OpenAI 这类 API,返回的 usage 字段里通常有 prompt tokens、completion tokens,有些模型还会返回 cached tokens 或 reasoning tokens。不要只把它当日志看,要把它当账本。

一个简单的成本日志长这样:

{
  "feature": "ticket_summary",
  "model": "gpt-4.1-mini",
  "prompt_tokens": 1820,
  "completion_tokens": 360,
  "cached_tokens": 1024,
  "latency_ms": 1280,
  "retry_count": 0,
  "estimated_cost_usd": 0.0031
}

别嫌麻烦。没有账本的系统,迟早靠拍脑袋治理。拍脑袋在工程里通常有个别名,叫事故预备役。

第二步:别拿大模型干所有活

LLM 不是越强越好,任务要和模型匹配。

我比较喜欢把任务分成四层:

任务类型 例子 模型选择
规则型 格式校验、字段映射、简单分类 尽量不用 LLM,用代码
轻语义 文本分类、关键词提取、短摘要、query 改写 小模型
中等理解 文档摘要、客服回复草稿、工单归因 中等模型
复杂推理 架构设计、故障分析、复杂代码 review、法律/财务风险判断 强模型

很多 token 浪费不是 prompt 太长,而是任务分配错了。

比如判断一句话是不是投诉,没必要上最强模型;抽取工单里的产品名,正则、词典、轻量分类器可能就够了。反过来,复杂事故复盘、跨文档推理、代码审查这类任务,硬上小模型省钱,最后会得到一堆"看起来差不多"的答案——最贵的不是大模型,最贵的是便宜模型给了错误答案,然后人再花半天返工。

如果你的模型网关把模型封装成类似下面这种命名,就可以直接拿来做路由规则:

xxx-{low|medium|high|xhigh}-[fast]
xxx-thinking-{low|medium|high|xhigh}

这里的 xxx 可以是 gpt,也可以是 claude-4.7-opusclaude-4.7-sonnect 这类模型族名称。先不纠结名字是否漂亮,关键是把它们当成不同的"计算档位",而不是一堆随手可点的下拉选项。

这里的 low / medium / high / xhigh 不是厂商标准,而是模型网关里的能力和成本分层。也有团队把 xhighmax,意思差不多:都是最高档。

档位 大致含义 典型用途 成本特征
low 便宜、快、能力够用,但上下文理解和复杂推理有限 分类、抽取、格式转换、短文本改写 适合高频低风险任务
medium 质量和成本比较均衡,适合做默认工作档 query 改写、普通摘要、客服草稿、FAQ 生成 大多数日常任务先从这里试
high 理解能力、稳定性和长上下文处理更好 长文档总结、复杂工单归因、代码解释 适合中高价值任务,要控制调用量
xhigh 最高能力档,也可能叫 max 架构评审、事故复盘、复杂代码 review、高风险决策 贵,应该有明确使用理由
模型形态 适合做什么 不适合做什么 成本提醒
xxx-low-fast 格式检查、简单分类、短文本改写、标题生成 复杂推理、长文档总结、代码 review 便宜、快,但别指望它懂太多上下文
xxx-medium-fast query 改写、FAQ 初稿、普通摘要、轻量客服回复 高风险判断、跨文档推理 很适合作为默认工作马,先从这里起步
xxx-high 长文档总结、复杂工单归因、较复杂的代码解释 大批量低价值任务 质量更稳,但要配合 token budget
xxx-xhigh 架构设计、事故复盘、复杂代码 review、法律/财务等高风险分析 日常分类、字段抽取、模板化生成 贵,应该像生产变更一样有使用理由
xxx-thinking-low/medium 需要一点推理的规划、分步分析、复杂 prompt 自检 简单问答、固定格式转换 reasoning tokens 会额外烧钱,别默认开启
xxx-thinking-high/xhigh 多约束决策、疑难故障分析、跨系统方案评审 高频在线请求、低风险批处理 适合"少量高价值问题",不适合当自来水

模型族也要分工。一个粗略但实用的判断是:

模型族 适合场景 使用建议
gpt-* 通用问答、结构化输出、工具调用、批量自动化任务 适合作为默认通用模型族,配合 low/medium/high 做成本分层
claude-4.7-sonnect-* 日常写作、总结、需求分析、代码解释、较长上下文处理 适合作为主力工作模型,质量和成本之间比较容易平衡
claude-4.7-opus-* 复杂推理、架构评审、深度代码 review、重要文档润色 适合关键任务兜底,不建议所有请求都直接打到 Opus 档

一句话:先选任务档位,再选模型家族,最后才决定要不要 thinking。 顺序反了,就容易变成"这个模型最强,所以全都用它"。这在 Demo 阶段很爽,在账单阶段很疼。

我的建议是做一张模型路由表:

if task == "format_check":
    use code
elif task in ["classify", "extract", "rewrite_query"]:
    use small_model
elif task in ["summarize", "draft_reply"]:
    use medium_model
else:
    use strong_model

不是为了优雅,是为了可控。否则每个调用点都自由发挥,成本曲线会像青春期的孩子,长得快,还不听话。

第三步:Prompt 要减肥

很多 prompt 的问题不是写得不好,而是写得太胖。

常见肥胖来源:

- system prompt 里堆了十几条重复规则
- 每轮对话都带完整历史
- RAG 上下文里塞了大量无关段落
- 给模型讲太多背景故事
- 工具 schema 又长又多,每次全量发送
- 输出格式要求写了三遍,生怕模型看不见

Prompt 要像函数参数——能少传就少传,能结构化就结构化,能复用就复用。

一个瘦身例子

胖的写法:

你是一个专业、优秀、有经验的客服专家。
请你仔细阅读下面的大量背景资料,并结合用户的问题,
给出一个详尽、完整、专业、有帮助、语气友好的回答。
如果资料中没有答案,也请尽量根据你的经验回答。
......

瘦的写法:

角色:客服助手
规则:
1. 只基于参考资料回答
2. 资料不足时回答:"根据现有资料无法确认"
3. 输出不超过 200 字
4. 必须给出来源编号

参考资料:
{context}

用户问题:
{question}

少一点文学,多一点约束。模型不需要你夸它"专业优秀",它需要你告诉它边界在哪里。

固定内容放前面,变量放后面

如果服务商支持 prompt caching,prompt 的结构会直接影响成本和延迟。以 OpenAI 为例,prompt caching 更容易命中完全一致的前缀,所以静态内容应该放前面,用户问题、临时上下文这类变量放后面:

固定部分:
  - 角色
  - 输出格式
  - 安全边界
  - 示例
  - 工具定义

变量部分:
  - 用户问题
  - 当前检索结果
  - 当前会话状态

这件事看起来像小优化,流量一大就不小了。就像写代码时把循环里的常量挪出去,单次看不出什么,跑一百万次就知道差别了。

第四步:RAG 上下文别乱塞

RAG 是 token 消耗大户。

很多系统的思路是:怕模型答不出来,那就多塞点文档。结果模型像一个被塞了十本参考书的学生——书是都有了,人也懵了。

RAG 的核心不是"给模型更多内容",而是"只给模型当前问题需要的内容"。可以按这个顺序优化:

  1. 先粗召回:从向量索引、BM25、元数据过滤里找候选。
  2. 再重排序:用 reranker 把最相关的 3-5 个 chunk 排前面。
  3. 做去重和压缩:重复段落不要塞两遍,长段落先摘要。
  4. 保留引用信息:来源、章节、更新时间必须跟着 chunk 走。
  5. 按预算截断:超过 token budget 就丢弃低分内容,别平均主义。

一个上下文预算可以这样定:

total_context_budget = 6000 tokens

system_prompt: 1000
user_question: 200
retrieved_context: 3500
output_budget: 1000
reserve: 300

reserve 很重要。没有余量的系统,就像出门只带刚刚好的钱,路上多买一瓶水都尴尬。

第五步:限制输出,别让模型写散文

很多人盯着 input tokens,却忘了 output tokens 也要钱。

模型很听话。你让它"详细说明",它就详细;你让它"全面分析",它就全面;你让它"给出完整方案",它能给你写出一篇小论文。

所以输出也要有预算:

普通问答:100-300 字
工单摘要:5 条 bullet
代码解释:先给结论,再给不超过 3 个关键点
风险分析:高/中/低 + 证据 + 建议动作
长文生成:先生成大纲,确认后再展开

尤其是长文生成,不要一上来就让模型写全文。更稳的方式:

Step 1: 生成大纲
Step 2: 人或程序检查大纲
Step 3: 分章节生成
Step 4: 最后统一润色

这样不仅省 token,也更容易控制质量。一口气让模型写全文,像让一个实习生关进会议室写 20 页方案,中间不检查——出来以后你会发现他很努力,也很离题。

第六步:缓存,缓存,还是缓存

缓存是工程师的老朋友,到了 LLM 时代依然管用。

可以分三层:

缓存类型 缓存什么 适合场景
Prompt cache 固定 prompt 前缀、工具定义、示例 大量请求共享同一系统提示
Response cache 完整问题对应的答案 FAQ、制度查询、高频问题
Retrieval cache query 对应的检索结果 RAG 检索成本高,知识库变化不频繁

Response cache 要小心。缓存答案必须考虑:

- 用户权限是否相同?
- 知识库是否更新?
- 问题是否真的等价?
- 答案里是否包含个人信息或敏感信息?

千万不要把 A 用户的权限答案缓存后返回给 B 用户——那不是省钱,是给安全事故预热。

一个可用的缓存 key 通常要包含:

tenant_id
user_role / permission_scope
normalized_query
knowledge_base_version
prompt_version
model

缓存不是简单的 hash(question)。在企业系统里,权限和数据版本永远要放进设计里。

第七步:离线任务用 Batch,不要全走同步

有些任务不需要立即返回:

- 批量文档摘要
- 历史工单分类
- 离线评估集打分
- 大规模 embedding
- 每日知识库质量检查

这些如果全部走同步 API,不但成本高,还会挤占在线请求的配额。更合理的做法是用 Batch API 或类似的异步队列。

OpenAI 的 Batch API 文档明确写了,适合不需要立即响应的任务,成本更低,速率限制也独立。具体数字会随平台政策变化,真正用之前看最新文档,但思路不变:在线请求要快,离线任务要便宜。

这和后台任务不要挤占前台流量是一个道理。用户正在等回答,你却让离线摘要任务把额度吃满——这不叫智能系统,这叫内部抢饭。

第八步:管住 Agent 的手

Agent 很迷人,也很烧钱。

一个普通问答也许只调用一次模型;一个 Agent 可能这样干:

思考一次
调用搜索
再思考一次
调用工具
解析工具结果
发现不够
继续搜索
再调用模型总结
最后输出答案

每一步都在花 token。更麻烦的是,如果没有边界,它可能绕圈。

Agent 必须有护栏:

max_steps: 5
max_tool_calls: 3
max_total_tokens: 8000
max_wall_time: 10s
stop_when_confidence_high: true
fallback_to_human: true

还要记录每一步的 token 和工具调用。否则你只看到最终答案,不知道它在后台跑了一场马拉松。

我不反对 Agent——复杂任务里 Agent 很有价值。但 Agent 应该像实习生:有任务、有预算、有截止时间、有复盘。不能给它一张公司信用卡然后说"你看着办"。

第九步:把"不用 LLM"也当成一种能力

不是所有问题都需要 LLM。很多场景,传统方法更稳、更快、更便宜:

场景 更合适的方案
固定格式校验 JSON Schema / 正则 / 代码
精确字段抽取 Parser / 规则引擎
高并发 FAQ 搜索 + 模板答案
权限判断 后端授权服务
金额计算 业务代码
审计记录 结构化日志

LLM 擅长语言理解、生成和模糊推理,不擅长当数据库、计算器和权限系统。把所有问题都扔给 LLM,就像家里买了个电钻,从此拧螺丝、切菜、刷牙都想用它。

工具好不好,看你怎么用。

尤其是那些重复、确定、不需要推理的常规任务,脚本通常比 LLM 更经济、更稳定,也更容易审计。LLM 每次回答都像请了个聪明外包,脚本则像一台自动售货机:投币、出货、少废话。

场景 更合适的做法 为什么别优先用 LLM
去除个人敏感信息 用正则、NER、字段白名单做脱敏,比如邮箱、手机号、身份证、IP、access token 规则清晰,必须稳定;LLM 漏掉一次就是事故
政治正确 / 合规敏感词 用词库、Trie、Aho-Corasick、规则引擎做匹配,再配人工复核 需要可解释、可回溯、可配置;LLM 判断会漂
模板生成文件 Jinja2、Handlebars、Mustache 这类模板引擎生成配置、报告、代码骨架 输入输出结构固定,用 LLM 反而可能改坏格式
批量字段转换 用脚本、SQL、ETL、JSON Schema 校验 成本低,结果可重复,失败原因清楚
固定业务判断 用业务规则或决策表,比如金额区间、权限开关、状态流转 这是系统逻辑,不该交给概率模型临场发挥

我的经验法则是:如果规则能写清楚、输入输出能定义、失败后要追责,就先写脚本。 LLM 更适合处理模糊语言、复杂上下文和开放式推理,不要让它去抢正则表达式和模板引擎的饭碗。

最佳实践、常见错误与反模式速查

前面讲的东西不少,这里收束成三张表。做设计评审的时候拿出来对一遍比看完全文管用。

最佳实践

做法 说明
先度量,再优化 记录 prompt_tokenscompletion_tokenscached_tokenslatency_msestimated_cost,按 feature 归因
任务分级用模型 规则能解决的不用 LLM,小模型做抽取和分类,大模型做复杂推理
Prompt 模板化与版本化 每个 prompt 有版本号,方便 A/B 测试成本和效果
固定前缀 + 动态后缀 固定规则放前面,变量放后面,利于 prompt caching
限制输出长度 明确字数、结构、字段,不让模型自由发挥
RAG 上下文预算化 只传 top-k 高质量 chunk,做去重、rerank 和截断
离线任务走 Batch 摘要、分类、评估、embedding 等不急的任务,不要挤在线 API
缓存带权限边界 cache key 必须包含 tenant、role、knowledge version,避免串数据

常见错误

错误 后果
没有 token 账本 月底才知道钱花哪了,排查像考古
所有任务都上大模型 分类、抽取、格式化也用强模型,典型"杀鸡用牛刀"
历史消息无限追加 对话越聊越贵,最后模型也迷路
RAG 什么都塞 以为上下文越多越好,噪声把答案淹了
不限制输出 一句"详细分析"换来一篇收费小论文
Agent 没有步数限制 工具调用绕圈,token 在后台悄悄烧
缓存只按 question hash 忽略权限、租户、知识库版本,省钱省出安全事故
只看单次调用成本 忽略重试、失败、批量任务和工具调用的链式成本

模式 vs 反模式

好模式 坏模式
模型路由:按任务难度选模型 一把梭:所有请求打最强模型
预算盒:每个功能有 token budget 自来水:调用点想用多少用多少
上下文漏斗:召回、重排、压缩后再喂模型 资料倾倒:整本知识库塞进 prompt
缓存分层:prompt、retrieval、response 分别缓存 裸奔:同样问题每次重新算
人机分工:规则、搜索、LLM 各做擅长的事 LLM 万能:数据库、计算器、权限判断都交给模型
离线批处理:不急的任务异步跑 在线堵车:批量任务和用户请求抢额度
Agent 护栏:限制步数、工具调用和总 token Agent 放羊:让它自己"看着办"
版本实验:prompt/model 变更可比较 拍脑袋:改了不知道效果变好还是变坏

这张表的价值不在于背下来,而在于做设计评审时能拿出来问一句:咱们现在是在用模式,还是在制造反模式?

一张可以抄走的 token 成本检查表

上线前拿这张表过一遍:

检查项 问题
用量打点 是否记录 prompt、completion、cached、reasoning tokens?
成本归因 能否按 feature、tenant、user、model 看成本?
模型路由 简单任务是否用了小模型或规则代码?
Prompt 版本 prompt 有没有版本号,方便比较成本和效果?
Prompt 结构 静态内容放前面了吗,变量放后面了吗?
历史消息 是否限制对话历史长度,做了摘要压缩?
RAG 上下文 有没有 top-k、rerank、去重、截断和来源信息?
输出预算 是否限制 max output tokens 和回答格式?
缓存策略 是否区分 prompt cache、response cache、retrieval cache?
权限隔离 缓存 key 包含 tenant、role、数据版本了吗?
Batch 任务 离线任务走异步或批处理了吗?
Agent 护栏 限制了 max steps、tool calls、total tokens 吗?
重试策略 解析失败是否无限重试?有没有退避和上限?
预算告警 成本异常时能及时发现吗?
敏感数据 是否避免把 secrets、token、隐私数据发给模型?

明天就能做的五件小事

如果你还没时间搭一套完整治理体系,先做五件小事:

  1. 给所有 LLM 调用加上 usage 日志,至少能按 feature 聚合。
  2. 把最贵的 10 个 prompt 打印出来,人工砍掉废话和重复上下文。
  3. 给每个调用点标注任务类型:规则、小模型、中模型、强模型。
  4. 给 RAG 设一个上下文 budget,不允许无限塞 chunk。
  5. 给 Agent 加上 max_stepsmax_tool_callsmax_total_tokens

这些事情不花哨,但能马上见效。很多成本不是被大模型吃掉的,是被"没人管"吃掉的。

总结

LLM API 贵不贵?贵。值不值得用?当然值得。

关键是别把它当许愿池——许愿池里丢硬币,响一下就没了;LLM API 里丢 token,响得更小,账单更大。

靠谱的做法是把 LLM 当成一套工程系统来管:度量、预算、路由、缓存、降级、安全边界、持续评估,一个都不能少。

好钢用在刀刃上。token 也是。

思维导图

@startmindmap
* LLM API 成本控制
** 先度量
*** usage 日志
*** feature / tenant / model 归因
*** 成本告警
** 选对模型
*** 规则优先
*** 小模型处理轻任务
*** 强模型处理复杂推理
** Prompt 瘦身
*** 删除废话
*** 固定前缀
*** 变量后置
*** 限制输出
** 控制上下文
*** RAG top-k
*** Rerank
*** 去重压缩
*** token budget
** 复用结果
*** Prompt cache
*** Response cache
*** Retrieval cache
** 异步处理
*** Batch API
*** 离线评估
*** 批量摘要
** 模式与反模式
*** 模型路由 vs 一把梭
*** 预算盒 vs 自来水
*** 上下文漏斗 vs 资料倾倒
*** Agent 护栏 vs Agent 放羊
** 管住 Agent
*** max steps
*** max tool calls
*** max total tokens
*** fallback to human
** 安全边界
*** 不上传 secrets
*** 权限进入 cache key
*** 敏感数据脱敏
@endmindmap

LLM API 成本控制思维导图

扩展阅读

  1. OpenAI Prompt Caching
  2. OpenAI Batch API
  3. Azure OpenAI Prompt Engineering

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。