
1. 账单涨了30%但价目表纹丝没动如果你正在用 Claude API 跑业务最近大概率遇到过这种怪事官方定价页面翻来覆去看了好几遍每百万 token 的单价一个字没改可月底账单就是比上个月多出两三成。第一反应通常是是不是被多扣了于是去翻 usage 明细结果发现调用次数没暴涨、模型也没换钱就是实打实多花了。这个现象在开发者圈子里讨论度很高热搜词里tokenizer、count_tokens、usage、模型迁移这几个词扎堆出现其实已经把线索摆到台面上了。账单上涨的根源绝大多数时候不在价格而在你送进去的东西被算成了多少 token。换句话说同样的文字在不同的 tokenizer 眼里token 数量可能差出一大截。这篇内容适合三类人看一是正在用 Claude API 做产品、对成本敏感的后端或全栈工程师二是负责 AI 应用预算、被账单搞得一头雾水的技术负责人三是刚把模型从旧版本迁到新版本、还没搞清计费口径变化的开发者。我会把价格没变账单却涨这件事拆成几个可验证的环节tokenizer 到底怎么影响计费、count_tokens这个接口怎么用、模型迁移时哪些隐性成本会被放大、以及一套能落地的用量分析排查流程。全程给的是能直接抄的操作和参数不是泛泛而谈。先给一个反直觉的结论打底你看到的单价没变只保证了每 token 的价格不变但完全没保证你的请求会被切成同样多的 token。计费公式是费用 token 数 × 单价单价是常量token 数是变量而 token 数由 tokenizer 决定。只要 tokenizer 变了、或者你送进去的内容结构变了账单就会变哪怕价目表一动不动。2. tokenizer 才是账单的隐形操盘手2.1 为什么同一段文字的 token 数会不一样要理解账单为什么涨得先接受一个事实模型不是按字或词来读你的输入的而是按 token。tokenizer 就是那个把文本切成 token 的工具。不同的 tokenizer 有不同的切分规则和词表同一句话切出来的 token 数量可以差很多。举个生活化的类比。假设你搬家要按件付搬运费你把东西打包成箱子。同样一堆杂物用大箱子装可能 5 箱搞定用小箱子装可能要 12 箱。东西没变但件数变了费用自然变。tokenizer 就是那个决定用大箱子还是小箱子的角色。具体到技术层面影响切分的因素主要有几个词表大小与覆盖范围词表越大越多的常见词能被当成一个 token词表小或者对某些语言覆盖差一个词可能被拆成好几个 token。对非英文文本的处理中文、日文这类没有空格分隔的语言切分策略差异尤其明显。同一段中文不同 tokenizer 切出来的 token 数可能相差 30% 到 50%。特殊字符与格式代码、JSON、Markdown、URL、emoji 这些内容往往会被切得很碎token 密度远高于普通自然语言。空白与换行缩进、多余空格、连续换行看起来没内容但都可能各自占 token。所以当你发现账单涨了第一步不是怀疑计费系统而是去确认我送进去的内容在新 tokenizer 下到底被算成了多少 token。2.2 模型迁移为什么是账单上涨的高发区热搜词里模型迁移和tokenizer同时出现不是巧合。模型迁移是账单悄悄上涨最典型的场景原因有三层。第一层新旧模型的 tokenizer 往往不是同一个。你从旧版本迁到新版本代码里可能只改了一个模型名字符串但底层的切分规则已经换了。你的 prompt 一个字没动token 数却变了。如果新 tokenizer 对中文或代码的切分更细token 数上升账单就跟着涨。第二层新模型可能对上下文长度、系统提示的处理方式不同。有些版本会把系统提示、工具定义、历史消息以不同方式拼接进上下文拼接方式一变实际计费的 token 就变。你以为只是换了模型实际上每次请求送进去的总 token 包变大了。第三层迁移时容易顺手加东西。比如为了效果更好把系统提示写得更长、加了 few-shot 示例、加了工具 schema。这些内容每一轮对话都要重复计费累积起来非常可观。很多人迁移时只盯着模型效果变好了没意识到每次请求的输入 token 已经悄悄翻倍。提示模型迁移后务必用同一批真实请求分别在新旧模型上跑一遍count_tokens把 token 数差异量化出来。这一步能直接解释大部分账单莫名上涨。2.3 一个可复现的对比思路假设你有一段 500 字左右的中文产品说明要作为系统提示反复使用。在旧 tokenizer 下它可能是 400 token在新 tokenizer 下可能是 560 token。单次看只差 160 token但如果这个系统提示每天被调用 10 万次一天就多出 1600 万 token 的输入量。按输入单价折算这就是一笔实打实的增量成本而且它不会出现在调用次数统计里只会体现在 token 总量上。这就是为什么很多人查 usage 时觉得次数没变啊但账单就是涨了——涨的是每次请求的 token 密度不是请求数量。3. count_tokens 接口把看不见的 token变成可核对的数字3.1 这个接口到底解决什么问题count_tokens是 Anthropic 提供的一个独立接口作用很直接在你真正发起对话请求之前先算一下这段内容会被切成多少 token。它不产生对话、不消耗生成额度只做计数。对于成本控制来说这个接口的价值相当于结账前先看小票。很多人做成本优化时习惯先跑起来再看账单这是被动挨打。正确姿势是在请求发出前就把 token 数掌握在手里尤其是那些会反复使用的内容——系统提示、工具定义、固定模板、知识库片段。这些内容每次请求都要计费它们的 token 数就是你的固定成本基数必须精确掌握。3.2 怎么调用与核对调用逻辑很朴素把你要发送的消息结构包括 system、messages、tools 等传给计数接口拿回一个 token 总数。下面是一个 Python 示例展示如何对一段系统提示加用户消息做计数import anthropic client anthropic.Anthropic(api_key你的密钥) resp client.messages.count_tokens( modelclaude-sonnet-4-20250514, system你是一名资深客服负责解答产品使用问题。以下是产品背景……此处省略长文本, messages[ {role: user, content: 我的订单为什么还没发货} ], ) print(resp.input_tokens)拿到input_tokens之后你可以做几件事把它和账单里的 token 用量做交叉核对确认计费口径一致。对同一段内容分别用新旧模型计数量化迁移带来的差异。对系统提示做瘦身实验看删掉哪些部分能显著降低 token 数。3.3 计数时最容易踩的三个坑第一个坑只数用户消息不数系统提示和工具定义。实际计费的是整个请求包系统提示、工具 schema、历史消息全都算。只数用户那句话会严重低估真实用量。第二个坑用估算公式代替真实计数。网上流传的一个 token 约等于 4 个英文字符或一个汉字约等于 1.5 个 token这类经验值只适合做粗略预估不能用来对账。中文、代码、特殊符号的偏差很大真要控成本必须用接口实测。第三个坑忽略了消息结构的开销。每条消息除了内容本身还有角色标记、分隔符等结构开销。消息条数越多这部分累积越明显。做多轮对话成本分析时不能只算文本长度。注意count_tokens的结果会随模型版本变化。做跨版本对比时一定要指定对应的模型名否则对比没有意义。3.4 把计数嵌进你的发布流程单次计数只能解决这一次要长期控成本得把计数变成流程的一部分。我的做法是在 CI 或发布脚本里加一道token 预算检查把系统提示、工具定义这些固定内容抽出来每次改动后自动跑一遍计数超过预设阈值就报警。这样做的好处是token 增长会在代码合并前就被发现而不是等到月底看账单才后知后觉。系统提示从 800 token 涨到 1200 token在代码评审里可能没人注意但在 token 预算检查里会立刻亮红灯。4. 从 usage 明细里读出钱花在哪4.1 usage 字段该怎么看每次 API 响应里都会带 usage 信息通常包含输入 token、输出 token有些还细分了缓存读取、缓存写入等。这些字段是成本分析的一手数据但很多人只看总数不看结构。正确的看法是把输入和输出分开看再把输入拆成固定部分和变动部分。固定部分指系统提示、工具定义这类每次都要重复发送的内容变动部分指用户实际输入和历史对话。固定部分占比越高说明你的成本结构越重优化空间也越大。一个典型的成本结构可能是这样的成本构成占比优化难度优化手段系统提示固定30%-50%低精简措辞、去掉冗余示例工具定义固定10%-25%中只保留必要工具、精简 schema历史对话变动15%-30%中截断、摘要、滑动窗口用户输入变动5%-15%低前端限制长度模型输出20%-40%中限制 max_tokens、优化提示这张表不是标准答案但它提供了一个排查框架先定位哪一块占比异常再针对性优化。如果系统提示占了 50%那再怎么优化用户输入都是杯水车薪。4.2 用日志把 token 消耗归因到具体功能光看总量不够还得知道是哪个功能在烧钱。做法是在应用层记录每次请求的 usage并打上功能标签。比如客服问答文档摘要代码补全各自消耗多少 token一周下来就能看出哪个功能是成本大户。这里有个实操细节记录 usage 时要连模型名、时间戳、请求 ID 一起记。这样当账单出现异常波动时你能快速定位到是哪个时间段、哪个模型、哪类请求导致的。没有这些维度usage 数据就是一堆没法归因的数字。4.3 缓存命中率是被忽视的成本杠杆Anthropic 的提示缓存机制允许你把固定内容标记为可缓存命中缓存的部分计费更低。如果你的系统提示很长且反复使用缓存能显著降低成本。但缓存有命中条件比如内容前缀必须一致、有最短长度要求等。排查账单时要专门看一眼缓存命中率。如果命中率很低说明你的请求结构可能有问题——比如每次都在系统提示前面插入了变化的内容导致前缀不一致缓存永远命中不了。这种情况下把变化内容挪到后面、固定内容放前面就能把命中率提上去。5. 模型迁移时的成本对照实验怎么做5.1 设计一组可对比的请求迁移前做成本对照不能凭感觉要设计实验。我的做法是准备一组有代表性的真实请求覆盖你的主要使用场景短问答、长文档处理、多轮对话、带工具调用的请求各来几条。然后在新旧两个模型上分别跑count_tokens记录输入 token 数。对比时重点看三个指标单次输入 token 数、单次输出 token 数、固定内容占比。如果新模型的输入 token 数明显更高就要进一步拆解是系统提示变长了还是 tokenizer 切分更细了。5.2 区分tokenizer 差异和内容差异这两者容易混淆但处理方式完全不同。区分方法是用完全相同的请求内容只换模型名跑计数。如果 token 数变了那就是 tokenizer 或计费口径的差异如果内容也改了那就分不清是谁的锅。实操上建议分两步走第一步内容不动只换模型测出纯 tokenizer 差异第二步在新模型上做内容优化看能压回多少。这样你就能清楚知道账单上涨里有多少是被迫的tokenizer 变了有多少是自找的内容变多了。5.3 迁移后的监控要盯哪些指标迁移不是改完模型名就完事之后至少盯两周的关键指标每请求平均输入 token 数这是最直接的信号涨了就说明单次成本上升。每请求平均输出 token 数输出单价通常更高这个指标更敏感。缓存命中率迁移后缓存策略可能需要调整。单位业务量的 token 成本比如每处理一个订单消耗多少 token这个指标能排除业务量增长的干扰真实反映效率变化。把这些指标做成趋势图迁移带来的成本变化会一目了然。如果发现某天突然跳涨结合请求日志就能快速定位原因。6. 把 token 成本压回去的几个实操手段6.1 系统提示的减法比加法更值钱很多人优化提示词时习惯不断加内容——加示例、加规则、加背景。但系统提示是每次请求都计费的固定成本加得越多单位成本越高。真正有效的优化往往是做减法。具体做法把系统提示里的每一段都拿出来问一句删掉它效果会明显变差吗。如果不会就删。很多提示词里的礼貌用语重复强调冗余示例都是可以砍掉的。我做过一次实验把一段 1200 token 的系统提示精简到 700 token效果几乎没变化但固定成本直接降了四成。6.2 工具定义要按需加载如果你用了工具调用工具 schema 会随每次请求发送并计费。工具越多、schema 越详细固定成本越高。优化思路是按场景动态加载工具客服场景只加载客服相关工具代码场景只加载代码相关工具而不是把所有工具一股脑塞进每次请求。另一个细节是精简 schema 描述。工具参数的 description 字段写得太啰嗦会显著增加 token。把描述写清楚但别写作文能省下不少。6.3 历史对话的截断与摘要多轮对话里历史消息会不断累积token 数随轮次线性增长。控制手段有三种滑动窗口只保留最近 N 轮、摘要压缩把早期对话总结成一段、关键信息提取只保留实体和结论。三种方式各有取舍滑动窗口最简单但可能丢上下文摘要压缩效果好但需要额外调用模型。选择哪种取决于你的场景。如果是短对话客服滑动窗口就够了如果是长流程任务摘要压缩更合适。关键是别让历史对话无限增长那是最容易被忽视的成本黑洞。6.4 输出长度要主动设限输出 token 的单价通常高于输入而且模型有话痨倾向不限制就会写很长。设置合理的max_tokens是最直接的控成本手段。同时可以在提示里明确要求简洁回答只给结论减少不必要的输出。提示max_tokens设得太低会导致回答被截断影响体验。建议根据场景实测找到够用且不浪费的平衡点而不是一刀切设成很小的值。7. 几个我踩过的坑和对应经验第一个坑是用字符数估算 token 数。早期我图省事按中文一个字约 1.5 token来估结果实际计费比估算高出不少尤其是含大量标点和代码的请求。后来全部改成用count_tokens实测估算误差才降下来。经验就是只要涉及对账和预算就别用估算用接口。第二个坑是迁移后没重新测缓存。有一次换模型后账单涨了排查半天才发现是新模型下缓存前缀匹配规则变了原本能命中的缓存全部失效固定内容按全价计费。教训是迁移后要专门验证缓存命中率别默认它还能用。第三个坑是只优化用户输入忽略系统提示。一开始我把精力都放在限制用户输入长度上效果甚微因为系统提示才是大头。后来把系统提示从 1500 token 压到 800 token成本立刻降下来。优化要先看占比别凭直觉挑软柿子捏。第四个坑是没给 usage 打标签。账单涨了却不知道是哪个功能涨的只能瞎猜。后来在日志里加了功能标签和模型名异常波动一查就清楚。这个改动成本很低但排查效率提升巨大。8. 一套可以照着跑的排查清单如果你现在正面对价格没变账单涨了的情况可以按这个顺序排查确认单价是否真的没变核对官方定价页和你实际计费的模型版本注意有些模型有不同档位。用count_tokens实测当前请求的 token 数拿真实请求测别用估算。对比迁移前后的 token 数内容不变只换模型量化 tokenizer 差异。拆解成本结构把输入拆成系统提示、工具定义、历史对话、用户输入看哪块占比异常。检查缓存命中率命中率低就调整请求结构把固定内容前置。给 usage 打标签定位到具体功能找出成本大户。做减法优化精简系统提示、按需加载工具、截断历史对话、限制输出长度。建立 token 预算检查把计数嵌进发布流程防止成本悄悄回升。这套流程跑一遍基本能把账单为什么涨这个问题定位到具体环节。大部分情况下涨的那 30% 里tokenizer 差异和固定内容膨胀各占一部分真正被多扣的情况极少。最后分享一个我自己的习惯每个月固定做一次 token 成本复盘把当月 usage 和上月对比重点看每单位业务量的 token 成本这个指标。只要这个指标稳定就算总账单涨了也只是业务量增长带来的正常结果如果这个指标本身在涨那就说明效率在下降得赶紧排查。这个习惯帮我提前发现过好几次隐性成本上升比等到季度预算超支再补救要从容得多。