【免费下载链接】mini-AGI
Continual learning model trained from scratch on 8GB VRAM laptop with batch-1 stream of data.
mini-AGI是一个持续学习的字节级(byte-level)语言模型,它的分词器没有传统词表:整个"字母表"就是256 个字节值 + 9 个结构标记,合计 265 个符号。任何文件、任何语言、任何新数据类型都不需要重新建表——数据天然就能被模型读入。本文带你从零看懂这套字节级分词器的设计、编码过程,以及 9 个结构标记如何让对话、棋局和思考过程各就各位。
🧩 为什么放弃传统分词器:字节级设计的三个好处
传统 LLM 的分词器(BPE 等)需要先"拟合"一份词表:遇到词表外的字符就是 OOV(未登录词),换一类数据往往要重新建表。mini-AGI 把这条路整个砍掉了,核心设计在 minagi/tokenizer.py 的开头就写明了:
"The vocabulary is the 256 byte values plus a handful of structural markers. There is nothing to fall outside it."
由此带来三个直接好处:
- 不存在"未知字符"。任何文本按 UTF-8 展开都是 0–255 的字节,全部在表内,中文、emoji、代码、日志统统能读;
- 每个数字都是独立 token。这对算术能力很关键——模型能逐数字处理
4917 + 388,而不是靠分词器把数字切碎或合并; - 新数据类型不需要新词表。README.md 的原话:"The alphabet is the 256 byte values, so there is no tokenizer to fit and no data type that needs a new vocabulary."
代价是序列变长(一个字符一个 token)——但对一个逐字符推理、上下文 4,096 字符的模型来说,这本来就是它的工作方式。
模型一次读入一个字符(也就一个字节 token),左侧色块是它实际动用的专家计算量。
📦 词表构成:256 字节 + 9 个结构标记
词表只有两类符号,在 minagi/tokenizer.py#L24-L29 中定义:
| 类别 | 符号 | ID 范围 |
|---|---|---|
| 字节 | 全部 256 个 byte 值(UTF-8 编码后的原始字节) | 0–255 |
| 结构标记 | ` |
、、、、、、、、[END]` | 256–264 |
9 个结构标记的分工:
| 标记 | ID | 作用 |
|---|---|---|
| ` |
/| 256 / 257 | "思考"开始与结束(scratchpad,推理语料用) | |/| 258 / 259 | 用户发言的开始与结束 | |/| 260 / 261 | 模型回复的开始与结束 | |/| 262 / 263 | 棋局开始与结束(如<g 1850 1-0> e4 e5 ...) | |[END]` | 264 | 文档结束 |
词表总大小size = 256 + 9 = 265,模型侧也按这个数字构建嵌入层:minagi/create.py#L67 中RecurConfig(vocab_size=265, ...),minagi/recur.py#L64 中nn.Embedding(265, d_model)。
🔍 编码与解码:bytes in, bytes out
ByteTokenizer的编码逻辑非常直白(minagi/tokenizer.py#L45-L52):
- 用正则扫描全文,先定位所有结构标记;
- 标记之间的普通文本按 UTF-8 编码,一个字节一个 token;
- 每个命中的标记整体替换为一个 ≥256 的 ID。
几个例子:
"Hi"→[72, 105](2 个 token);"你好"→ 6 个字节 token(UTF-8 下每个汉字占 3 字节);"<bot>\n你好"→[260, 10, ...]——<bot>只占 1 个位置。
解码是逆过程(minagi/tokenizer.py#L57-L70):0–255 的 ID 攒进字节缓冲区,遇到 ≥256 的 ID 就先把缓冲区还原成文本、再整体输出对应的标记字符串——所以<user>这样的边界在解码时永远不会被拆散。
绿色部分是模型自己写出的内容:每个字符(字节 token)都经过与"读"完全相同的前向路径。
💡 结构标记为什么必须是"单个 token"
这是字节级设计里最有取舍感的一点。代码注释(minagi/tokenizer.py#L20-L23)解释得很清楚:
</think>拼出来要 7 个字节、占 7 个位置,还得让模型去学这条字面字符序列;作为 1 个 token,它就是一个专门表示"正在思考"的嵌入——这才是它真正的含义。
三个实际收益:
- 信号不需要拼写。标记不是模型在读的"文本",而是关于"模型在做什么"的信号;
- 永远不会写一半。如果
<bot>是 4 个字符,生成时可能只输出<bo就断开;作为单符号,输出要么完整、要么没有; - 节省上下文。一轮对话里
<user>、</user>、<bot>、</bot>共占 24 个字节位置,现在只占 4 个 token。
模型自己的"自我说明书"也是这么描述的(corpora/self_knowledge.yaml#L500-L512):它们"是字母表中的单个符号,而不是拼写,所以我永远写不出半个标记"。
✅ 如何读入任意数据:零预处理
字节级词表最直接的回报是:文件本身就是模型能读的唯一格式。minagi/ingest.py#L1-L16 把这句话写成了模块注释——"没有要拟合的分词器、没有要建的语料、没有要重跑的预处理"。
实际使用就一条命令:
python3 train.py read ~/notes python3 train.py read ~/src ~/docs --passes 3 --save读入时的规则(train.py#L593-L609):
- 目录会递归遍历,
node_modules、.git等目录被跳过; - 二进制文件靠内容判断而非扩展名:采样前 4096 字节,能按 UTF-8 解码且 >90% 可打印才算文本(minagi/ingest.py#L32-L50);
- 文件从头读到尾,因为"文档是有顺序的";
- 文件中若含
<user>这类标记,会经由分词器编码成单个 ID,而不是被拆成 6–7 个字符(minagi/ingest.py#L128-L146)——普通文本两条路径结果完全一样。
训练面板上,模型就是对着语料不停读、不停学:
min-run 面板:把模型指向语料目录,它就持续读入并持续学习。
⚙️ 标记如何贯穿训练流水线
分词器不只是"入口",它决定了数据怎么落地、怎么被重放:
| 环节 | 位置 | 分词器的角色 |
|---|---|---|
| 语料生成 | corpora/chat.py#L44、corpora/chess_games.py#L108 | 用<user>...<bot>包裹对话轮次、用<g>...</g>包裹棋局,再encode_batch成 uint16 的.bin流 |
| 语料落盘 | corpora/expand.py#L53-L64 | 标记 ID ≥256,直接按 uint8 截断会悄悄变成控制字节、丢掉所有轮次边界;所以必须走tok.decode()还原成文本 |
| 运行时加载 | minagi/tokenizer.py#L82-L89 | load_tokenizer()读语料的meta.json:"tokenizer": "byte"就返回ByteTokenizer();旧语料才回退到 HuggingFacetokenizers的tokenizer.json |
| Web 服务 | serve.py#L145 | 本地对话界面直接用ByteTokenizer()编解码你的消息 |
注意一个细节:标记 ID 以uint16存储(256–264 超出了 uint8 的范围),这也是每个语料目录的meta.json里要写明"tokenizer": "byte"的原因——它告诉下游"这份数据是字节级词表编码的,别按旧格式解析"。
📌 小结
- mini-AGI 的分词器 =256 个字节 + 9 个结构标记 = 265 词表,定义在 minagi/tokenizer.py;
- 字节级 → 没有未知字符、新数据零适配,
python3 train.py read <目录>即读即学; - 9 个标记是"单符号信号":思考(
</think>)、对话轮次(<user>/<bot>)、棋局(<g>)、文档结束([END]),各占 1 个 token、永不拆半; - 编码 UTF-8 字节 1:1、解码无损还原;标记以 uint16 存储并由
meta.json声明,避免边界被截断丢失。
想动手验证:python3 -m corpora all --limit 5000建一个小语料,再python3 train.py read data/train,你就能亲眼看到"任意数据"如何不经过任何预处理进入模型。
【免费下载链接】mini-AGI
Continual learning model trained from scratch on 8GB VRAM laptop with batch-1 stream of data.
相关推荐
10个必学Illustrator脚本:终极效率提升指南
10个必学Illustrator脚本:终极效率提升指南 Adobe Illustrator是设计师日常工作的核心工具,但面对重复性任务和复杂操作时,效率往往成为
工作流自动化Rufus 完整教程:一次制作 UEFI 启动盘,格式化、校验与查虚标全搞定
Rufus 完整教程:一次制作 UEFI 启动盘,格式化、校验与查虚标全搞定 Rufus 是一款免安装的 U 盘格式化工具,能把 U 盘格式化后写入系统镜像,制
桌面应用开发工具Catch2字节类型:字节级数据测试
Catch2字节类型:字节级数据测试 引言:为什么需要专门的字节类型测试? 在现代C++开发中, std::byte (C++17引入)已成为处理原始字节数据的
测试开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考