Mini-AGI:8GB显存持续学习语言模型架构解析
Show HN: Mini-AGI – Dynamic continual learning model trained on 8GB VRAM
在消费级硬件上实现无遗忘持续学习的工程实践极具参考价值,架构细节完整可复现,适合关注端侧AI与个性化模型的研究者深入阅读。
mini-AGI
mini-AGI
mini-AGI - is a continual learning byte-level language model that assembles its own architecture, trains from scratch on a single 8 GB VRAM GPU, and keeps learning from everything it reads. It stores its weights as ordinary files on disk and pages them onto the card as it needs them, so the parameter count is bounded by free disk space rather than by VRAM. It grows new capacity while training when it runs short, prunes what nothing asks for, and reads through exactly the same code path it serves on. Targeted at a PC or laptop with at least an 8 GB VRAM GPU on the board.
mini-AGI 是一个持续学习的字节级语言模型,它能组装自己的架构,在单张 8 GB VRAM 的 GPU 上从头训练,并从其阅读的所有内容中持续学习。它将权重作为普通文件存储在磁盘上,并根据需要将其分页加载到显卡上,因此参数量受限于可用磁盘空间而非 VRAM。当训练中出现容量不足时,它会增长新的容量;当没有任何请求使用某些参数时,它会进行剪枝;并且它通过与其服务完全相同的代码路径进行读取。目标设备为配备板载至少 8 GB VRAM GPU 的个人电脑或笔记本电脑。
NOTE: as of now this is a small toy-level model. Do not expect a frontier level capabilities. This is rather a small experiment to show, that continual learning from the single stream of data without catastrophic forgetting is possible. Furthermore it is possible on a modest hardware. Which means that almost everyone could train their own version of the model (or simply continue training this one) exactly as they see it fit. And the capabilities would be bounded by the actual hardware, scale and quality of the data available and the amount of time one willing to spend on training the model.
注意:截至目前,这只是一个小型玩具级模型。不要期望它具有前沿级别的能力。这更像是一个小型实验,旨在证明从单一数据流中进行持续学习且不会发生灾难性遗忘是可能的。此外,这种能力在适度硬件上也是可行的。这意味着几乎每个人都可以按照自己的意愿训练他们自己的模型版本(或者简单地继续训练这个模型)。其能力将受限于实际硬件、可用数据的规模和质量,以及用户愿意投入在模型训练上的时间。
Here is how min-run dashboard looks like. The model is pointed to the corpus to constantly read and learn from.
以下是 min-run 仪表盘的样貌。模型被指向语料库,以持续阅读并从中学习。
History - here is the samples from the whole training run history so far. You can inspect them yourself to see how the model improved over the course of training/reading the corpus.
历史记录 - 这里展示了迄今为止整个训练运行过程中的样本。你可以自行检查它们,以了解模型在训练/阅读语料库的过程中是如何改进的。
The weights are not published yet. The run is still reading its first pass over the corpus, the weights go up once it has been through all of it, which is a couple of weeks away at the current rate.
权重尚未发布。该运行仍在对其语料库的第一遍进行读取,只有在遍历完所有数据后权重才会上传,按当前速度计算,这需要几周的时间。
Motivation
动机
Every language model you can actually own today is a model somebody else trained and then froze. You can fine-tune around the edges of it, but you cannot train one from scratch on your own hardware, and you cannot keep training it on what you do day to day - the moment you try, it forgets what it knew before. The result is that a personal model is always somebody else's model with a thin layer of you on top, and it stops learning the day it ships.
如今你真正能拥有的每个语言模型,都是别人训练好然后冻结的模型。你可以在其边缘进行微调,但你无法在自己的硬件上从头训练一个模型,也无法在你日常使用的过程中持续训练它——一旦尝试,它就会忘记之前所学的知识。结果是,个人模型总是别人的模型加上薄薄的一层你的印记,而且它在发布的那一天就停止了学习。
mini-AGI model has small enough GPU footprint that it is possible to train end-to-end on one consumer card, and it is built so that training never has to stop. It reads a stream of characters one chunk at a time, takes a gradient step on each, and the same path serves generation. There is no separate fine-tuning regime and no frozen base: reading and being trained are the same event.
mini-AGI 模型具有足够小的 GPU 占用空间,使其能够在单张消费级显卡上端到端训练,并且其构建方式确保训练过程无需中断。它以块为单位逐字符读取数据流,对每个块执行梯度更新,且同一路径同时用于生成。不存在独立的微调阶段,也没有冻结的基础模型:阅读与训练是同一事件。
Three constraints shape everything else in the design:
三个约束条件塑造了设计中的其他一切:
- It has to fit on 8 GB. Not with quantisation - training needs gradients and optimiser state, which is roughly three times the weights again. So the weights live on disk and only the working set is resident.
- It has to not forget. A model that learns continually and overwrites itself is worse than one that does not learn at all.
- It has to be able to read anything. The alphabet is the 256 byte values, so there is no tokenizer to fit and no data type that needs a new vocabulary.
- 它必须能适配 8 GB 显存。不能依靠量化——训练需要梯度和优化器状态,这大约使权重体积再增加三倍。因此,权重存储在磁盘上,仅工作集驻留在内存中。
- 它必须不会遗忘。一个持续学习并覆盖自身的模型,比完全不具备学习能力的模型更差。
- 它必须能够读取任何内容。字母表由 256 个字节值构成,因此无需拟合分词器,也无需为数据类型定义新的词汇表。
The model is genuinely yours: trained on your hardware, on your data, that keeps learning from every conversation you have with it, and that nobody else can take it away or switch it off.
该模型真正属于你:在你的硬件上、使用你的数据进行训练,并从你与之进行的每次对话中持续学习,且无人能将其夺走或关闭。
How the architecture works
架构工作原理
Characters (bytes) does not pass through a fixed stack of layers as it would be in a traditional LLM. Instead, it passes through two dense prelude blocks and then through one recurrent block applied up to 24 times, each application choosing its own experts from a shared pool. The latent state between applications is never decoded - it is merged with the embedded input by an adapter each time round, so the loop cannot drift away from the text it is reading.
字符(字节)不像在传统 LLM 中那样通过固定的层堆栈传递。相反,它先经过两个稠密的前奏块(prelude blocks),然后通过一个循环块最多应用 24 次,每次应用都从共享池中自主选择专家。应用之间的潜在状态(latent state)从不被解码——每轮循环中,它都会通过适配器与嵌入输入合并,从而防止循环偏离其所读取的文本。
Three distinct blocks, up to 26 block-applications per character.
三个不同的块,每个字符最多经历 26 次块应用。
- Adaptive depth. A halting head scores every character at every row, and the character stops as soon as another row would not change the answer. Easy characters take one row, hard ones take many. This is the PonderNet recipe: while training, every depth is computed and weighted by its halting probability, so the halting head learns through those weights.
- Routing per block-application, not per character. Each of the 26 applications picks its own top-8 experts, so one character touches far more of the pool than "top-8" suggests, and the same expert can be selected several times at different depths. What varies is which eight at each point.
- No expert is assigned a subject. There are no labels anywhere. Soft top-k routing distributes capability across the pool by itself, and a character can combine fragments from several experts. The cost is that capabilities share parameters and so can interfere.
- 自适应深度。一个停止头(halting head)对每一行的每个字符进行评分,一旦另一行不会改变答案,该字符即停止处理。简单的字符只需一行,困难的字符则需要多行。这是 PonderNet 的方案:在训练期间,所有深度均被计算并根据其停止概率加权,从而使停止头通过这些权重进行学习。
- 按块应用而非按字符进行路由。26 次应用中的每一次都选择其各自的 top-8 专家,因此单个字符会触及比“top-8”暗示更多的池化资源,且同一专家可在不同深度被多次选中。变化的是在每个节点处具体是哪八个专家。
- 没有专家被分配特定主题。任何地方都没有标签。软 Top-k 路由自行将能力分布到整个专家池中,一个字符可以组合来自多个专家的片段。代价是能力共享参数,因此可能会相互干扰。
This is the architecture assembling itself, one character at a time, captured from the live model - nothing here is drawn by hand.
这是模型自我组装的架构,一次处理一个字符,从实时模型中捕获——这里没有任何手绘内容。
Each tile on the left is one expert; colour is expert identity and stays the same for the whole clip. A row is one application of the recurrent block, and the eight tiles in it are the eight experts that row actually ran. The stack grows downward as the model keeps going, and the amber line is where halting stopped it - the grey rows below are computation the model declined to spend.
左侧的每个图块代表一个专家;颜色表示专家身份,在整个片段中保持不变。每一行代表循环块的一次应用,其中的八个图块是该行实际运行的八个专家。随着模型的持续运行,堆栈向下增长,琥珀色的线条表示停止机制在此处截断——下方的灰色行是模型拒绝进行计算的部分。
The trace on the right is how many rows each character took. It moves constantly between 4 and 14 against a ceiling of 24, and the caret under the text shows which character is being read.
右侧的轨迹显示每个字符消耗的行数。它在上限为 24 的情况下在 4 到 14 之间不断变化,文本下方的尖号指示当前正在读取哪个字符。
Positions are rotary and carry no learned parameters, which is why the context window can be extended by continued training rather than by re-initialising anything.
位置编码是旋转式的且不携带任何学习参数,这就是上下文窗口可以通过继续训练而非重新初始化来扩展的原因。
...and the same thing while it writes
...以及它在写作时的相同情况
The clip above is the model reading - every character is held-out text it is being shown. This one is the model writing: it was primed with 2,500 characters of a held-out story and then continued on its own, so the grey text is what it was given and the green text is entirely its own. Greedy decoding, no sampling anywhere - run it twice and you get the same sentence.
上面的片段是模型在阅读——每个字符都是它被展示的保留文本。这一个片段是模型在写作:它以一篇保留故事的前 2,500 个字符作为提示,然后自行继续生成,因此灰色文本是提供给它的部分,绿色文本完全是它自己生成的。使用贪婪解码,全程无采样——运行两次你会得到相同的句子。
Two things are worth watching. The stack behaves the same way, because generating and reading are the same forward pass in this model - the only difference is whether the next character comes from a file or from the model's own argmax. And writing costs more depth than reading: about 9.9 rows a character against 8.0 on the same subject. The dotted lines mark where the working set was re-chosen, which happens every 64 characters; in this clip nothing swapped, because the prompt had already pulled the right experts onto the card.
有两点值得关注。堆栈的行为方式相同,因为在这个模型中,生成和阅读是相同的正向传播过程——唯一的区别在于下一个字符是来自文件还是来自模型自身的 argmax。写作比阅读需要更多的深度:在同一主题下,写作平均每字符约 9.9 行,而阅读为 8.0 行。虚线标记了工作集被重新选择的位置,这每 64 个字符发生一次;在这个片段中没有发生交换,因为提示词已经将正确的专家加载到了显存中。
What it produced, continuing a story about a cherry tree:
它生成的内容,延续了一个关于樱桃树的故事:
They worked together and saw their favorite shore. One day, they wanted to play with their favorite shore. They wanted to play with it, but
他们一起工作并看到了他们最喜欢的海岸。有一天,他们想和他们最喜欢的海岸玩耍。他们想和它玩耍,但是
Grammatically correct and on-topic. It does repeats itself for now - which is a fair picture of where the model is at 243M characters.
语法正确且切题。目前它仍在重复自己——这公平地反映了模型在 2.43 亿字符规模下的状态。
How paging works
分页的工作原理
Every expert is a file on disk holding its weights and its Adam moments. Above disk sit two caches and a working set:
每个专家都是磁盘上保存其权重和 Adam 动量矩的文件。在磁盘之上设有两个缓存和一个工作集:
| key | what it is | |
|---|---|---|
| disk | — | every expert the model has; bounded by free space |
| RAM | ram_cache | recently wanted experts, least-recently-used evicted |
| VRAM | resident | the working set - what a character may route through |
| 键 | 含义 | |
|---|---|---|
| disk | — | 模型拥有的所有专家;受可用磁盘空间限制 |
| RAM | ram_cache | 最近被请求的专家,采用最近最少使用(LRU)策略淘汰 |
| VRAM | resident | 工作集 - 字符可能路由经过的部分 |
Before every chunk the model is asked what the text about to be read wants, and the answer becomes the working set. Demand is scored on the hidden states the call sites actually routed on while reading the previous chunk - an embedding carries no context, so scoring on raw embeddings would have every subject asking for the same experts.
在处理每个数据块之前,模型会被询问即将阅读的文本需要什么,答案即成为工作集。需求评分基于读取前一个数据块时调用站点实际路由的隐藏状态——嵌入向量本身不携带上下文信息,因此若仅对原始嵌入进行评分,会导致所有主题都请求相同的专家。
Two rules the project holds to:
该项目遵循两条规则:
- Adam's moments travel with the expert. They belong to the expert, not to the slot of VRAM it happened to occupy. Leaving them behind would hand one expert's momentum to whatever took its place, and training would carry on looking healthy while every swapped expert inherited a stranger's history.
- Adam 的动量矩随专家一起移动。它们属于专家本身,而非其恰好占用的 VRAM 槽位。若将其遗留原地,则会将一个专家的动量传递给接替其位置的专家,导致训练看似正常,但每个交换进来的专家都继承了陌生人的历史。
更进一步:量化金融体系
看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力