Token 与计费
计费单位是 token,不是字:常见英文单词可能只占一个,生僻汉字要两三个。所以字数估不出成本,上下文上限也不是字数。
它不按字数收费,按 token 收费。所以拿字数估出来的成本,和账单上的数字可以对不上——含表格、代码或中英混排的内容,字数估出来的常常只有实测的一半,反过来也有字数少而 token 数高得多的文档。这个错位是所有成本估算问题的起点。
读完你能回答:
- 同一段文字为什么会被切成数量不等的碎片,哪些写法吃亏最大?
- 它为什么数不清篇幅,连有几个字都数不准?
- 上下文上限、限流和账单为什么都不能按字数理解?
- 想知道一次请求到底花多少,你该做什么?
计费单位不是字
你写的是字,它算的是 token。文字进模型之前,先要按一张固定的表切成碎片,每片算一个 token;计费、限长、限流都以这个数为准。
这张表不是谁手工编出来的,而是从语料里统计出来的结果:出现频率最高的那些字符组合会被合并到一起,这样反复进行几万轮,最后得到一张几万到几十万条的词表,主流做法称为字节对编码。bpe-wiki 规律只有一条:越常见的写法越容易被收进一整块,越罕见的越会被拆开。
于是同样一段内容,切法可以差很远:
- 常见的英文单词,一片往往就够。词表里为它单独留了一条。
- 长的专业词、带连字符的技术名,通常要两三片。词根和词缀各占一片。
- 常用汉字接近一片,生僻的会退化成按字节拆。两三个字节,就是两三个 token。
- 数学符号、希腊字母、日文假名这类字符最吃亏。词表里找不到整块条目,只能被切碎。
- 代码里的缩进和换行照样计数。缩进很深的代码、竖向对齐的配置,会比按字符数估出来的多一截。
还有一条要先知道:这张表在训练时就定死了,改不了。你们业务里自造的说法、内部缩写、产品代号,表里找不到对应条目,只能被拆成很多碎片。这既让钱花得更多,也让模型不容易把它识别成一个完整概念——它读到的不是一个词,是一串没有意义的残片。
它数不清篇幅,是因为看不见字符
字符级的活它做不好,原因不在聪明程度,而在它拿到的东西:碎片里没有单个字符的位置。
- 数不清篇幅。你让它把一段摘要压到六十个字,或者要求每个小标题都写成八个字,它报出来的数会偏,而且偏多少没有规律。要卡准篇幅,只能由你的代码去截,或者让它调用工具去数。
- 数字母、数字、倒着拼这类任务很吃力。问它这段文字里有几个「的」、把一段话倒过来写、判断一个字符串是否回文,都要求它看见字符,而它看见的是碎片。
- 长数字算不稳。一张 24 位的运单号进来就被切成好几段,位与位之间的关系在统计上并不牢固。所以涉及计算的场景,靠得住的用法是让它先写出算式,再把求值这一步交出去。
「这么简单的事它为什么做不好」这个疑问,答案大多落在这里。对应的解法同样不复杂:把需要逐字符操作的活交回代码。
窗口、限流、账单用的是同一个数字
说「多少 K 上下文」,指的是 token 数,不是字数。所以窗口里到底装得下多少,取决于你装的是什么:中文比同字数的英文占得多,代码比你以为的占得多。
限流用的也是这个数。厂商通常同时对「每分钟多少次」和「每分钟多少 token」两条线设上限,而先撞上的往往是后一条:一条带着长材料的请求和一条简短问题,占掉的额度可以差很多倍。如果你只按调用次数做容量规划,高峰期被拒几乎必然发生。
这带来一个很实际的后果:你在本地按字数算好「装得下」,发过去可能已经被截断了。截掉的那部分,模型是真的看不到,而且它不会主动告诉你。窗口里装什么、按什么顺序装 属于另一层的话题,但长度用什么单位,这一步先要搞对。
账单用的也是这个数:输入一个价、输出另一个价,一次调用的三种价 单独讲。这里只说两条和 token 数直接相关的判断。
真正贵的是整条上下文,不是最后那句话。会话进行到后半程,用户刚发出的也许只有十几个字,但那一次调用要把之前的全部对话连同检索到的材料重新发一遍,输入早就涨到几千甚至上万 token;Agent 循环里更是每一步都要重发。所以压成本要压「每次调用实际发出去的全部内容」,不能盯着用户那句话的字数。
输出长度是最值钱的旋钮。输出是它逐片生成出来的,这个长度同时决定花费和等待时间。要求它「先给结论,理由压到三行以内」,省下的是钱和时间两样。
换个语言,同一个数字就变了
压缩率取决于这种写法在语料里出现过多少次。所以同一份文档的中文版和英文版,token 数不一样,账单也不一样。
新一代词表对中文的压缩已经好了很多,但差距没有消失:生僻字、专有名词、竖排表格、中英混排,中文这边仍然明显吃亏。
这条判断的用法很具体:做成本对比时,比的必须是同一种语言、同一种内容形态。拿一份英文文档算出来的实测值去估中文场景,估算可能只有实际的一半,预算自然跟着偏。
想要准数,只能拿真实请求实测
字数和 token 数之间不存在稳定的换算比例,也没有哪个系数能一劳永逸。正确做法是实测,并且把实测结果留在日志里。
先取一条真实请求,按目标模型的切分方式数一遍。开源生态里有现成的工具可以直接数。hf-tokenizers 遇到中英混排、含表格或含代码的内容,光凭字数推出来的数经常只有实测的一半左右。
再把这个数埋进日志。每次调用分别记下输入和输出各占多少 token,按天汇总,再按功能拆开。有了这行数据,成本才从感觉变成指标;缺了它,前面每一条判断都只能靠猜。
页数、字数、文件大小,没有一样能拿来反推 token 数——一份排版密集、表格横排的文档,和同样文件大小的纯文字,账完全是两码事。
这一条推不出什么
推不出「所以都改用英文写提示词」。语言是被任务决定的,不是被价格决定的;为省一半输入费把口径写歪,代价远大于省下的钱。
也推不出「所以这只是一个账单问题」。同一个数字同时是它的感知单位:数不清篇幅、字符级的活做不好、长数字算不稳,都从这里来。想让成本真的可控,还要知道这些 token 花在链路的哪一步——把成本归因到每一步 讲的是下一层。
