Token估算工具那把尺子刻得很准,只是刻的是上一代分词器的口径

Token估算工具那把尺子刻得很准,只是刻的是上一代分词器的口径
张文保 36 分钟阅读 3,818 阅读
本文目录
  1. 这把尺子到底是怎么刻的?
  2. 五类字符,一把算盘
  3. 三档系数摊开看
  4. 那个悄悄乘1.18的开关
  5. 先把复刻校准了再往下走
  6. 它承诺的误差一成五,实测兑现了吗?
  7. 对照组用真正的词表
  8. 对上一代词表,它准得让人意外
  9. 唯一那三篇例外,坏在同一件事上
  10. 换一代分词器,同一份内容为什么差出五成?
  11. 五成一,不是五个百分点
  12. 它的区间画在了同一边
  13. 更麻烦的是,换代不只有一个方向
  14. 那个标着对中文更友好的下界,一次都没够着
  15. 说明书写的是少三成,代码写的是少两成
  16. 我以为改一个数就修好了,实测说不行
  17. 把误差拆开,看每类字符各背多少锅
  18. 照实测反解一遍,五个系数应该是多少
  19. 这组数字该怎么用,以及不该怎么用
  20. 英文被高估,数字被低估,各错各的方向
  21. 四个字母一个token,这条经验值老了
  22. 长词不等于生僻词,这一条恰好写反了
  23. 数字本身还行,坏在中间那些点和冒号
  24. 顺手一条反直觉的:加空格反而更便宜
  25. 哪几类字符是它算不准的重灾区?
  26. 全角标点:中文正文里最密集的非汉字
  27. emoji:一个字符被数成两个符号
  28. 冷僻字与扩展区:正则内外都不准
  29. 这些加起来影响有多大
  30. 检测到代码特征这个开关按什么判?
  31. 它认的是一个语言家族,不是代码
  32. 更要紧的是,触发跟准不准没什么关系
  33. 反过来,中文里提一句就中招
  34. 窗口占用条为什么和它自己的说明打架?
  35. 说明书第二节写得很清楚
  36. 把输出改到7000,条子纹丝不动
  37. 成本面板也少了半张脸
  38. 照着它的红灯去拆内容,会不会白拆?
  39. 十一档里有四档判反了
  40. 两种翻转,代价不一样
  41. 放到真实规模上是多少钱
  42. 这工具到底该怎么用才不亏?
  43. 先量级,后精确,中间隔一道修正
  44. 两个修正系数,直接拿去用
  45. 要精确,就去问模型本人
  46. 顺带一个能省钱的写法:写得越常规越便宜
  47. 真正的省钱杠杆,多半不在输入这一侧
  48. 什么时候它依然是最好的选择
  49. 常见问题解答
  50. 这个工具估出来的数,我到底该不该信?
  51. 它的下界写着对中文更友好的新词表,为什么反而够不着新词表?
  52. 新一代分词器是不是一定更省token?
  53. 窗口占用那几根条子为什么不算输出token?
  54. 它说我的内容超出窗口了,要不要马上拆开?
  55. 检测到代码特征这个提示,是按什么判的?
  56. 为什么中文标点和emoji的估算偏差特别大?
  57. 有没有办法让同样的内容少花点钱?
  58. 权威参考资料

摘要:这款工具的估算不是不准,是准得偏心。拿站内120篇长文做对照,它给的中间档相对GPT-4那代词表的中位偏差只有6.2%,97.5%的文章落在它给的上下界之间——承诺的一成五误差兑现得干干净净。

问题出在换代之后。同样这120篇,换成GPT-4o那代词表再数一遍,它系统性多报51.2%,而且没有一篇的真实值落进它给的区间。它把新旧两档口径都画在了同一边,新的那一端从来没够着过。

先说这款工具的定位,免得后面的话听着像挑刺。它是一个纯前端的启发式估算器:把文本按汉字、英文字母、数字、空白、其余符号分成五类,各自乘一个折算系数加起来,给出低中高三个数,再顺手算一下占各种上下文窗口的比例和调用成本。全程不上传,商业提示词也能放心往里粘。

这个设计取向是对的。浏览器里塞不下真正的词表文件——那些东西动辄几兆,为了估个数把它们全下载下来不划算。工具的使用说明里也把这一层交代得很坦白,甚至主动写了一节叫“这款工具做不到什么”,把不精确、不区分模型、不算图片音频四条限制都列了。

能主动写限制的工具不多。所以我这次没打算去证明它不准,而是想验证一件更具体的事:它承诺的那个误差范围,到底兑不兑现。

这把尺子到底是怎么刻的?

