Hugging Face Transformers 源码学习指南
Hugging Face Transformers 源码学习指南
一、学习前准备
1.1 环境配置
# 安装依赖
pip install -e ".[dev]"
pip install torch accelerate
# 验证安装
python -c "from transformers import BertModel; print('OK')"
1.2 必读论文
按顺序阅读:
-
Attention Is All You Need (2017) - Transformer 架构基础
- 论文链接: https://arxiv.org/abs/1706.03762
- 重点:Self-Attention 机制、Multi-Head Attention、位置编码
-
BERT: Pre-training of Deep Bidirectional Transformers (2018)
- 论文链接: https://arxiv.org/abs/1810.04805
- 重点:双向编码、MLM 预训练、NSP 任务
二、项目结构概览
2.1 Transformers 框架与模型的关系
Transformers 定义了统一的标准接口,各大模型厂商按照这个标准来实现自己的模型:
┌─────────────────────────────────────────────────────────┐
│ Transformers 框架(定义标准) │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ PreTrainedModel │ │ PretrainedConfig│ ... │
│ │ - forward() │ │ - from_dict() │ │
│ │ - from_pretrained() │ │ │
│ └────────┬────────┘ └────────────────┘ │
└───────────┼───────────────────────────────────────────┘
│ 继承 & 实现
▼
┌───────────────────────────────────────────────────────┐
│ 各厂商模型实现 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ BERT │ │ LLaMA │ │ Qwen │ │DeepSeek │ ... │
│ │ (Google)│ │ (Meta) │ │(阿里云) │ │(深度求索)│ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└───────────────────────────────────────────────────────┘
这样做的好处:
- 用户侧:学会一个 API,就能用所有模型
- 厂商侧:按标准实现,立刻获得整个生态的支持
Transformers 就像 AI 模型界的 "Android SDK",各厂商主动适配是因为:
"如果你的模型不在 Transformers 里,用户用起来就很麻烦"
2.2 目录结构
transformers/
├── src/transformers/
│ ├── models/ # 各模型实现(重点)
│ │ ├── bert/ # BERT 模型
│ │ ├── gpt2/ # GPT-2 模型
│ │ ├── llama/ # LLaMA 模型
│ │ └── ...
│ ├── configuration_utils.py # 配置基类
│ ├── modeling_utils.py # 模型基类 PreTrainedModel
│ ├── tokenization_utils_base.py # Tokenizer 基类
│ ├── trainer.py # 训练器
│ └── pipelines/ # 推理管道
├── tests/ # 测试代码
└── docs/ # 文档
三、核心代码学习路径(以 BERT 为例)
3.1 学习顺序
第1步: configuration_bert.py → 理解模型配置参数
第2步: modeling_bert.py → 理解模型架构实现
第3步: tokenization_bert.py → 理解文本分词
第4步: 动手调试 → 加深理解
3.2 BERT 模型架构(对应论文)
modeling_bert.py 中的类层次:
BertModel (完整模型)
├── BertEmbeddings # 输入嵌入层
│ ├── word_embeddings # 词嵌入 (vocab_size × hidden_size)
│ ├── position_embeddings # 位置嵌入 (max_position × hidden_size)
│ ├── token_type_embeddings # 段落嵌入 (type_vocab_size × hidden_size)
│ ├── LayerNorm
│ └── Dropout
│
├── BertEncoder # Transformer 编码器
│ └── BertLayer × 12 # 12 层 Transformer
│ ├── BertAttention # 注意力模块
│ │ ├── BertSelfAttention # 自注意力(核心!)
│ │ └── BertSelfOutput # 输出投影 + 残差 + LayerNorm
│ ├── BertIntermediate # FFN 第一层 (hidden → intermediate)
│ └── BertOutput # FFN 第二层 + 残差 + LayerNorm
│
└── BertPooler # 池化层(取 [CLS] token)
3.3 关键代码解读
3.3.1 配置类 (configuration_bert.py)
class BertConfig(PreTrainedConfig):
def __init__(
self,
vocab_size=30522, # 词表大小
hidden_size=768, # 隐藏层维度 (论文中的 d_model)
num_hidden_layers=12, # Transformer 层数
num_attention_heads=12, # 注意力头数
intermediate_size=3072, # FFN 中间层维度 (通常是 4 × hidden_size)
hidden_act="gelu", # 激活函数
hidden_dropout_prob=0.1, # Dropout 概率
attention_probs_dropout_prob=0.1,
max_position_embeddings=512, # 最大序列长度
...
):
3.3.2 嵌入层 (BertEmbeddings)
# 对应论文:Input Embedding = Token Embedding + Position Embedding + Segment Embedding
def forward(self, input_ids, token_type_ids, position_ids, ...):
# 词嵌入
inputs_embeds = self.word_embeddings(input_ids)
# 段落嵌入(区分句子A和句子B)
token_type_embeddings = self.token_type_embeddings(token_type_ids)
# 位置嵌入
position_embeddings = self.position_embeddings(position_ids)
# 三者相加
embeddings = inputs_embeds + token_type_embeddings + position_embeddings
embeddings = self.LayerNorm(embeddings)
embeddings = self.dropout(embeddings)
return embeddings
3.3.3 自注意力机制 (BertSelfAttention) - 核心!
# 对应论文公式: Attention(Q,K,V) = softmax(QK^T / √d_k) V
def __init__(self, config):
# Q、K、V 投影矩阵
self.query = nn.Linear(config.hidden_size, self.all_head_size)
self.key = nn.Linear(config.hidden_size, self.all_head_size)
self.value = nn.Linear(config.hidden_size, self.all_head_size)
# 缩放因子 √d_k
self.scaling = self.attention_head_size ** -0.5
def forward(self, hidden_states, attention_mask, ...):
# 1. 线性投影得到 Q、K、V
query_layer = self.query(hidden_states) # [batch, seq_len, hidden]
key_layer = self.key(hidden_states)
value_layer = self.value(hidden_states)
# 2. 重塑为多头形式 [batch, num_heads, seq_len, head_dim]
query_layer = query_layer.view(*hidden_shape).transpose(1, 2)
key_layer = key_layer.view(*hidden_shape).transpose(1, 2)
value_layer = value_layer.view(*hidden_shape).transpose(1, 2)
# 3. 计算注意力分数 (对应 QK^T / √d_k)
attn_weights = torch.matmul(query, key.transpose(-2, -1)) * self.scaling
# 4. 应用 mask(padding 位置设为 -inf)
attn_weights = attn_weights + attention_mask
# 5. Softmax 归一化
attn_weights = nn.functional.softmax(attn_weights, dim=-1)
# 6. 加权求和得到输出
attn_output = torch.matmul(attn_weights, value)
return attn_output
3.3.4 前馈网络 (BertIntermediate + BertOutput)
# 对应论文: FFN(x) = GELU(xW1 + b1)W2 + b2
class BertIntermediate(nn.Module):
def forward(self, hidden_states):
hidden_states = self.dense(hidden_states) # hidden_size → intermediate_size
hidden_states = self.intermediate_act_fn(hidden_states) # GELU 激活
return hidden_states
class BertOutput(nn.Module):
def forward(self, hidden_states, input_tensor):
hidden_states = self.dense(hidden_states) # intermediate_size → hidden_size
hidden_states = self.dropout(hidden_states)
hidden_states = self.LayerNorm(hidden_states + input_tensor) # 残差连接
return hidden_states
四、调试学习方法
4.1 基础调试脚本
在项目根目录创建 debug_bert.py:
from transformers import BertModel, BertTokenizer
import torch
# 加载预训练模型和分词器
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased")
# 准备输入
text = "Hello, how are you?"
inputs = tokenizer(text, return_tensors="pt")
print("=== 输入信息 ===")
print(f"input_ids shape: {inputs['input_ids'].shape}")
print(f"input_ids: {inputs['input_ids']}")
print(f"tokens: {tokenizer.convert_ids_to_tokens(inputs['input_ids'][0])}")
# 前向传播(在这里打断点)
outputs = model(**inputs)
print("\n=== 输出信息 ===")
print(f"last_hidden_state shape: {outputs.last_hidden_state.shape}")
print(f"pooler_output shape: {outputs.pooler_output.shape}")
4.2 PyCharm 调试步骤
- 在
debug_bert.py的outputs = model(**inputs)行打断点 - 右键 → Debug 'debug_bert'
- 使用 "Step Into" (F7) 进入
BertModel.forward() - 继续 Step Into 进入各个子模块
4.3 重点调试位置
在以下位置打断点,观察张量变化:
| 文件 | 位置 | 观察内容 |
|---|---|---|
modeling_bert.py |
BertEmbeddings.forward() |
嵌入向量如何生成 |
modeling_bert.py |
BertSelfAttention.forward() |
Q/K/V 计算、注意力分数 |
modeling_bert.py |
eager_attention_forward() |
注意力计算细节 |
modeling_bert.py |
BertLayer.forward() |
单层 Transformer 流程 |
4.4 可视化注意力权重
from transformers import BertModel, BertTokenizer
import torch
import matplotlib.pyplot as plt
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased", output_attentions=True)
text = "The cat sat on the mat"
inputs = tokenizer(text, return_tensors="pt")
outputs = model(**inputs)
# 获取注意力权重
attentions = outputs.attentions # tuple of (batch, heads, seq, seq)
# 可视化第一层第一个头的注意力
tokens = tokenizer.convert_ids_to_tokens(inputs['input_ids'][0])
attn = attentions[0][0, 0].detach().numpy() # 第1层,第1个头
plt.figure(figsize=(8, 8))
plt.imshow(attn, cmap='viridis')
plt.xticks(range(len(tokens)), tokens, rotation=45)
plt.yticks(range(len(tokens)), tokens)
plt.colorbar()
plt.title("Attention Weights (Layer 1, Head 1)")
plt.tight_layout()
plt.savefig("attention_visualization.png")
plt.show()
五、进阶学习路径
5.1 学完 BERT 后的下一步
| 模型 | 特点 | 对应文件 |
|---|---|---|
| GPT-2 | 单向解码器、因果注意力 | models/gpt2/modeling_gpt2.py |
| T5 | 编码器-解码器架构 | models/t5/modeling_t5.py |
| LLaMA | RoPE 位置编码、RMSNorm | models/llama/modeling_llama.py |
| Qwen2 | 现代 LLM 架构 | models/qwen2/modeling_qwen2.py |
5.2 关键概念对比
| 概念 | BERT | GPT | 区别 |
|---|---|---|---|
| 注意力类型 | 双向 | 单向(因果) | GPT 只能看到前面的 token |
| 位置编码 | 绝对位置嵌入 | 绝对/RoPE | 现代模型多用 RoPE |
| 预训练任务 | MLM + NSP | 下一个词预测 | 不同的训练目标 |
5.3 重要基类学习
src/transformers/
├── configuration_utils.py # PreTrainedConfig - 所有配置的基类
├── modeling_utils.py # PreTrainedModel - 所有模型的基类
├── tokenization_utils_base.py # PreTrainedTokenizerBase - 分词器基类
└── trainer.py # Trainer - 训练器
六、学习资源
6.1 官方资源
- 官方文档: https://huggingface.co/docs/transformers
- 源码: https://github.com/huggingface/transformers
- 论文集: https://huggingface.co/papers
6.2 推荐阅读顺序
- 先跑通
debug_bert.py,熟悉基本流程 - 精读
BertSelfAttention,对照论文公式 - 理解
BertLayer的完整流程 - 学习
BertModel.forward()的整体架构 - 扩展到其他模型(GPT-2、LLaMA)
6.3 学习建议
- 边读代码边画架构图
- 用调试器观察张量 shape 变化
- 对照论文公式理解每一步计算
- 先忽略缓存、量化等优化代码,专注核心逻辑
- 遇到不懂的先跳过,建立整体认知后再回头
七、常见问题
Q1: 代码太多,从哪里开始?
从 BertSelfAttention.forward() 开始,这是 Transformer 的核心。
Q2: 论文公式和代码对不上?
代码中有很多工程优化(如多头并行计算),但数学本质相同。关注 eager_attention_forward() 函数。
Q3: 什么是 attention_mask?
用于屏蔽 padding token,防止模型关注无意义的位置。值为 0 的位置会被 mask 掉。
Q4: hidden_states 的 shape 是什么?
通常是 [batch_size, sequence_length, hidden_size],例如 [1, 7, 768]。
八、BertModel 模型加载深度解析
8.1 Tokenizer vs Model 对比
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased") # 加载分词器
model = BertModel.from_pretrained("bert-base-uncased") # 加载模型
| 对象 | 作用 | 下载的文件 | 大小 |
|---|---|---|---|
tokenizer |
文本 → 数字 ID | vocab.txt, tokenizer.json | ~1MB |
model |
神经网络计算 | pytorch_model.bin / model.safetensors | ~440MB |
简单类比:
tokenizer = 翻译官(把人话翻译成机器能懂的数字)
model = 大脑(用神经网络处理这些数字,理解语义)
from_pretrained = 下载一个已经"学过很多知识"的大脑
而不是用一个空白的大脑从头学习
8.2 BertModel 的结构
class BertModel(BertPreTrainedModel):
def __init__(self, config, add_pooling_layer=True):
super().__init__(config)
# 三大核心组件
self.embeddings = BertEmbeddings(config) # 嵌入层
self.encoder = BertEncoder(config) # 12层 Transformer
self.pooler = BertPooler(config) # 池化层
对应的架构:
输入: input_ids [1, 8] (batch=1, seq_len=8)
│
▼
┌─────────────────────┐
│ BertEmbeddings │ 词嵌入 + 位置嵌入 + 段落嵌入
│ 输出: [1, 8, 768] │
└─────────────────────┘
│
▼
┌─────────────────────┐
│ BertEncoder │ 12 层 Transformer
│ (BertLayer × 12) │ 每层: Self-Attention + FFN
│ 输出: [1, 8, 768] │
└─────────────────────┘
│
▼
┌─────────────────────┐
│ BertPooler │ 取 [CLS] token,过一个全连接层
│ 输出: [1, 768] │
└─────────────────────┘
8.3 from_pretrained 完整流程
BertModel.from_pretrained("bert-base-uncased")
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第一步:下载配置文件 config.json │
│ 包含: vocab_size=30522, hidden_size=768, │
│ num_hidden_layers=12, num_attention_heads=12, ... │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第二步:根据配置创建模型结构 │
│ model = BertModel(config) │
│ 此时权重是随机初始化的 │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第三步:下载预训练权重文件 │
│ model.safetensors 或 pytorch_model.bin (~440MB) │
│ 包含 1.1 亿个参数的具体数值 │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第四步:加载权重到模型 │
│ model.load_state_dict(weights) │
│ 随机权重被替换为预训练好的权重 │
└───────────────────────────────────────────────────────────┘
│
▼
返回加载好权重的 model 实例
8.4 预训练权重包含什么?
# 查看模型参数
for name, param in model.named_parameters():
print(f"{name}: {param.shape}")
# 输出示例:
# embeddings.word_embeddings.weight: [30522, 768] ← 词嵌入矩阵
# embeddings.position_embeddings.weight: [512, 768] ← 位置嵌入
# encoder.layer.0.attention.self.query.weight: [768, 768] ← Q 矩阵
# encoder.layer.0.attention.self.key.weight: [768, 768] ← K 矩阵
# encoder.layer.0.attention.self.value.weight: [768, 768] ← V 矩阵
# ... (共 12 层)
# pooler.dense.weight: [768, 768]
这些权重是 Google 用大量文本(Wikipedia + BookCorpus)预训练得到的,包含了语言知识。
8.5 源码 vs 权重:理解"开源大模型"
核心概念:
| 文件 | 是什么 | 在哪里 | 开源? |
|---|---|---|---|
modeling_bert.py |
模型源码(网络结构) | transformers 仓库 | ✅ 开源 |
model.safetensors |
权重文件(训练好的参数) | Hugging Face Hub | ✅ 开源 |
文件位置:
模型源码位置(本地 transformers 仓库):
src/transformers/models/bert/
├── modeling_bert.py # 模型代码 ← 定义网络结构
├── configuration_bert.py # 配置类
├── tokenization_bert.py # 分词器
└── ...
权重文件位置(Hugging Face Hub 云端):
https://huggingface.co/bert-base-uncased/
├── model.safetensors # 权重文件 ← 训练好的参数
├── config.json # 配置
├── vocab.txt # 词表
└── ...
开源大模型 = 开源的源码 + 开源的权重:
modeling_bert.py (源码) + model.safetensors (权重)
↓ ↓
定义网络长什么样 训练好的具体数值
(骨架) (血肉)
↓ ↓
└──────────── 合并 ────────────┘
↓
完整可用的模型
这就是为什么两行代码就能跑起大模型:
from transformers import BertModel # 导入源码(骨架)
model = BertModel.from_pretrained("bert-base-uncased") # 下载权重(血肉)
不同厂商的开源程度:
┌────────────────────────────────────────────────────────────┐
│ 开源程度对比 │
├──────────────┬─────────┬─────────┬─────────┬──────────────┤
│ │ 权重 │ 代码 │训练代码 │ 训练数据 │
├──────────────┼─────────┼─────────┼─────────┼──────────────┤
│ LLaMA (Meta) │ ✅ │ ✅ │ ❌ │ ❌ │
│ Qwen (阿里) │ ✅ │ ✅ │ ❌ │ ❌ │
│ DeepSeek │ ✅ │ ✅ │ ✅ │ ❌ │
│ GPT-4 (OpenAI)│ ❌ │ ❌ │ ❌ │ ❌ │
│ BERT (Google)│ ✅ │ ✅ │ ✅ │ ✅ │
└──────────────┴─────────┴─────────┴─────────┴──────────────┘
为什么权重文件最有价值?
- 训练权重需要:TB 级数据 + 数百万美元算力 + 数周时间
- 有了开源权重:几分钟下载,直接使用或微调
九、Tokenizer 分词器深度解析
8.1 from_pretrained 完整流程
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
这一行代码背后发生了很多事情:
BertTokenizer.from_pretrained("bert-base-uncased")
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第一步:解析参数 │
│ "bert-base-uncased" 是 Hugging Face Hub 上的模型 ID │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第二步:下载/缓存文件 │
│ 从 Hub 下载这些文件到本地缓存: │
│ - vocab.txt (词表文件) │
│ - tokenizer.json (快速分词器配置) │
│ - tokenizer_config.json (分词器参数配置) │
│ - special_tokens_map.json (特殊 token 映射) │
└───────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ 第三步:初始化 BertTokenizer │
│ - 加载词表 (30522 个词) │
│ - 配置特殊 token: [CLS], [SEP], [PAD], [UNK], [MASK] │
│ - 初始化 WordPiece 分词算法 │
│ - 设置 normalizer, pre_tokenizer, post_processor │
└───────────────────────────────────────────────────────────┘
│
▼
返回 tokenizer 实例
8.2 类继承关系
BertTokenizer
└── TokenizersBackend # 快速分词器后端 (Rust)
└── PreTrainedTokenizerBase # 所有分词器的基类
└── PushToHubMixin # 上传到 Hub 的功能
注意:在旧版本中有独立的 SpecialTokensMixin,但在 V5 版本中已合并到 PreTrainedTokenizerBase。
8.3 Rust 后端证明
BertTokenizer 底层调用 Rust 代码,证据如下:
# tokenization_bert.py 中的导入
from tokenizers import Tokenizer, decoders, normalizers, pre_tokenizers, processors
from tokenizers.models import WordPiece
tokenizers 库是 HuggingFace 的独立项目,用 Rust 编写,通过 PyO3 绑定到 Python。
验证方法:
import tokenizers
import os
# 查看 tokenizers 安装位置
print(tokenizers.__file__)
# 输出: C:\Users\xxx\...\tokenizers\__init__.py
# 在该目录下会发现 .pyd 文件(Windows)或 .so 文件(Linux)
# 这些是编译后的 Rust 二进制文件
dir_path = os.path.dirname(tokenizers.__file__)
print([f for f in os.listdir(dir_path) if f.endswith('.pyd') or f.endswith('.so')])
# 输出: ['tokenizers.pyd']
8.4 分词器初始化核心代码
# BertTokenizer.__init__() 中的关键代码:
# 1. 创建 WordPiece 分词模型(Rust 实现)
self._tokenizer = Tokenizer(WordPiece(vocab, unk_token="[UNK]"))
# 2. 设置文本规范化器 (normalizer)
self._tokenizer.normalizer = normalizers.BertNormalizer(
clean_text=True, # 清理控制字符
handle_chinese_chars=True, # 处理中文字符
strip_accents=None, # 去除重音
lowercase=do_lower_case # 转小写
)
# 3. 设置预分词器 (pre_tokenizer)
self._tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
# 4. 设置后处理器 (post_processor) - 添加 [CLS] 和 [SEP]
self._tokenizer.post_processor = processors.TemplateProcessing(
single="[CLS]:0 $A:0 [SEP]:0", # 单句模板
pair="[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1", # 句对模板
special_tokens=[("[CLS]", 101), ("[SEP]", 102)]
)
8.5 不同模型的分词器对比
每个模型需要适配自己的分词器,但复用了底层算法:
| 模型 | 分词算法 | 特殊 token | 词表文件 |
|---|---|---|---|
| BERT | WordPiece |
[CLS], [SEP], [MASK] | vocab.txt |
| LLaMA | BPE |
<s>, </s> | tokenizer.model |
| GPT-2 | BPE |
<|endoftext|> | vocab.json + merges.txt |
| Qwen2 | BPE |
<|endoftext|> | vocab.json + merges.txt |
代码对比:
# BERT 用 WordPiece
self._tokenizer = Tokenizer(WordPiece(vocab, unk_token="[UNK]"))
self._tokenizer.normalizer = normalizers.BertNormalizer(...)
# LLaMA 用 BPE + 字节回退
self._tokenizer = Tokenizer(BPE(vocab, merges, byte_fallback=True))
# Qwen2 用 BPE + 特殊预分词正则
self._tokenizer = Tokenizer(BPE(vocab, merges, ...))
self._tokenizer.pre_tokenizer = pre_tokenizers.Split(Regex(PRETOKENIZE_REGEX), ...)
8.6 分词器架构图
TokenizersBackend (基类)
│
│ 提供统一接口
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
BertTokenizer LlamaTokenizer Qwen2Tokenizer
│ │ │
│ 配置 │ 配置 │ 配置
▼ ▼ ▼
WordPiece BPE BPE
+ BertNormalizer + ByteFallback + 特殊正则
+ [CLS][SEP] + <s></s> + <|endoftext|>
│ │ │
└──────────────────┼──────────────────┘
│
▼
Rust 编译的二进制
(tokenizers.pyd)
8.7 WordPiece 分词算法示例
# 输入: "unhappiness"
# 分词过程:
# 1. 查找 "unhappiness" → 不在词表中
# 2. 查找 "unhappines" → 不在词表中
# 3. ...
# 4. 查找 "un" → 在词表中! 保留
# 5. 对剩余 "happiness" 继续,加 ## 前缀
# 6. 查找 "##happiness" → 不在词表中
# 7. ...
# 8. 查找 "##happi" → 在词表中! 保留
# 9. 对剩余 "ness" 继续
# 10. 查找 "##ness" → 在词表中! 保留
# 最终结果: ["un", "##happi", "##ness"]
8.8 vocab.txt 词表结构
[PAD] # ID: 0
[UNK] # ID: 1
[CLS] # ID: 101
[SEP] # ID: 102
[MASK] # ID: 103
...
hello # ID: 7592
world # ID: 2088
##ing # ID: 2075 ← WordPiece 子词,## 表示非词首
##ed # ID: 2098
...
# 共 30522 个词
8.9 总结
- 底层算法(WordPiece、BPE)是 Rust 实现的,所有模型共用
- 上层配置(词表、特殊 token、预处理)每个模型需要自己适配
- 这就像:发动机是通用的,但每辆车的外壳、内饰、配置不同
祝学习顺利!🚀

浙公网安备 33010602011771号