Appearance
分词与词表 — 练习
练习 1:使用 llama-cli 测试分词
使用 llama-cli --verbose-prompt 查看一段中文文本的分词结果,分析哪些 token 是完整的汉字,哪些被拆分。
参考答案
运行命令:
bash
./llama-cli -m model.gguf -p "你好世界" --verbose-prompt输出会显示 token 序列和对应的文本。对于 LLaMA 模型,中文通常被编码为多个 byte-fallback token,因为 SPM 词表中中文字符覆盖有限。
练习 2:追踪 BPE 编码过程
在 llama-vocab.cpp 中找到 BPE 编码的实现,画出从输入 "hello" 到 token IDs 的完整流程。
参考答案
流程:
llama_tokenize()调用内部llama_vocab::tokenize()- 文本
"hello"经过预分词(GPT-2 风格正则分割) - 对
"hello"执行 BPE 编码:- 初始:
[h, e, l, l, o] - 合并
ll→["h", "e", "ll", "o"] - 查找词表得到对应的 token IDs
- 初始:
- 返回
[token_id_h, token_id_e, token_id_ll, token_id_o]
练习 3:比较不同模型的词表
下载两个不同架构的 GGUF 模型,用 gguf-py 分别查看它们的词表大小和类型。
参考答案
python
from gguf import GGUFReader
for model_path in ["llama.gguf", "gpt2.gguf"]:
reader = GGUFReader(model_path)
vocab_type = reader.fields.get("tokenizer.ggml.model")
n_tokens = reader.fields.get("tokenizer.ggml.n_tokens")
print(f"{model_path}: type={vocab_type}, n_tokens={n_tokens}")典型结果:
- LLaMA 2: SPM, 32000 tokens
- GPT-2: BPE, 50257 tokens
- Qwen2: BPE, 151936 tokens
练习 4:追踪 HybridDNA 分词过程
假设输入为 "基因序列 <dna>ACGTACGT</dna> 结束",追踪 HybridDNA 分词器的处理流程。思考:<dna> 和 </dna> 标签是如何被检测和处理的?ACGTACGT 会被分成哪些 k-mer?
参考答案
处理流程:
- 检测到
<dna>标签,切换到 DNA 模式 ACGTACGT按 6-base k-mer 分词:- 前 6 个碱基
ACGTAC→ 对应 DNA k-mer token - 剩余 2 个碱基
GT不足 6 个,需要根据具体实现处理(可能补齐或使用短 k-mer)
- 前 6 个碱基
- 检测到
</dna>标签,切回 BPE 模式 "基因序列 "和" 结束"分别走标准 BPE 编码
如果输入中包含非 ACGT 字符(如 ACGTXACGT),X 会被替换为 <oov> token。
拓展挑战
- 阅读 Unicode 处理代码 (
unicode.cpp),理解 byte-fallback 机制 - 实现一个简单的 BPE 分词器(Python),与 llama.cpp 的结果对比
- 分析 chat template 如何影响分词结果