tiny-llm-27m / README.md
sergeymanevitch's picture
tiny-llm: 27M from-scratch pipeline (BPE, pretrain, SFT, DPO, draft, RAG)
7e56b25 verified
|
Raw
History Blame Contribute Delete
3.53 kB
---
language: en
license: mit
tags:
- tiny-llm
- tinystories
- from-scratch
- educational
- speculative-decoding
- dpo
datasets:
- roneneldan/TinyStories
pipeline_tag: text-generation
---
# tiny-llm β€” a 27M-parameter LLM built from scratch, end to end
A complete modern LLM pipeline built by hand as a learning mission β€” every
stage written from scratch in readable PyTorch (no HF Transformers, no
external tokenizer), trained on free Colab T4 and a Mac CPU.
**Pipeline:** own byte-level BPE tokenizer β†’ pretraining β†’ SFT (instruction
following) β†’ DPO (preference alignment) β†’ distilled draft model + speculative
decoding β†’ RAG with copy-tuning β†’ this release.
## Sizes
| File | Model | Params | What it is |
|------|-------|-------:|------------|
| `dpo-m4c.pt` | main | **27.0M** (dim 512, 8 layers, 8 heads, vocab 4096, ctx 512) | pretrained β†’ SFT β†’ DPO story-writer |
| `rag-m6.pt` | RAG variant | 27.0M | same model copy-tuned to quote retrieved context faithfully |
| `draft-m5.pt` | draft | **1.28M** (dim 128, 4 layers) | distilled from the main model for speculative decoding (1.4Γ— on CPU) |
| `tokenizer.json` | BPE | 4096 merges | byte-level BPE trained from scratch on TinyStories |
## Training data
- **Only dataset:** [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories)
(synthetic children's stories, English). The validation file was deduplicated
against train (33% of it duplicated train stories) before any evaluation.
- SFT pairs: `"Write a story about X.\n\n" + story`, where X is strictly the
story's first-sentence subject appearing β‰₯2 times (data-quality lesson:
a noisier heuristic taught the model to ignore instructions).
- DPO pairs: chosen = human story, rejected = the SFT model's own sample.
## Honest limitations
- Writes **only simple children's stories in English**. Nothing else.
- It does not know facts about the world, cannot do math, cannot chat in
Russian or any other language.
- Instruction following ("about X") works on ~7/10 held-out topics; very rare
words (e.g. "unicorn") may be ignored.
- The RAG variant only quotes from a supplied context line; without context it
invents.
- Trained on ~500M tokens of synthetic text at 27M params β€” a *toy*, roughly
25,000Γ— smaller than frontier models. Built for learning, not for use.
## Usage
```python
import torch
from model import TinyLLM, ModelConfig # model.py from this repo
from bpe import BPETokenizer # bpe.py from this repo
tok = BPETokenizer.load("tokenizer.json")
ck = torch.load("dpo-m4c.pt", map_location="cpu")
m = TinyLLM(ModelConfig(**ck["cfg"])); m.load_state_dict(ck["model"]); m.eval()
# IMPORTANT: encode word-by-word (the same word-cache encoding used in training)
import re
ids = []
for w in re.findall(r"\S+\s*", "Write a story about dragon.\n\n"):
ids += tok.encode(w)
out = m.generate(torch.tensor([ids]), 120, temperature=0.7)
print(tok.decode(out[0].tolist()))
```
Speculative decoding (`speculative.py`) makes greedy generation ~1.4Γ— faster
on CPU with byte-identical output; `rag.py` + `rag-corpus.txt` show the RAG
setup.
## Validation
Every stage was gated by a frozen validation contract (18 assertions):
pretrain val loss 1.656 (≀2.3), instruction following judged blind 7/10,
DPO preferred blind in 90% of 20 pairs, speculative decoding exact on 20/20
prompts at 1.40Γ—, RAG answers contain the fact on 9/10 questions (0/10
without retrieval). Fresh-context judges never saw the training code.