localaiforum
登录
指南 › 基础知识

词元与分词器

模型从未见过“词”或“字母”。它看到的是词元 ID——索引一个固定子词片段词表的整数,用字节对编码(BPE)或其近亲变体构建。分词是一切的关卡:你的提示词、回复、上下文窗口、每秒词元计数、API 账单。一旦你开始用词元思考,关于 LLM 行为的一半民间传说就消散了。

词表是如何构建的

BPE 从原始字节出发,反复合并最频繁的相邻对,直到词表达到预算。结果是:常见词成为单个词元,罕见词拆成 2–5 片,而且没有无法表示的字符串——字节回退覆盖一切字符串,包括错别字和 emoji。词表规模从 ~30k 条目(老模型)到 ~250k(现代多语种):

分词器 词表大小 备注
GPT-2 ~50k 以英语/网络文本为主
Llama 2 ~32k 韩语拆分得很痛苦
Llama 3 ~128k 大幅多语种升级
Qwen 2 / 2.5 / 3 ~151k 强大的 CJK 合并
Gemma ~256k 常见词表中最大

主要用英语训练的分词器会激进地合并英语片段;韩语音节对得到的有用合并少得多。早在模型本身韩语好坏之前,词表就决定了你的“韩语税”。

实例:英语

"Tokenization turns text into pieces."

→ ["Token", "ization", " turns", " text", " into", " pieces", "."]
→ 37 characters → 7 tokens ≈ 5.3 chars/token

注意细节:常见词 "Token" 是一片;后缀自成一派;前导空格属于后面的词元(" turns" 而不是 "turns")。这就是为什么 "hello"、" hello" 和 "Hello" 是不同的词元——差一个空格或大小写的提示词,分词结果就不同。

实例:韩语

同一句话,更差的经济性。谚文以音节块书写,而韩语合并在英语为主的词表里更稀少(下面的拆分是合理推测,非精确值):

"안녕하세요, 만나서 반가워요."        # 17 个字符

强多语种词表(~150k 条目):
["안녕", "하세요", ",", " 만나", "서", " 반", "가", "워", "요", "."]
→ ~10 tokens ≈ 1.7 chars/token

弱词表(~32k 条目,字母级拆分):
["안", "녕", "하", "세", "요", ",", " 만", "나", "서", ...]
→ 15+ tokens ≈ 1.1 chars/token

英语平均 ~4 chars/token。韩语常见落在 1–1.5。同样的含义,3–4 倍的词元。这解释了:

  • CJK 提示词以惊人的速度消耗上下文窗口——一个 8k 词元窗口装下的英语内容约为韩语的 3–4 倍。
  • 相同 tok/s 下韩语生成“感觉”更慢:每句更多词元,每词元更少文本。
  • 韩语在按词元计费的 API 上成本更高,用韩语写的推理轨迹同样烧预算。

为什么数字母的问题会失败

问 "strawberry 里有几个 r",连大模型都会翻车。原因:模型从未见过字母。"strawberry" 到达时大致是 ["straw", "berry"]——两个整数。整数里没有字母计数,就像页码不会告诉你那一页的拼写。模型可以背诵记忆的拼写或一步步推理,两者都不可靠。如果必须做:强制模型先把单词逐字母一行一行拼写出来,然后数行数。

词表随模型一起发布

  • 分词器文件(词表、合并表)是发布的一部分;GGUF 内嵌它们,safetensors 仓库把它们与权重放在一起。
  • 引擎(llama.cpp、LM Studio、vLLM……)自动加载正确的分词器。你永远不用自己挑。
  • 词元计数相对于模型:同一段文本在某一族的词表下可能是 1,000 词元,在另一族下是 1,150。绝不要跨模型硬编码词元预算。
  • 词表质量和模型质量是两个独立维度:32k 词表的模型能处理韩语(它理解自己的词元);只是每句话花更多词元。

一切都以词元计价

你关心的 计量单位
上下文窗口(4k → 128k+) 输入 + 输出词元合计
生成速度 每秒词元
KV 缓存内存 随上下文词元增长(KV 缓存)
API 定价 每百万词元
输出长度上限 最大输出词元
推理/思考预算 模型回答前可花费的词元
为 RAG 嵌入文档 按百万词元分块计数

特殊词元与对话模板

除文本片段外,词表还保留了控制 ID:序列开始、序列结束和角色标记。你的聊天 UI 发消息时,发的不是裸文本——它填充一个对话模板,把 <|im_start|>user ... <|im_end|> 之类的特殊词元穿插在你的文字周围。这层包装就是引擎报告的词元数总比你消息纯文本略高的原因,也是混用不同家族的模板会让模型糊涂的原因。

估算规则:英语字符数 ÷ 4。韩语字符数 ÷ 1.0–1.5——按最坏情况假设。模拟器 使用 ~4 chars/token 近似并针对英语校准;韩语请自行在脑内放大。

自己数词元

pip install tiktoken
python -c "import tiktoken as t; e = t.get_encoding('o200k_base'); print(len(e.encode('hello world')))"
  • tiktoken(https://github.com/openai/tiktoken)覆盖 OpenAI 家族的编码;其他家族不同,但英语大致落在 ±15% 以内。
  • Hugging Face 模型页带分词器查看器;分词器 playground 可以粘贴文本实时看拆分。
  • 本地引擎会在日志里打印提示词词元数——用真实提示词核对一次,然后按比例估算。

相关: 深入 Transformer 内部 · 预填充与解码 · KV 缓存