【大模型应用开发】Token 与分词器 —— 模型是怎么“看“文字的
2.1 一句话先搞懂 Token
Token 就是模型处理文字的最小单位。
模型不认识汉字,也不认识英文单词,它只认识数字。所以任何文字进入模型之前,都要先被切成一小块一小块,每一块转换成一个数字(编号),这个"块"就叫 Token。
"我爱北京天安门"
↓ 分词
["我", "爱", "北京", "天安门"]
↓ 查表编号
[8593, 2679, 3111, 5511]
模型看到的是 [8593, 2679, 3111, 5511] 这串数字,而不是汉字本身。

图:一篇文章被"切"成一个个带编号的小纸片(Token),模型读的是编号,不是文字。
2.2 为什么不能一个字一个字地教?
可能你会想:直接按字切不就行了吗?问题出在词汇表上。
方案一:按字切
- 常用汉字大约 3500 个,全量汉字几万个 —— 词汇表还不算太大
- 但字没有完整语义:"北京"是两个字的组合,单看"北"和"京"意思差远了
- 英文更麻烦:“run”、“running”、“ran” 都要当独立词
方案二:按词切
- 英文看起来合理,但词汇表会爆炸:互联网上的英文单词有几百万个(拼写变体、专业术语、人名地名)
- 词汇表越大,模型越难学,内存占用越高
- 还永远会遇到没见过的词(OOV,out-of-vocabulary)
所以需要一种折中方案:把文字切成比字大、比词小的单位 —— 这就是 Token。
2.3 主流分词算法:BPE
BPE = Byte Pair Encoding(字节对编码),现在几乎所有主流模型(GPT、Llama、Qwen 等)都在用它。
核心思想
从字母/字节开始,反复把"出现频率最高的相邻对"合并成一个新单位。
初始:['l', 'o', 'w', 'e', 'r', 'l', 'o', 'w']
统计相邻对频率:'lo' 出现 2 次,'ow' 出现 2 次
第 1 轮合并 'lo' → ['lo', 'w', 'e', 'r', 'lo', 'w']
第 2 轮合并 'ow' → ['lo', 'w', 'e', 'r', 'lo', 'w']
第 3 轮合并 'low' → ['low', 'e', 'r', 'low']
合并一定次数后,词汇表里就既有"低层"的字母,又有"高层"的常见词了。

图:BPE 就像积木拼接——小字母一次次合并成更大的单位,拼出常见词。
BPE 的好处
| 特点 | 说明 |
|---|---|
| 词汇表可控 | 一般 3 万 ~ 20 万,不膨胀 |
| 没有 OOV | 任何生词都能拆成字节拼出来 |
| 常见词整词存储 | “the”、“北京” 是一个 Token,效率高 |
| 生僻词拆开 | 没见过的新词拆成更小片段,也能处理 |
通俗理解:BPE 就是"把最常用的组合装进缓存"。天天见的词直接整体识别,不认识的拆开了也能拼读。
2.4 其他算法:WordPiece 与 SentencePiece
WordPiece(BERT 在用)
和 BPE 很像,区别在于合并的判定标准:BPE 看"出现频率",WordPiece 看"合并后带来的收益"(语言模型概率提升多少)。效果更精细,但计算更重。
SentencePiece(T5、Llama 在用)
它的特殊之处是:不预先切词,直接拿原始文本(包括空格)当字节流处理。
英文原句: "Hello world" → ["▁Hello", "▁world"]
中文原句: "我爱北京" → ["我", "爱", "北", "京"]
注意那个 ▁ 符号,它代表"空格"。SentencePiece 把空格也当成普通字符处理,所以中文和英文用同一套流程,不需要语言专属的预处理。
2.5 中文的特殊性:为什么中文"贵"?
这是大家最关心的问题。同样一句话,中文和英文的 Token 消耗差很多:
| 文本 | 大致 Token 数 |
|---|---|
| “I love Beijing” | 3 ~ 5 |
| “我爱北京” | 3 ~ 6 |
| 1000 个英文单词 | 约 1300 |
| 1000 个汉字 | 约 1500~2000 |
经验法则:1 个汉字 ≈ 1~2 个 Token;1 个英文单词 ≈ 1.3 个 Token。

图:同样的语义,中文要切出更多 Token,天平自然向"更贵"的一侧倾斜。
为什么中文更"贵"?因为中文没有天然的空格分词。像"北京"这种常用双字词可以合成一个 Token,但很多单字组合必须拆开,导致同样语义下 Token 数更多。而 Token 数直接决定 API 费用(输入输出都按 Token 计费),所以中文项目的成本天然比英文高一些。
实用建议
- 一个模型的上下文窗口(如 8K、128K)指的也是 Token 数,不是字数
- 长文本处理前,先用工具统计 Token,防止超出窗口
- 提问尽量简洁,能省不少钱
2.6 怎么统计 Token?
用 tiktoken(OpenAI 官方库)
pip install tiktoken
import tiktoken
# 选择对应模型的编码器
enc = tiktoken.encoding_for_model("gpt-4o")
text = "我爱北京天安门"
tokens = enc.encode(text)
print(f"Token 数量: {len(tokens)}")
print(f"Token 编号: {tokens}")
print(f"还原文本: {enc.decode(tokens)}")
输出类似:
Token 数量: 6
Token 编号: [8593, 2679, 3111, 5511, 5511, 354]
还原文本: 我爱北京天安门
按 Token 裁剪长文本
def truncate_to_tokens(text, max_tokens=2000):
"""把文本裁剪到指定 Token 数以内"""
enc = tiktoken.encoding_for_model("gpt-4o")
tokens = enc.encode(text)
if len(tokens) <= max_tokens:
return text
return enc.decode(tokens[:max_tokens])
2.7 常见问题
| 问题 | 答案 |
|---|---|
| 词汇表大小一般是多少? | 3 万 ~ 20 万之间,不同模型不同 |
| 为什么有些模型处理中文特别强? | 训练数据里中文占比高 + 词汇表对中文优化 |
| Token 数和字节数有什么关系? | 一个 UTF-8 英文字符 1 字节,一个汉字 3 字节,但 Token 是"语义单位"不是字节 |
| 不同的模型 Token 切法一样吗? | 不一样!每个模型有自己的分词器,Token 数只能估算 |
| max_tokens 设多少合适? | 看任务:短回答 200-500,长文 2000-4000,别超过模型上限 |
更多推荐
所有评论(0)