要验证承诺,先得知道承诺是怎么算出来的。我把页面里那段脚本抽了出来,逐行读完,再用另一种语言原样复刻了一遍。

五类字符,一把算盘

它的分类逻辑很干脆:汉字与中日韩字符走一个正则,英文字母走一个,数字走一个,空白走一个,剩下的全部归进“符号”这一类。五个计数乘各自的系数,相加取整,一个数就出来了。

这里有个细节值得先记下:字符总数用的是JavaScript字符串的长度属性。这个属性数的是UTF-16码元,不是我们直觉里的“字”。后面会看到,这一条埋了几个坑。

三档系数摊开看

三个档位的差别,全在五个系数上:

字符类别下界中间档上界
汉字与中日韩每字1.00每字1.25每字1.60
英文字母每4.4个1个每4.0个1个每3.6个1个
数字每3.0位1个每2.5位1个每2.0位1个
符号与标点每个0.55每个0.70每个0.95
空白每个0.28每个0.28每个0.28

空白那一行三档全一样,说明作者认为空格的折算不随词表变化。这个判断后面会被数据部分证实。

页面上对三档的解释是:下界代表“对中文更友好的新词表”,上界代表“早期词表或代码密集”,中间那档最接近实际。这句话是整篇文章的引信——它把新旧两代词表分别指派给了区间的两端。

那个悄悄乘1.18的开关

五类字符算完之后还有一步:如果文本命中了一组代码特征的正则,三个档位分别再乘1.12、1.18、1.25。这个开关是全局的,不按比例——一篇中文文章末尾贴了两行示例代码,整篇的估算都会被抬起来。

触发条件是六个模式取或:行尾是花括号或分号、出现function加空格、出现箭头函数符号、出现const加空格、出现import加空格、出现形如尖括号包字母的标签,以及模板字符串的插值起始符。这一组模式选得很有倾向性,第七节会专门算这笔账。

先把复刻校准了再往下走

猜算法容易翻车,所以我做了交叉验证:在浏览器里点“加载示例”按钮,让工具用它自带的那段提示词跑一次,再把同一段文本喂给我的复刻版。

两边的输出逐字段对上了:字符数491,下界274,中间档348,上界458,代码特征命中。五个数字一个不差。往后所有的批量结果,都建立在这次校准之上。

它承诺的误差一成五,实测兑现了吗?

先给结论:兑现了,而且兑现得比我预想的漂亮。

对照组用真正的词表

启发式估算的对照组只能是真分词器。我用了两个:一个是cl100k_base,另一个是o200k_base。这两个名字不是我编的口径,OpenAI官方的计数教程里有一张明确的对照表——cl100k_base对应gpt-4-turbo、gpt-4、gpt-3.5-turbo,o200k_base对应gpt-4o、gpt-4o-mini。前者是2022年底那一代,后者是2024年那一代。

语料我没有构造,直接从站里拉了120篇真实长文,去掉标签只留正文,每篇3000字以上。这些都是中文为主、夹杂英文术语和少量代码块的内容,跟大多数人往这个工具里粘的东西形态接近。

对上一代词表,它准得让人意外

120篇跑完,中间档相对cl100k_base的中位偏差是 +6.2%,均值 +7.3%。最小的一篇只差 -1.1%,最大的一篇 +32.7%。

更关键的是分布:114篇落在正负15%以内,占95.0%;117篇的真实值落在它给的上下界之间,占97.5%。工具的FAQ里那句“与真实分词器的差距通常在一成到一成五之间”,在这一档上是句实话。

一个不加载任何词表、纯靠五个系数硬算的估算器能做到这个水平,说明那几个系数不是拍脑袋填的,是照着真实数据调过的。这一点值得先讲清楚,因为接下来的内容会显得没那么友好。

唯一那三篇例外,坏在同一件事上

没落进区间的三篇,偏差最大的是站内那篇拆JS在线运行工具异步输出去哪了的教程,中间档13392,真实10089,多报32.7%。原因不难猜:那篇正文里贴了大量JavaScript代码,代码特征开关被打开,整篇乘了1.18。

这三篇的共同点是代码块占比高。也就是说,那个乘1.18的开关,在它最该发挥作用的场景里反而把误差推大了。这个线索先记着。

换一代分词器,同一份内容为什么差出五成?

把对照组换成o200k_base,同样这120篇,同样的工具输出,数字整个变了脸。

五成一,不是五个百分点

中位偏差从 +6.2% 跳到 +51.2%,均值 +51.9%。最保守的一篇也多报了35.9%,最离谱的一篇多报80.5%。

但真正让我停下来的不是51这个数,是另一个数:120篇里,落在正负15%以内的有0篇,真实值落进上下界之间的也是0篇。不是大部分没落进,是一篇都没有。

