Grading pass: Momo-free validation split, 1,000 truly unique Momo stories, decoded terms, widget fixes, honest numbers
Browse files- PLAYBOOK.md +24 -17
- README.md +4 -2
- model.pt +1 -1
- momo_stories.py +8 -1
- tiny_llm_from_scratch.ipynb +0 -0
- tokenizer.json +0 -0
PLAYBOOK.md
CHANGED
|
@@ -7,23 +7,25 @@ and Ella the elephant. Pick the path that fits you.
|
|
| 7 |
## What you get
|
| 8 |
|
| 9 |
A 5.9-million-parameter GPT-style language model, trained from scratch on simple children's
|
| 10 |
-
stories (TinyStories) plus a thousand stories about Momo and Ella
|
| 11 |
-
and it continues with a short, simple story. It is a
|
| 12 |
-
charming nonsense now and then
|
|
|
|
| 13 |
|
| 14 |
## Path A: run it in Google Colab (no install, free GPU)
|
| 15 |
|
| 16 |
1. Open https://colab.research.google.com and choose **Upload notebook**.
|
| 17 |
2. Pick `tiny_llm_from_scratch.ipynb` (download it from this repo first).
|
| 18 |
3. In Colab go to **Runtime > Change runtime type** and choose **T4 GPU**.
|
| 19 |
-
4. Press **Run all**. Everything above the training section runs
|
| 20 |
-
about
|
| 21 |
5. Scroll to **Part 8** to read the generated stories, and change the prompts to your own.
|
| 22 |
|
| 23 |
-
The
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
| 27 |
|
| 28 |
## Path B: run it on your own computer
|
| 29 |
|
|
@@ -33,7 +35,7 @@ on plain CPU (slower, but it works).
|
|
| 33 |
```bash
|
| 34 |
# 1. Python environment (any Python 3.10+; uv is fastest but pip works too)
|
| 35 |
uv venv --python 3.13 && source .venv/bin/activate
|
| 36 |
-
uv pip install torch transformers datasets tokenizers huggingface_hub nbformat nbconvert ipykernel
|
| 37 |
|
| 38 |
# 2. Run the notebook end to end (about 4 minutes on an M-series Mac)
|
| 39 |
jupyter nbconvert --to notebook --execute tiny_llm_from_scratch.ipynb --output run.ipynb
|
|
@@ -42,13 +44,15 @@ jupyter nbconvert --to notebook --execute tiny_llm_from_scratch.ipynb --output r
|
|
| 42 |
jupyter lab tiny_llm_from_scratch.ipynb
|
| 43 |
```
|
| 44 |
|
| 45 |
-
To publish from your machine,
|
| 46 |
-
|
| 47 |
|
| 48 |
## Path C: skip training, just use the model
|
| 49 |
|
| 50 |
-
The trained model lives on the Hugging Face Hub as `singhpratech/tiny-storyteller`.
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
|
| 53 |
```python
|
| 54 |
from huggingface_hub import hf_hub_download
|
|
@@ -85,11 +89,12 @@ story from the story marker.
|
|
| 85 |
|---|---|
|
| 86 |
| `N_STORIES` 20,000 → 100,000 | Noticeably better grammar and memory of characters |
|
| 87 |
| `MAX_STEPS` 1,500 → 5,000 | Lower loss; about 4 minutes on a T4 |
|
| 88 |
-
| `n_layer` 6 → 8, `n_embd` 256 → 384 | Bigger model (about
|
| 89 |
| More Momo stories, or your own text | The model writes about what it reads |
|
| 90 |
|
| 91 |
-
Watch **perplexity** in the training output. Random guessing is 4,096.
|
| 92 |
-
sentences. This recipe lands
|
|
|
|
| 93 |
|
| 94 |
## When something goes wrong
|
| 95 |
|
|
@@ -100,6 +105,8 @@ sentences. This recipe lands around 9.
|
|
| 100 |
- **Out of memory on a small GPU**: lower `BATCH_SIZE` in Part 7 to 16.
|
| 101 |
- **Stories are all about Lily**: the Momo stories are only a few percent of the data. Raise
|
| 102 |
the repeat factor in the Momo data cell from 3 to 6, or prompt with Momo's name.
|
|
|
|
|
|
|
| 103 |
|
| 104 |
## Rules of the road
|
| 105 |
|
|
|
|
| 7 |
## What you get
|
| 8 |
|
| 9 |
A 5.9-million-parameter GPT-style language model, trained from scratch on simple children's
|
| 10 |
+
stories (TinyStories) plus a thousand generated stories about Momo the monkey and Ella the
|
| 11 |
+
elephant. Give it the first few words and it continues with a short, simple story. It is a
|
| 12 |
+
learning project, not a product: expect charming nonsense now and then, and expect the Momo
|
| 13 |
+
stories to be recited from memory rather than invented (the notebook explains why).
|
| 14 |
|
| 15 |
## Path A: run it in Google Colab (no install, free GPU)
|
| 16 |
|
| 17 |
1. Open https://colab.research.google.com and choose **Upload notebook**.
|
| 18 |
2. Pick `tiny_llm_from_scratch.ipynb` (download it from this repo first).
|
| 19 |
3. In Colab go to **Runtime > Change runtime type** and choose **T4 GPU**.
|
| 20 |
+
4. Press **Run all**. Everything above the training section runs in well under a minute.
|
| 21 |
+
Training takes about 2 minutes on a T4. The whole notebook is about 5 minutes.
|
| 22 |
5. Scroll to **Part 8** to read the generated stories, and change the prompts to your own.
|
| 23 |
|
| 24 |
+
The publish cell in Part 9 uploads the model to your own Hugging Face account, as a
|
| 25 |
+
**private** repo. It needs a Hugging Face access token with write permission. The easiest way
|
| 26 |
+
on Colab: open the **Secrets** panel (the key icon on the left), add a secret called
|
| 27 |
+
`HF_TOKEN`, switch on notebook access, then run the cell. Without a token, set
|
| 28 |
+
`PUSH_TO_HUB = False` in the save cell just above it and the model is only saved locally.
|
| 29 |
|
| 30 |
## Path B: run it on your own computer
|
| 31 |
|
|
|
|
| 35 |
```bash
|
| 36 |
# 1. Python environment (any Python 3.10+; uv is fastest but pip works too)
|
| 37 |
uv venv --python 3.13 && source .venv/bin/activate
|
| 38 |
+
uv pip install torch transformers datasets tokenizers huggingface_hub nbformat nbconvert ipykernel jupyterlab
|
| 39 |
|
| 40 |
# 2. Run the notebook end to end (about 4 minutes on an M-series Mac)
|
| 41 |
jupyter nbconvert --to notebook --execute tiny_llm_from_scratch.ipynb --output run.ipynb
|
|
|
|
| 44 |
jupyter lab tiny_llm_from_scratch.ipynb
|
| 45 |
```
|
| 46 |
|
| 47 |
+
To publish from your machine, either run `hf auth login` once, or export `HF_TOKEN=hf_...`
|
| 48 |
+
in your shell before starting Jupyter. The notebook never prints the token.
|
| 49 |
|
| 50 |
## Path C: skip training, just use the model
|
| 51 |
|
| 52 |
+
The trained model lives on the Hugging Face Hub as `singhpratech/tiny-storyteller`. While
|
| 53 |
+
that repo is private you need its owner's token to download it; once it is public (or once
|
| 54 |
+
you have published your own copy, under your own name) the lines below work for anyone. The
|
| 55 |
+
notebook's Part 10, **Loading it back later**, has the full loader. In short:
|
| 56 |
|
| 57 |
```python
|
| 58 |
from huggingface_hub import hf_hub_download
|
|
|
|
| 89 |
|---|---|
|
| 90 |
| `N_STORIES` 20,000 → 100,000 | Noticeably better grammar and memory of characters |
|
| 91 |
| `MAX_STEPS` 1,500 → 5,000 | Lower loss; about 4 minutes on a T4 |
|
| 92 |
+
| `n_layer` 6 → 8, `n_embd` 256 → 384 | Bigger model (about 16M parameters), slower, better |
|
| 93 |
| More Momo stories, or your own text | The model writes about what it reads |
|
| 94 |
|
| 95 |
+
Watch **perplexity** in the training output. Random guessing is 4,096. Around 10 means real
|
| 96 |
+
sentences. This recipe lands at about 10 on the hidden quiz stories (200 TinyStories the
|
| 97 |
+
model never trains on, with no Momo stories in them, so the number is honest).
|
| 98 |
|
| 99 |
## When something goes wrong
|
| 100 |
|
|
|
|
| 105 |
- **Out of memory on a small GPU**: lower `BATCH_SIZE` in Part 7 to 16.
|
| 106 |
- **Stories are all about Lily**: the Momo stories are only a few percent of the data. Raise
|
| 107 |
the repeat factor in the Momo data cell from 3 to 6, or prompt with Momo's name.
|
| 108 |
+
- **Momo stories are recited word for word**: that is memorising. Add more scenes to the
|
| 109 |
+
sentence pools in `momo_stories.py` (more unique stories) and lower the repeat factor.
|
| 110 |
|
| 111 |
## Rules of the road
|
| 112 |
|
README.md
CHANGED
|
@@ -7,12 +7,14 @@ tags: [tiny, from-scratch, pytorch, educational, text-generation]
|
|
| 7 |
# Tiny Storyteller
|
| 8 |
|
| 9 |
A 5.9M-parameter GPT-style language model trained **from scratch** (random init, no pretrained weights)
|
| 10 |
-
on
|
|
|
|
|
|
|
| 11 |
|
| 12 |
- Architecture: 6 transformer blocks, 4 heads, 256-dim embeddings, 256-token context
|
| 13 |
- Tokenizer: byte-level BPE, 4,096 tokens, trained on the same data
|
| 14 |
- Training: 1500 steps, batch 32, AdamW, cosine schedule
|
| 15 |
-
- Final validation loss 2.
|
| 16 |
|
| 17 |
The full build, explained step by step, is in `tiny_llm_from_scratch.ipynb` in this repo.
|
| 18 |
Load with plain PyTorch: `GPT(cfg).load_state_dict(torch.load("model.pt"))`.
|
|
|
|
| 7 |
# Tiny Storyteller
|
| 8 |
|
| 9 |
A 5.9M-parameter GPT-style language model trained **from scratch** (random init, no pretrained weights)
|
| 10 |
+
on 19,800 TinyStories plus 3,000 short synthetic stories about two characters, Momo the monkey and
|
| 11 |
+
Ella the elephant (1,000 unique stories, each repeated 3 times, generated by `momo_stories.py`), as a learning project.
|
| 12 |
+
Use case: a bedtime story starter for young kids.
|
| 13 |
|
| 14 |
- Architecture: 6 transformer blocks, 4 heads, 256-dim embeddings, 256-token context
|
| 15 |
- Tokenizer: byte-level BPE, 4,096 tokens, trained on the same data
|
| 16 |
- Training: 1500 steps, batch 32, AdamW, cosine schedule
|
| 17 |
+
- Final validation loss 2.202 (perplexity 9.0) on 200 held-out TinyStories (no Momo stories in the validation set)
|
| 18 |
|
| 19 |
The full build, explained step by step, is in `tiny_llm_from_scratch.ipynb` in this repo.
|
| 20 |
Load with plain PyTorch: `GPT(cfg).load_state_dict(torch.load("model.pt"))`.
|
model.pt
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 23434075
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:75d4755f95c1e8bc4f051e38114bc28efa02b186e36b11c309840e5a7a157095
|
| 3 |
size 23434075
|
momo_stories.py
CHANGED
|
@@ -88,8 +88,15 @@ def make_story(rng: random.Random) -> str:
|
|
| 88 |
|
| 89 |
|
| 90 |
def momo_stories(n: int = 1000, seed: int = 0) -> list[str]:
|
|
|
|
| 91 |
rng = random.Random(seed)
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
|
| 95 |
if __name__ == "__main__":
|
|
|
|
| 88 |
|
| 89 |
|
| 90 |
def momo_stories(n: int = 1000, seed: int = 0) -> list[str]:
|
| 91 |
+
# n distinct stories: repeats from the pools are skipped, so "unique" really is unique.
|
| 92 |
rng = random.Random(seed)
|
| 93 |
+
out, seen = [], set()
|
| 94 |
+
while len(out) < n:
|
| 95 |
+
s = make_story(rng)
|
| 96 |
+
if s not in seen:
|
| 97 |
+
seen.add(s)
|
| 98 |
+
out.append(s)
|
| 99 |
+
return out
|
| 100 |
|
| 101 |
|
| 102 |
if __name__ == "__main__":
|
tiny_llm_from_scratch.ipynb
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|