前阵子一个做 SaaS 的朋友半夜给我发消息,说他们公司的大模型 API 账单这个月又翻倍了,十来个研发的团队,光 API 费用一个月烧掉二十多万,老板已经放话要砍掉 AI 功能。我让他把账单明细和调用日志发过来,花了一个多小时就定位到三个问题:一个 Agent 项目的循环调用没有设上限;系统提示词被某位同学塞了两万字的业务说明;全公司所有 AI 功能默认都走同一个最贵的旗舰模型。这三件事单看都不起眼,叠在一起就是每月六位数的额外支出。
这其实不是个例。大模型 API 的成本不像服务器和带宽那样有一个明确的峰值概念,它藏在每一次请求的输入输出 token 里,藏在你没注意到的重试和超时里,藏在越攒越长的对话历史里。等到月底看见账单才惊觉“失控”,其实失控早就发生了。
这篇内容我就围绕一套四步闭环来讲:看得见、压得下、守得住、持续省。不管你是独立开发者、小团队的技术负责人,还是公司里专门负责成本治理的架构师,只要业务在调大模型 API,这套方法都能直接落地。后面会用真实场景、计算公式和可直接抄走的配置来说,少讲空话。
1. 先弄清钱烧在哪:大模型 API 的成本账本长什么样
1.1 按 token 计费:账本到底怎么算
几乎所有主流大模型 API 都是按 token 计费,输入和输出分开计价,输出通常比输入贵好几倍。以市面上一款旗舰模型为例,输入大约 3 美元/百万 token,输出大约 15 美元/百万 token;而一款轻量小模型,输入可能只要 0.2 美元/百万 token,输出 0.6 美元/百万 token。模型之间单价相差 15 到 25 倍,这是成本差异最大的一个杠杆。
问题在于 token 数量不是肉眼可见的。一次请求消耗多少 token,取决于你塞进去多少上下文。举个例子:一个客服对话机器人,system prompt 1500 token,用户历史消息 4000 token,本轮用户输入 300 token,那么输入就是 5800 token;模型回答平均 600 token。单看这一次请求没多少钱,但乘上业务量就不一样了。
算一笔账:1 万日活用户,平均每人每天 20 轮对话,就是 20 万次调用/天。输入侧 20 万 × 5800 = 11.6 亿 token,输出侧 20 万 × 600 = 1.2 亿 token。如果全都用旗舰模型,输入一天就是 1160 × 3 = 3480 美元,输出一天 120 × 15 = 1800 美元,加起来每天 5280 美元,一个月按 30 天算就是 15.8 万美元,折合人民币一百多万。这就是很多团队账单“莫名其妙”翻倍的原因——不是用量突然涨了多少,而是从第一天开始就选了一个远超需求的模型,并且没有人意识到单次请求的 token 成本在悄悄膨胀。
1.2 账单翻倍的三个典型元凶
第一,全量请求都打旗舰模型。很多项目立项的时候根本不会想成本,哪个模型效果好就用哪个。等业务跑起来,大量“内容分类”“意图识别”“JSON 抽取”这类简单任务,也跟复杂推理任务一样走最贵的模型,等于拿大炮打蚊子。第二,上下文无限膨胀。对话类产品最典型:历史消息一直往请求里塞,不做裁剪也不做摘要。系统提示词从最初的几百 token 被改到几千、几万,我见过最夸张的是一个客服系统把完整产品手册两万字写进了 system prompt,每次请求光是固定部分就多花 2 万 token。最近不少人在技术群里贴“api error: 400 this model's maximum context length is 1048576 tokens”这类报错,表面是上下文超限,背后往往是同一个问题:token 在无节制堆积。报错只是结果,成本早就先爆了。第三,重试与并发失控。上游服务不稳定、网络抖动、模型偶发 429 或 503,代码里如果按最简单的方式“失败了就立刻重试”,一次高峰期的模型抖动就能让调用量翻三倍。有些 Agent 项目还存在循环调用没有上限的问题,Agent 自己调自己、工具 A 调工具 B 再调回 A,一个任务最终触发几十次模型调用,账单直接失控。
这三个元凶有一个共同点:它们都发生在代码和配置层面,而不是发生在“真实业务用量增长”层面。所以成本治理不能靠事后看账单,得靠事前埋点和事中控制。
2. 闭环第一步:看得见——把每一笔调用变成可量化的数据
2.1 全链路日志埋点:别等账单来了才后悔
成本管理的起点是数据。不用搞什么高大上的平台,先把最基础的调用日志补齐就有用。每条日志至少要记录这些字段:请求时间、业务线、功能模块、模型名称、输入 token 数、输出 token 数、响应耗时、HTTP 状态码、是否重试、用户标识、费用估算。
费用估算直接用 token 数乘以单价。建议在代码里做一个统一封装,不要每个业务各写各的。以下是 Python 的一个极简示例,核心逻辑是每次调用后把 usage 字段和单价记录下来。
import time, json, logging PRICING = { "flagship": {"input_per_m": 3.0, "output_per_m": 15.0}, "light": {"input_per_m": 0.2, "output_per_m": 0.6}, } def estimate_cost(model: str, input_tokens: int, output_tokens: int) -> float: p = PRICING[model] return input_tokens / 1_000_000 * p["input_per_m"] + \ output_tokens / 1_000_000 * p["output_per_m"] def log_llm_call(biz: str, feature: str, model: str, resp: dict): usage = resp.get("usage", {}) input_tokens = usage.get("prompt_tokens", 0) output_tokens = usage.get("completion_tokens", 0) record = { "ts": time.time(), "biz": biz, "feature": feature, "model": model, "input_tokens": input_tokens, "output_tokens": output_tokens, "cost_usd": round(estimate_cost(model, input_tokens, output_tokens), 6), "status": resp.get("status_code", 200), } logging.getLogger("llm_cost").info(json.dumps(record))注意几个细节。第一,不要只在成功响应里记日志,超时、限流、报错也必须记,因为重试和失败才是真正的成本黑洞。第二,如果用了流式输出,很多 SDK 默认不会返回 usage,需要在请求参数里显式打开 stream_options 或 include_usage 之类的开关,否则统计会少一大截。第三,日志必须带业务标识,否则后面没法按功能归因——这一步决定了你之后能不能回答“哪个功能最烧钱”。
2.2 成本大盘怎么搭:从零开始也不难
日志有了,下一步是把数据变成看板。如果团队已经有 Grafana + Prometheus,或者云厂商现成的监控体系,直接把 llm_cost 日志接进去就行。没有的话,用 ClickHouse 或者 PostgreSQL 存日志,再配一个简单的查询页面也够用,不用追求一次性到位。
看板至少要盯这几类指标:总费用趋势(按天、按周)、按模型分组的费用占比、按业务线分组的费用排名、单次请求平均 token 数、上下文长度分布、重试率与失败率。其中“按模型分组的费用占比”最直观——如果旗舰模型占了 90% 以上的费用,而业务里 70% 是简单任务,那么成本优化的突破口几乎就锁定了。
我习惯每天早上先看一眼“昨日费用 TOP5 功能”这个列表,把问题在当天就处理掉。这个习惯比任何复杂的成本治理平台都管用,因为绝大多数失控都不是一夜之间发生的,而是连续几天悄悄爬坡,直到越过心理阈值才发现。
2.3 用数据锁定“烧钱大户”的实操方法
有了日志和看板,找烧钱大户就是个查询的事。核心思路是按业务线或功能模块分组,按 cost 倒序排列,再对 Top 模块进一步下钻,看它们的平均输入 token 和调用量。这里分享三个常用的分析视角:
- 调用量大 × 模型贵:典型“规划失误”,简单业务走了贵模型。
- 调用量不大 × 单次输入 token 高:典型“上下文膨胀”,去看是不是历史消息和 system prompt 失控。
- 调用量不大 × 失败重试多:典型“稳定性问题”,看是不是没有退避重试、没有熔断。
这三个视角基本能解释 90% 的异常账单。下面这张表可以贴在团队 wiki 里,谁怀疑成本有问题就按这个顺序排查。
| 现象 | 优先怀疑方向 | 下一步动作 |
|---|---|---|
| 费用高但调用量平稳 | 模型选型偏贵 | 检查模型路由,拆分简单任务 |
| 调用量涨但费用涨更多 | 上下文膨胀 | 控制 token 总量,加摘要裁剪 |
| 报错多且费用同步涨 | 重试风暴 | 检查退避策略、超时和熔断 |
| 某个功能费用异常增长 | Agent 循环调用 | 设置最大调用轮次和预算上限 |
3. 闭环第二步:压得下——不牺牲效果的三种瘦身手段
3.1 模型路由:让简单任务别再“大炮打蚊子”
模型路由是我的第一推荐。不把鸡蛋放在同一个模型里,按任务难度动态选择模型,是投入产出比最高的成本优化手段。
具体做法:先用一个低成本分类器判断任务类型,再路由到对应模型。分类器可以是很小的模型,甚至规则匹配。比如客服机器人,用户问“怎么退货”“订单状态”这类标准化问题,走轻量模型完全够;只有法律条款解释、复杂代码排查这类任务才转旗舰模型。实测下来,一个典型客服场景里 70% 的请求可以路由到小模型,成本直接下降 50% 到 70%。
路由规则不建议一开始就做得太复杂。先用最简单的关键词或意图白名单,跑两周观察准确率,再把拿不准的边界样本收集起来逐步迭代。同时注意不要让分级路由影响用户体验——如果小模型给出的结果质量不可控,至少要对小模型做结果兜底校验,不满足置信度时再升级到旗舰模型重新处理。这个“先小模型后升级”的路径,既能省钱又能保质量。
3.2 Prompt 压缩与缓存复用:把重复的钱省回来
Prompt 压缩是被低估的省钱手段。几乎每个项目都能从 system prompt 里挤出 30% 以上的冗余。做法分三步:第一步,把固定说明和动态内容拆开,动态内容不要一股脑塞进 system prompt;第二步,把超长业务文档做离线切块和检索,只在需要时把相关片段注入上下文,而不是全量写入;第三步,给对话历史设窗口,超过 N 轮就把更早的内容用摘要代替,摘要本身就用轻量模型生成。
缓存方面分两种。一种是“语义缓存”:高频请求的问题和答案如果高度重复,直接在 Redis 里命中最新的有效回答,不再调用模型。教育类、客服类产品里这类请求占比能到 20% 到 30%,命中率非常可观。另一种是主流云厂商推出的“上下文缓存”,把重复出现的固定前缀(比如 system prompt)做 KV Cache 命中,命中的输入 token 只按原来的 10% 计价。这类便宜是平台给的,但前提是你要让请求的固定前缀保持稳定,不要每次拼接顺序都不一样,否则缓存永远命中不了。
这里也值得算一笔账。还是前面那个客服系统,每天 20 万次调用,每次输入 5800 token。先做模型路由,70% 走向小模型,日成本从 5280 美元降到约 1800 美元;再做历史摘要压缩和前缀缓存,把平均输入 token 从 5800 压到 2500,日成本进一步降到约 1100 美元。从 5280 到 1100,降幅接近 80%。我在多个项目里实测,模型路由、提示词压缩、缓存三件套一起上,绝大多数业务都能在不明显影响输出质量的前提下把 API 成本砍掉一半以上。
3.3 重试、超时与上下文控制:细节里的隐形开销
第三个手段是细节控制,也是最容易被忽略的。先说重试:模型接口偶发 429、5xx 很正常,但重试策略必须用指数退避加随机抖动。重试次数建议 3 次以内,超过就降级返回兜底文案,不要无限重试。说得直白一点,一个没有退避策略的重试循环,等于在帮模型供应商刷你的钱包。
超时也要设置,不能等一个慢请求拖死整个服务。流式接口可以把超时设为 90 秒,非流式建议 60 秒以内,具体根据模型响应速度实测调整。上下文控制主要体现在两个参数上:max_tokens 和对话窗口。max_tokens 不设或设很大,模型可能产生冗长输出,而输出价格往往是输入的 5 倍;按场景把输出上限卡住,既能省钱又能让响应更可控。对话窗口则建议在代码里强制裁剪,超过窗口就把最早的消息摘要化,摘要任务用轻量模型做,费用几乎可以忽略。
还有一个小技巧:能用结构化输出约束就尽量用。让模型输出 JSON 或固定枚举值,而不是自由文本,可以在保证效果的同时大幅减少 token 冗余,也让下游更方便做缓存和路由判断。我自己写抽取类功能时,输出格式写死、字段名尽量短,实测省 token 的效果非常明显。
4. 闭环第三步:守得住——预算红线、配额告警与自动熔断
4.1 配额与限流:把钱关进笼子
优化做到位之后,预算红线才是兜底。这一步的目标是:就算上游出了问题、代码里有 bug、或者有人上线了一个不靠谱的新功能,平台也能把钱控制在预算内,而不是等月底看账单崩溃。
主流云厂商的 API 控制台基本都支持配额管理,建议给每个 API Key 设置三类限制:月度预算上限、每分钟请求数(RPM)、每分钟 token 数(TPM)。如果你的 Key 是业务共享的,务必按业务线拆成不同的 Key,分别设置预算,这样某个业务失控不会拖垮全局。比如总预算是每月 1 万美元,可以拆成:核心客服 4000、内容生成 3000、内部研发测试 2000、临时活动 1000,每类独立限额、独立告警。拆 Key 不仅是成本管理,也是权限和安全隔离。
限流参数设置的时候不要只拍脑袋。先统计当前业务的调用量峰值,比如某业务峰值 200 RPM,那么 Key 限额就设 300 RPM,留 50% 余量;TPM 同理,根据平均输入 token 估算。如果没有历史数据,就从小往大调,宁可先限得紧一点,再根据业务反馈逐步放宽。平台上的限额配置一般都支持控制台或 API 修改,不会影响业务连续性。
4.2 告警分级与熔断策略
告警不要搞成“全告警等于没告警”,要分级。我的分法是:
- P0:单日费用超过预算 80%,立即拉群并触发自动熔断。熔断可以设定为“接下来的请求自动切换到便宜模型”,或者“非核心功能直接降级返回缓存”。
- P1:按天费用环比增长超过 50%,自动通知技术负责人,进入排查流程。
- P2:某个业务线 Key 的费用逼近限额,邮件或群消息通知,供开发同学自查。
自动化方面,最实用的是在网关或封装层写一个“预算开关”。每次调用前检查当前日费用是否超阈值,超了就拒绝或降级。这个逻辑很短,但能救命。我见过不止一次,因为某条 prompt 里出现一个 bug 导致模型疯狂重试,全靠这个开关把损失控制在两小时内,而不是烧掉一周预算。
注意:熔断降级一定要提前设计好兜底文案和人工处理路径,不能一降级用户就面对一片空白。降级可以是“返回缓存中的同类答案”“提示稍后再试”,或者直接转到人工客服。
5. 闭环第四步:持续省——把成本治理变成团队习惯
5.1 成本周报与复盘:数据对齐是第一步
四步闭环的最后一步是把“一次性治理”变成“持续机制”。我比较推荐成本周报制度:每周一由负责同学拉一份上周成本数据,包含总费用、环比变化、Top 模型占比、Top 功能排名、异常调用次数,然后在团队周会上用 10 分钟过一遍。这个动作的价值不是“看数字”,而是让每个研发都建立起“我的代码是要花钱的”这个意识。
周报模板可以参考:
| 指标 | 本周 | 上周 | 环比 |
|---|---|---|---|
| API 总费用(美元) | 3120 | 2860 | +9% |
| 旗舰模型费用占比 | 42% | 55% | -13% |
| 单次请求平均输入 token | 3200 | 4100 | -22% |
| 重试率 | 2.1% | 5.4% | -61% |
周会复盘时不要只盯着上升的数字骂人,重点看两件事:这周有没有新增功能上线导致成本结构变化;上周制定的优化措施有没有落地、效果是否符合预期。如果不符合,就当场重新定位原因,是数据埋点漏了,还是优化方案本身有缺陷。
5.2 让“省钱”成为团队约定
机制要变成约束,得写进团队的开发规范里。我在团队里推动过几条规则,实测下来有效:
- 新功能接入大模型前,必须填写“模型选型评审”:目标场景、预估调用量、预估单次 token、选择的模型、月度预算、降级预案。评审通过才能申请 Key。
- 任何对 system prompt 的修改都要走 review,并且记录修改前后的 token 变化。很多同学不知道,几行 prompt 的改动可能每天多花好几百块。
- 非生产环境的调试流量,尽量走本地模型或免费额度,不要全打到线上 API。现在用 Ollama 这类工具在本地跑 7B 到 14B 的模型非常方便,开发联调、回归测试完全够用。
另外,关于是否要自己部署私有模型,我的建议是分阶段考虑。如果业务量小、团队没有 GPU 运维经验,直接用商业 API 是划算的;当调用量到了一定规模,比如月成本稳定在 5 万美元以上,再评估用 vLLM 等方案私有化部署开源模型,长期边际成本会低很多,但要把 GPU 采购、运维、模型效果的隐性成本都算进去。很多团队在这上面栽跟头,只算了 GPU 成本,没算人力和迭代成本。
6. 常见问题与排查技巧实录
6.1 账单翻倍排查清单
把前面所有经验压缩成一张排查清单,按顺序执行即可定位大部分问题:
- 拉账单明细,按模型、按业务线、按日期分组,看增量来自哪里。
- 查调用日志里的 token 用量,重点关注单次输入 token 是否异常膨胀。
- 查重试率和错误码分布,429、5xx 比例高说明重试策略有问题。
- 上模型路由和 prompt 缓存,看高频重复请求有没有命中缓存。
- 检查是否有人直接绕过封装层调用 API——绕过意味着日志和限流全部失效,这是隐蔽性最强的坑。
6.2 三个真实踩坑案例
案例一:客服机器人上下文无限膨胀。团队反馈“用户多聊了几轮后响应变慢且费用暴涨”。日志显示 60% 的请求输入 token 超过 1 万,最长的有 5 万。原因是对话历史只追加不清理。修复:引入摘要压缩,超过 10 轮就把更早的消息摘要成一段话,系统提示词从 3000 字精简到 800 字。上线后费用下降约 45%,且用户几乎无感知。
案例二:Agent 循环调用无上限。一个文档分析 Agent,因为工具链里有个 bug,一次任务里反复调用模型 30 多次,单任务成本从预期的 0.2 美元变成 6 美元,当天直接烧掉一周预算。修复:在 Agent 框架里强制设置最大调用轮次,比如 8 次,到达上限强制输出当前结果并告警;同时给该业务单独设置低预算 Key,从根上限制损失。
案例三:重试风暴。某天线上模型服务商报错 503,代码里是“失败就立刻重试”,一瞬间所有请求同时反复重试,导致账单异常飙高。修复:改成指数退避加随机抖动,最多重试 2 次,并且加入熔断开关,连续失败超过阈值就切备用模型或走兜底缓存。
这三个案例的共同教训是:成本失控很少来自“业务量真的涨了”,更多来自工程细节和技术债。提前埋点、设定上限、兜底降级,这三件事比事后研究任何账单都管用。
说句实在话,大模型 API 成本管理这件事,技术含量不在“知道某个高级技巧”,而在愿不愿意把这些基础动作老老实实做完。我自己带过好几个项目,每次都是重复同样的路径:先补日志、再砍冗余、再设红线、最后定制度。只要把四步闭环跑起来,账单翻倍这种事基本就能从“惊吓”变成“正常波动”。最后再分享一个小技巧:每个季度做一次模型选型复盘,因为模型价格和性能变化太快,半年前的最优解,现在很可能已经不是了。