一个区间如果只是偏了,会有零星几个样本擦边命中。整整120篇全部出界,说明这不是精度问题,是这把尺子的量程整个平移了。

它的区间画在了同一边

把每汉字的实际消耗单独拎出来看,事情就清楚了。汉字超过500个的那120篇里,cl100k_base的实测中位是每字1.269个token,区间1.166到1.444;o200k_base的实测中位是每字0.897,区间0.825到1.086。

再对照工具的三档:下界1.00、中间1.25、上界1.60。中间档1.25几乎正压在cl100k的1.269上,这就是它对上一代如此精准的原因。而o200k的0.897,比它的下界还低一截——工具标着“对中文更友好的新词表”的那一端,恰恰够不到真正对中文更友好的那一代

打个不太严谨的比方:这就像一份按2015年汇率表做的报关单模板,公式列得一点没错,只是表老了。你照着填,每一步都合规,最后那个数就是不对。

更麻烦的是,换代不只有一个方向

工具的说明里有一句判断:“新一代分词器对中文更友好,同样一段中文,用较新的词表切出来的token数比早期词表少三成左右。”从cl100k到o200k,1.269降到0.897,正好降了29.3%——这句话准得可以当结论引用。

问题是它被当成了一条规律。而Anthropic的官方文档里写着完全相反的一段:Claude 4.7及之后的模型换了新的分词器,同样的输入文本产生的token数比早先的模型大约多三成,文档还专门提醒不要拿旧模型上量到的数字去估成本和窗口占用,要按你打算用的那个模型重新数一遍。

同一年里,一家的新词表让中文便宜了三成,另一家的新词表让同样的文本贵了三成。“新的一定更省”从来不是一条定律,它只是过去某一次换代的方向。工具把这个方向刻进了系数,于是它的下界永远只往一边留余量。

那个标着对中文更友好的下界,一次都没够着

找到病灶之后,我第一反应是这东西应该很好修:把下界的汉字系数往下挪一点就行。结果被实测打了脸,这一节讲的就是打脸的过程。

说明书写的是少三成,代码写的是少两成

先看一个对不上的地方。中间档是每字1.25,说明里承诺新词表“少三成左右”,那下界按理应该落在1.25乘0.7,也就是0.875。而代码里写的是1.00——相对中间档只降了20%。

而o200k的实测中位是0.897,离0.875只差0.022,离1.00差0.103。也就是说,这款工具的文字描述比它自己的代码更接近事实。作者对现实的判断是对的,落到系数上的时候少走了一步。

我以为改一个数就修好了,实测说不行

顺着这个思路,我做了个反事实测试:只把下界的汉字系数从1.00改成0.875,其余四个系数原样不动,再跑一遍那120篇。

结果是2篇。落进区间的从0篇变成2篇,覆盖率从0%变成1.7%。这个数字远低于我的预期,说明汉字系数只是问题的一部分,不是全部。这条论点我原本已经写进提纲了,实测之后只能改写。

把误差拆开,看每类字符各背多少锅

与其猜,不如把账拆了。我按五类字符做了一次误差归因:工具的中间档比o200k多出来的那65万个token,分别是哪一类贡献的。

字符类别对超出量的贡献占比
汉字与中日韩+696808+107.2%
符号与标点-62785-9.7%
空白+15142+2.3%
英文字母+3227+0.5%
数字-873-0.1%

汉字那一项占了107.2%,超过百分之百,因为标点那一项是负的——工具把标点算便宜了,反过来抵掉一部分。其余三类加起来影响不到3%。

所以病灶确实在汉字系数上,只是它错的幅度比“少走一步”大得多。1.25要降到0.76上下才对得上o200k,而不是0.875。我先前那个反事实之所以只修好2篇,就是因为改的幅度还不够一半。

照实测反解一遍,五个系数应该是多少

既然要给数,就给到底。我拿那120篇做了一次最小二乘拟合,反解出每类字符在两种口径下的真实单价:

字符类别工具中间档cl100k实测o200k实测
汉字与中日韩1.2501.0900.761
英文字母0.2500.1310.210
数字0.4000.2380.462
符号与标点0.7001.7561.131
空白0.280-0.1350.052

这组系数在同一批语料上的自检成绩:cl100k口径的绝对偏差中位1.6%,120篇里有114篇落在正负5%以内;o200k口径中位1.8%,117篇落在正负5%以内。

三个地方值得单独说。第一,符号与标点的真实单价是1.1到1.8,而工具按0.70算,等于把中文正文里最密集的那类非汉字字符打了对折。第二,空白的系数接近零甚至为负,说明空格基本被并进了相邻的token里,不额外收费——工具那个三档不变的0.28,方向上是多收了。第三,英文和数字这两栏在两种口径下方向相反,这也是为什么下一节要把它们分开讲。

