Token 与计费单位
模型看不见字,它看见的是 token。你写的每一段话,都要先按一张固定的表切成碎片,再变成数字进模型。
- 算好的成本上线后翻了一倍,因为你按字数估的
- 让它「数一数这段话有几个字」,它数不对
- 同样一份文档,中文版和英文版的 token 数差得莫名其妙
怎么切出来的
切分表不是人定的,是从语料里统计出来的:把最常一起出现的字符组合并成一个 token,反复合并几万轮,得到一张几万到几十万条的词表。越常见的东西,越可能被压成一个 token;越少见的,越会被拆碎。
于是就出现了几种反直觉的情况。一个完整的英文常用词,往往只占 1 个 token。一个长一点的专业词,会被拆成两三段。一个汉字,可能是 1 个 token,也可能因为生僻而被按字节拆成 2 到 3 个。一个 emoji 通常占 2 个以上。空格和换行也算,缩进多的代码会比你想的贵。
| 内容 | 大致 token 数 | 说明 |
|---|---|---|
| 常见英文单词 | 1 | 词表里直接有一条 |
| 较长的专业术语 | 2 – 4 | 被拆成词根加后缀 |
| 常用汉字 | 0.6 – 1 | 高频词组会被合并成一个 |
| 生僻字、异体字 | 2 – 3 | 退化成按字节切 |
| emoji | 2 – 4 | 同上 |
| 一段带缩进的代码 | 比看上去多 | 空格和换行都要算钱 |
还要知道一条:词表是训练时定死的,不能改。你们业务里那些自造词、内部缩写、产品代号,在词表里没有专门的条目,会被切得很碎。这既费钱,也让模型更难把它当成一个完整概念来理解。
账单从这来
所有模型都按 token 计费,输入一个价,输出另一个价,输出通常贵好几倍。所以估成本的公式不是「字数 × 单价」,而是要先把字数换算成 token 数。
- 先做一次实测,别用经验值。拿你们真实的一条请求,用目标模型的 tokenizer 数一遍。中英文混排、带表格、带代码的内容,估算误差经常在两倍以上。
- 算的是整条上下文,不是这一句。多轮对话里,每一轮都要把前面所有内容重发一遍。第十轮的那句话很短,但那次调用的输入可能是几万 token。真正贵的从来不是最后那句。
- 输出长度是最值钱的旋钮。输出单价高,而且它是一个一个吐的,所以输出还直接决定延迟。让它「用三句话回答」,同时省了钱和时间。
- 中英文的价差没有传说中那么大,但确实在。新一代词表对中文的压缩好了很多,可一旦碰上生僻字、专有名词、竖排表格,中文这边仍然会明显吃亏。
还带来这些副作用
token 不只是计费单位,它是模型的感知单位。很多莫名其妙的失灵,根都在这。
它数不清字数。因为它看到的是 token,不是字。让它「写一段刚好 100 字的文案」,它只能凭感觉估,估不准是必然的。要精确控字数,得由你的代码去截,或者让它调工具去数。
它数学不稳。一个长数字会被切成好几个 token,数位之间的关系在统计上不是强规律。所以涉及计算的场景,正确做法是让它写出算式、交给计算工具,而不是让它心算。
字符级的任务它很吃力。数某个字母出现了几次、把一个词倒着拼、判断回文,这些任务要求它看见字符,可它只看得见 token。
上下文长度也是按 token 算的。说「200K 上下文」,指的是 20 万个 token,不是 20 万字。你能塞进去的中文内容比这个数字多一些,塞进去的代码则往往比你估的少。
