AI 产品单位成本怎么算:从 token 账单到每用户毛利模型
跟做 AI 产品的团队聊成本,通常会遇到两种状态。
第一种是完全不知道单个用户花了多少钱。产品已经上线几个月,用得挺好,问一句”你们一个付费用户一个月消耗多少 token”,对方要么答不上来,要么说”应该不多吧”。第二种稍微好一点:有账单。财务每月拉一个数字出来,比如”这个月 API 花了两万三”,然后大家看着这个数字点点头,下个月再看一次。
这两种状态其实是同一种状态——你手上没有可以用来做决策的成本数据。总账单是个结果,不是个模型。它回答不了下面这几个问题:
- 定价定 19 还是 99,成本这一侧能不能撑住?
- 要不要给免费用户设上限?设在哪?
- 昨天签的那个大客户,是在赚钱还是在烧钱?
- 如果用户量翻十倍,成本是翻十倍还是翻三十倍?
这些都是单位经济模型(unit economics)的问题。你要能回答”每个用户每月花你多少钱”,才能回答”这门生意成不成立”。这篇讲的就是怎么从一堆 token 日志,一层层推到毛利。
一、别一步跨到”每用户成本”,先建中间量
很多人一上来就想直接算每用户成本:总账单除以月活。这个数字算出来是有的,但它几乎没用——因为它把所有信息都糊掉了。用户量变了它变,用户结构变了它变,模型换了它变,prompt 改了它也变。你分不清这个月涨了 20% 是因为用户重了、还是因为你上周加了一段系统提示词。
要建的中间量是:每次业务操作的平均 token 消耗。
“业务操作”指的是你产品里用户能感知到的动作,不是 API 调用。比如”提一个问题""生成一份周报""改写一段文案""分析一个文档”。一次业务操作背后可能是一次 API 调用,也可能是三次(意图识别 + 检索改写 + 生成),甚至是一个多轮 Agent 循环。用户不知道,也不需要知道,但你的成本模型必须以用户能感知的那一层为单位——因为定价是按那一层定的。
为什么这个中间量最有价值,有两个很实在的理由。
第一,换平台的时候它不变。 token 消耗是你的产品设计决定的:上下文塞多长、输出要多少字、检索召回几条、要不要多轮反思。这些跟你用谁家的模型没关系。单价是变的,token 量是相对稳的。所以你把成本拆成”token 量 × 单价”以后,换供应商只需要换后面那个数,前面那个数照抄。这也是为什么我一直建议成本表里 token 量和单价必须分成两列,而不是直接记一个金额——金额那一列一换平台就全废了。
第二,单价一查就有。 各家平台的价格表都是公开的,控制台里也有。你缺的从来不是单价,是”我这一次操作到底吃了多少 token”。这个只有你自己能测。
怎么测
取真实样本。不是估算,不是拿一段示例文本数字数,是从生产日志(或者灰度环境的真实流量)里捞出足够多的实际调用记录。
分操作类型统计,每一类分开记这三样:
| 记什么 | 为什么要单独记 |
|---|---|
| 输入 token(未命中缓存) | 按标准输入价计费,通常是大头之一 |
| 输入 token(命中缓存) | 计费方式和标准输入不同,混在一起会把成本估高 |
| 输出 token | 单价通常明显高于输入,且最受 prompt 写法影响 |
这三类必须拆开,否则你后面做”提升缓存命中率能省多少钱”这类测算的时候会没有抓手。中文场景下 token 和字数的换算关系还有额外的坑,需要先把估算口径校准好,这一步可以参考 中文 token 估算 里的方法。
统计的时候不要只取平均值,至少同时记下中位数、P90、P95。原因下一节讲。
样本量方面,我的经验是每类操作至少几百次真实调用才有意义,而且要覆盖不同时段、不同用户群。只跑一遍 demo 数据得到的数字,会系统性偏低——demo 输入短、上下文干净、没有多轮对话累积。
二、从操作成本推到用户成本
有了每类操作的单位成本,用户月成本就是一个加权求和:
用户月成本 = Σ(各类操作的月次数 × 该类操作的单位成本)
下面走一个完整的算例。注意:以下所有单价、token 量、使用频次都是为了演示算术而设的假设值,不代表任何厂商的实际报价,也不是任何真实产品的实测数据。你必须用自己的数替换。
假设参数
单价(假设,元 / 百万 token):
| 项目 | 假设单价 |
|---|---|
| 输入(未命中缓存) | 2.00 |
| 输入(命中缓存) | 0.40 |
| 输出 | 8.00 |
三类业务操作的 token 画像(假设):
| 操作 | 缓存命中输入 | 未命中输入 | 输出 |
|---|---|---|---|
| A 问答 | 2,000 | 1,000 | 500 |
| B 文档摘要 | 0 | 12,000 | 800 |
| C 批量改写 | 0 | 2,000 | 1,500 |
单次操作成本
操作 A:
- 缓存输入 2,000 × 0.40 / 1,000,000 = 0.0008 元
- 未命中输入 1,000 × 2.00 / 1,000,000 = 0.0020 元
- 输出 500 × 8.00 / 1,000,000 = 0.0040 元
- 合计 0.0068 元
操作 B:
- 输入 12,000 × 2.00 / 1,000,000 = 0.0240 元
- 输出 800 × 8.00 / 1,000,000 = 0.0064 元
- 合计 0.0304 元
操作 C:
- 输入 2,000 × 2.00 / 1,000,000 = 0.0040 元
- 输出 1,500 × 8.00 / 1,000,000 = 0.0120 元
- 合计 0.0160 元
这里已经能看出一件事:操作 B 的输入是操作 C 的六倍,但单次成本只贵不到一倍,因为 C 的输出多。输出单价高,所以”输出长度”往往比”上下文长度”更值得先管。很多团队一门心思压缩上下文,却放任模型每次都写八百字,方向反了。
中位用户的月成本
假设中位用户每月:A 60 次、B 8 次、C 5 次。
- A:60 × 0.0068 = 0.4080 元
- B:8 × 0.0304 = 0.2432 元
- C:5 × 0.0160 = 0.0800 元
- 小计 0.7312 元
这还只是”理想调用”的成本,隐性项还没加,下一节补。
三、必须计入的隐性项
上面那个 0.7312 元,统计的是”成功交付了业务价值的操作”。账单统计的是”你实际发出去并产生了 token 的每一个请求”。这两个口径之间有一整类消耗,不加进来,模型就是假的。
重试与返工。 网络抖动、限流、超时触发的自动重试,每一次重试都是完整计费的请求。更隐蔽的是”幽灵成功”:服务端已经生成完并计了费,响应在回传路上断了,客户端判定失败又重来一遍——你付了两份钱,只拿到一份结果。这一类的机制和口径,重试的隐藏成本 里拆得比较细,这里不重复。
结构化输出的返工。 要求模型返回 JSON,解析失败就重来一次。返工率取决于你的 schema 复杂度和提示词写法,团队之间差异很大,必须自己测。
失败请求。 参数错误、内容被拦截、上下文超限被拒——有的计费有的不计费,取决于失败发生在哪一步。以平台账单口径为准,别自己推断。
开发测试消耗。 这一项经常被完全忽略。工程师调 prompt 的时候一天能烧掉不少 token,评测集每次回归跑一遍也是钱。这部分不属于任何一个用户,但它是真实成本,应该按当月总量摊到单位成本里去,否则你的毛利是虚的。
被用户放弃的结果。 模型生成完了,用户看了一眼直接关掉、或者点了”重新生成”。这次生成一分钱没少花,但没产生任何价值。如果你的成本统计只统计”被采纳的操作”,这部分就凭空消失了。
加上隐性项
继续用假设值:重试与失败 +8%、结构化返工 +5%、开发测试分摊 +3%,合计加成系数 1.16。
- 中位用户月成本 = 0.7312 × 1.16 = 0.8482 元(0.7312 + 0.1170 = 0.8482)
这个 16% 是假设的。你自己的数可能是 5%,也可能是 40%。唯一的办法是把平台账单的总 token 数和你自己日志里”成功交付”的总 token 数相除,差额就是你的真实加成系数。这个比值应该每个月核一次。
四、看分布,不要看均值
这是整篇里最容易出事的地方。
继续算例。假设有 1000 个用户,结构如下(假设值):
| 用户群 | 人数 | 每人月成本 | 该群总成本 |
|---|---|---|---|
| 轻度(中位的 0.3 倍) | 700 | 0.2545 元 | 178.12 元 |
| 中位 | 250 | 0.8482 元 | 212.05 元 |
| 重度 | 50 | 5.2246 元 | 261.23 元 |
| 合计 | 1000 | — | 651.40 元 |
重度用户的 5.2246 元是这么来的(假设 A 300 次、B 60 次、C 40 次):
- A:300 × 0.0068 = 2.0400
- B:60 × 0.0304 = 1.8240
- C:40 × 0.0160 = 0.6400
- 小计 4.5040,× 1.16 = 5.2246 元
现在看几个数:
- 平均每用户成本 = 651.40 / 1000 = 0.6514 元
- 中位用户成本 = 0.8482 元
- 重度用户成本 = 5.2246 元
平均值 0.6514 比中位用户 0.8482 还低,因为 700 个轻度用户把它拉下去了。而重度用户是平均值的 8 倍多。占 5% 的重度用户吃掉了 261.23 / 651.40 = 40.1% 的总成本。
问题在于:定价几乎总是按平均值定的。有人算出”平均每用户 0.65 元”,然后定价 19 元,觉得毛利率高得离谱,安心了。但真实情况是:
| 用户类型 | 售价(假设 19 元) | 单位成本 | 毛利 | 毛利率 |
|---|---|---|---|---|
| 平均口径 | 19.00 | 0.6514 | 18.35 | 96.6% |
| 重度用户 | 19.00 | 5.2246 | 13.78 | 72.5% |
这个例子里还撑得住,因为假设的单价比较低、重度倍数只有 8 倍。但真实产品里长尾能拖得非常长。假设出现一个用户跑到中位的 100 倍——月成本 84.82 元,售价 19 元,单这一个用户就亏 65.82 元,需要 65.82 / 18.35 ≈ 3.6 个平均用户的毛利来填。如果你的产品又恰好对重度用户特别有吸引力(比如做批量处理的),这类用户会自己找上门,而且会互相推荐。
结论就一句:成本模型必须按分位数看。至少要有 P50、P90、P99 三个数,以及”最贵的那 1% 用户占了总成本多少”这个比值。只有一个均值,你就是在盲飞。
五、毛利怎么算,三种定价形态各自的风险
毛利的公式很简单:
单用户毛利 = 售价 − 单位成本(含隐性项)
毛利率 = 单用户毛利 / 售价
难的是定价形态的选择,因为不同形态对”成本分布”的暴露程度完全不同。
无限量订阅
固定月费,随便用。用户体验最好,转化率最高,销售最好讲。
风险在于:成本没有上限。你的收入是有界的(19 元),成本是无界的。上面那个”100 倍用户”在这种形态下会直接把你打穿。而且这类用户往往不是恶意的,就是真的重度依赖你的产品。
要用这种形态,必须准备好软性防线,而且要提前写进条款、上线前就做好:
- 公平使用条款:写清楚”异常用量我们会联系你”,别等出事了才补
- 速率限制:不是封禁,是把并发和频率压下来,重度用户体验略降但仍可用
- 降级路径:超过某个量之后自动切换到成本更低的模型或更短的输出
- 高用量告警:某个账号成本突然跳到 P99 之外,运营应该当天就知道
这里的关键是”软”。硬性封顶会激怒用户,软性降级大部分人根本感知不到。
按量计费
用多少付多少。毛利率稳定,成本永远不会跑赢收入,财务模型最干净。
风险在增长侧:用户不敢用。每点一次都在花钱,这个心理负担会显著压制使用频次,而使用频次低就意味着产品价值感知低、留存差。B 端客户还有一层麻烦:报销和预算审批流程受不了浮动金额,采购会要求你给一个固定数。
混合:含额度的订阅 + 超额按量
最常见,也是我认为多数 AI 产品最终会落到的形态。基础月费包含一定额度,超出部分按量计费或者按包购买。
好处是两边的优点都占了一点:绝大多数用户在额度内,体验等同于无限量;极少数重度用户自动进入按量,成本被自动对冲。
关键全在额度怎么定。 不给死数字,给方法:
- 先画出你的用量分位数曲线:把所有用户按月消耗排序,画出 P50、P75、P90、P95、P99 各自的值。这条曲线是所有决策的底图。
- 额度设在哪个分位数,取决于你想让多少人感知到超额。 设在 P90,意味着 10% 的用户会撞到额度——这些人要么升级、要么付超额费、要么流失。设在 P99,几乎没人撞到,产品体验最顺滑,但你就等于回到了无限量订阅,重度用户没被对冲。
- 看撞线人群的画像。如果撞到 P90 的那批人恰好是你的核心付费意愿人群,那额度就设低了——你在惩罚最爱你的用户。如果那批人是薅羊毛的批量用户,那设对了。
- 额度对应的毛利要算清楚:额度上限的用户,单位成本是多少,售价减掉之后还剩多少。这个数是你的”最坏情况毛利”,它必须为正,否则形态就不成立。
- 超额单价要留出安全垫。超额价格如果贴着你的成本价定,一旦上游调价你就直接倒挂。留多少取决于你对价格波动的判断,但绝不能是零。
- 额度用什么单位表达。直接暴露 token 数对 C 端用户不友好,多数产品会换算成”次数""条数""页数”。换算的时候要按 P90 而不是均值来定换算率,否则重的那批操作会击穿你的换算。
额度定完还要能落到预算上。把用户数、用量分布和额度设置一起放进一个月度预算表里推演,怎么做月度预算 里有可以直接套的表结构。
六、降本杠杆的排序
单位成本高了怎么办。下面按”见效快慢 × 你能不能自己做”排序,越靠前越应该先做。
1. 提高缓存命中率。 这是最没有副作用的一项。系统提示词、few-shot 示例、固定的知识片段——这些每次都一样的前缀,如果能稳定命中缓存,输入侧成本会明显下降。要做的事情是把 prompt 结构改成”固定前缀在前、变化内容在后”,并且不要在固定部分里插入时间戳、随机 ID 这类每次都变的东西。我见过一个案例,就是因为系统提示词开头写了当前日期,导致缓存永远不命中——把日期挪到末尾就修好了。具体机制以平台文档为准,各家缓存的触发条件和最短前缀长度不完全一样。
2. 控制输出长度。 输出单价通常明显高于输入,而输出长度是你最容易控制的变量。在提示词里明确要求字数上限、要求”不要复述问题""不要给结论段”,配合 max_tokens 兜底。做结构化输出的话,字段名短一点也是真金白银。这一项通常能立刻见效,而且顺带改善了延迟。
3. 分层模型。 不是所有操作都需要最强的模型。意图分类、格式转换、简单抽取这类任务,用小模型完全够用;只有真正需要推理的那一步才上大模型。做法是先把操作按”错一次的代价”分档,代价低的下沉。这一项收益大,但需要改代码、需要重新跑评测,工期比前两项长。怎么分档可以看 按成本选模型。
4. 减少重试和返工。 把重试策略从”固定次数硬重试”改成”分类型退避”:限流类退避后重试,参数错误类直接失败不重试。结构化输出的返工率靠简化 schema、给明确示例来压。这一项的天花板取决于你现在的返工率有多高,先测再改。
5. 谈量价。 用量到了一定规模,跟平台谈折扣或者预留容量是有空间的。但这一项放在最后,不是因为它没用,而是因为前面四项不需要跟任何人谈判就能做,而且做完之后你手上的谈判材料更硬——你能拿出”我们的用量结构是这样、增长曲线是这样”的数据,比空口要折扣有力得多。另外,前四项做完往往能砍掉相当比例的成本,砍完再谈,你需要的折扣幅度也变小了。
顺序很重要。我见过团队第一反应就是去谈价,谈了两个月拿到一点折扣,回头发现输出长度失控导致的浪费比折扣大得多。
七、把单位成本做成看板,不是季度盘点
最后一件事:这个模型不是算一次就完了的。
它会漂移,而且是双向漂移。上游模型价格在变,新模型出来老模型降价,缓存计费规则也会调整。你自己这边变得更快:产品加了新功能、prompt 改了一版、检索召回数从 3 条改成 5 条、有人为了提升效果加了一轮反思——每一个改动都在动你的 token 画像,但没有一个改动会在评审里被标注”这会让单位成本涨 20%”。
所以单位成本必须是一个持续观测的看板指标,而不是季度会议前临时算的一张 PPT。至少要有这几条曲线:
- 每类操作的平均 token(输入 / 缓存 / 输出 三条分开)
- 每类操作的单位成本
- 每用户月成本的 P50 / P90 / P99
- 账单总 token ÷ 成功交付 token(也就是隐性加成系数)
- 缓存命中率
这几条里任何一条突然跳变,都应该能关联到当天的发布记录。做到这一点,你才能在”上周三上线的那个版本让单位成本涨了三成”发生的当周就发现,而不是月底看账单才发现。看板和告警怎么搭,成本监控与可观测性 里有具体的指标口径。
另外提醒一句:把定价评审和成本看板绑在一起。每次要改价、改额度、改套餐,第一件事就是打开这个看板,而不是打开竞品的价格页。
自查清单
- 你能说出每类业务操作的平均输入 token、缓存 token、输出 token 吗?三个数是分开记的吗?
- 成本表里是”token 量 × 单价”两列,还是只记了一个金额?(只记金额的,换平台时会全部作废)
- 你的单位成本里包含了重试、失败请求、结构化返工、开发测试消耗这几项吗?加成系数是多少,怎么算出来的?
- 平台账单的总 token,和你自己日志统计的成功交付 token,差多少?这个比值上次核是什么时候?
- 你的每用户月成本有 P50、P90、P99 吗?最贵的 1% 用户占总成本的百分之几?
- 按当前定价,处在 P99 用量的那个用户,毛利是正的还是负的?
- 如果是订阅制,有没有软性限制或降级机制?高用量账号有没有当天告警?
- 单位成本是看板上的实时指标,还是需要有人手动算?上一次 prompt 改版,单位成本的变化被记录下来了吗?