这组数字该怎么用,以及不该怎么用

提醒一句:这是在以中文为主的语料上拟合出来的整篇口径系数,不是逐字符的真值。汉字那一项因为占绝对多数,拟合得最稳;英文、数字、标点在这批语料里占比小,彼此还有共线性,单看某一栏的绝对值意义有限。

拿它来做什么合适?拿来解释误差的来源、以及给中文长文做整篇修正,是靠谱的。拿来给一份纯英文的产品文案做逐类换算,就别用了——那批语料里根本没有这种形态。

英文被高估,数字被低估,各错各的方向

把语料换成非中文的形态,误差不是变大变小的问题,是换了方向。

四个字母一个token,这条经验值老了

工具中间档按每4.0个字母1个token算,下界4.4、上界3.6。我拿四段不同风格的英文实测了一下:

英文类型实际字母/token中间档偏差
通用散文4.68+46.3%
电商产品描述3.67+31.0%
术语与长词密集8.10+123.8%
含品牌名与网址3.41+20.5%

四段全部高估,最少两成,最多一倍还多。注意最后一列的偏差不只来自字母那一项——同一段文本里的空格和标点也在往上加——但方向是一致的:对英文内容,这个工具的整个区间都压在真实值上方。

我特意做了一段混合英文再验一次:454个字母,cl100k实际92个token,等于每4.93个字母1个token。工具给的下界128、中间140、上界155,真实值92连下界的边都摸不到。

长词不等于生僻词,这一条恰好写反了

工具的说明里写着:“常见词往往整词一个token,生僻词和长词会被切成好几段。”前半句对,后半句里的“长词”得单拎出来。

那段术语密集的英文之所以能做到8.10个字母才1个token,正是因为里头全是Internationalization、characterization、normalization这类长词。它们长,但一点也不生僻——词根和后缀都是高频子词,分词器两三刀就切完了。子词切分这套做法本来就是为了这个设计的:Sennrich那篇2016年的论文标题直接写着用子词单元处理罕见词,把没见过的长词拆成见过的碎片,而不是每个字母单独算。

真正会被切碎的是随机串:订单号、哈希值、拼错的单词、生造的品牌名。它们长得像词但从没一起出现过,只能一小段一小段地拼。所以判断一段英文贵不贵,看的不是词长,是这些字符组合有没有一起出现过很多次。

数字本身还行,坏在中间那些点和冒号

数字这一栏工具按每2.5位1个token算。单看纯数字串,这个折算相当接近:现代分词器把长数字按三位一组切,123是1个,1234是2个,1234567是3个。平均下来就在2.5到3位之间。

坏事的是分隔符。实测几个常见形态:

  • 19:31:22一个时间戳,5个token——两个冒号各占一个
  • 103.39.225.35一个IP地址,7个token——三个点各占一个
  • 3.14159 4个token,小数点单独一个
  • ¥12,800.50 6个token,货币符号、千分位逗号、小数点各一个

工具把这些点、冒号、逗号统统归进符号那一类,按0.70折算,而它们每一个都是实打实的1个token。日志、报表、订单数据这类内容里分隔符密度很高,估算就会往低了走。我那段混着订单号、IP和耗时的样本,工具给36,真实53,少报了32.1%。

顺手一条反直觉的:加空格反而更便宜

很多人压提示词的时候会顺手把空格删掉,觉得字符少了就是省了。实测正好相反:

  • token counting带空格,2个token
  • tokencounting去掉空格,4个token
  • token_counting用下划线,3个token
  • token-counting用连字符,3个token

因为空格是被并进后一个词里的, counting连着前面那个空格正好是词表里的一个完整条目;一旦粘在一起,分词器不认识这个组合,只能硬拆成四段。省下1个字符,多付2个token,这笔账划不来。

哪几类字符是它算不准的重灾区?

五类字符里,最容易被忽略的是那个叫“符号”的兜底类。它不是垃圾桶,里面装的恰恰是中文写作最常用的那批字符。

全角标点:中文正文里最密集的非汉字

工具的汉字正则覆盖四个区段:常用汉字、扩展A、日文假名、谚文音节。全角标点一个都不在里面——逗号在U+FF0C,句号在U+3002,顿号、分号、冒号、问号、感叹号、书名号、全角括号全部落到符号那一类,按0.70折算。

而实测下来,这些标点在两种词表里每一个都是整整1个token,一个不多一个不少。我把12个常用中文标点连着写,工具算9,cl100k实际12。

