很多人第一次拉用量明细时会愣住:返回体里的几个字段加起来,跟账单上的数对不上。问题多半不在站点,而在四项计价没分清——哪项是这次新写入缓存的,哪项是命中缓存便宜读的,哪项是普通输入,哪项是输出。这篇给一张对照表和一套对账顺序,让你下次看到 usage 就能自己拆开。
很多人第一次把用量明细拉出来会愣一下:返回体里那几行 token 数字,加一加跟账单上的金额对不上。第一反应是「站点算错了」,但多数时候问题出在自己这边——四项计价的边界没分清。哪笔是这次刚写进缓存的,哪笔是命中缓存便宜读的,哪笔只是普通输入,哪笔是输出,各自单价不一样,混在一起当然对不上。
这篇不讲原理,只做两件事:给一张四项对照表,让你知道每项什么时候产生、在返回体里大概长什么样;再给一套从总数拆到四项的对账顺序。看完你下次打开 usage 就能自己拆开,而不是发消息问客服。字段命名各家有差异,具体名字到站内资料页核对当时的字段说明。
四项计价对照表:什么时候产生、返回体里叫什么
先把四项拆干净。普通输入和输出是每次请求都有的基础两项,跟缓存无关;缓存写和缓存读只在用了提示词缓存之后才出现,且不会同时发生——一次请求要么是在写缓存,要么是在读缓存,很少两个都大。理解这一点,对账时第一步就能把请求分成两类。
| 项目 | 什么时候产生 | 返回体大致叫什么 | 账单里怎么认 |
|---|---|---|---|
| 普通输入 | 每次请求的提示词部分,未命中缓存的那部分 | input_tokens 一类字段 | 按输入单价计 |
| 输出 | 模型生成的回答部分,每次都有 | output_tokens 一类字段 | 单价通常最高,长回答贵得明显 |
| 缓存写 | 内容第一次被存进缓存的那次请求 | 带 cache_creation 字样的字段 | 一次性投入,单价一般高于普通输入 |
| 缓存读 | 后续请求命中已有缓存的那部分 | 带 cache_read 或 cached 字样的字段 | 单价低于普通输入,但不为零 |
字段名各家不完全一样。Anthropic 系偏 cache_creation_input_tokens 与 cache_read_input_tokens 这种写法,OpenAI 系更多用带 cached 字样的明细字段。别死记名字,去站内 /ai-dict 查名词解释,再去 /official-api/providers/anthropic-claude-api 这类厂商页对照当时的字段说明和单价。
对账顺序:从总数拆到四项,别反过来
对账最容易犯的错是先盯差额、再猜哪项漏了。正确顺序是从总数往下拆:先拿到返回体里的总 token,再按四项分开,然后四项各自乘以当时的单价求和。单价别凭记忆,去 /official-api 或 /tools/token-price-calculator 按当时的数字换算,换算完再跟账单比。
- 拿到总数从返回体或日志里取这次请求的总 token,先不拆,确认这个数本身没有漏字段。
- 按四项拆开把总数分解成普通输入、输出、缓存写、缓存读四份,缺哪份就说明这类请求本来就不涉及。
- 分别乘单价再求和四项各自的量乘以当时单价,加总得到一个自算金额,单价到 /official-api 核对当时的数字。
- 跟账单比差额差额方向有意义:账单比自算高,多半是倍率或输出占比大;账单比自算低,多半是命中了缓存读。
求和跟账单对不上,先别怀疑字段漏算,先怀疑倍率与分组。倍率口径站内 /markup-group-pricing-columns 那篇已经讲过,这里不重复。你要做的是把倍率、分组这些站点侧参数单独列一行,跟四项分开算,混在一起算永远对不清。
三种最常见的误读,以及各自的纠正动作
下面三种误读几乎每次对不上账都能碰到。它们的共同点是「凭感觉估算某一项」——要么当它免费,要么当它不存在,要么只看总量不看结构。纠正动作都不复杂,关键是养成固定记录的习惯。
- 误读一:把缓存读当免费。纠正动作是把缓存读单价单独记一笔,哪怕它便宜,量大了一样进账单;命中率高的场景尤其要盯住这一项。
- 误读二:只算缓存读不算缓存写。第一次写入那笔通常更贵,长文档反复重发时这笔开销最容易被忽略,对账时先把缓存写单独列出来看。
- 误读三:只看总 token 不看结构。同样的总量,输出占比高和缓存命中高,花费能差出一截,去 /usage 看真实用量结构比看总量有用。
什么情况下这套逻辑不适用:短提示词、单轮问答基本不触发缓存,这时四项里只有输入和输出有效。硬套缓存逻辑去拆,只会拆出一堆零,白白增加困惑。先判断你的场景会不会命中缓存,再决定要不要拆四项。
落地动作:让以后每一笔都能对上
判断标准有了,接下来是让它变成日常动作。核心是把四项字段固定记进日志,把站点侧参数和四项分列,再定一个对账频率。做不到这三点,下次打开账单还是两眼一抹黑。
| 动作 | 怎么做 | 判断标准 |
|---|---|---|
| 固定记字段 | 在客户端日志里记录四项字段名 | 每笔请求都能拆出四项,字段清单参考 /usage-log-fields |
| 定对账频率 | 按用量定周期 | 日消耗小按月对,日消耗大按周对,连续两次对不上就停下来查 |
| 分列站点参数 | 倍率、分组与四项分开放 | 同一张表里两类数字不混算 |
| 复核单价 | 到站内页面查当时数字 | 不靠记忆、不靠猜,口径以页面为准 |
不确定口径的时候,去 /price-watch 和 /tools/model-cost-calculator 复核当时的数字,别靠自己记的旧单价。站点计价规则和模型单价都可能调整,你手里那张表要么定期更新,要么每次对账时现查一次,省下来的时间远比查一次多。
下一步把你最近一笔对不上的请求按四项拆一遍,顺手到站内核对当时的单价与倍率口径;想省掉手工换算,直接用定价工具按当前数字跑一次。→常见问题
缓存读为什么不是免费的?
缓存读只是比普通输入便宜,不是零成本。它省的是重复处理长前缀的那部分开销,站点依然要按命中量计费。判断是否划算,要拿缓存写的一次性成本加上后续多次缓存读,跟全部走普通输入比,量大且复用多才划算。
返回体四项加起来对不上账单,先查什么?
先确认倍率和分组,再看四项乘的单价是不是同一时间点的。很多对不上不是字段漏了,而是自算时用了旧单价,或者把未命中缓存的输入按命中价算了。建议按输入、缓存写、缓存读、输出分别列一行再求和。
只看总 token 有什么问题?
总量相同,结构不同,花钱可以差很多。输出单价通常最高,缓存读单价通常最低,所以一个输出占大头的请求和一个几乎全命中缓存的请求,即使总 token 一样,账单也不一样。核对时至少要拆到四项,有条件再看请求级别的分布。