📚 学习笔记:tokenizer_config.json
详解
一、什么是 tokenizer_config.json
?
- 这是 Hugging Face Transformers 框架中用于保存 分词器(Tokenizer)配置信息 的 JSON 文件。
- 它与模型一起保存,确保加载模型时能正确还原分词行为。
- 通常与
vocab.json
、merges.txt
、tokenizer.json
等文件共存。
二、核心字段解析
1. "added_tokens_decoder"
作用:记录所有在原始词表基础上新增的 token(如特殊标记)
"added_tokens_decoder": {
"151329": {
"content": "",
"special": true,
"lstrip": false,
"rstrip": false,
"normalized": false,
"single_word": false
},
"151330": {
"content": "[MASK]",
"special": true,
...
}
}
✅ 字段含义:
字段 | 说明 |
---|---|
content | token 的实际文本内容(如 [MASK] ) |
special | 是否为特殊 token(不参与正常分词,如 [MASK] , `< |
lstrip | 是否自动去除左侧空格(True 会自动去左空格) |
rstrip | 是否自动去除右侧空格 |
normalized | 是否在标准化前处理(如大小写转换) |
single_word | 是否只匹配完整单词(较少用) |
🔍 特点:
- 所有 token 的 ID 从
151329
开始 → 说明原始词表最大 ID 小于151329
- 这些 token 是训练后添加的,用于支持对话、多模态、思维链等功能
special: true
的 token 不会被拆分(如<|user|>
一定是一个整体)
2. "additional_special_tokens"
作用:列出所有额外添加的特殊 token 字符串列表
"additional_special_tokens": [
"", "[MASK]", "[gMASK]", "<|user|>", "...", "/nothink"
]
- 这些 token 都应在
added_tokens_decoder
中定义 - 用于告诉模型:“这些字符串是特殊指令,不要拆分”
3. "model_max_length"
"model_max_length": 128000
- 模型支持的最大上下文长度(token 数)
128000
表示支持 128K 上下文,适用于长文本处理(如 GLM-4-128K、Qwen-110B 等)
4. "padding_side"
"padding_side": "left"
- 填充方向:
left
(左填充)或right
(右填充) - 生成任务常用
left
,避免影响注意力机制 - 分类任务常用
right
5. "clean_up_tokenization_spaces"
"clean_up_tokenization_spaces": false
- 是否在解码时清理多余空格
false
表示保留原始空格格式
6. "do_lower_case"
"do_lower_case": false
- 是否将输入转为小写
false
表示区分大小写(如 BERT-base-cased)
7. "eos_token"
和 "pad_token"
"eos_token": ""
"pad_token": ""
- 结束符(End of Sequence)和填充符
- 这里为空字符串
""
,可能是用added_tokens_decoder
中的""
作为占位 - 实际可能使用
<eop>
或其他 token 作为结束符
8. "tokenizer_class"
"tokenizer_class": "PreTrainedTokenizer"
- 分词器的类名
- 常见值:
BertTokenizer
,GPT2Tokenizer
,LlamaTokenizer
,ChatGLMTokenizer
等 - 表示使用哪种分词逻辑
三、关键概念总结
概念 | 说明 |
---|---|
Token ID 是固定的吗? | ✅ 在同一个模型中,每个 token 的 ID 是固定的(如 `< |
不同模型 ID 相同吗? | ❌ 不同模型的 token ID 不同,词汇表独立 |
added_tokens_decoder 是新增的吗? | ✅ 是!这些 token 是在原始词表基础上动态添加的 |
ID 会冲突吗? | ❌ 不会!分词器自动从 len(tokenizer) 开始分配新 ID,保证唯一 |
特殊 token 会被拆分吗? | ❌ 不会!special: true 的 token 会被当作整体处理 |
四、典型应用场景(基于此配置)
该配置极大概率属于 GLM 系列模型(如 ChatGLM3、GLM-4),支持:
功能 | 对应 token |
---|---|
多轮对话 | `< |
思维链(CoT) | <think> , </think> , /nothink |
多模态输入 | `< |
代码生成 | `< |
掩码任务 | [MASK] , [gMASK] , [sMASK] |
段落控制 | <sop> , <eop> (start/end of passage) |
五、Tokenizer 的工作流程
文本输入
↓
1. 分词(Tokenization) → 拆成 tokens
↓
2. 映射为 Token ID → 查 vocab 表
↓
3. 添加特殊标记、填充、截断
↓
输出:input_ids, attention_mask 等
↓
送入模型 → Embedding 层 → 向量化 → 模型计算
✅ Tokenizer 负责:文本 → token IDs
❌ 不负责向量化(那是 Embedding 层的工作)
六、常见问题解答(FAQ)
问题 | 回答 |
---|---|
为什么要有 added_tokens_decoder ? | 为了支持训练后添加的特殊功能 token(如对话、多模态) |
新增 token 的 ID 会重复吗? | 不会!分词器自动分配,从原始词表末尾开始 |
我需要手动指定 token ID 吗? | 不需要!使用 tokenizer.add_tokens() 自动分配 |
这个配置适合什么模型? | 极可能是 GLM-4 / ChatGLM 系列,支持 128K 上下文 |
lstrip /rstrip 有什么用? | 控制 token 前后是否自动去除空格,影响文本还原 |
七、学习建议
✅ 动手实践:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("path/to/model")
print(tokenizer.encode("<|user|>")) # 查看 ID
print(tokenizer.decode([151336])) # 查看 token
print(len(tokenizer)) # 当前总 token 数
✅ 重点记忆:
“分词器负责数字化,模型负责向量化”
“特殊 token 不可拆,ID 分配不冲突”
✅ 总结
tokenizer_config.json
是大模型理解文本的“说明书”,它定义了:
- 哪些是特殊 token
- 如何处理空格和填充
- 支持多长的上下文
- 分词器的行为模式