大可的 AI Builder 手记
跟随系统
颜色主题
长沙小桌实战
大可 Dako
大可 Dako大可 DakoAI Builder · Agent 实践者用 AI 做真正能用的产品。专注探索 Agent 工程化落地、Vibe Coding 实践与商业化交付。
内容平台即将上线,敬请期待
计费、限长、限流都按 token 算,没有一样按字数算01你写一段字字数、词数、页数,你都数得清按这个数估成本02切成 token按一张训练时定死的表切成碎片常见词整块,生僻字切碎03按量计价输入和输出都按 token 数收费账单和字数不成比例04按量限长上下文窗口的上限也是 token数按字数换算会超限✓ 成本只能拿真实请求实测
字数是你数出来的,token 是它切出来的。两个数字不成比例,成本估算的误差都从这里开始。

Token 与计费

计费单位是 token,不是字:常见英文单词可能只占一个,生僻汉字要两三个。所以字数估不出成本,上下文上限也不是字数。

它不按字数收费,按 token 收费。所以拿字数估出来的成本,和账单上的数字可以对不上——含表格、代码或中英混排的内容,字数估出来的常常只有实测的一半,反过来也有字数少而 token 数高得多的文档。这个错位是所有成本估算问题的起点。

读完你能回答:

  • 同一段文字为什么会被切成数量不等的碎片,哪些写法吃亏最大?
  • 它为什么数不清篇幅,连有几个字都数不准?
  • 上下文上限、限流和账单为什么都不能按字数理解?
  • 想知道一次请求到底花多少,你该做什么?

计费单位不是字

你写的是字,它算的是 token。文字进模型之前,先要按一张固定的表切成碎片,每片算一个 token;计费、限长、限流都以这个数为准。

这张表不是谁手工编出来的,而是从语料里统计出来的结果:出现频率最高的那些字符组合会被合并到一起,这样反复进行几万轮,最后得到一张几万到几十万条的词表,主流做法称为字节对编码。bpe-wiki 规律只有一条:越常见的写法越容易被收进一整块,越罕见的越会被拆开。

于是同样一段内容,切法可以差很远:

  • 常见的英文单词,一片往往就够。词表里为它单独留了一条。
  • 长的专业词、带连字符的技术名,通常要两三片。词根和词缀各占一片。
  • 常用汉字接近一片,生僻的会退化成按字节拆。两三个字节,就是两三个 token。
  • 数学符号、希腊字母、日文假名这类字符最吃亏。词表里找不到整块条目,只能被切碎。
  • 代码里的缩进和换行照样计数。缩进很深的代码、竖向对齐的配置,会比按字符数估出来的多一截。

还有一条要先知道:这张表在训练时就定死了,改不了。你们业务里自造的说法、内部缩写、产品代号,表里找不到对应条目,只能被拆成很多碎片。这既让钱花得更多,也让模型不容易把它识别成一个完整概念——它读到的不是一个词,是一串没有意义的残片。

它数不清篇幅,是因为看不见字符

字符级的活它做不好,原因不在聪明程度,而在它拿到的东西:碎片里没有单个字符的位置。

  • 数不清篇幅。你让它把一段摘要压到六十个字,或者要求每个小标题都写成八个字,它报出来的数会偏,而且偏多少没有规律。要卡准篇幅,只能由你的代码去截,或者让它调用工具去数。
  • 数字母、数字、倒着拼这类任务很吃力。问它这段文字里有几个「的」、把一段话倒过来写、判断一个字符串是否回文,都要求它看见字符,而它看见的是碎片。
  • 长数字算不稳。一张 24 位的运单号进来就被切成好几段,位与位之间的关系在统计上并不牢固。所以涉及计算的场景,靠得住的用法是让它先写出算式,再把求值这一步交出去。

「这么简单的事它为什么做不好」这个疑问,答案大多落在这里。对应的解法同样不复杂:把需要逐字符操作的活交回代码。

窗口、限流、账单用的是同一个数字

说「多少 K 上下文」,指的是 token 数,不是字数。所以窗口里到底装得下多少,取决于你装的是什么:中文比同字数的英文占得多,代码比你以为的占得多。

限流用的也是这个数。厂商通常同时对「每分钟多少次」和「每分钟多少 token」两条线设上限,而先撞上的往往是后一条:一条带着长材料的请求和一条简短问题,占掉的额度可以差很多倍。如果你只按调用次数做容量规划,高峰期被拒几乎必然发生。

这带来一个很实际的后果:你在本地按字数算好「装得下」,发过去可能已经被截断了。截掉的那部分,模型是真的看不到,而且它不会主动告诉你。窗口里装什么、按什么顺序装 属于另一层的话题,但长度用什么单位,这一步先要搞对。

账单用的也是这个数:输入一个价、输出另一个价,一次调用的三种价 单独讲。这里只说两条和 token 数直接相关的判断。

真正贵的是整条上下文,不是最后那句话。会话进行到后半程,用户刚发出的也许只有十几个字,但那一次调用要把之前的全部对话连同检索到的材料重新发一遍,输入早就涨到几千甚至上万 token;Agent 循环里更是每一步都要重发。所以压成本要压「每次调用实际发出去的全部内容」,不能盯着用户那句话的字数。

输出长度是最值钱的旋钮。输出是它逐片生成出来的,这个长度同时决定花费和等待时间。要求它「先给结论,理由压到三行以内」,省下的是钱和时间两样。

换个语言,同一个数字就变了

压缩率取决于这种写法在语料里出现过多少次。所以同一份文档的中文版和英文版,token 数不一样,账单也不一样。

新一代词表对中文的压缩已经好了很多,但差距没有消失:生僻字、专有名词、竖排表格、中英混排,中文这边仍然明显吃亏。

这条判断的用法很具体:做成本对比时,比的必须是同一种语言、同一种内容形态。拿一份英文文档算出来的实测值去估中文场景,估算可能只有实际的一半,预算自然跟着偏。

想要准数,只能拿真实请求实测

字数和 token 数之间不存在稳定的换算比例,也没有哪个系数能一劳永逸。正确做法是实测,并且把实测结果留在日志里。

先取一条真实请求,按目标模型的切分方式数一遍。开源生态里有现成的工具可以直接数。hf-tokenizers 遇到中英混排、含表格或含代码的内容,光凭字数推出来的数经常只有实测的一半左右。

再把这个数埋进日志。每次调用分别记下输入和输出各占多少 token,按天汇总,再按功能拆开。有了这行数据,成本才从感觉变成指标;缺了它,前面每一条判断都只能靠猜。

页数、字数、文件大小,没有一样能拿来反推 token 数——一份排版密集、表格横排的文档,和同样文件大小的纯文字,账完全是两码事。

这一条推不出什么

推不出「所以都改用英文写提示词」。语言是被任务决定的,不是被价格决定的;为省一半输入费把口径写歪,代价远大于省下的钱。

也推不出「所以这只是一个账单问题」。同一个数字同时是它的感知单位:数不清篇幅、字符级的活做不好、长数字算不稳,都从这里来。想让成本真的可控,还要知道这些 token 花在链路的哪一步——把成本归因到每一步 讲的是下一层。

参考资料

  1. Byte pair encoding — Wikipedia
  2. Tokenizers — Hugging Face