
https://huggingface.co/deepseek-ai/DeepSeek-V3.2/tree/main/inference
DeepSeek-V3.2
DeepSeek-V3/
├── 📁 assets/ # 媒体与宣传资源
│ ├── 🖼️ benchmark.png # 模型性能对比图(各维度跑分)
│ └── 📄 paper.pdf # 技术白皮书(详细记录架构创新与训练细节)
├── 📁 encoding/ # 分词处理扩展代码
│ ├── 🐍 encoding_dsv32.py # V3.2 版本特有的编码/解码逻辑实现
│ ├── 🐍 test_encoding_dsv32.py # 针对编码逻辑的单元测试
│ └── 📄 test_input.json # 编码测试用的输入样例
├── 📁 inference/ # 推理核心组件
│ ├── 🐍 convert.py # 权重格式转换工具(如从 PyTorch 转为自定义格式)
│ ├── 🐍 generate.py # 文本生成的主入口脚本(Chat 逻辑)
│ ├── 🐍 kernel.py # GPU 底层算子加速优化代码(CUDA 相关)
│ └── 🐍 model.py # Transformer 模型结构的 PyTorch 实现
├── 📁 olympiad_cases/ # 顶级竞赛题目评测集(证明模型的逻辑推理上限)
│ ├── 📊 CMO2025.jsonl # 2025 中国数学奥林匹克题库
│ ├── 📊 IMO2025.jsonl # 2025 国际数学奥林匹克题库
│ ├── 📊 ioi_submissions_final.json # 国际信息学奥赛提交结果评测
│ └── 📊 wf_submissions.json # 世界级编程竞赛(如 ICPC)评测数据
├── 📄 config.json # 模型的全局超参数(隐藏层维度、专家数量等)
├── 📄 config_671B_v3.2.json # 针对 671B 参数量的特定硬件/架构配置文件
├── 📄 generation_config.json # 推理采样参数(Temperature, Top-P 等默认值)
├── 📄 tokenizer.json # 核心词表文件(BPE 算法生成的 Token 映射)
├── 📄 tokenizer_config.json # 分词器的 Python 调用配置
├── 📄 requirements.txt # 项目依赖环境列表
├── 📄 model.safetensors.index.json # 权重索引文件(记录每个参数在哪个 .safetensors 里)
└── 📦 model-00001-of-00163.safetensors # 权重分片 (共 163 个文件,存储了 671B 的参数)
Tokenizer 的 灵魂 ,也是体积最大的JSON文件。这是一个静态的数据库,记录了模型认识的所有“零件”(Tokens)
{"apple": 512, "Deep": 3021, "Seek": 89}。示例内容:
{
"version": "1.0", // 格式版本
"truncation": null, // 截断配置:如果句子超过 512 或 1024 个词,该如何裁掉多余部分
"padding": null, // 填充配置:如果句子太短,用哪个 ID 补齐(通常是 0)
"added_tokens": [ // 预设的特殊词
{
"id": 0,
"content": "<|endoftext|>", // 类似 DeepSeek/GPT 的结束符
"single_word": false,
"special": true
}
],
"normalizer": { // 第一步:文本标准化
"type": "Sequence", // 序列处理:按顺序执行多个标准化操作
"normalizers": [
{ "type": "Lowercase" }, // 将所有输入转为小写
{ "type": "Strip", "left": true, "right": true } // 去除首尾空格
]
},
"pre_tokenizer": { // 第二步:粗分词
"type": "Sequence",
"pretokenizers": [
{ "type": "Whitespace" }, // 将句子按空格切开,变成 ["hello", "world"]
{ "type": "ByteLevel", "add_prefix_space": false } // GPT 常用,将文本转为字节流处理
]
},
"post_processor": { // 第四步:后处理(用于给模型增加特定标记)
"type": "ByteLevel",
"add_prefix_space": true,
"trim_offsets": false,
"use_regex": true
},
"decoder": { // 第五步:解码(将数字变回人话)
"type": "ByteLevel",
"add_prefix_space": true,
"trim_offsets": true,
"use_regex": true
},
"model": { // 第三步:核心 BPE 算法模型
"type": "BPE", // 使用 Byte Pair Encoding 算法
"dropout": null, // 训练时的随机丢弃率,推理时通常为 null
"unk_token": null, // BBPE 算法因为涵盖所有字节,通常不需要“未知词”标记
"continuing_subword_prefix": null,
"end_of_word_suffix": null,
"fuse_unk": false,
"byte_fallback": false, // 是否启用字节回退(防止出现不认识的字)
"vocab": { // 核心字典:Token -> ID 的映射
"<|endoftext|>": 0,
"h": 1,
"i": 2,
"u": 3,
"g": 4,
"hu": 5,
"hug": 6
},
"merges": [ // 合并规则:决定了切分的“先后顺序”
"h u", // 规则 1:看到 h 和 u 相邻,合并成 hu
"hu g" // 规则 2:看到 hu 和 g 相邻,合并成 hug
]
}
}
决定分词器在代码层面如何被初始化
作用:告诉 Transformers 该用哪个类加载这个分词器。
关键字段:
left 或 right)LlamaTokenzier 或 PreTrainedTokenizerFast示例内容
{
// 是否在编码后的序列开头自动加上 BOS(开始符)。
// 这里设为 false,意味着需要手动控制或由模型类根据任务添加。
"add_bos_token": false,
// 是否在编码后的序列末尾自动加上 EOS(结束符)。
"add_eos_token": false,
// 定义 BOS(Beginning of Sentence)开始符的具体属性
"bos_token": {
"__type": "AddedToken",
"content": "<|begin▁of▁sentence|>", // 具体的字符串内容,这是 DeepSeek 特有的标记
"lstrip": false, // 是否自动删除该 token 左侧的空格
"normalized": true, // 是否对此 token 进行 Unicode 标准化处理
"rstrip": false, // 是否自动删除该 token 右侧的空格
"single_word": false // 是否将其视为一个完整的单词(不进行子词拆分)
},
// 是否自动清理分词后多余的空格(通常设为 false 以保持文本原貌,尤其是代码模型)
"clean_up_tokenization_spaces": false,
// 定义 EOS(End of Sentence)结束符的具体属性
"eos_token": {
"__type": "AddedToken",
"content": "<|end▁of▁sentence|>", // 告诉模型:到这里对话就结束了
"lstrip": false,
"normalized": true,
"rstrip": false,
"single_word": false
},
// 是否使用旧版的 SentencePiece 逻辑。设为 true 通常是为了兼容老版本的 Llama 分词实现
"legacy": true,
// 模型能处理的最大上下文长度。
// 131072 代表这个模型支持 128K 的超长文本输入。
"model_max_length": 131072,
// 定义 PAD(Padding)填充符。当多个句子长度不一时,用它补齐。
// 在 DeepSeek 中,通常复用 EOS 作为 PAD 符。
"pad_token": {
"__type": "AddedToken",
"content": "<|end▁of▁sentence|>",
"lstrip": false,
"normalized": true,
"rstrip": false,
"single_word": false
},
// 传递给底层的 SentencePiece 模型的额外参数(当前为空)
"sp_model_kwargs": {},
// 未知词标记。这里设为 null 是因为该分词器基于 Byte-level,
// 理论上能处理所有字节,不存在“不认识”的词。
"unk_token": null,
// 告诉 Transformers 库使用哪个 Python 类来加载。
// 这里使用的是经过 Rust 优化的 Llama 快速分词器类。
"tokenizer_class": "LlamaTokenizerFast"
}
Python 代码如下:
from transformers import AutoTokenizer
# 自动读取目录中的 tokenizer.json, tokenizer_config.json
tokenizer = AutoTokenizer.from_pretrained('./deepseek-v3.2-tokenizer')
text = """
正如我们第一部分所说,LLM 是一个概率模型,通过数学计算来进行下一个字的预测。然而,计算机只认识数字(0和1),并不认识"今天"、"天气"或者"Today"这些单词。因此,想要让计算机能够理解人类的语言,需要通过特定的编码机制将自然语言翻译成模型能运算的数字序列。分词器(Tokenizer)是实现这一功能的核心组件,它能够将连续文本拆解为离散语义单元(即Token)并转换为唯一索引(Token ID)用于模型输入。
所有 LLM 的输入都依赖 Tokenizer 的预处理结果。如果分词策略不合理,如拆分后丢失语义或 Token 粒度过细,会直接影响模型对文本的理解能力。因此,一个设计优良的 Tokenizer 是提升 LLM 性能的基础前提。
2.2 Tokenizer分类
根据切分粒度的不同,Tokenizer可分为三大类:字符级Tokenizer(Character-level)、词级Tokenizer(Word-level)以及子词级 Tokenizer(Subword-level)。我们以句子 "Today is sunday." 为例,看看它们是如何工作的。
"""
# encode 方法会将文本转换为数学序列
input_ids = tokenizer.encode(text)
print(f"{'ID':<10} | {'Token (原始)':<15} | {'解码后的内容'}")
print("-" * 45)
for idx in input_ids:
# 1. 获取原始 token(可能包含字节乱码)
raw_token = tokenizer.convert_ids_to_tokens(idx)
# 2. 将单个 ID 解码为文本(这样能正确显示汉字碎片)
# skip_special_tokens=False 保证能看到 [BOS] 等特殊字符
decoded_word = tokenizer.decode([idx])
print(f"{idx:<10} | {raw_token:<15} | {decoded_word}")
print(f"总共Token数量:{len(input_ids)}")
内容输出如下:
ID | Token (原始) | 解码后的内容
---------------------------------------------
201 | Ċ |
26328 | æŃ£å¦Ĥ | 正如
1300 | æĪij们 | 我们
99964 | 第ä¸Ģéĥ¨åĪĨ | 第一部分
41172 | æīĢ说 | 所说
303 | ï¼Į | ,
3699 | LL | LL
47 | M | M
223 | Ġ |
6715 | æĺ¯ä¸Ģ个 | 是一个
21366 | æ¦Ĥçİĩ | 概率
8842 | 模åŀĭ | 模型
303 | ï¼Į | ,
2490 | éĢļè¿ĩ | 通过
8570 | æķ°åѦ | 数学
...
28407 | 为ä¾ĭ | 为例
303 | ï¼Į | ,
8403 | çľĭçľĭ | 看看
7174 | å®ĥ们 | 它们
37096 | æĺ¯å¦Ĥä½ķ | 是如何
10116 | å·¥ä½ľçļĦ | 工作的
876 | ãĢĤĊ | 。
总共Token数量:229