这里有个小小的讽刺:工具自带示例的提示词里,第五条要求写的是“中文与英文数字之间不加空格,标点使用全角”。它教用户多用全角标点,而它自己把全角标点按七折收。

emoji:一个字符被数成两个符号

前面提过字符总数用的是UTF-16码元。MDN那份文档说得很直白:JavaScript用UTF-16编码,每个Unicode字符可能占一个或两个码元,所以长度属性返回的值不一定等于实际的字符数;文档还专门点名了三类需要留神的内容——emoji、数学符号,以及冷僻的汉字。

落到这个工具上就是:一个火箭emoji占2个码元,两个都不匹配汉字正则,于是变成2个符号,中间档算出1.4个token,取整1。真实是多少?cl100k要3个,o200k要2个。

组合emoji更夸张。那个由三个人加两个零宽连接符拼起来的一家三口,UTF-16长度是8,工具算6个token,cl100k实际要13个。少报了一半还多。

冷僻字与扩展区:正则内外都不准

MDN点名的第三类更有意思,因为它在这个工具里有两种不同的坏法。

字符在汉字正则内工具算cl100k实际
12
䶮(扩展A)13
𠮷(扩展B)14

前两个在正则里,按每字1.25算,取整还是1,实际要2到3个。第三个在正则外——扩展B区的字是代理对,两个码元,正则的四个区段都是基本多文种平面内的范围,够不着——于是它被当成2个符号,算出1.4取整1,实际要4个。

常用汉字之所以只要1个token,是因为词表里给它们留了位置;冷僻字没这个待遇,只能按UTF-8的字节一个个拼,三字节的字就是3个token起。做古籍、姓名库、生僻商品名这类内容的,这一栏的误差会明显放大。

这些加起来影响有多大

说完误差方向,得给个量级,不然容易被当成鸡蛋里挑骨头。在那120篇中文长文里,符号这一项整体是把估算往低了拉的,贡献是负9.7%——它部分抵消了汉字那一项的高估。

换句话说,在常规中文内容上,这几个坑互相打了个折。真正会露出来的是特殊形态:emoji密集的社媒文案、生僻字多的名录、点和冒号密集的日志。这些内容用它估,得心里有数。

检测到代码特征这个开关按什么判?

第一节留了个线索:那个乘1.18的开关。现在把它拆开。

它认的是一个语言家族,不是代码

那组正则里的关键词是function、箭头符号、const、import、行尾分号或花括号、尖括号标签。这几样凑在一起,画像非常清楚:它认的是JavaScript这一系。

我拿十二种常见片段各跑了一遍:

语言是否触发中间档相对cl100k
JavaScript触发+21%
CSS触发+14%
Go触发0%
Rust触发-17%
JSON触发+64%
Python(含import)触发+8%
Python(不含import)不触发-12%
SQL不触发+26%
Shell不触发-31%
YAML不触发-19%
Markdown表格不触发-4%

同一段Python代码,加一行import就触发,去掉那行就不触发。SQL、Shell、YAML这三种在运维和数据场景里最常见的形态,全部漏网。

更要紧的是,触发跟准不准没什么关系

看上表第三列:Go触发了,偏差正好是0;Rust触发了,反而还低估17%;JSON触发了,偏差冲到 +64%。而Shell没触发,低估了31%——它才是最需要上调的那一个。

JSON那一格最能说明问题。上调之前中间档是15,真实11,已经高估39%;上调之后变成18,高估变成64%。这个开关在实测的十二种形态里,没有一次把误差改小到值得。原因也不难理解:符号密度高确实会让token变多,但那个影响已经体现在符号计数本身了,再整篇乘一次等于收了两遍。

反过来,中文里提一句就中招

假阳性这一侧更好复现。以下每一句都是纯中文,每一句都会让整篇估算上调18%:

  • 这个function的作用是把中文切成词。
  • 流程是:抓取 => 清洗 => 入库。
  • 这里的const值写死在了页面里。
  • 把词表import进来要几兆。
  • 在 <p> 标签里写正文。

写技术类内容的人躲不开这几个词。我在站里那120篇中扫了一遍,有6篇命中,全是工具教程类的文章,正文里引了代码片段——这几篇属于该上调的。但只要在一篇纯策略文里提一句“流程是抓取到清洗到入库”,并写成箭头,整篇的账就被抬高了一档。

窗口占用条为什么和它自己的说明打架?

前面聊的都是估得准不准。这一节的问题不一样:它算得对不对。

说明书第二节写得很清楚

工具的使用说明第二节第一句是:“窗口大小是输入加输出的总额度,不是只算输入。”下面还建议留三成余量,理由是模型回复、多轮历史、系统提示词、工具定义都挤在同一个窗口里。

