团队 API 月度预算怎么排:从拍脑袋到可对账的预算流程
我见过两种排预算的失败,长得完全不一样,病根却是同一个。
第一种是拍脑袋型。老板问”这个 AI 功能一个月要花多少钱”,技术负责人心算三秒,报了一个听起来体面的数字。这个数字在第一周看着很宽裕,第三周开始追平,月中就撞线了。于是全组临时开会,砍功能、降模型、加限流,忙了两天把这个月糊弄过去,下个月接着来一遍。
第二种是宽松型,表面上从没出过事。预算报得很足,每个月都花不完,谁也没被追问过。直到年底做成本复盘,财务问”这笔钱里有多少是真正给用户创造价值的调用”,没人答得上来——不知道哪个功能吃掉了多少,不知道有多少是测试环境刷的,不知道有没有一个写错的循环在后台默默烧了半年。
这两种失败的根源相同:账单是一个总数,而不是一组可归属的用量数据。总数只能告诉你”花超了”,不能告诉你”哪里花超了、该找谁、下一步动哪个旋钮”。排预算这件事的本质,不是把数字估得多准,而是建立一条从业务量到账单的可追溯链路——估算只是这条链路的起点,归属、预警、预案才是它真正的价值。
下面这套流程我按四步讲:怎么自下而上算出来、必须补上哪四项隐性成本、怎么让预算落到人头上、以及超支之前怎么被叫醒。
一、自下而上算,别自上而下拍
自上而下是这样的:老板说”这块每月控制在 X 以内”,技术团队想办法塞进去。这个做法唯一的好处是快,坏处是这个 X 和真实用量之间没有任何函数关系——它超不超,完全看运气。
自下而上只有一个公式,但每个因子都必须有出处:
月成本 = 月业务操作数 × 每次操作平均 token 数 × 单价
拆成三个因子分别看:
| 因子 | 谁给 | 怎么拿到 | 估错的代价 |
|---|---|---|---|
| 月业务操作数 | 产品/运营 | 现有埋点的日活与人均触发次数,新功能用同类功能类比 | 偏差一般在 2 倍以内,且事后容易校准 |
| 每次操作平均 token 数 | 你自己 | 实测:跑一批真实样本,统计输入/输出 token | 最容易估错,偏差可以到 5 倍以上 |
| 单价 | 厂商官网/控制台 | 以官方最新价目为准,注意输入与输出分别计价 | 抄错档位或漏看单位,整个模型全错 |
第三个因子最没悬念,第一个因子最好商量,第二个因子最容易把整个预算带沟里。
为什么是”每次操作平均 token 数”?因为几乎所有人第一次估它的时候,估的都是”单轮请求”:一条系统提示词 + 一句用户输入 + 一段回复,加起来几百 token,看着很便宜。但线上真实发生的是:
- 多轮对话累积。第五轮请求会把前四轮的问答一起带上去,输入 token 是随轮次单调递增的。一次十轮的会话,累计输入远不是”单轮 × 10”,而更接近一个等差数列求和。
- 检索拼进来的上下文。做 RAG 的时候,召回几段文档一拼,输入立刻从几百涨到几千。而召回长度取决于用户上传了什么,不取决于你的测试样本。
- 重试也是真金白银。失败的那次调用照样计费,后面还得再来一次。
- 隐藏的固定开销。系统提示词、few-shot 示例、工具定义(function calling 的 schema 是每次请求都要发的)——这些每次都摊在输入里。
所以估这个因子的正确姿势是:别算,去测。挑一批真实的用户输入(不是你自己造的干净样本),完整跑一遍链路,把每次请求的输入/输出 token 记下来,取平均。关于怎么做这一步的采样与建模,上线前怎么估算月成本那篇讲得更细,这里不重复。
走一遍完整算例
下面这组参数全部是为了演示算术而设的假设值,不是任何行业基准,你必须换成自己的数。单价我一律写成变量 P_in(输入,元/百万 token)和 P_out(输出,元/百万 token)——你自己去官网查填。
假设:
- 每天使用该功能的用户 800 人,人均每天 3 次会话 → 2400 次会话/天
- 实测每次会话平均输入 6000 token、输出 900 token(已含多轮累积与检索上下文)
- 一个月按 30 天算
那么裸的生产用量是:
月输入 = 2400 × 6000 × 30 = 432,000,000 token = 432 百万 token
月输出 = 2400 × 900 × 30 = 64,800,000 token = 64.8 百万 token
月成本 = 432 × P_in + 64.8 × P_out
到这一步,你手上有了一个有出处的数——每一位都能回溯到某个人给的输入。这比”我觉得两万块差不多”强的地方不在于更准,而在于它是可以被质疑和修正的:产品说日活会到 1500,你把 800 换掉重算就行。
把这三个因子填进成本估算器可以直接出月成本,它按月输入/输出 token 量对各家模型自动计算并排序,省掉自己拉表格的功夫,也顺便让你看到换一档模型对总数的影响有多大。
二、必须计入的四项隐性成本
上面那个数字是”理想世界的生产用量”。真实账单一定比它高,高出来的部分就来自下面四项。这一节是整套流程里最值钱的部分——绝大多数预算翻车不是因为主公式算错,而是因为这四项一项都没算。
1. 重试与失败
计费是按请求发生算的,不是按你满意算的。以下几类都会产生”付了钱但没拿到可用结果”的调用:
- 撞限速被拒(部分错误响应不计费,但你的重试会计费)
- 超时后客户端重发
- 返回的 JSON 格式不合格、字段缺失,业务层判定失败后重跑
- 工具调用参数不对,模型被要求重新生成
怎么估:直接从你的调用日志里数。统计一段时间内”最终成功的业务操作数”和”实际发出的 API 请求数”,比值减一就是重试开销率。如果还没上线没有日志,先按一个保守值起步,上线两周后用真实数据替换掉——这是整个预算里最应该尽早用实测数替换的假设。
本例假设重试开销率 8%,也就是所有生产用量乘以 1.08。
2. 开发与测试消耗
这项最容易被完全遗忘,因为它不发生在生产环境,没人把它和”业务成本”联系起来。但它花的是同一笔钱,而且在开发高峰期能轻松超过生产用量。三个来源:
- CI 里的集成测试:每次提交跑一遍,一天几十上百次
- 开发本地调试:改一版提示词就得跑一遍看效果,改十版跑十遍
- 评测集回归:每次动模型或提示词,跑一遍几百条样本的评测集验证没退化
怎么估:分别按”频次 × 每次样本数 × 每样本 token”算。继续用假设值:
| 来源 | 假设参数 | 月输入(百万) | 月输出(百万) |
|---|---|---|---|
| CI 集成测试 | 200 次/天 × 3000 输入 / 500 输出 | 18 | 3 |
| 评测集回归 | 8 次/月 × 500 条 × 4000 输入 / 800 输出 | 16 | 3.2 |
| 本地调试 | 5 人 × 40 次/天 × 3000 输入 / 500 输出 | 18 | 3 |
| 合计 | 52 | 9.2 |
注意这里的量级:52 百万输入 token,相对于生产的 432 百万,是 12% 左右的额外开销。这不是零头。
顺便说一个工程上的建议:评测集回归和 CI 应该走独立的 key,理由下一节讲。
3. 长尾请求
平均值会骗人。真实的输入长度分布几乎总是右偏的——大多数请求规规矩矩,少数请求超长(用户上传了一份几十页的文档、粘贴了整个日志文件、一次会话聊了六十轮没开新窗口)。这少数请求会吃掉不成比例的预算。
怎么估:不要只看平均值,把实测样本的 P95、P99 输入长度也算出来。如果 P95 是平均值的 3 倍以内,长尾影响有限;如果 P99 是平均值的十几倍,你必须单独给它列一项。
本例假设:2% 的会话输入达到 48000 token(是平均值 6000 的 8 倍)。这部分多出来的量:
每次会话的平均增量 = (48000 - 6000) × 2% = 840 token
月会话数 = 2400 × 30 = 72,000
额外月输入 = 72,000 × 840 = 60,480,000 = 60.48 百万 token
修正后月输入 = 432 + 60.48 = 492.48 百万 token (+14%)
长尾还有一个比钱更重要的副作用:超长请求更容易超时、更容易撞上下文上限、更容易触发重试——它同时推高了上面第 1 项。所以处理长尾的正确做法不只是”预算里加钱”,还应该在工程上设一道输入长度硬闸,超过阈值走截断或分段策略。
4. 增长
**按今天的量排出来的预算,三个月后一定不够。**这不是悲观,这是你希望发生的事——业务在涨。但预算如果不带增长率,你会在业务最好的那个月被自己的预算卡住脖子,然后把”要不要加预算”这个本该提前决定的问题,变成一个必须当天决定的救火问题。
怎么估:用最近几个月的业务量环比增速,而不是用愿望。如果是新功能没有历史,就用同期上线的类似功能的爬坡曲线。
本例假设月环比增长 15%。如果预算周期是一个季度,用”当前水位 × 3”是错的:
三个月合计 = S × (1 + 1.15 + 1.15²) = S × 3.4725
与 S × 3 相比,多 15.75%
季度预算必须按这个系数放大,否则第三个月必然穿。
把四项加回去
按顺序叠加(长尾先修正基数,再乘重试,最后加测试量):
生产输入(含长尾) = 492.48 百万
生产输出 = 64.8 百万
× 重试系数 1.08:
输入 = 492.48 × 1.08 = 531.88 百万
输出 = 64.80 × 1.08 = 69.98 百万
+ 开发测试:
输入 = 531.88 + 52 = 583.88 百万
输出 = 69.98 + 9.2 = 79.18 百万
月预算 = 583.88 × P_in + 79.18 × P_out
和最初那个”干净”的数字比一比:输入从 432 涨到 583.88(+35%),输出从 64.8 涨到 79.18(+22%)。
把修正后的这组量(583.88 / 79.18 百万 token)重新填一次成本估算器,和第一版的数字并排看——这两个数之间的差距,就是你以后每个月不用去救火的理由。
这 35% 就是拍脑袋和排预算的差距。而且请注意,这里面没有一分钱是浪费——重试、测试、长尾都是真实业务必然产生的开销,只是之前它们从来没进过那张表。
三、预算要能落到人头上
算出一个总数只解决了”报多少”。真正的难题在下个月:账单来了,比预算高 30%,你怎么知道是哪个功能、哪个团队、哪个环境干的?
如果全公司共用一把 key,答案是你不知道,只能靠人肉翻日志。而日志能不能翻出来,取决于半年前有没有人想到要记这个字段。
正确的做法是让账单在产生的时候就自带归属信息:通过网关下发虚拟 key,每把 key 绑定一个维度组合,网关按 key 统计用量。LiteLLM 虚拟 key 那篇讲了具体怎么配预算、限速和模型白名单,这里只讲一条设计原则:
你希望账单按什么维度切开,就按什么维度发 key。
这条原则听起来像废话,但它能直接推导出你的 key 体系。常见的三个维度:
- 按团队/成本中心:搜索组、客服组、内容组各一把。这是财务对账的最小单位,几乎必配。
- 按项目/功能:同一个团队下的”智能摘要”和”工单分类”分开。这样某个功能成本异常时,能一眼定位,而不用去猜。
- 按环境:
prod/staging/ci/dev必须分开——这是最重要的一刀。前面算的 52 百万测试输入,只有在 key 分开的前提下才能被独立看到;否则它永远混在生产账单里,你会一直以为是用户在花钱。而且分开之后可以给 CI 和 dev 设更低的硬上限:一个写错的死循环在 CI 里跑一夜,能把整月预算吃光,而这种事故只要 key 分开就是可控的。
几条实操上的注意点:
- key 的命名要能自解释,比如
search-prod、search-ci、content-dev。半年后没人记得key-3是谁的。 - key 要有生命周期。临时给外包或做 POC 发的 key,发的时候就设好过期时间,别指望有人记得回收。
- 别为了”方便”共用。每多一个人共用一把 key,这把 key 的账单归属就模糊一分,而共用带来的方便只值几分钟。
- 粒度不是越细越好。切到”每个人一把”通常没有必要,管理成本会反噬。先切到”团队 × 环境”,遇到具体的定位困难再往下细分。
四、预警,而不是事后对账
月底看账单是验尸,不是控制。预算真正发挥作用的地方在月中——在你还有时间改变结果的时候把你叫醒。
软阈值优先于硬上限
只设硬上限(到额度就断)是一种偷懒的做法:它确实不会让你超支,但它的表现形式是生产环境在某个毫无预告的时刻突然不可用。用户看到的是功能挂了,你看到的是一堆 500。
正确的配置是软硬结合:
- 50% 报警:如果月中过半才用一半,节奏正常;如果第 10 天就到 50%,说明你的估算或业务量有偏差,现在开始调整还来得及。
- 80% 报警:这是”必须做决定”的线。要么申请追加,要么启动降级预案,不能装作没看见。
- 100% 硬上限:留着,但把它当成保险丝而不是刹车。生产 key 的硬上限应该显著高于预算(比如 1.5 倍),真正卡死的是那些跑飞了会烧钱的 key(CI、dev、POC)。
盯速率,而不是只盯累计值
累计值是滞后指标——它告诉你已经花了多少,但你要的是”照这个势头下去月底会花多少”。所以监控的主指标应该是日均消耗速率,并据此做线性外推:
预计月末消耗 = 当前累计 ÷ 已过天数 × 当月总天数
举例:月预算 B,第 10 天累计已用 60%。
预计月末 = 0.6B ÷ 10 × 30 = 1.8B —— 会超支 80%
这个信号在第 10 天就出现了,而累计值要到第 17 天才会撞上 100%。速率突变是异常的先行信号:新版本上线、某个用户开始批量刷、缓存失效导致重复计算,都会先表现为速率跳变,再表现为账单变高。所以除了看”预计月末”,还要看日环比——今天比昨天多 3 倍,立刻查,别等累计线爬上来。
把重试率也纳入监控
这是一个很多人没做的动作,但性价比很高:重试率上涨会先于账单上涨。
原因很直白。当上游开始限速、某个模型响应变慢、或者你新改的提示词让输出格式合格率下降时,最先变化的是”每个成功业务操作对应几次 API 请求”这个比值。它涨了,说明你在为同一件事付两遍钱,而这时候累计消耗曲线可能还没明显偏离。等它偏离了,钱已经花掉了。
所以监控面板上至少要有三条线:累计消耗、日均速率、重试率。三层告警体系怎么搭(平台侧、代码侧、可观测平台)在调用量监控与预算告警那篇里有更完整的实现,可以配合着看。
五、超支了怎么办:分级预案
告警响了,然后呢?如果这时候才开始讨论”我们该怎么办”,你会在压力下做出糟糕的决定——通常是直接把功能关掉。
预案要在预算排出来的同一天就写好,而且必须分级。每一级都有明确的业务代价,写清楚代价是为了让当时的人能快速判断该走到哪一级。
第一级:降档。把非核心链路换到更便宜的小模型。 业务代价:输出质量下降,但功能还在。适用于摘要、分类、标签这类容错度高的场景。前提是你事先做过降档模型的效果评测——临时切换到一个没测过的模型,等于用线上用户做实验。这也是为什么评测集要常备。
第二级:降频。对非关键路径限流或延后。 业务代价:部分请求变慢或排队。典型可降频的对象:批量后台任务(推迟到下个计费周期)、非付费用户的高频请求(加冷却时间)、自动化的定时分析任务(降低频率)。这一级的关键是你事先分好了哪些路径是关键的——如果分不出来,降频就等于随机伤害用户。
**第三级:停服。**关掉功能或断掉 key。 业务代价:用户直接受损,会产生客诉和信任损失。这一级只应该出现在两种情况:一是确认遭遇滥用或攻击,二是前两级都用尽了还在失控。注意顺序:真出事故的时候人会本能地去做最彻底的动作,而最彻底的动作往往代价最大。预案的价值就是在慌乱的时候替你按住手。
再补一句更重要的:每次走到任何一级,都要在事后回填到预算模型里。是量估低了?是重试率变高了?是长尾比例超预期?——这条反馈闭环才是让下个月的预算比这个月准的唯一途径。预算不是一份年初交上去就锁死的文件,它是一个每月都要被真实账单校正一次的模型。
自查清单
排完预算,对照下面几条过一遍:
- 三个因子都有出处吗——业务量是谁给的、平均 token 是实测的还是猜的、单价是哪天从官网抄的?任何一项答不上来,这个预算就是拍的。
- “每次操作平均 token”是用真实样本测出来的吗?多轮累积、检索上下文、系统提示词和工具定义都算进去了吗?
- 四项隐性成本都加了吗——重试、开发测试、长尾、增长?季度预算用的是等比求和系数,不是简单乘 3 吧?
- key 是按你想对账的维度发的吗?至少做到”团队 × 环境”分离,CI 和 dev 有独立的低额度硬上限。
- 告警设的是软阈值(50%/80%)还是只有硬上限?硬上限是保险丝,不该是唯一的防线。
- 监控面板上有速率和重试率吗,还是只有累计值?能不能一眼算出”预计月末消耗”?
- 降档 / 降频 / 停服三级预案写下来了吗?降档要用的小模型跑过评测了吗?哪些路径算”非关键”,有人拍板了吗?
- 这个月的实际账单,回填到模型里了吗?偏差来自哪个因子,找出来了吗?
至于降档之后还能从哪里继续省,大模型 API 成本优化 10 招按环节列了一遍,可以当作预案第一级的备选动作库。
把上面这些因子填进成本估算器,几分钟就能拿到一份带出处的月成本初稿,剩下的时间留给归属和预警。