大模型 API 账单怎么算:三个把预算烧穿的地方

接完大模型 API,第一周账单往往比预估高好几倍。原因不是单价贵,是计费口径和直觉不一样。

一、计价的基本单位是「每百万 token」,不是一个请求

所有厂商的定价页长这样:

项 计价方式
输入(input / prompt) 每百万 token 多少钱
输出(output / completion) 每百万 token 多少钱,通常是输入的 2~5 倍
缓存命中输入 输入价的 10%~50%
批量接口(batch) 常规价的 5 折左右

具体数字各家不同且经常调整,不要看博客里的价格,直接看官方定价页。真正要记住的是结构:

  • 输出比输入贵得多。让模型写 1000 字,比让它读 1000 字贵 2~5 倍。
  • 缓存命中的折扣很猛。重复的长系统提示词,第二次开始可能只要十分之一的价。
  • 批量接口便宜一半,代价是几小时内返回,适合离线任务。

二、一次对话到底多少钱:把公式写出来

设:

N_turn  = 对话轮数
S       = 系统提示词 token
H_i     = 第 i 轮用户消息 token
A_i     = 第 i 轮模型回答 token
P_in    = 输入单价(每 token)
P_out   = 输出单价(每 token)

第 i 轮的输入是:

input_i = S + H_1 + A_1 + H_2 + A_2 + ... + H_i

注意这里:每一轮都要把全部历史重新发一遍。所以 N 轮对话的总输入 token 不是 S + ΣH,而是近似:

总输入 ≈ N × S + Σ (N - i + 1) × (H_i + A_i)

这就是第一个烧钱点:历史是平方级增长的。

举个具体例子。假设系统提示词 800 token,用户每轮问 100 token,模型每轮答 400 token,聊 20 轮:

项 计算 结果
系统提示词 20 × 800 16,000
用户消息(加权) 100 × (20+19+...+1) 21,000
模型回答(加权) 400 × (20+19+...+1) 84,000
总输入 121,000 token

也就是说,20 轮对话处理了 2,000 token 的新内容,却消耗了 12 万 token 的输入。倍率 60 倍。

如果开了缓存,系统提示词那 16,000 能压到 1,600 左右;但历史消息每轮都在变,缓存命中不了。这就是为什么长对话的成本降不下来。

先用字数统计把每部分的实际字数算出来,再乘换算系数,比拍脑袋准得多:

👉 字数统计(在线、不上传)

三、三个烧穿预算的地方

1. 输出单价高,而且没人限制长度

一次请求输出 3,000 token 和输出 300 token,成本差十倍。很多项目在提示词里写「请详细说明」,结果每次回答都写满,一天几千次调用就是几十倍差价。

做法:提示词里给长度上限(「不超过 150 字」),接口层设 max_tokens,两处都卡。

2. 重试是乘法的

for (let i = 0; i < 5; i++) {
  try { return await call() } catch { /* 重试 */ }
}

失败重试 5 次,最坏情况成本 ×5。如果失败原因是「输出被截断」,那么每次都会重新消耗完整输入——输入成本 ×5,输出成本也 ×5。

做法:重试上限 2 次,且失败后先判断原因。超时重试有意义,schema 不合法重试意义有限,额度不足重试纯浪费。

3. 没人用的定时任务

「每天凌晨把所有文章重新生成一遍摘要」,上线时觉得不多,跑一个月才发现它比真实用户流量贵十倍。AI 任务特别容易变成这种情况,因为单次便宜、无感、容易加。

做法:每个 AI 任务都记 tokens × 单价,按任务维度出日报。看到哪个任务在榜首,就知道该优化谁。

四、五个降本手段,实测压缩比例

手段 典型节省 代价
压缩系统提示词(删例子、删客套) 20%~40% 效果可能轻微下降
历史对话滚动摘要(只留最近 3 轮 + 摘要) 50%~70% 早期细节会丢
输出长度硬限制 30%~60% 回答变简短
小模型分流(简单任务不用大模型) 40%~80% 要分类判断
开启缓存(长固定前缀) 系统提示词部分省 50%~90% 需前缀稳定
批处理接口 40%~50% 非实时

最值得先做的两个:历史摘要 + 小模型分流。 前者省得最多,后者省得最稳。

小模型分流怎么做?用一个极便宜的判断:消息长度、是否含代码块、是否要计算。短的、闲聊的、格式转换的,全部走小模型;只有长的、要推理的才走大模型。这类规则能覆盖 60% 以上请求。

五、上线前必须做的估算

月成本 = 日调用量 × 30 × (平均输入 token × 输入单价 + 平均输出 token × 输出单价)

填数之前先用真实请求测三次,拿到 usage 里的实际值,别用估的。算的时候直接算:

👉 在线计算器

再乘一个 1.5 的安全系数。原因:上线后提示词会变长、用户输入会比测试长、重试率会高于预期。

一个参考量级(仅示意,不代表任何厂商现价):如果每次请求输入 2,000 token、输出 500 token,一天 1,000 次调用,那么一个月的输入量是 6,000 万 token、输出 1,500 万 token。按「输出 = 4 倍输入价」算,输出那部分贡献了总成本的一半。输出才是成本大头,不是输入。

六、几个容易忽略的计费细节

失败请求也可能计费。 输出到一半被中断、超时断开,只要已经产生了 token,多数厂商照样收。所以「超时重试」是双倍成本。

图片按块算,不按文件大小。 同一张图压缩成 200KB 还是 2MB,计费一样,因为计费看分辨率和切块数。要省就把分辨率降下来。

微调模型的调用价高于基座。 训练是一次性成本,调用是长期的,量大时算总账才知道划不划算。

上下文缓存要求前缀完全一致。 系统提示词里加一个当前时间戳,缓存立刻全废。这类「动态字段放在提示词开头」的写法,是缓存失效最常见的原因。把变化的内容放末尾,固定的放开头。

七、成本监控的最小实现

不需要上监控系统,先做这三件事就够了:

// 1. 每次调用都记账,落到一个表里
await db.insert('ai_usage', {
  ts: Date.now(),
  task: 'article_summary',     // 任务名,必须区分
  model: resp.model,
  in: resp.usage.prompt_tokens,
  out: resp.usage.completion_tokens,
  cached: resp.usage.prompt_tokens_details?.cached_tokens ?? 0,
})

// 2. 每天按 task 汇总一次,看排名
// 3. 设日预算告警,超了就降级到小模型或直接停

有了 task 这个维度,才能回答「钱花在哪」。没有它,账单只是一堆数字。

八、小结

  • 输出比输入贵 2~5 倍,输出才是成本大头
  • 历史对话每轮重新计费,20 轮能让 2,000 token 的新内容消耗 12 万 token
  • 重试是乘法,上限 2 次
  • 降本优先级:历史摘要 > 小模型分流 > 输出限长 > 缓存 > 批处理
  • 预算按实测值 × 1.5 估,别按字数估

最后一条:先测三笔真实请求,再谈成本优化。没有 usage 数据的所有估算,误差都在一倍以上。


相关工具:字数统计|在线计算器|单位换算|AI 工具入口

还有 66 个免费在线工具

纯前端实现,不用注册,数据不上传服务器。

浏览全部工具