这段话没有任何问题。有问题的是它下面那五根进度条。

把输出改到7000,条子纹丝不动

我在页面里做了个直接的测试。先点“加载示例”跑一次,8K窗口那一格显示4.2%,绿色。这时候底下的“预计输出token”填的是默认值800。

然后我把那个数字改成7000,触发它的重算事件。成本面板立刻跟着变了,而8K窗口那一格还是4.2%,一动没动

按它自己说明书里的口径算一下:输入348加输出7000,一共7348,占8192的89.7%——早该进橙色警告区了。但页面上是绿的。

那个输出数字就在同一屏往下滚三厘米的地方,它已经拿去算钱了,只是没拿去算窗口。像是同一个人管着两个抽屉,抽屉之间不通气。

成本面板也少了半张脸

顺着成本这一块再看,还有三处。

第一,估算给了三档区间,还专门写了一句“把这个区间当作规划的余量比盯着某个具体数字更稳妥”,可成本面板只用中间那一档。拿一份5670字的中文测算:按下界算1000次是28.28,按中间档32.37,按上界38.16——区间两端差了9.88,占中间值的31%,而面板上只有32.37这一个数。

第二,四个输入框都写了最小值0,但那是HTML属性,不走表单提交就不生效。我把“预计输出token”填成负5000,面板老老实实算出单次输出成本负0.075、一千次合计负73.96。负数成本这东西,报给老板大概能提前下班。

第三,“调用次数”填0,面板显示的是“1次合计”。代码里那个取整之后接了个默认值1,0被当成空值换掉了,页面没有任何提示。

照着它的红灯去拆内容,会不会白拆?

前面两节各自成立,合起来会产生一个更实际的后果:窗口那五根条子给出的绿黄红判定,可能和真实情况对不上。

十一档里有四档判反了

我用同一段中文按不同长度重复,从1890字到11340字排了十一档,每一档比两个判定:工具怎么说,按o200k加上800输出实际是多少。

中文字数工具算8K占用工具判定实际判定
472569.1%绿绿
567082.9%橙色警告绿
661596.7%橙色警告橙色警告
7560110.5%红色超出橙色警告
8505124.3%红色超出橙色警告
9450138.2%红色超出橙色警告
10395152.0%红色超出红色超出

十一档里四档不一致,而且全部是同一个方向:工具比实际紧张。

两种翻转,代价不一样

5670字那一档是虚惊:工具报橙色,你以为快撑爆了,实际才用掉六成三。代价是你会去做一次没必要的精简。

7560到9450那三档更贵。工具报“超出”,你的第一反应是把内容切开分两次调用,或者换一个窗口更大的模型。而实际上o200k口径下这些内容加上输出还有一到两成的余量,一次就能跑完。多切一刀就是多一次调用、多一份系统提示词,还多一道把结果拼回去的活儿。

要是这个判断被写进了自动化流程里——比如按窗口占用自动决定走不走分块检索——那就不是多花点钱的事了,是整条链路的行为被一个偏了五成的估算带着走。做检索增强的时候这一层尤其要注意,切不切、切多大,取决于的是真实token数,不是估算值;关于切块本身有多少种切法、每种切出来差多少,RAG分块预览器那篇拆得更细。

放到真实规模上是多少钱

抽象的百分比不好感受,换个具体场景:把站里这120篇长文当成一批要改写的输入,一次跑完。

工具面板给的输入token合计是1941630。cl100k实际1815944,o200k实际1278968。按每百万3块的输入单价折:面板5.82,cl100k口径5.45,o200k口径3.84。

只看这个数字不算多,但注意比例:按o200k结算,面板把输入预算多报了34%。120篇是小批量,把它乘到几万篇的量级,或者用在一个需要向上申请预算的项目里,三分之一的偏差就不是小数了——尤其是这个偏差还是单向的,永远往贵了报。

好消息是它偏得很稳定,这就意味着可以修。

这工具到底该怎么用才不亏?

写到这儿该给操作了。前面挑出来的问题没有一条否定它的价值——它解决的是“我完全没有量的概念”这个真问题,而这个问题绝大多数团队还真没解决。只是用法得调一调。

先量级,后精确,中间隔一道修正

把它当成三步流程里的第一步,而不是唯一一步:

  1. 拿它过一遍,只看数量级。是几千还是几万,会不会撑爆窗口,这一层它给得又快又稳。
  2. 按你实际要用的模型乘一个系数,把口径拉回来。系数下面就给。
  3. 真要签预算或者写进自动化,去调官方的计数接口。这一步只在决策要花钱的时候做。

这个顺序的好处是,前两步花不了一分钟,第三步只在必要时才做。反过来把第三步提前,等于每改一版提示词就要跑一次接口,得不偿失。

