mini-AGI
Het model slaat zijn gewichten op als gewone bestanden op de schijf en pagineert deze naar de videokaart wanneer dat nodig is. Hierdoor wordt het aantal parameters beperkt door de beschikbare schijfruimte in plaats van door het VRAM. Tijdens het trainen breidt het model zijn capaciteit uit wanneer dit nodig is, snoeit het weg wat niet wordt opgevraagd, en gebruikt het exact hetzelfde codepad voor zowel training als generatie. Het project is gericht op pc's of laptops met minimaal een 8 GB VRAM GPU.
LET OP: Momenteel is dit een model op "speelgoedniveau". Verwacht geen prestaties die vergelijkbaar zijn met frontier-modellen. Dit is een experiment om aan te tonen dat continu leren vanuit een enkele datastroom, zonder catastrofale vergetelheid, mogelijk is op bescheiden hardware. Dit betekent dat vrijwel iedereen een eigen versie van het model kan trainen (of het bestaande model kan blijven trainen) naar eigen inzicht. De mogelijkheden worden bepaald door de hardware, de schaal en kwaliteit van de beschikbare data, en de tijd die men in de training steekt.
Motivatie
Elk taalmodel dat je vandaag de dag echt kunt bezitten, is een model dat door iemand anders is getraind en vervolgens is bevroren. Je kunt het aan de randen finetunen, maar je kunt er niet één vanaf nul trainen op je eigen hardware, en je kunt het niet blijven trainen op je dagelijkse activiteiten — zodra je dat probeert, vergeet het model wat het eerder wist. Het resultaat is dat een persoonlijk model altijd het model van iemand anders is met een dun laagje van jou erbovenop, en het stopt met leren op de dag dat het wordt uitgebracht.
Het mini-AGI model heeft een GPU-voetafdruk die klein genoeg is om end-to-end op één consumentenkaart te trainen, en het is zo gebouwd dat de training nooit hoeft te stoppen. Het leest een stroom karakters per blok, voert op elk blok een gradient-stap uit, en hetzelfde pad dient voor generatie. Er is geen apart regime voor finetuning en geen bevroren basis: lezen en getraind worden zijn hetzelfde event.
Drie beperkingen vormen de basis van het ontwerp:
- Het moet passen op 8 GB. Niet via kwantisatie — training vereist gradients en de status van de optimizer, wat ongeveer drie keer zoveel ruimte inneemt als de gewichten. Daarom leven de gewichten op de schijf en is alleen de working set resident in het geheugen.
- Het mag niet vergeten. Een model dat continu leert en zichzelf overschrijft, is slechter dan een model dat helemaal niet leert.
- Het moet alles kunnen lezen. Het alfabet bestaat uit de 256 byte-waarden, dus er is geen tokenizer nodig en geen datatype dat een nieuw vocabulaire vereist.
Het model is echt van jou: getraind op jouw hardware, op jouw data, het blijft leren van elk gesprek dat je ermee voert, en niemand kan het afpakken of uitschakelen.
Hoe de architectuur werkt
Karakters (bytes) passeren niet een vaste stapel lagen zoals in een traditioneel LLM. In plaats daarvan gaan ze door twee dense prelude blocks en vervolgens door één recurrent blok dat tot 24 keer wordt toegepast, waarbij elke applicatie zijn eigen experts kiest uit een gedeelde pool. De latente status tussen applicaties wordt nooit gedecodeerd — deze wordt elke ronde samengevoegd met de embedded input via een adapter, zodat de loop niet kan afwijken van de tekst die wordt gelezen.
- Drie verschillende blokken: Tot 26 blok-applicaties per karakter.
- Adaptieve diepte: Een halting head scoort elk karakter bij elke rij; het karakter stopt zodra een volgende rij het antwoord niet meer zou veranderen. Eenvoudige karakters vereisen één rij, moeilijke karakters vele. Dit volgt het PonderNet-recept: tijdens training wordt elke diepte berekend en gewogen door zijn stopkans, waardoor de halting head via deze gewichten leert.
- Routing per blok-applicatie: In plaats van per karakter kiest elke van de 26 applicaties zijn eigen top-8 experts. Eén karakter raakt dus veel meer van de pool aan dan "top-8" suggereert, en dezelfde expert kan meerdere keren worden geselecteerd op verschillende dieptes.
- Geen vaste subjecten: Geen enkele expert is toegewezen aan een specifiek onderwerp. Er zijn geen labels. Soft top-k routing verdeelt de capaciteit autonoom over de pool, en een karakter kan fragmenten van verschillende experts combineren. Het nadeel is dat capaciteiten parameters delen en elkaar kunnen beïnvloeden.
Lezen versus schrijven
Bij het lezen is elk karakter een held-out tekst die aan het model wordt getoond. Bij het schrijven (genereren) kan het model worden geprimed met tekst en vervolgens zelfstandig verdergaan. Er wordt gebruikgemaakt van greedy decoding zonder sampling.
Twee observaties:
- De stack gedraagt zich hetzelfde, omdat genereren en lezen dezelfde forward pass zijn. Het enige verschil is of het volgende karakter uit een bestand komt of uit de argmax van het model.
- Schrijven kost meer diepte dan lezen: ongeveer 9,9 rijen per karakter tegenover 8,0 voor hetzelfde onderwerp.
Voorbeeld van output (vervolg van een verhaal over een kersenhout): "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" (Grammaticaal correct en on-topic, hoewel het zich momenteel nog herhaalt bij een omvang van 243M karakters).
Werking van Paging
Elke expert is een bestand op de schijf met daarin de gewichten en de Adam-momenten. Boven de schijf bevinden zich twee caches en een working set:
| Locatie | Component | Beschrijving |
|---|---|---|
| Disk | — | Alle experts van het model; begrensd door vrije schijfruimte |
| RAM | ram_cache | Recentelijk gewenste experts, LRU (least-recently-used) evicted |
| VRAM | resident | De working set — waar een karakter doorheen kan routen |
Vóór elk blok wordt het model gevraagd wat de tekst die gelezen gaat worden nodig heeft, en het antwoord wordt de working set. De vraag wordt gescoord op de hidden states waarop de call-sites routeerden tijdens het lezen van het vorige blok.
Twee strikte regels:
- Adam's momenten reizen mee met de expert. Ze horen bij de expert, niet bij het VRAM-slot dat hij toevallig bezet.
- Een expert die al op de kaart staat, blijft in zijn slot. Matching gebeurt op identiteit in plaats van positie, wat het aantal ladingen minimaliseert.
Om te voorkomen dat de working set fluctueert bij ruis, wordt hysteresis gebruikt: een kandidaat moet een resident expert met een bepaalde marge verslaan om hem te vervangen, en een nieuwkomer is veilig voor een aantal dwell_chars aan lezen.
Groei en Snoeien
De pool groeit wanneer er een tekort aan capaciteit is en krimpt wanneer delen ervan niet meer worden opgevraagd.
Nieuwe experts worden speculatief toegevoegd via een kleine gate, zodat ze aanvankelijk bijna niets veranderen. Ze worden alleen behouden als er consistent naar gevraagd wordt. Een nieuwe expert wordt gebouwd door recombinatie — volledige hidden units genomen uit verschillende bestaande experts.
Groei wordt geweigerd tenzij aan alle volgende voorwaarden (brakes) is voldaan:
- room: Disk en VRAM hebben ruimte.
- used: De reeds toegevoegde capaciteit wordt daadwerkelijk opgevraagd.
- earning: De vorige cohort heeft de testperiode overleefd.
- fits: Er zijn niet te veel experts in hun testperiode.
- honest: Train- en held-out data zijn niet uit elkaar gelopen.
Snoeien: Experts worden als "dood" beschouwd wanneer ze niet worden aangesproken. Het belangrijkste inzicht hier is dat de gate niet informatief is, maar juist anti-predictief: de kleinste gates horen vaak bij de drukste experts. Een expert is veilig gedurende een volledige survival window zodat hij een kans krijgt om gekozen te worden.
Continu Leren
Training op een enkele stroom, één onderwerp tegelijk, is het klassieke recept voor catastrofale vergetelheid.
Het mechanisme om dit te voorkomen is de trunk learning rate. De trunk (embeddings, attention, routers, halting head) is het deel waar elk karakter doorheen gaat en draagt 97,6% van de squared gradient norm. Door de trunk op 0,1x de snelheid van de experts te trainen, wordt vergetelheid vrijwel geëlimineerd (van +2,2300 naar +0,0067 nats).
Metingen van retentie versus kans:
| Configuratie | Ongelezen subjecten | Retentie vs kans |
|---|---|---|
| Working set bevroren, trunk LR = expert LR | +2.5871 | 42.88% |
| Swapping, trunk LR = expert LR | +2.2300 | 50.68% |
| Swapping, trunk op 0.1x (gebruikt in run) | +0.0067 | 99.84% |
| Controle: alle zeven subjecten gelezen | -0.0077 | — |
Belangrijke conclusies:
- De expertpool is niet wat vergetelheid voorkomt. Het bevriezen van de working set kost slechts 0,3571 nats (13,8% van het effect).
- De schade is verplaatsing, niet vernietiging. Wanneer een model ernstig beschadigd is en vervolgens alles opnieuw leest, komt driekwart van de kennis terug in 131.000 karakters, tegenover de ~50M karakters die de eerste keer nodig waren.
Je eigen bestanden lezen
Dit is de kortste route naar een model dat specifieke informatie kent.
python3 train.py read ~/notes # Droge run - niets wordt bewaard
python3 train.py read ~/src ~/docs --passes 3 --save
Het alfabet bestaat uit de 256 byte-waarden, dus bestanden zijn al geschreven in het enige vocabulaire dat het model heeft. Mappen worden doorzocht, binaire bestanden worden overgeslagen via sampling, en elk bestand wordt van begin tot eind gelezen.
Vlaggen:
--passes N: Lees de hele set N keer.--save: Bewaar wat is geleerd; zonder dit blijft de mapweights/ongewijzigd.--lr: Standaard 5e-5 (lager dan een training run om te voorkomen dat het model wordt overschreven).--mix "": Sla de scoring voor/na over.
Benchmarks
De volgende cijfers zijn voor trackingdoeleinden en veranderen naarmate de run vordert.
Huidige status (318.1M karakters gelezen, 169 experts):
| Metriek | nats/char | bits/byte |
|---|---|---|
| Held-out, alle acht subjecten | 0.8336 ± 0.0331 | 1.2026 |
| Train | 0.6809 | 0.9823 |
Held-out loss per subject:
| Subject | nats/char | bits/byte |
|---|---|---|
| chess | 0.552 | 0.796 |
| stories | 0.637 | 0.919 |
| arithmetic | 0.657 | 0.948 |
| code | 0.739 | 1.066 |
| reasoning | 0.794 | 1.145 |
| chat | 0.831 | 1.199 |
| chat_hermes | 1.178 | 1.699 |
| wikipedia | 1.280 | 1.847 |
Dataschaling
Het model volgt een power law ($L \propto D^{-0.239}$), wat wijst op een gezonde exponent tussen Kaplan en Chinchilla.
Prognose voor benodigde bytes:
| Doel (Held-out) | Bytes nodig | Dagen op ~778 char/s |
|---|---|---|
| 1.10 BPB | 0.51B | ~3 |
| 1.00 BPB | 0.75B | ~6 |
| 0.93 BPB | 1.02B | ~10 |
| 0.80 BPB | 1.92B | ~24 |
Installatie en Uitvoering
Vereisten:
- CUDA-compatibele GPU met minimaal 8 GB VRAM.
- Python 3.10 of nieuwer.
Stappen:
- Clone de repository:
``bash git clone <repository-url> cd mini-AGI ``
- Installeer afhankelijkheden:
``bash pip install torch numpy pyyaml matplotlib pip install flask pip install tokenizers chess zstandard pip install scipy ``
- Bouw het corpus:
``bash python3 -m corpora all # Alle acht subjecten, een paar GB python3 -m corpora all --limit 5000 # Kleine slice om te testen python3 -m corpora all --full # Volledige datasets: tientallen GB ``
- Start het lezen:
``bash python3 train.py read data/train --save --weights-dir weights \ --held-out data/val --sample-every 10 ``
- Serveer het model:
``bash python3 serve.py --port 8080 # Open daarna http://127.0.0.1:8080 ``
Projectstructuur
minagi/: De kern van het model.config.py: Leestconfig.yaml.precision.py: Berekeningen en opslag van momenten.tokenizer.py: Bytes in, bytes uit (256 waarden + markers).model.py: De transformer (RMSNorm, rotary positions, SwiGLU, flash attention).decode.py: Methode voor karakterselectie.ingest.py: Omzetting van bestanden naar leesbare data.pool.py: De expert pool en groeiregels.paged.py: Pool verspreid over disk, RAM en VRAM.recur.py: Latente recurrentie met adaptieve diepte.stream.py: Lezen van een corpus via een KV cache.store.py: Beheer van deweights/map.optim.py: Gradient signaal analyse.plasticity.py: Learning rate beheer via held-out loss.live.py: Server voor een model dat gelijktijdig wordt getraind.report.py: Statistieken van de gewichten.create.py: Initialisatie van deweights/map.train.py: Hoofdscript voorread,streamofponder-probe.serve.py: Lokale web UI.config.yaml: Instellingen.corpora/: De gedownloade en bewerkte datasets.weights/: De daadwerkelijke modelbestanden.
De weights/ directory als model
De map weights/ bevat:
manifest.json: Inventarisatie en vorm.core.npz: Embeddings, attention, norms, adapter, halting head.routers.npz: De gate en segment router.optim.npz: Adam momenten voor de trunk en routers.experts/: Individuele.npzbestanden per expert.
Technische details van het model
- Byte level: Vocabulair van 265 (256 bytes + 9 markers zoals
<think>,<user>,<bot>,<g>, etc.). - Context window: 4,096.
- Body: RMSNorm, RoPE, SwiGLU, flash attention.
- Diepte: 3 distincte blokken, tot 26 applicaties per karakter.
- Recurrentie: Eén weight-shared blok, tot 24 keer toegepast; de latent is nooit gedecodeerd.
- Halting: PonderNet — karakters stoppen onafhankelijk.
- Routing: Top-8 experts per blok-applicatie.
- Paging: 32 experts resident op de kaart, de rest op schijf.
Parameter count (bij schrijftijd):
- Core: 8.27M
- Routers: 0.17M
- Experts: 531.6M (169 x 3.15M)
- Totaal: 540.1M
VRAM wordt bepaald door de working set, niet de pool. Slechts 32 experts (ca. 109M parameters) zijn resident, wat groei op een 8 GB kaart mogelijk maakt.
Gebruik van AI
Dit project is ondersteund door het "Claude Opus 5" model. Het model heeft het grootste deel van de code geïmplementeerd, geverifieerd en gedebugged. Daarnaast hielp het bij het zoeken naar relevante wetenschappelijke papers, het bouwen van tests en experimenten, en brainstormen over complexe problemen. Animaties, grafieken en media zijn eveneens door Claude gegenereerd op basis van echte datatraces. De auteur zorgde voor de hoofdi-ideeën, sturing, intuïtie, monitoring, verificatie en de definitieve architecturale beslissingen.
Erkenningen
Gebouwd met PyTorch, NumPy en Matplotlib. De architectuur is gebaseerd op:
- Sparsely-Gated MoE (Shazeer et al., 2017)
- Switch Transformers (Fedus et al., 2021)
- PonderNet (Banino et al., 2021)
- RoFormer / RoPE (Su et al., 2021)
- SwiGLU (Shazeer, 2020)
- RMSNorm (Zhang & Sennrich, 2019)
- FlashAttention (Dao et al., 2022)
- AdamW (Loshchilov & Hutter, 2017)
- Gradient Checkpointing (Chen et al., 2016)
- ZeRO-Offload/Infinity (Ren et al., 2021; Rajbhandari et al., 2021)
- Dynamic MoE (Kim et al., 2025)
- Chinchilla Scaling Laws (Hoffmann et al., 2022)
- The Pile (Gao et al., 2020)
- Transformer-XL / Compressive Transformers (Dai et al., 2019; Rae et al., 2019)
- Gradient Noise Scale (McCandlish et al., 2018)
- AdEMAMix Optimizer (Pagliardini et al., 2024)
Corpus: TinyStories, OpenHermes-2.5, OpenThoughts-114k, Lichess open database, Wikipedia en publieke source-code dumps.
Citatie
@software{Borsky_mini_AGI_2026,
author = {Borsky, Alexey},
month = {9},
title = {{mini-AGI: A Continually Learning Byte-Level Language Model}},
url = {https://github.com/volotat/mini-AGI},
version = {1.0.0},
year = {2026}
}
Groetjes,