Appearance
分词与词表 — 代码走读
src/llama-vocab.cpp — 分词器实现
核心类结构
llama_vocab 类管理整个词表和分词逻辑:
cpp
struct llama_vocab {
// 词表数据
std::vector<llama_vocab_token> tokens;
std::unordered_map<std::string, llama_token> token_to_id;
// 分词类型
enum llama_vocab_type type;
// 特殊 token ID
llama_token bos_token_id;
llama_token eos_token_id;
llama_token pad_token_id;
// BPE 合并规则
std::vector<std::pair<std::string, std::string>> merges;
};分词入口
cpp
int32_t llama_tokenize(
const struct llama_model * model,
const char * text,
llama_token * tokens,
int32_t n_max_tokens,
bool add_bos,
bool special);BPE 编码流程
cpp
// 1. 预处理:Unicode 规范化
text = unicode_normalize(text);
// 2. 预分词:按正则分割为词
auto words = pre_tokenize(text);
// 3. 对每个词执行 BPE
for (auto & word : words) {
auto tokens = bpe_encode(word);
result.insert(result.end(), tokens.begin(), tokens.end());
}
// 4. 添加特殊 token
if (add_bos) result.insert(result.begin(), vocab.bos_token_id);BPE 合并
cpp
// BPE 核心:重复合并最高优先级的 token 对
while (true) {
auto best = find_best_merge(tokens, merges);
if (best.score == -INF) break;
tokens = merge_pair(tokens, best.pair);
}Detokenization
cpp
// 将 token ID 转回文本
int32_t llama_token_to_piece(
const struct llama_model * model,
llama_token token,
char * buf,
int32_t length,
int32_t lstrip,
bool special);关键函数索引
| 函数 | 说明 |
|---|---|
llama_tokenize | 文本 → token IDs |
llama_token_to_piece | token ID → 文本片段 |
llama_vocab_get_text | 获取 token 的文本表示 |
llama_vocab_get_type | 获取分词器类型 |
llm_load_vocab | 从 GGUF 加载词表 |