如果你的用量集中在订阅制的编程助手上,这三步之外还要看清楚订阅档位与接口计费的分界在哪儿——Claude Code到底要花多少钱那篇把Pro、Max、Team和接口四种口径拆开算过一遍,跟本文的估算这一层刚好互补。日常想随时盯住上下文用掉多少,也可以在终端里挂一个实时显示上下文与Token占用的状态栏,比每次手动粘进估算器省事。

两个修正系数,直接拿去用

拿那120篇算的比值,中位数是这样的:

  • 工具的中间档 乘0.94,约等于cl100k口径(GPT-4、GPT-3.5那一代)
  • 工具的中间档 乘0.66,约等于o200k口径(GPT-4o那一代)

两个数字都有离散:前者在0.75到1.01之间,后者在0.55到0.74之间。所以别把它当精确换算,当成一次量纲对齐就行——把一个稳定偏高五成的数拉回真实附近,比继续按原样报预算强得多。

这两个系数是在中文为主的长文上算的。纯英文内容要往下调得更多,因为前面看到英文那一栏工具高估得更狠;代码密集的内容如果触发了那个1.18的开关,也要额外往下再折一点。

要精确,就去问模型本人

Anthropic的接口里有一个专门的计数端点,路径是messages下的count_tokens,接受和发消息一模一样的结构——系统提示词、工具定义、图片、PDF都能算进去。返回的就是这次请求的输入token数。

两个细节值得知道。一是这个端点免费,只按用量层级限每分钟请求数,起步档就有2000次每分钟,跟发消息的限额是分开算的。二是官方把它的结果称为估算,说实际创建消息时用的token数可能有小幅出入,因为里面可能包含系统自动加的token——但那部分不计费。

另外补一句前面提过的:如果你用的是Claude 4.7之后的模型,官方明确提醒不要拿更早模型上量到的数字来估成本和窗口,因为那一代换了分词器,同样的文本大约多三成。要比就用这个端点把同一份请求按两个模型各数一次,直接对比两个返回值。

顺带一个能省钱的写法:写得越常规越便宜

这一条是我在拆分词边界的时候顺手测出来的,跟工具本身没关系,但对天天写提示词的人更有用。

同样19个汉字,我写了两个意思几乎一样的版本,用o200k数:

  • “搜索引擎优化的核心是内容质量和用户体验”——13个token,每字0.684
  • “搜寻引擎优选之要旨系文稿品第暨用者感受”——20个token,每字1.053

字数一样,语言一样,词表一样,价格差54%。因为第一句里的“搜索”“优化”“核心”“内容”“质量”“用户”“体验”在词表里都是现成的整块,第二句里那些生造的书面语只能一个字一个字地拼。

推论很直接:提示词写大白话比写文绉绉的公文体便宜,而且大白话模型还理解得更好,这是少见的两头都占的事。想省钱先别急着删字,先把生僻表达换成常用说法。日常用编程助手时还有一批更琐碎的省法,十个常见坑里的省Token部分整理过一份。

真正的省钱杠杆,多半不在输入这一侧

最后说个容易搞错优先级的地方。用工具的默认配置跑它自带的示例:输入348个token、输出800个,输入单价3、输出单价15。单次输入成本0.00104,单次输出成本0.01200——输出那一头是输入的11.5倍。

换句话说,在这个配置下就算你把提示词砍掉一半,省下的也不到总成本的4%。工具说明里“约束输出长度通常比压缩输入更有效”这句话是对的,而且比它写的还要更对。

比这更狠的是另外两条。重复调用同一段长系统提示词的,走提示词缓存;不要求实时返回的批量任务,走批量接口——Anthropic官方文档写的是成本降低50%,大多数批次不到一小时就跑完。这两条的效果,往往比在提示词里抠几百个token大得多。想把这类账系统性算清楚的,可以顺着AI团队Token失控那笔账再往下看一层,那篇讲的是聚合服务和自建之间怎么权衡。

什么时候它依然是最好的选择

说了这么多,得把它的长处也落到实处。

一是快。我喂了一份7.56万字符的中文进去,15毫秒出结果;再喂56.7万字符,91毫秒。这个量级的文本,任何需要网络往返的方案都比不了。

二是不上传。竞品分析的资料、还没发布的产品文案、客户给的原始需求,这些东西粘进一个会往服务器发请求的页面,本身就是个风险。纯前端计算这一点在商业场景里的价值,比多准五个百分点重要。

三是它把窗口占用和成本测算摆在了同一屏。虽然那两块各有前面说的毛病,但“一份内容同时看量、看窗口、看钱”这个信息组织方式是对的,比开三个页面分别算强。想顺手看看还有哪些同类工具,全部免费工具那一页都在。

