Skip to content

Token 与分词:为什么「字数」和「计费」对不上号

一、背景

调用大模型 API 时,账单上写的是 Token 数,不是汉字数;有时候你觉得就几句话,Token 却不少;英文单词有时一个词一个 Token,中文往往 一个字要拆成多个 Token。做 RAG 切文档、做提示省成本、估上下文够不够装下检索结果,都绕不开 分词器(Tokenizer)

搞懂 Token,你才能解释:为什么同样的意思,换一种语言写法价格不同;为什么模型偶尔会 半个字乱码(边界切在 UTF-8 字节中间的概念类比);为什么在上下文窗口里「1 万字」只是个粗略说法——以 Token 为准

二、核心概念和核心原理(详细解答+通俗解释)

(一)核心概念(先通俗,再详细)

  • **1. Token——模型眼里的「最小积木块」**通俗解释:模型不直接吃「汉字」,吃的是整数 ID序列;每个 ID 对应一个词表里的片段,这个片段就叫一个 Token。可以是完整英文单词、也可以是中文里的半个词、一个偏旁级片段,取决于词表怎么建。详细解答:主流 LLM 多用 BPE(Byte Pair Encoding) 或类似子词算法:在语料上统计高频子串,合并成新符号,直到词表大小固定(常见几万到十几万)。子词的好处是:罕见词可以拆成多个子词拼出来,未登录词(OOV) 问题比纯「词表」好很多。

  • 2. 分词器(Tokenizer)——文本 ↔ Token ID 的双向桥通俗解释:编码(encode)把字符串变 ID 列表;解码(decode)把 ID 变回字符串(不一定和原文每个标点完全一致,但人类可读)。详细解答:不同模型 必须用配套的分词器;混用会导致 乱码、性能差、甚至完全错误。开源模型一般在仓库里带 tokenizer.json 或 SentencePiece 模型文件。

(二)核心原理(通俗拆解,一步一步讲清楚)

  1. 第一步:Normalization与预分割通俗解释:有些分词前会做 Unicode 规范化、小写化等(视语言与模型而定),减少无意义变体。详细解答:细节因实现而异,工程上要 按官方文档 处理特殊空白、换行。

  2. 第二步:BPE 合并规则贪心应用通俗解释:从字符起步,反复把「最常一起出现的对」粘成新符号,像压缩算法里造字典。详细解答:推理时按 固定合并表 从左到右切分,复杂度低,适合 GPU批量算注意力。

  3. 第三步:和上下文窗口的关系通俗解释:窗口限制的是 Token 数,不是字数;中文信息密度高,但 UTF-8 子词可能让 同样语义 占用更多 Token。详细解答:做中文应用预算上下文时,用真实分词器数一遍 比估算可靠。

三、补充进阶知识点(易懂不晦涩,适配新手进阶)

  • 1. 特殊 Token通俗解释:如 <|im_start|>[INST] 等,标记角色、段落边界,也算 Token。简单补充:聊天模板(chat template)就是 把这些特殊 Token 拼进 Prompt 的规则。

  • 2. 为什么截断要在 Token 边界做通俗解释:按「字符」硬截可能切断多字节字符或子词,模型看到 残缺片段 容易胡答。简单补充:RAG 切块时常预留 overlap,也要用同一套 tokenizer 计量。

  • 3. 和 Embedding的关系通俗解释:Embedding 层把 Token ID 变成向量;同一个词 在不同位置若被切成不同子词序列,向量序列也会不同——这正是 上下文相关(动态)表示 的基础之一。简单补充:与 RNN、Transformer 文章里「词嵌入」呼应。

  • 4. 和之前知识点的关联计费与窗口都看 Token;上下文窗口 文章里的「能装多少代码/文档」要用 Token 实测;量化 主要压权重,Tokenizer 词表大小影响嵌入矩阵规模但通常不是个人用户首要关注点。

四、文章知识总结

  1. 背景:API 按 Token 计费;中英文压缩率不同;RAG 与 Prompt 设计都要会 数 Token
  2. 核心概念:Token 是子词级单位;Tokenizer 负责编解码;BPE 类算法平衡 词表大小与 OOV
  3. 核心原理:语料驱动合并规则;模型只吃 ID 序列;窗口 = Token 上限
  4. 进阶:特殊 Token + 聊天模板;截断要对齐子词;与 Embedding、注意力链条衔接。
  5. 核心逻辑别猜字数,用官方 tokenizer.encode 数一遍——这是工程习惯。

总结:Tokenizer 是 LLM 的「前门」,搞懂它,成本和上下文才数得清;和后端同学对齐问题时,说 Token 比说「字符」专业一大截。