背景
第一次打开某个大模型的定价页,看到的往往是这样一张表:
| 项目 | 价格 |
|---|---|
| 百万 tokens 输入(缓存命中) | ¥0.5 |
| 百万 tokens 输入(缓存未命中) | ¥4 |
| 百万 tokens 输出 | ¥16 |
三行字,每个字都认识,连起来就懵了 🤯:
- 我发一句话,"输入"是指我发的这句话吗?
- "输出"是模型回我的话,那为什么比输入贵好几倍?
- "命中"是命中什么?我怎么知道自己命中没命中?
- 同样是"输入",命中和未命中差 8 倍,这钱到底怎么省?
这篇把这套计费体系从头拆一遍。搞懂之后你会发现:AI 的账单不是玄学,它精确地反映了 GPU 到底干了多少活。
一、先搞懂 token:计价的最小单位
所有账单的基本单位都是 token,不是"字数",也不是"次数"。
1.1 token 是什么
模型不认识文字,它只认识数字。所以文本进模型之前,要先被分词器(Tokenizer) 切成一个个小块,每块映射成一个整数 ID,这些小块就是 token。
输入文本: "AI 计费真有意思"
切分结果: ["AI", " 计", "费", "真", "有意思"]
映射 ID : [15836, 8721, 3312, 1904, 45023]
↑ 这就是 5 个 token1.2 一个 token 大概是多少内容
| 语言/内容 | 大致换算 | 说明 |
|---|---|---|
| 英文 | 1 token ≈ 4 个字符 ≈ 0.75 个单词 | 常见词是一个整 token,生僻词会被切碎 |
| 中文 | 1 个汉字 ≈ 1~2 token | 中文更"贵",同样意思比英文多花 token |
| 代码 | 1 token ≈ 3~4 个字符 | 缩进、括号、符号都单独占 token |
| 图片 | 按分辨率折算 | 一张 1024×1024 大约上千 token |
一个好记的估算
中文正文:字数 ≈ token 数 ×0.7。一篇 1000 字的中文文章,大约 1400~1500 token。 一本 30 万字的小说,大约 45 万 token——正好够你直观感受"百万 token"是多少:约两本长篇小说。
不要用"字数"估算成本
"你好" 是 2 个 token,"antidisestablishmentarianism" 也可能是 7 个 token。 真要精确算,用官方的 tokenizer 工具或 API 返回的 usage 字段,别自己猜。
二、输入 vs 输出:为什么输出贵这么多
2.1 定义:谁算输入,谁算输出
一句话版本:
你送进去的一切 = 输入(Input / Prompt tokens)模型吐出来的一切 = 输出(Output / Completion tokens)
具体来说,一次 API 调用里,输入包含:
- ✅ System Prompt(系统提示词,你设定的角色、规则)
- ✅ 历史对话(前面所有轮的用户提问 和 模型回答)
- ✅ 本轮你发的这句话
- ✅ 附带的文档、代码、图片
- ✅ 工具/函数定义(Function Calling 的 schema)
输出包含:
- ✅ 模型这一次生成的回复正文
- ✅ 模型生成的工具调用参数
- ✅ 思考过程 / 推理链(Reasoning tokens)——即使你看不到,也照样计费 💸
最容易踩的坑:上一轮的"输出",会变成下一轮的"输入"
模型是无状态的,它不记得你们聊过什么。所谓"多轮对话",是客户端每次都把完整历史重新发一遍。 所以第 10 轮时,前 9 轮的问答全部作为输入被重新计费一次。这就是长对话越聊越贵的真正原因。
2.2 为什么输出的单价是输入的 3~5 倍
这不是厂商乱定价,是计算方式的物理差异。
大模型推理分成两个截然不同的阶段:
阶段一:Prefill(预填充)—— 处理输入
你的 1000 个 token 输入
↓
一次性全部送进 GPU
↓
矩阵并行计算,所有 token 同时处理
↓
得到 KV Cache(后面会讲),准备生成关键词是 并行。1000 个 token 可以塞进同一批矩阵运算里一起算完,GPU 的算力被榨得很满,属于 计算密集型(compute-bound),效率极高。
阶段二:Decode(解码)—— 生成输出
生成第 1 个 token → 追加到序列末尾
生成第 2 个 token → 需要看到第 1 个,追加
生成第 3 个 token → 需要看到前 2 个,追加
...
生成第 N 个 token → 需要看到前 N-1 个关键词是 串行。这叫自回归生成(Autoregressive):每生成一个 token,都要把整个模型的权重从显存里读一遍。
而且每次只算 1 个 token,GPU 的计算单元大部分时间在空转,瓶颈卡在显存带宽上,属于 访存密集型(memory-bound)。
| 对比项 | Prefill(输入) | Decode(输出) |
|---|---|---|
| 处理方式 | 并行,一批算完 | 串行,逐个生成 |
| 瓶颈 | 算力 | 显存带宽 |
| GPU 利用率 | 高 | 低 |
| 权重读取次数 | 1 次处理 N 个 token | 每个 token 读 1 次 |
| 结论 | 便宜 | 贵 |
用个比喻:输入像扫描一整页纸,输出像用打字机一个字一个字敲。扫描仪一秒扫一页,打字机一秒敲几个字——单位成本自然天差地别 ⌨️
这解释了一个现象
为什么"让 AI 写一篇 5000 字文章"比"让 AI 读一篇 5000 字文章"慢得多、贵得多? 因为前者是 Decode 5000 次,后者是 Prefill 1 次。
三、缓存命中:省钱的关键
这是三个概念里最难懂、但也最值钱的一个。
3.1 KV Cache 是什么
回到刚才的 Prefill 阶段。模型处理你的输入时,会为每个 token 算出一组中间结果,叫 Key / Value 向量,简称 KV。
这些 KV 会一直被后续生成用到(注意力机制要回看前文)。它们被暂存在显存里,就叫 KV Cache。
关键性质:第 N 个 token 的 KV,只取决于它自己和它前面的所有 token。
这意味着——只要前缀一模一样,算出来的 KV 就一模一样,可以直接复用,不用重算。
3.2 什么叫"命中"
于是就有了 Prompt Caching(提示词缓存) / 前缀缓存(Prefix Caching):
服务端把你上次请求算过的 KV 存起来。下次请求来了,先比对:
第 1 次请求:
[System Prompt 2000 tokens][文档 8000 tokens][问题A 50 tokens]
└──────────── 全部重新计算,10050 tokens 未命中 ────────────┘
└──────────── 计算完顺手缓存起来 ────────────┘
第 2 次请求:
[System Prompt 2000 tokens][文档 8000 tokens][问题B 60 tokens]
└────── 前缀完全一致,10000 tokens 命中 ──────┘└─ 60 未命中 ─┘
直接读缓存 重新计算- 缓存命中(Cache Hit / Cache Read):这部分前缀之前算过,直接取现成的 KV → 便宜,通常只要原价的 10%
- 缓存未命中(Cache Miss):没算过,老老实实跑一遍 Prefill → 原价
3.3 命中的三条铁律
铁律一:必须是前缀匹配,不是内容匹配
缓存是从第一个 token 开始逐位比对的,一旦中间有一个字不同,后面全部失效。
✅ 命中:
请求1: [固定长文档][问题A]
请求2: [固定长文档][问题B] ← 文档部分命中
❌ 不命中:
请求1: [今天是2026-08-07][固定长文档][问题A]
请求2: [今天是2026-08-08][固定长文档][问题B]
└─ 开头一变,后面全废 ─┘最经典的翻车姿势
在 System Prompt 开头塞当前时间戳、随机 ID、用户名。 开头变一个字符,整个缓存直接归零,你会发现账单完全没降。
铁律二:正确的顺序是"静态在前,动态在后"
❌ 错误排列
[用户问题(每次都变)][系统提示][知识库文档]
└ 从第一个 token 就不同,缓存 0% 命中 ┘
✅ 正确排列
[系统提示][知识库文档][工具定义][历史对话][用户问题]
└────────── 这一大段每次都一样,全部命中 ──────────┘铁律三:缓存有有效期,且通常要"写入费"
| 概念 | 别名 | 典型价格 | 说明 |
|---|---|---|---|
| 缓存写入 | Cache Write / Cache Creation | 输入价 ×1.25 | 第一次建缓存,比原价还贵一点点 |
| 缓存读取 | Cache Read / Cache Hit | 输入价 ×0.1 | 命中时的价格,通常打 1 折 |
| 缓存未命中 | Cache Miss | 输入价 ×1.0 | 就是标准输入价 |
缓存存活时间(TTL)一般是 5 分钟到 1 小时,不同厂商不同策略:
- 有的厂商是自动缓存,你什么都不用做,重复前缀自动命中
- 有的厂商需要显式标记(比如在请求里加
cache_control断点) - 超过 TTL 没有新请求,缓存被回收,下次又是未命中
缓存写入比不缓存还贵
所以只调用一次的前缀,不要缓存。 经验阈值:同一段前缀至少会被复用 2 次以上,缓存才回本。
四、算笔账:这三个价格差多少
假设定价(示意,实际以官方为准):
| 项目 | 单价(每百万 token) |
|---|---|
| 输入(缓存未命中) | ¥4 |
| 输入(缓存命中) | ¥0.4 |
| 缓存写入 | ¥5 |
| 输出 | ¥16 |
场景:一个文档问答机器人
设定:一份 50000 token 的产品手册,用户连续问 20 个问题,每个问题 100 token,每次回答 500 token。
方案 A:不用缓存
输入:(50000 + 100) × 20 = 1,002,000 tokens × ¥4/M = ¥4.008
输出:500 × 20 = 10,000 tokens × ¥16/M = ¥0.16
────────────────────────────────────────────────────────
合计:¥4.17方案 B:手册部分做缓存
缓存写入:50000 × 1 = 50,000 tokens × ¥5/M = ¥0.25
缓存命中:50000 × 19 = 950,000 tokens × ¥0.4/M = ¥0.38
未命中 :100 × 20 = 2,000 tokens × ¥4/M = ¥0.008
输出 :500 × 20 = 10,000 tokens × ¥16/M = ¥0.16
────────────────────────────────────────────────────────
合计:¥0.798省了 81% 💰,而且首 token 延迟(TTFT)通常也能降 50% 以上——因为省掉的不只是钱,还有那 50000 token 的 Prefill 时间。
反直觉的结论
注意看方案 B:输出的 ¥0.16 已经占了总成本的 20%,而输出只有 1 万 token,输入有 100 万 token。
缓存用好了以后,成本大头会从"输入"转移到"输出"。 这时候再想省钱,就得去控制"让模型少废话"了。
五、实战案例:Agent 写代码,月耗 300M tokens 要花多少
上一章是虚构的示意价,这一章用一份真实价目表从头算一遍。
5.1 场景与价目表
- 业务形态:用 Agent(Claude Code / Cline 这类)写代码
- 月消耗:300M tokens(厂商只给总量,不区分输入输出)
- 价目表(DeepSeek):
| 项目 | 单价(¥/M) | 相对倍数 |
|---|---|---|
| 输入·缓存命中 | 0.025 | 1× |
| 输入·缓存未命中 | 3 | 120× |
| 输出 | 6 | 240× |
先注意这张表的特殊之处
命中 / 未命中差 120 倍,而多数厂商只差 10 倍。这直接决定了后面的结论: 对这家厂商,缓存命中率是唯一重要的变量,输出占比反而是次要的。
另外它的缓存是自动开启、无需显式标记、没有额外写入费(未命中价 = 标准输入价), 所以不用像第三章那样再算一笔「缓存写入」的账。
5.2 第一步:确定业务比例
厂商不告诉你 300M 怎么拆,但比例由业务形态决定,跟厂商无关。Agent 写代码的典型值:
| 参数 | 典型值 | 为什么是这个值 |
|---|---|---|
| 输出占比 | 1~3% | 每轮要读几万 token 的代码上下文,却只写几百 token 的 diff / 工具调用 |
| 缓存命中率 | 80~95% | Agent 的对话是 append-only 增长的,前缀天然高度复用 |
其他场景的经验值
| 业务形态 | 输出占比 | 缓存命中率 |
|---|---|---|
| 编码 Agent | 1~3% | 80~95% |
| RAG 知识库问答 | 3~8% | 60~85% |
| 多轮客服对话 | 8~15% | 50~80% |
| 单轮问答 / API 调用 | 10~20% | 0~30% |
| 内容生成 / 写作 | 40~70% | 低 |
| 翻译 / 改写 | 45~55% | 低 |
| 分类 / 抽取 / 打标 | <1% | 视批量而定 |
| 推理模型(带思维链) | ×2~5 倍 | — |
5.3 第二步:代入基准值算一遍
取中位值 输出 2% / 命中率 90%:
总量 300M
├─ 输出 300 × 2% = 6.0M × ¥6 = ¥36.00
└─ 输入 300 × 98% = 294.0M
├─ 命中 294 × 90% = 264.6M × ¥0.025 = ¥ 6.62
└─ 未命中 294 × 10% = 29.4M × ¥3 = ¥88.20
────────────────────────────────────────────────────────────
月费用 ≈ ¥130.8
混合单价 = 130.8 / 300 ≈ ¥0.436/M5.4 第三步:跑敏感度矩阵
单点估算靠不住,把两个参数都拉开跑一遍(月费用,单位:元):
| 缓存命中率 \ 输出占比 | 1% | 2% | 3% |
|---|---|---|---|
| 95% | ¥69.6 | ¥87.1 | ¥104.6 |
| 90%(基准) | ¥113.8 | ¥130.8 | ¥147.9 |
| 85% | ¥158.0 | ¥174.6 | ¥191.1 |
| 80% | ¥202.1 | ¥218.3 | ¥234.4 |
| 70% | ¥290.5 | ¥305.8 | ¥321.0 |
| 50% | ¥467.2 | ¥480.7 | ¥494.1 |
| 0%(缓存完全失效) | ¥900.0 | ¥918.0 | ¥936.0 |
合理区间 ¥70 ~ ¥235,中位约 ¥130。
对比两个参数的杀伤力:
| 变化 | 费用影响 |
|---|---|
| 输出占比 +1 个百分点 | +¥17 |
| 缓存命中率 −1 个百分点 | +¥8.8 |
单看每 1 个百分点,输出更狠。但实际波动范围完全不同——输出只在 1~3% 之间晃(±¥34),命中率能在 50~95% 之间晃(±¥400)。
所以只需要盯一个数
🔴 缓存命中率能让你的账单相差 6 倍以上,输出占比最多影响 25%。
5.5 第四步:用真实账单反推自己的命中率
不用猜,拿上个月的账单直接解方程(固定输出占比 2%):
r = (3 − (账单金额 − 36) / 294) / 2.975| 你的账单 | 反推命中率 | 判断 |
|---|---|---|
| ¥90 | ≈ 95% | ✅ 极好 |
| ¥130 | ≈ 90% | ✅ 正常 |
| ¥220 | ≈ 79% | ⚠️ 偏低,该查了 |
| ¥400 | ≈ 59% | 🔴 有问题 |
| ¥900+ | ≈ 0% | 🔴 缓存根本没生效 |
更准的办法当然还是读 usage——DeepSeek 直接给了现成字段:
"usage": {
"prompt_cache_hit_tokens": 264600,
"prompt_cache_miss_tokens": 29400,
"completion_tokens": 6000
}5.6 Agent 场景保住命中率的几件事
| 做法 | 影响 |
|---|---|
| ✅ 对话 append-only,新内容只追加到末尾 | 命中率能稳在 90%+ |
| ❌ 改写历史消息(压缩上下文、删中间轮、重排顺序) | 改动点之后全部失效 |
| ❌ System Prompt 里注入当前时间 / session ID / 随机数 | 命中率直接归零,账单 ×7 |
| ❌ 频繁切换工具集、动态增删工具定义 | 工具定义在前缀里,一变就全废 |
| ⚠️ 用推理模型(带思维链) | 思考 token 全算输出,占比可能从 2% 涨到 10%+ |
| ⚠️ 长时间空闲后再发(缓存 TTL 过期) | 单次未命中,影响可控 |
最值得立刻检查的一件事
如果你用的是第三方 Agent 框架,先去看它有没有在 System Prompt 里注入当前时间戳。 这是最常见的隐形杀手——你的 ¥130 账单会变成 ¥918 💸
5.7 顺便:这套算法怎么用来比价
上面拆出的 264.6M 命中 / 29.4M 未命中 / 6M 输出 就是你的业务指纹,可以直接套到任何厂商的价目表上:
| 厂商 | 未命中 | 命中 | 输出 | 月费用 |
|---|---|---|---|---|
| A | ¥3 | ¥0.025 | ¥6 | ¥130.8 |
| B | ¥1.5 | 无缓存优惠(¥1.5) | ¥8 | ¥489.0 |
厂商 B 的输入单价只有 A 的一半,看定价页会以为便宜一半,实际贵 274%——因为它没有缓存折扣,而你 90% 的输入是可命中的。
换厂商时还有一个大坑:300M ≠ 300M
不同厂商的 tokenizer 不一样,同一篇中文文本 token 数能差 30~80%。 所以对外描述用量时,锚点应该是业务量而不是 token 数:
❌ "我一个月 300M tokens" ← 换厂商后这个数会变
✅ "我一个月 12 万次请求,每次约 2400 汉字输入 / 120 汉字输出" ← 这个数不变便宜 20% 的单价,可能被多出 40% 的 token 数吃掉还倒亏。
六、还有哪些容易被忽略的计费项
| 项目 | 归类 | 注意点 |
|---|---|---|
| 思考 / 推理 tokens | 输出 | 推理模型的思维链即使不展示给你,也全额计费,可能是正文的好几倍 |
| Function / Tool 定义 | 输入 | 工具 schema 每轮都要发一遍,定义越多越贵;放前面可被缓存 |
| 图片 / 视频 | 输入 | 按分辨率折算 token,高清图很贵 |
| 结构化输出(JSON Schema) | 输入 | schema 本身占输入 token |
| Batch API | 折扣 | 异步批处理通常打 5 折,但要等(几分钟~24 小时) |
| 长上下文阶梯价 | 溢价 | 超过某个长度(如 128K/200K)后单价翻倍 |
| 失败重试 | 全额 | 网络超时、内容被拒,已经算过的 token 照样计费 |
永远相信 usage 字段
所有正规 API 都会在响应里返回类似结构:
{
"usage": {
"prompt_tokens": 10050,
"completion_tokens": 500,
"prompt_tokens_details": {
"cached_tokens": 10000
}
}
}别猜,读这个字段。它是账单的唯一真相来源,也是你判断"缓存到底命中没有"的唯一依据 ✅
七、省钱清单
按性价比从高到低排:
- 把静态内容放最前面——System Prompt、文档、工具定义排在最前,用户输入排最后。改一下顺序,可能就省一半
- 别在开头放时间戳/随机数——这是缓存杀手,把动态信息挪到 prompt 末尾
- 控制输出长度——输出是最贵的。明确要求"直接给答案,不要解释"、设置
max_tokens - 该用小模型就用小模型——分类、抽取、格式化这类任务,小模型便宜 10~20 倍
- 长对话做截断或摘要——只保留最近 N 轮,或把早期对话压缩成摘要
- RAG 优于全文塞入——检索出最相关的 2000 token,好过把 50000 token 全喂进去
- 能异步就用 Batch API——不要求实时的任务(日报生成、批量打标)直接省一半
- 精简工具定义——只挂载本次可能用到的工具,别一次性挂 50 个
一句话总结
输入 = 你送进去的所有东西(含历史对话),并行计算,便宜;输出 = 模型吐出来的所有东西(含隐藏思考),串行生成,贵 3~5 倍;命中 = 这段前缀之前算过,KV 直接复用,打 1 折——但前缀必须一字不差地从头对上。
理解了这三句话,定价页上那三行字就不再是天书,而是一张可以主动优化的成本地图 🗺️