动手试试:Token估算与成本测算

粘一段内容就出三档token估算、五种上下文窗口的占用比例,以及按你自己填的单价算出来的调用成本。单价不内置,永远不会过时。全部在浏览器里算,内容不上传。

保哥自研免费在线工具,浏览器打开就能用。

→ 打开Token估算与成本测算

常见问题解答

这个工具估出来的数,我到底该不该信?

看你用的是哪一代模型。拿站内120篇中文长文实测,它的中间档相对cl100k_base(GPT-4、GPT-3.5那一代)的中位偏差只有6.2%,95%的文章落在正负15%以内,承诺完全兑现。但换成o200k_base(GPT-4o那一代),中位偏差变成 +51.2%,120篇里没有一篇落进它给的上下界。实用做法是:先用它看数量级,再按模型乘一个系数——cl100k口径乘0.94,o200k口径乘0.66。

它的下界写着对中文更友好的新词表,为什么反而够不着新词表?

因为下界的汉字系数定在了每字1.00,而o200k实测中位是0.897,整个区间的下沿比目标高了一档。有意思的是它的文字描述是对的——说明里写“新词表比早期词表少三成左右”,中间档1.25少三成正好是0.875,很接近实测值。误差归因下来,工具比o200k多报的部分有107.2%来自汉字这一项,其余四类基本互相抵消。

新一代分词器是不是一定更省token?

不是,这正是工具那个区间失效的根本原因。从cl100k到o200k,中文确实降了29.3%,跟工具说明里写的“少三成”对得上。但Anthropic的官方文档写着,Claude 4.7及之后的模型换了新分词器,同样的输入文本产生的token数比早先的模型大约多三成,还专门提醒不要拿旧模型量到的数字估成本和窗口。同一年里两个方向都发生过,所以“新的更省”只能当成某一次换代的事实,不能当规律。

窗口占用那几根条子为什么不算输出token?

代码里那几根条子只用了输入的估算值,页面下方“预计输出token”那个输入框没有参与计算。实测把它从800改到7000,成本面板立刻变了,8K窗口那一格还是4.2%纹丝不动——按输入加输出算应该是89.7%,早该进警告区。而工具自己的使用说明第二节第一句就写着窗口是输入加输出的总额度。用的时候把输出数自己加上去再判断。

它说我的内容超出窗口了,要不要马上拆开?

先别急。我按不同长度排了十一档做对照,有四档的判定和实际对不上,而且全是同一个方向——工具比实际紧张。7560到9450字那三档,工具报红色超出,按o200k口径加上输出实际还有一到两成余量,一次就能跑完。多切一刀意味着多一次调用、多一份系统提示词,还多一道拼接。建议把工具的估算乘0.66,再加上你预计的输出token,然后自己跟窗口大小比一次。

检测到代码特征这个提示,是按什么判的?

它匹配的是一组JavaScript家族的特征:function、箭头符号、const、import、行尾花括号或分号、尖括号标签。实测十二种片段,SQL、Shell、YAML、Markdown表格以及不含import的Python全部漏网;而纯中文句子里只要出现这几个词,比如写一句“这里的const值写死在了页面里”,整篇也会被上调18%。更关键的是,触发与否跟准不准没什么关系——JSON触发之后偏差从 +39% 被推到 +64%。

为什么中文标点和emoji的估算偏差特别大?

因为它们都落进了那个叫“符号”的兜底类,按每个0.70折算。而实测中文全角标点每一个都是整整1个token,逗号、句号、顿号、书名号无一例外。emoji更绕:字符总数用的是UTF-16码元,一个火箭占2个码元,被当成2个符号算出1个token,实际cl100k要3个;那个一家三口的组合emoji工具算6个,实际13个。扩展B区的冷僻汉字同理,𠮷被算成1个,实际要4个。

有没有办法让同样的内容少花点钱?

有三条,效果依次递增。第一条是改写法:同样19个汉字,用常用词组写是13个token,换成生造的书面语变成20个,差54%——写大白话比写公文体便宜,而且模型还理解得更好。第二条是约束输出长度:按工具默认配置,输出那一头的成本是输入的11.5倍,砍一半提示词省下的不到总额的4%。第三条是走缓存和批量接口,Anthropic官方文档写的批量处理是成本降低50%,多数批次一小时内完成。

权威参考资料

分享到
标签
版权声明

本文标题:《Token估算工具那把尺子刻得很准,只是刻的是上一代分词器的口径》

本文链接:https://zhangwenbao.com/token-counter-tokenizer-generation-gap-window-cost-guide.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交