这次"事故",不是系统崩了,而是钱包崩了。我们一个 AI 功能上线大概一个月后,财务的同事找上门来,语气凝重:"你们那个用大模型的功能,这个月的 API 账单,是当初预估的好几倍——这花钱的速度,有点超预算了。"我当时还有点懵:不就是个调用大模型的功能吗,平时看着请求量也不算特别大,怎么会烧掉这么多钱?可账单是实打实的,白纸黑字,远超我们最初拍脑袋估算的成本。这逼着我第一次,认认真真地去算了一笔"大模型到底是怎么花钱的"账——而这一算,让我对"用大模型"这件事的成本,有了脱胎换骨的认识。
排查下来,我们的钱,主要"漏"在了三个我们当初完全没在意的地方:第一,我们每次调用大模型,都带了一个又长又啰嗦的"系统提示词(system prompt)"加一大堆"示例(few-shot)",光这个固定的前缀就有好几千 token;而真正的用户输入可能就几十个字——也就是说,我们每次请求,绝大部分的钱,都花在了反复发送那个"固定不变的长前缀"上。第二,很多用户问的其实是重复的、一样的问题,我们却没有任何缓存,每一次都老老实实地、真金白银地去调一次模型。第三,有些其实很简单的任务(比如做个分类、抽个字段),我们图省事,也用了那个最强、最贵的模型——杀鸡用牛刀,钱花得冤枉。根子上,是我们对"token 就是钱"这件事,完全没有概念,把大模型当成了一个可以随便、免费调用的东西。这篇文章,就从这次"AI 账单暴涨"的事故讲起,聊聊用大模型时那个最实际、却最容易被开发者忽视的话题——成本。
故障现场:钱是怎么一点点漏掉的
先把"钱漏在哪"算笔明白账。大模型 API 的计费,核心就一条:按 token 收费,输入(你发给它的)和输出(它返回的)都算钱。而我们的浪费,全藏在这个"按 token 收费"的细节里:
大模型 API 计费的本质: 输入token + 输出token, 都按量收钱
我们浪费的三个地方:
【浪费1】固定长前缀, 每次重复发送
每次请求 = [几千token的system prompt + few-shot示例] + [几十token的用户输入]
→ 95% 的输入token, 都花在那个"每次都一样的固定前缀"上!
→ 一天几万次调用, 就是把那几千token的前缀, 白白重复付费几万遍。
【浪费2】重复请求, 没有缓存
用户A问"怎么退货", 用户B也问"怎么退货" ... 同样的问题问了一万遍,
我们就真去调了一万次模型、付了一万次钱 —— 而答案其实是一样的!
【浪费3】简单任务用最贵的模型
"判断这句话是不是投诉"这种简单分类, 也用最强最贵的旗舰模型,
而其实用便宜十倍的小模型, 效果完全够用 —— 贵的那部分钱, 纯属浪费。
看明白这笔账了吗?大模型的成本,不是一个模糊的"调用一次多少钱",而是精确地、残忍地正比于你"消耗了多少 token"——而 token,在这三个地方被我们大把大把地浪费了。浪费1最隐蔽也最普遍:我们总想着把系统提示词写得详尽、把示例给得充分,好让模型表现更好;却没意识到,这个"又长又全"的前缀,会在每一次调用里,都被原封不动地重新发送、重新计费——你的前缀有多长,你就为每一次调用,多付多少这个前缀的钱。浪费2则是把"大模型"当成了"无状态的计算",忘了它每一次调用都是有真实成本的,该缓存的重复结果没缓存。浪费3是没有"成本意识"地、一刀切地用最贵的模型干所有活。
这三个浪费叠加起来,就让我们的账单,在不知不觉中"虚胖"了好几倍。而它之所以"不知不觉",正是因为大模型的便利,掩盖了它的成本——你写代码时,调用大模型就是一行 client.chat(...),和调用任何一个普通函数没什么两样,丝毫感觉不到"这一行,正在花钱";只有当月底那张账单砸下来,你才猛然惊觉:原来我每一次轻飘飘的调用背后,都是真金白银在流淌。这篇文章要讲的,就是怎么把这个"看不见的成本",变成"看得见、管得住"的工程问题。
第一件事:建立"token 就是钱"的成本意识
要管住成本,第一步是建立一个根本的意识:用大模型,每一次调用、每一个 token,都是有真实成本的;"token 就是钱"。这听起来是句废话,可恰恰是这句"废话",是我们最初完全没放在心上的——而所有的成本失控,都源于这份"成本意识"的缺失。
建立成本意识, 从"会算一笔账"开始:
一次调用的成本 = 输入token数 × 输入单价 + 输出token数 × 输出单价
举例感受一下(数字示意):
system prompt + 示例: 3000 token
用户输入: 50 token
模型输出: 200 token
→ 一次调用 ≈ 3050 输入 + 200 输出
→ 如果一天 10 万次调用: 3.05亿输入token + 2000万输出token / 天
→ 而其中 3000/3050 ≈ 98% 的输入, 是那个"每次都一样的前缀"!
关键认知:
- 大模型不是"免费随便调"的, 它的成本精确正比于 token 消耗
- 输入和输出都算钱(有些模型输出更贵)
- 同样的功能, token 用得多还是少, 成本可能差几倍甚至几十倍
关键认知是:大模型不是一个"调一次几乎不要钱、可以随便用"的工具,而是一个"成本精确地正比于 token 消耗"的付费服务;你每多发一个 token、每多调一次,都在实打实地花钱。建立了这个意识,你看待每一行调用大模型的代码,眼光就变了——你会下意识地去想:"这次调用,我发了多少 token?有没有浪费?这个调用,有没有必要真去调一次?"而成本优化的第一步,甚至不是任何具体的技术,而是先学会"算这笔账"——知道你的一次调用大概消耗多少 token、值多少钱,你的功能一天调多少次、一个月烧多少钱。只有当成本从一个模糊的"应该不多吧"的感觉,变成一个清清楚楚、可量化的数字时,你才能真正地、有的放矢地去优化它。我那次的根本失误,就是从头到尾,都没有认真地算过这笔账。
第二件事:省钱招数一——精简提示词 + 利用 Prompt 缓存
针对"浪费1:固定长前缀每次重发",有两招:一是给提示词"瘦身",二是用很多模型 API 都提供的 Prompt 缓存(prompt caching)——它能让那个"每次都一样的前缀",在重复发送时享受大幅折扣。
# 招1a: 给提示词瘦身 —— 该精简就精简, 别为了"详尽"塞一堆没用的
# - 砍掉啰嗦的废话、重复的强调、用不上的示例
# - few-shot 示例: 用最少的、最有代表性的几个, 而非堆十几个
# - 别把整个文档/超长上下文无脑塞进去, 该截断/摘要就处理(呼应RAG那篇)
# 招1b: 利用 Prompt 缓存 —— 固定不变的长前缀, 命中缓存后大幅降价
resp = client.chat.completions.create(
model="...",
messages=[
{"role": "system", "content": LONG_FIXED_PROMPT}, # 长且固定的前缀
{"role": "user", "content": user_input}, # 变化的部分
],
# 很多API支持: 标记/自动缓存固定前缀, 命中后这部分token大幅折扣(甚至1折)
)
# 原理: 把"固定不变的前缀"在服务端缓存住, 重复请求时不必重新完整计费
# → 那几千token的前缀, 从"每次全价", 变成"首次全价、之后享折扣"
这两招都针对那个"最大的浪费——固定长前缀重复计费":"精简提示词"是从源头减少 token——很多提示词其实是"虚胖"的,塞了一堆为了"显得详尽"而其实模型并不需要的废话、重复强调、过多的示例;把它精炼到"刚好够用",就能直接砍掉一大块固定开销。"Prompt 缓存"则是利用平台能力降价——现在很多大模型 API 都支持缓存那个"固定不变的前缀部分",当你重复发送同样的前缀时,这部分 token 能享受大幅折扣(有的低至原价的一折)。把你那几千 token 的系统提示词、few-shot 示例放进可缓存的部分,就能让"每次全价付前缀"变成"首次全价、之后享折扣"——对于"前缀固定、只有用户输入在变"的高频场景,这能省下惊人的成本。所以,优化的第一刀,砍向你的提示词:先给它瘦身(去掉不必要的 token),再看能不能用上 Prompt 缓存(让固定部分享折扣)。我把成本优化的几个抓手画成一张图:
这张图汇总了大模型成本优化的五大抓手:砍输入(精简提示词)、降前缀成本(Prompt 缓存)、免重复调用(结果缓存)、选对模型(按难度分级)、控输出(限制长度)。它们从不同角度,共同把"token 消耗"这个成本的源头压下来。下面几招,逐个细说。
第三件事:省钱招数二——缓存重复结果 + 按难度选模型
针对"浪费2:重复请求"和"浪费3:大材小用",对应两招:给重复的请求加缓存,以及按任务难度,选用不同档次(价格)的模型。
# 招2: 缓存重复请求的结果 —— 一样的问题, 只真调一次模型
def ask_llm(question):
cache_key = hash_normalize(question) # 把问题归一化成缓存key
cached = cache.get(cache_key)
if cached is not None:
return cached # 命中缓存, 0成本! 直接返回
answer = real_call_llm(question) # 没命中才真调模型(花钱)
cache.set(cache_key, answer, ttl=3600) # 缓存结果
return answer
# 对"高频重复问题"(FAQ类), 缓存命中率高时能省下巨量成本
# 招3: 按任务难度, 选不同档次的模型(模型分级路由)
def route_model(task):
if task.type in ("分类", "情感判断", "简单抽取"):
return cheap_small_model # 简单任务: 用便宜的小模型, 够用
elif task.type in ("复杂推理", "长文生成", "高质量要求"):
return expensive_flagship # 难任务: 才用贵的强模型
# 别一刀切全用最贵的旗舰模型!
这两招都能立竿见影地省钱:"缓存重复结果"的思路和普通的缓存一模一样——既然大模型对同样的输入会给出(基本)一样的输出,那对那些"高频重复"的请求(尤其是 FAQ 类、固定问题),完全可以把第一次的答案缓存起来,后续同样的请求直接返回缓存、根本不必再调模型。对重复率高的场景,这能直接把成本砍掉一大块(命中缓存的那部分,是零成本的)。 "按难度选模型"(模型分级路由)则是利用"模型有不同档次、价格差很大"这个事实——大模型不是只有一个,而是一个从"小而便宜"到"大而昂贵"的谱系;一个简单的分类、情感判断、字段抽取任务,用便宜十倍的小模型,效果可能完全够用,根本没必要动用那个最贵的旗舰模型。所以,别一刀切地"所有任务都用最强的模型",而要根据任务的难度,给它匹配一个"够用就好、价格最低"的模型——把贵的模型,只用在真正需要它那份强大能力的难任务上。这种"按需选型、好钢用在刀刃上"的模型分级,往往能在不损失效果的前提下,大幅降低成本。
第四件事:控输出 + 监控成本,把账单"看得见管得住"
除了输入(提示词),输出也花钱(而且很多模型输出比输入更贵)。所以还要控制输出长度。更重要的是,要给成本装上"眼睛和闸门"——监控成本、设置预算告警,别再让账单像我那次一样,憋一个月才在结算时爆雷。
# 招4: 控制输出长度 —— 输出也是钱, 别让模型啰嗦
resp = client.chat.completions.create(
model="...", messages=[...],
max_tokens=200, # 限制最大输出, 防止它长篇大论烧钱
)
# 提示词里也明确要求"简洁回答""只返回XX, 不要解释" → 输出更短更省
# 招5: 监控成本 + 预算告警 —— 把成本变成可观测、可控的指标
def call_with_tracking(messages):
resp = real_call(messages)
# 记录这次调用的 token 消耗和折算成本
cost = resp.usage.prompt_tokens * IN_PRICE + resp.usage.completion_tokens * OUT_PRICE
metrics.record("llm_cost", cost) # 上报到监控
daily_budget.add(cost) # 累计到当日预算
if daily_budget.exceeded():
alert("LLM 当日成本超预算!") # 超预算告警 / 甚至降级
return resp
# 关键: 每天的成本曲线、按功能/用户的成本分布, 都要能看到 —— 别等月底账单
这两招一个管"省"、一个管"控":"控输出长度"——大模型 API 输入输出都计费,而且不少模型的输出单价比输入还高,所以让模型"少废话"也能省钱:用 max_tokens 限制最大输出,并在提示词里明确要求它"简洁、只返回需要的、别长篇大论解释"。"监控成本 + 预算告警"则是最该补、却最容易被忽略的一环——我那次最大的问题,不是花了钱,而是对"正在花多少钱"完全无感,直到月底账单才知道。所以,必须把成本变成一个"可观测的指标":记录每次调用的 token 消耗和折算成本、画出每天的成本曲线、按功能/用户维度看成本分布、设置预算阈值并告警(甚至超预算时自动降级到便宜模型或限流)。有了监控,成本就从一个"月底才揭晓的惊吓",变成了一个"实时可见、超了就报警、能及时干预"的可控指标。把浪费点和对应的省钱招数汇总成一张表:
| 浪费点 | 对策 | 省的是什么 |
|---|---|---|
| 提示词又长又啰嗦 | 精简提示词 | 每次的输入 token |
| 固定长前缀重复发 | Prompt 缓存 | 重复前缀的费用(享折扣) |
| 重复请求每次真调 | 缓存重复结果 | 整次调用(命中即零成本) |
| 简单任务用贵模型 | 按难度分级选模型 | 用贵模型的差价 |
| 输出又长又啰嗦 | max_tokens + 提示约束 | 每次的输出 token |
| 不知道在花多少钱 | 监控成本 + 预算告警 | 失控的风险(可及时干预) |
第五件事:省钱不能牺牲效果——要量化评估
最后一个重要的提醒:所有的成本优化(精简提示词、换便宜模型、控输出长度),都可能影响效果——所以优化时,必须配合"效果评估",确保你省了钱、却没把效果省没了。不能为了省钱,把一个好用的功能,优化成了一个不好用的功能。
# 成本优化必须配合效果评估, 避免"省了钱、丢了效果"
# 1. 准备一个评估集: 一批"输入 + 期望输出/质量标准"
# 2. 每次成本优化后, 跑评估集, 看效果有没有明显下降
# - 精简了提示词 → 准确率还达标吗?
# - 换了便宜小模型 → 这个任务它做得还够好吗?
# - 限制了输出长度 → 回答还完整吗?
# 3. 找到"成本和效果"的平衡点: 在效果可接受的前提下, 成本最低的方案
# (这和前面RAG/Agent篇反复强调的"建评估集量化"是同一套方法)
这一步是成本优化的"安全绳",绝不能省。成本和效果,往往是一对需要权衡的矛盾:更精简的提示词、更便宜的模型、更短的输出,都可能让效果打折扣。所以,你不能只盯着"省了多少钱",而要同时盯着"效果有没有掉"——而要客观地衡量"效果有没有掉",就需要一个评估集(一批输入和对应的质量标准),在每次优化后跑一遍,确认效果还在可接受的范围内。成本优化的真正目标,不是"成本最低"(那把功能关了成本最低),而是"在效果达标的前提下,成本最低"——是在"效果"和"成本"这两个维度上,找到那个最佳的平衡点。(这套"建评估集、量化、找平衡"的方法,和我之前聊 RAG、聊 Agent 时反复强调的,是同一个工程思想——AI 应用里的几乎一切优化,最终都要靠"可量化的评估"来保驾护航。)所以,带着评估集去做成本优化:每砍一刀成本,都回头看一眼效果,确保你砍掉的是"浪费",而不是"价值"。
一张"大模型成本怎么优化"的决策图
把这次踩坑沉淀成一张图。每当你要上线一个用大模型的功能、或想优化已有功能的成本时,照着它过一遍:
这张图的起点和终点都很关键:起点是"先算账"(把成本变成清楚的数字),终点是"配监控告警"(让成本持续可见可控);中间则是精简提示词、缓存、分级选模型、控输出这几招,每招都要用评估集守住效果。把"先算账、再优化、跑评估、配监控"这套流程走一遍,大模型的成本就从"失控的黑洞"变成了"可控的工程"。
我立下的几条大模型成本规矩
这次"账单暴涨"的事故后,团队用大模型的规范里加了这么几条:
- 上线前必算成本账:估算单次调用 token、预估调用量、折算月成本,心里有数再上线,别等账单爆雷。
- 提示词要精简:砍掉啰嗦废话和多余示例,把提示词精炼到刚好够用,从源头减少 token。
- 用上 Prompt 缓存:固定不变的长前缀,用 API 的 prompt caching 享折扣,别每次全价重发。
- 重复请求加缓存:高频重复的请求(FAQ类)缓存结果,命中即零成本。
- 按难度分级选模型:简单任务用便宜小模型,贵的旗舰模型只用在真需要的难任务上。
- 控制输出长度:用 max_tokens 和提示词约束输出,别让模型啰嗦烧钱。
- 监控成本设预算告警:把 token 消耗和折算成本纳入实时监控,设预算阈值告警,超了能及时干预。
- 优化必配效果评估:每次成本优化都跑评估集,确保省了钱没丢效果。
把这几招的"性价比"也排个序,帮你优先做最划算的:
| 优化招数 | 省钱力度 | 实施难度 |
|---|---|---|
| 缓存重复结果 | 大(重复率高时) | 低 |
| 精简提示词 | 大(前缀越长越省) | 低 |
| Prompt 缓存 | 大(固定前缀场景) | 低(API 支持即可) |
| 按难度分级选模型 | 大(差价大) | 中(要做路由+评估) |
| 控制输出长度 | 中 | 低 |
| 监控+预算告警 | 间接(防失控) | 中 |
这几条里,第一条"上线前必算成本账"是纲。我这次最大的教训,本质上是把大模型当成了"和调用普通函数一样、没什么成本"的东西——而它恰恰是一个"调用即花钱"的付费服务。在传统软件里,我们写代码,几乎不用为"每一次函数调用、每一次计算"操心成本(那点 CPU 和内存几乎免费);可大模型时代,这个习惯害了我——每一次大模型调用,都是一笔实打实的、可观的开销,你必须像对待一笔笔真实的花销那样,去精打细算地使用它。这是从"传统开发"转向"AI 应用开发"时,一个必须建立的、全新的"成本心智"。
写在最后:用 AI,要算好"经济账",而不只是"技术账"
这次 AI 账单暴涨的经历,给我一个超越技术的深刻提醒:做 AI 应用,光算"技术账"(效果好不好、能不能实现)是不够的,还必须认认真真地算好"经济账"(成本划不划算、可不可持续)。在做这个功能时,我满脑子想的都是"怎么让大模型把这件事做好"(技术账),却几乎完全没想过"这么做,一个月要烧多少钱、这个成本撑得起这个功能的价值吗"(经济账)。而一个功能,哪怕技术上做得再惊艳,如果它的成本高到无法持续、入不敷出,那它在商业上、在工程上,就是失败的。大模型这个东西,技术上能力惊人,可它的"昂贵",也是前所未有的——它把"成本"这个变量,以一种我们传统软件开发里很少需要直面的程度,推到了我们面前。
想通这一点,我对"做 AI 应用的工程师"该具备的能力,有了更全面的认识:我们不仅要会"用好大模型把效果做出来",更要会"精打细算地、经济地使用大模型,让这份效果以可持续的成本实现"。"在效果和成本之间找平衡"——这种过去我们可能很少操心的"性价比"权衡,在 AI 时代,成了一项核心的工程能力。一个成熟的 AI 工程师,看一个 AI 方案,眼里不只有"它效果好不好",还有"它一次调用多少 token、用什么模型、能不能缓存、一个月烧多少钱、这个成本和它创造的价值匹配吗"。因为真正能在生产里长久跑下去的 AI 功能,从来不是那个"不计成本地堆最强模型、把效果做到极致"的,而是那个"在满足效果的前提下,把成本控制得恰到好处、可持续"的。
所以,如果你也在做 AI 应用,我想把这次踩坑最想说的话送给你:从你写下第一行调用大模型的代码起,就把"成本"这根弦绷起来——它不是上线后才需要操心的事,而是从设计之初就该纳入考量的一等公民。算好你的 token 账,精简你的提示词,缓存你的重复请求,为你的任务选对模型,监控你的每一笔花销。别让大模型那"一行代码就能调用"的便利,麻痹了你对它"每一次调用都在烧钱"的警觉;也别只陶醉于它技术上的惊艳,而忘了去算一算,这份惊艳,你到底付不付得起、付得值不值。那张暴涨的账单,最终教给我的,正是这份"技术账之外还要算经济账"的清醒——它让我明白,在 AI 时代,一个优秀的工程师,既要能驾驭大模型的"强大",也要能精打细算它的"昂贵";既要把效果做好,也要把成本管住。愿你我做的每一个 AI 功能,都不只是技术上的炫技,更是经济上算得过账的、能长久跑下去的、真正可持续的好产品。
—— 别看了 · 2026