Upload tiny_llm_from_scratch.ipynb with huggingface_hub
Browse files- tiny_llm_from_scratch.ipynb +193 -63
tiny_llm_from_scratch.ipynb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
"cells": [
|
| 3 |
{
|
| 4 |
"cell_type": "markdown",
|
| 5 |
-
"id": "
|
| 6 |
"metadata": {},
|
| 7 |
"source": [
|
| 8 |
"# Tiny Storyteller: building a language model from scratch\n",
|
|
@@ -44,7 +44,7 @@
|
|
| 44 |
},
|
| 45 |
{
|
| 46 |
"cell_type": "markdown",
|
| 47 |
-
"id": "
|
| 48 |
"metadata": {},
|
| 49 |
"source": [
|
| 50 |
"# Before any code: Momo, Ella, and what we are about to build\n",
|
|
@@ -67,7 +67,8 @@
|
|
| 67 |
"In grown-up words: Momo is the **model**. His dials are the **weights**, also called\n",
|
| 68 |
"**parameters**: the numbers that get adjusted during learning. Ella's stories are the\n",
|
| 69 |
"**training data**. Her \"how wrong were you\" is the **loss**. Her shelf is the **KV cache**.\n",
|
| 70 |
-
"
|
|
|
|
| 71 |
"\n",
|
| 72 |
"## 1. What is PyTorch?\n",
|
| 73 |
"\n",
|
|
@@ -82,8 +83,8 @@
|
|
| 82 |
" one called a T4.\n",
|
| 83 |
"- **A tape recorder**, called **autograd** (automatic gradients). While Momo works it writes\n",
|
| 84 |
" down every step. Afterwards it reads the tape backwards and tells Momo which way to turn\n",
|
| 85 |
-
" every dial, and by how much.
|
| 86 |
-
"
|
| 87 |
"\n",
|
| 88 |
"PyTorch was built at Meta's AI lab and is behind most famous models (the GPT family, Llama,\n",
|
| 89 |
"Stable Diffusion, Whisper). **Hugging Face**, where we publish at the end, is the public\n",
|
|
@@ -138,7 +139,7 @@
|
|
| 138 |
"say, 92 percent. One token is picked.\n",
|
| 139 |
"\n",
|
| 140 |
"**Step 5, repeat.** \"Paris\" is added to the words so far and the whole journey runs again for\n",
|
| 141 |
-
"the next token, until Momo picks a special \"
|
| 142 |
"on screen because that is literally how they are made.\n",
|
| 143 |
"\n",
|
| 144 |
"## 5. How attention looks things up: the story circle\n",
|
|
@@ -150,7 +151,9 @@
|
|
| 150 |
"- a **key** card: \"here is what I am\" (\"France\" says: I am a country),\n",
|
| 151 |
"- a **value** card: \"here is what I will tell you if you pick me\" (France's actual meaning).\n",
|
| 152 |
"\n",
|
| 153 |
-
"
|
|
|
|
|
|
|
| 154 |
"match scores high, a poor match scores low. The scores are squashed into percentages\n",
|
| 155 |
"(softmax again) and the animal collects a blend of everyone's value cards, weighted by those\n",
|
| 156 |
"percentages. \"capital\" might take 70 percent from \"France\", 20 percent from \"of\", and crumbs\n",
|
|
@@ -180,7 +183,10 @@
|
|
| 180 |
"token keeps its cards there. A model's **context window** (how much text it can hold at\n",
|
| 181 |
"once) is partly how big the shelf is allowed to grow.\n",
|
| 182 |
"\n",
|
| 183 |
-
"Part 5 shows the shelf in twelve lines of code.\n",
|
|
|
|
|
|
|
|
|
|
| 184 |
"\n",
|
| 185 |
"## 7. The strange names, decoded\n",
|
| 186 |
"\n",
|
|
@@ -233,7 +239,7 @@
|
|
| 233 |
},
|
| 234 |
{
|
| 235 |
"cell_type": "markdown",
|
| 236 |
-
"id": "
|
| 237 |
"metadata": {},
|
| 238 |
"source": [
|
| 239 |
"## Live flow diagram\n",
|
|
@@ -248,7 +254,7 @@
|
|
| 248 |
{
|
| 249 |
"cell_type": "code",
|
| 250 |
"execution_count": null,
|
| 251 |
-
"id": "
|
| 252 |
"metadata": {},
|
| 253 |
"outputs": [],
|
| 254 |
"source": [
|
|
@@ -373,7 +379,7 @@
|
|
| 373 |
},
|
| 374 |
{
|
| 375 |
"cell_type": "markdown",
|
| 376 |
-
"id": "
|
| 377 |
"metadata": {},
|
| 378 |
"source": [
|
| 379 |
"## 0. Setup\n",
|
|
@@ -383,7 +389,7 @@
|
|
| 383 |
{
|
| 384 |
"cell_type": "code",
|
| 385 |
"execution_count": null,
|
| 386 |
-
"id": "
|
| 387 |
"metadata": {},
|
| 388 |
"outputs": [],
|
| 389 |
"source": [
|
|
@@ -393,7 +399,7 @@
|
|
| 393 |
{
|
| 394 |
"cell_type": "code",
|
| 395 |
"execution_count": null,
|
| 396 |
-
"id": "
|
| 397 |
"metadata": {},
|
| 398 |
"outputs": [],
|
| 399 |
"source": [
|
|
@@ -410,7 +416,7 @@
|
|
| 410 |
},
|
| 411 |
{
|
| 412 |
"cell_type": "markdown",
|
| 413 |
-
"id": "
|
| 414 |
"metadata": {},
|
| 415 |
"source": [
|
| 416 |
"## 1. Tensors and gradients: the two building blocks\n",
|
|
@@ -429,7 +435,7 @@
|
|
| 429 |
{
|
| 430 |
"cell_type": "code",
|
| 431 |
"execution_count": null,
|
| 432 |
-
"id": "
|
| 433 |
"metadata": {},
|
| 434 |
"outputs": [],
|
| 435 |
"source": [
|
|
@@ -472,7 +478,7 @@
|
|
| 472 |
},
|
| 473 |
{
|
| 474 |
"cell_type": "markdown",
|
| 475 |
-
"id": "
|
| 476 |
"metadata": {},
|
| 477 |
"source": [
|
| 478 |
"### How matrix multiplication actually happens\n",
|
|
@@ -494,7 +500,7 @@
|
|
| 494 |
{
|
| 495 |
"cell_type": "code",
|
| 496 |
"execution_count": null,
|
| 497 |
-
"id": "
|
| 498 |
"metadata": {},
|
| 499 |
"outputs": [],
|
| 500 |
"source": [
|
|
@@ -551,7 +557,7 @@
|
|
| 551 |
{
|
| 552 |
"cell_type": "code",
|
| 553 |
"execution_count": null,
|
| 554 |
-
"id": "
|
| 555 |
"metadata": {},
|
| 556 |
"outputs": [],
|
| 557 |
"source": [
|
|
@@ -564,7 +570,7 @@
|
|
| 564 |
},
|
| 565 |
{
|
| 566 |
"cell_type": "markdown",
|
| 567 |
-
"id": "
|
| 568 |
"metadata": {},
|
| 569 |
"source": [
|
| 570 |
"### The gradient: which way to turn each dial\n",
|
|
@@ -587,7 +593,7 @@
|
|
| 587 |
{
|
| 588 |
"cell_type": "code",
|
| 589 |
"execution_count": null,
|
| 590 |
-
"id": "
|
| 591 |
"metadata": {},
|
| 592 |
"outputs": [],
|
| 593 |
"source": [
|
|
@@ -627,7 +633,7 @@
|
|
| 627 |
},
|
| 628 |
{
|
| 629 |
"cell_type": "markdown",
|
| 630 |
-
"id": "
|
| 631 |
"metadata": {},
|
| 632 |
"source": [
|
| 633 |
"### Momo in the foggy jungle: thorn bushes, marks, and the slope\n",
|
|
@@ -640,9 +646,9 @@
|
|
| 640 |
"dials. One step is one dial turn.\n",
|
| 641 |
"\n",
|
| 642 |
"**A thorn bush is a step that made things worse.** Momo tried a direction and the mistake\n",
|
| 643 |
-
"went up.
|
| 644 |
-
"
|
| 645 |
-
"back the
|
| 646 |
"\n",
|
| 647 |
"**What the gradient adds.** A real monkey learns a thorn bush is there by walking into it.\n",
|
| 648 |
"The gradient is better than that. It is the slope under the feet, felt *before* stepping.\n",
|
|
@@ -656,8 +662,9 @@
|
|
| 656 |
"- The reading was noisy. Each step uses one batch of stories, so the slope is an estimate.\n",
|
| 657 |
"\n",
|
| 658 |
"**The marks on the map are real, in two forms.**\n",
|
| 659 |
-
"- *The dials themselves.* Every step is written into the dials
|
| 660 |
-
"
|
|
|
|
| 661 |
"- *The optimizer's memory.* The dial-turning rule we use, **AdamW**, keeps a running average\n",
|
| 662 |
" of recent slopes. That is Momo remembering \"the last ten readings all said left, so one odd\n",
|
| 663 |
" reading saying right is probably a bump; keep going left\". One bush does not fool him.\n",
|
|
@@ -672,7 +679,7 @@
|
|
| 672 |
{
|
| 673 |
"cell_type": "code",
|
| 674 |
"execution_count": null,
|
| 675 |
-
"id": "
|
| 676 |
"metadata": {},
|
| 677 |
"outputs": [],
|
| 678 |
"source": [
|
|
@@ -782,7 +789,7 @@
|
|
| 782 |
},
|
| 783 |
{
|
| 784 |
"cell_type": "markdown",
|
| 785 |
-
"id": "
|
| 786 |
"metadata": {},
|
| 787 |
"source": [
|
| 788 |
"### How does Momo feel the slope without walking? The blame game\n",
|
|
@@ -805,14 +812,17 @@
|
|
| 805 |
"numbers are the gradient, found for all dials in one backward trip.\n",
|
| 806 |
"\n",
|
| 807 |
"Grown-up words: the tape is **autograd**, reading it backwards is **backpropagation**, and\n",
|
| 808 |
-
"\"multiply by how hard I push\" at each step is the **chain rule**.
|
|
|
|
|
|
|
|
|
|
| 809 |
"slow-way check lets you see that the backward trip tells the truth."
|
| 810 |
]
|
| 811 |
},
|
| 812 |
{
|
| 813 |
"cell_type": "code",
|
| 814 |
"execution_count": null,
|
| 815 |
-
"id": "
|
| 816 |
"metadata": {},
|
| 817 |
"outputs": [],
|
| 818 |
"source": [
|
|
@@ -913,7 +923,7 @@
|
|
| 913 |
{
|
| 914 |
"cell_type": "code",
|
| 915 |
"execution_count": null,
|
| 916 |
-
"id": "
|
| 917 |
"metadata": {},
|
| 918 |
"outputs": [],
|
| 919 |
"source": [
|
|
@@ -931,7 +941,7 @@
|
|
| 931 |
},
|
| 932 |
{
|
| 933 |
"cell_type": "markdown",
|
| 934 |
-
"id": "
|
| 935 |
"metadata": {},
|
| 936 |
"source": [
|
| 937 |
"## 2. Data: Ella's bedtime stories (TinyStories)\n",
|
|
@@ -947,7 +957,7 @@
|
|
| 947 |
{
|
| 948 |
"cell_type": "code",
|
| 949 |
"execution_count": null,
|
| 950 |
-
"id": "
|
| 951 |
"metadata": {},
|
| 952 |
"outputs": [],
|
| 953 |
"source": [
|
|
@@ -965,7 +975,125 @@
|
|
| 965 |
},
|
| 966 |
{
|
| 967 |
"cell_type": "markdown",
|
| 968 |
-
"id": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 969 |
"metadata": {},
|
| 970 |
"source": [
|
| 971 |
"## 3. Momo's first trick: the bigram\n",
|
|
@@ -986,7 +1114,7 @@
|
|
| 986 |
{
|
| 987 |
"cell_type": "code",
|
| 988 |
"execution_count": null,
|
| 989 |
-
"id": "
|
| 990 |
"metadata": {},
|
| 991 |
"outputs": [],
|
| 992 |
"source": [
|
|
@@ -1017,7 +1145,7 @@
|
|
| 1017 |
{
|
| 1018 |
"cell_type": "code",
|
| 1019 |
"execution_count": null,
|
| 1020 |
-
"id": "
|
| 1021 |
"metadata": {},
|
| 1022 |
"outputs": [],
|
| 1023 |
"source": [
|
|
@@ -1037,7 +1165,7 @@
|
|
| 1037 |
{
|
| 1038 |
"cell_type": "code",
|
| 1039 |
"execution_count": null,
|
| 1040 |
-
"id": "
|
| 1041 |
"metadata": {},
|
| 1042 |
"outputs": [],
|
| 1043 |
"source": [
|
|
@@ -1086,7 +1214,7 @@
|
|
| 1086 |
},
|
| 1087 |
{
|
| 1088 |
"cell_type": "markdown",
|
| 1089 |
-
"id": "
|
| 1090 |
"metadata": {},
|
| 1091 |
"source": [
|
| 1092 |
"Momo learned *something* (the loss dropped, and he produces word-ish shapes with spaces), but\n",
|
|
@@ -1096,7 +1224,7 @@
|
|
| 1096 |
},
|
| 1097 |
{
|
| 1098 |
"cell_type": "markdown",
|
| 1099 |
-
"id": "
|
| 1100 |
"metadata": {},
|
| 1101 |
"source": [
|
| 1102 |
"## 4. A real tokenizer: how Momo decides where to bite\n",
|
|
@@ -1121,7 +1249,7 @@
|
|
| 1121 |
{
|
| 1122 |
"cell_type": "code",
|
| 1123 |
"execution_count": null,
|
| 1124 |
-
"id": "
|
| 1125 |
"metadata": {},
|
| 1126 |
"outputs": [],
|
| 1127 |
"source": [
|
|
@@ -1151,7 +1279,7 @@
|
|
| 1151 |
{
|
| 1152 |
"cell_type": "code",
|
| 1153 |
"execution_count": null,
|
| 1154 |
-
"id": "
|
| 1155 |
"metadata": {},
|
| 1156 |
"outputs": [],
|
| 1157 |
"source": [
|
|
@@ -1177,7 +1305,7 @@
|
|
| 1177 |
{
|
| 1178 |
"cell_type": "code",
|
| 1179 |
"execution_count": null,
|
| 1180 |
-
"id": "
|
| 1181 |
"metadata": {},
|
| 1182 |
"outputs": [],
|
| 1183 |
"source": [
|
|
@@ -1191,7 +1319,7 @@
|
|
| 1191 |
},
|
| 1192 |
{
|
| 1193 |
"cell_type": "markdown",
|
| 1194 |
-
"id": "
|
| 1195 |
"metadata": {},
|
| 1196 |
"source": [
|
| 1197 |
"## 5. Attention, by hand: the story circle in numbers\n",
|
|
@@ -1213,7 +1341,7 @@
|
|
| 1213 |
{
|
| 1214 |
"cell_type": "code",
|
| 1215 |
"execution_count": null,
|
| 1216 |
-
"id": "
|
| 1217 |
"metadata": {},
|
| 1218 |
"outputs": [],
|
| 1219 |
"source": [
|
|
@@ -1237,7 +1365,7 @@
|
|
| 1237 |
},
|
| 1238 |
{
|
| 1239 |
"cell_type": "markdown",
|
| 1240 |
-
"id": "
|
| 1241 |
"metadata": {},
|
| 1242 |
"source": [
|
| 1243 |
"### Ella's shelf (the KV cache), in twelve lines\n",
|
|
@@ -1251,7 +1379,7 @@
|
|
| 1251 |
{
|
| 1252 |
"cell_type": "code",
|
| 1253 |
"execution_count": null,
|
| 1254 |
-
"id": "
|
| 1255 |
"metadata": {},
|
| 1256 |
"outputs": [],
|
| 1257 |
"source": [
|
|
@@ -1281,7 +1409,7 @@
|
|
| 1281 |
},
|
| 1282 |
{
|
| 1283 |
"cell_type": "markdown",
|
| 1284 |
-
"id": "
|
| 1285 |
"metadata": {},
|
| 1286 |
"source": [
|
| 1287 |
"## 6. A tiny GPT: Momo's whole head\n",
|
|
@@ -1298,7 +1426,8 @@
|
|
| 1298 |
"3. **Blocks**, repeated `n_layer` times (6 branches of the tree). Each block has:\n",
|
| 1299 |
" - **multi-head attention**: the story circle, run 4 times at once with different cards;\n",
|
| 1300 |
" - a **feed-forward network**: after listening to everyone, each token goes off to its own\n",
|
| 1301 |
-
" branch and thinks alone (a small two-layer network
|
|
|
|
| 1302 |
" - **LayerNorm** (Ella keeping the numbers at a steady volume) and **residual connections**\n",
|
| 1303 |
" (each block *adds* its thoughts to what came in instead of replacing it, so nothing is\n",
|
| 1304 |
" lost on the way up the tree).\n",
|
|
@@ -1313,7 +1442,7 @@
|
|
| 1313 |
{
|
| 1314 |
"cell_type": "code",
|
| 1315 |
"execution_count": null,
|
| 1316 |
-
"id": "
|
| 1317 |
"metadata": {},
|
| 1318 |
"outputs": [],
|
| 1319 |
"source": [
|
|
@@ -1357,7 +1486,7 @@
|
|
| 1357 |
{
|
| 1358 |
"cell_type": "code",
|
| 1359 |
"execution_count": null,
|
| 1360 |
-
"id": "
|
| 1361 |
"metadata": {},
|
| 1362 |
"outputs": [],
|
| 1363 |
"source": [
|
|
@@ -1468,7 +1597,7 @@
|
|
| 1468 |
},
|
| 1469 |
{
|
| 1470 |
"cell_type": "markdown",
|
| 1471 |
-
"id": "
|
| 1472 |
"metadata": {},
|
| 1473 |
"source": [
|
| 1474 |
"## 7. Training: Ella's bedtime lessons\n",
|
|
@@ -1497,7 +1626,7 @@
|
|
| 1497 |
{
|
| 1498 |
"cell_type": "code",
|
| 1499 |
"execution_count": null,
|
| 1500 |
-
"id": "
|
| 1501 |
"metadata": {},
|
| 1502 |
"outputs": [],
|
| 1503 |
"source": [
|
|
@@ -1539,7 +1668,7 @@
|
|
| 1539 |
{
|
| 1540 |
"cell_type": "code",
|
| 1541 |
"execution_count": null,
|
| 1542 |
-
"id": "
|
| 1543 |
"metadata": {},
|
| 1544 |
"outputs": [],
|
| 1545 |
"source": [
|
|
@@ -1606,7 +1735,7 @@
|
|
| 1606 |
},
|
| 1607 |
{
|
| 1608 |
"cell_type": "markdown",
|
| 1609 |
-
"id": "
|
| 1610 |
"metadata": {},
|
| 1611 |
"source": [
|
| 1612 |
"**How to read the numbers.** The loss is Ella's average \"how surprised were you\" per token.\n",
|
|
@@ -1617,7 +1746,7 @@
|
|
| 1617 |
},
|
| 1618 |
{
|
| 1619 |
"cell_type": "markdown",
|
| 1620 |
-
"id": "
|
| 1621 |
"metadata": {},
|
| 1622 |
"source": [
|
| 1623 |
"## 8. Momo tells a story: the use case\n",
|
|
@@ -1635,13 +1764,14 @@
|
|
| 1635 |
{
|
| 1636 |
"cell_type": "code",
|
| 1637 |
"execution_count": null,
|
| 1638 |
-
"id": "
|
| 1639 |
"metadata": {},
|
| 1640 |
"outputs": [],
|
| 1641 |
"source": [
|
| 1642 |
"def tell_story(prompt, max_new_tokens=200, temperature=0.8):\n",
|
| 1643 |
" model.eval()\n",
|
| 1644 |
-
"
|
|
|
|
| 1645 |
" out = model.generate(idx, max_new_tokens, temperature=temperature)\n",
|
| 1646 |
" return tokenizer.decode(out[0].tolist(), skip_special_tokens=True)\n",
|
| 1647 |
"\n",
|
|
@@ -1652,7 +1782,7 @@
|
|
| 1652 |
},
|
| 1653 |
{
|
| 1654 |
"cell_type": "markdown",
|
| 1655 |
-
"id": "
|
| 1656 |
"metadata": {},
|
| 1657 |
"source": [
|
| 1658 |
"## 9. Put Momo's book in the library: the Hugging Face Hub\n",
|
|
@@ -1671,7 +1801,7 @@
|
|
| 1671 |
{
|
| 1672 |
"cell_type": "code",
|
| 1673 |
"execution_count": null,
|
| 1674 |
-
"id": "
|
| 1675 |
"metadata": {},
|
| 1676 |
"outputs": [],
|
| 1677 |
"source": [
|
|
@@ -1712,7 +1842,7 @@
|
|
| 1712 |
{
|
| 1713 |
"cell_type": "code",
|
| 1714 |
"execution_count": null,
|
| 1715 |
-
"id": "
|
| 1716 |
"metadata": {},
|
| 1717 |
"outputs": [],
|
| 1718 |
"source": [
|
|
@@ -1733,7 +1863,7 @@
|
|
| 1733 |
},
|
| 1734 |
{
|
| 1735 |
"cell_type": "markdown",
|
| 1736 |
-
"id": "
|
| 1737 |
"metadata": {},
|
| 1738 |
"source": [
|
| 1739 |
"## Loading it back later\n",
|
|
@@ -1744,7 +1874,7 @@
|
|
| 1744 |
{
|
| 1745 |
"cell_type": "code",
|
| 1746 |
"execution_count": null,
|
| 1747 |
-
"id": "
|
| 1748 |
"metadata": {},
|
| 1749 |
"outputs": [],
|
| 1750 |
"source": [
|
|
@@ -1765,7 +1895,7 @@
|
|
| 1765 |
},
|
| 1766 |
{
|
| 1767 |
"cell_type": "markdown",
|
| 1768 |
-
"id": "
|
| 1769 |
"metadata": {},
|
| 1770 |
"source": [
|
| 1771 |
"## What we built, in one paragraph\n",
|
|
|
|
| 2 |
"cells": [
|
| 3 |
{
|
| 4 |
"cell_type": "markdown",
|
| 5 |
+
"id": "b2fe09d4",
|
| 6 |
"metadata": {},
|
| 7 |
"source": [
|
| 8 |
"# Tiny Storyteller: building a language model from scratch\n",
|
|
|
|
| 44 |
},
|
| 45 |
{
|
| 46 |
"cell_type": "markdown",
|
| 47 |
+
"id": "c4f48f79",
|
| 48 |
"metadata": {},
|
| 49 |
"source": [
|
| 50 |
"# Before any code: Momo, Ella, and what we are about to build\n",
|
|
|
|
| 67 |
"In grown-up words: Momo is the **model**. His dials are the **weights**, also called\n",
|
| 68 |
"**parameters**: the numbers that get adjusted during learning. Ella's stories are the\n",
|
| 69 |
"**training data**. Her \"how wrong were you\" is the **loss**. Her shelf is the **KV cache**.\n",
|
| 70 |
+
"Ella plays two roles on purpose: the teacher while Momo learns (training), and the memory\n",
|
| 71 |
+
"while Momo writes (generation). Each of these gets its own section below.\n",
|
| 72 |
"\n",
|
| 73 |
"## 1. What is PyTorch?\n",
|
| 74 |
"\n",
|
|
|
|
| 83 |
" one called a T4.\n",
|
| 84 |
"- **A tape recorder**, called **autograd** (automatic gradients). While Momo works it writes\n",
|
| 85 |
" down every step. Afterwards it reads the tape backwards and tells Momo which way to turn\n",
|
| 86 |
+
" every dial, and by how much. Ordinary programs do not do this, and it is the reason modern AI\n",
|
| 87 |
+
" is practical at all. Part 1 has a game that shows exactly how the tape is read.\n",
|
| 88 |
"\n",
|
| 89 |
"PyTorch was built at Meta's AI lab and is behind most famous models (the GPT family, Llama,\n",
|
| 90 |
"Stable Diffusion, Whisper). **Hugging Face**, where we publish at the end, is the public\n",
|
|
|
|
| 139 |
"say, 92 percent. One token is picked.\n",
|
| 140 |
"\n",
|
| 141 |
"**Step 5, repeat.** \"Paris\" is added to the words so far and the whole journey runs again for\n",
|
| 142 |
+
"the next token, until Momo picks a special \"the story is over\" token or reaches the length limit. You see words appear one by one\n",
|
| 143 |
"on screen because that is literally how they are made.\n",
|
| 144 |
"\n",
|
| 145 |
"## 5. How attention looks things up: the story circle\n",
|
|
|
|
| 151 |
"- a **key** card: \"here is what I am\" (\"France\" says: I am a country),\n",
|
| 152 |
"- a **value** card: \"here is what I will tell you if you pick me\" (France's actual meaning).\n",
|
| 153 |
"\n",
|
| 154 |
+
"Every animal holds up its query card and compares it with the key cards of the animals\n",
|
| 155 |
+
"before it (during training all of them do this at the same time; when writing, only the\n",
|
| 156 |
+
"newest one needs to). A good\n",
|
| 157 |
"match scores high, a poor match scores low. The scores are squashed into percentages\n",
|
| 158 |
"(softmax again) and the animal collects a blend of everyone's value cards, weighted by those\n",
|
| 159 |
"percentages. \"capital\" might take 70 percent from \"France\", 20 percent from \"of\", and crumbs\n",
|
|
|
|
| 183 |
"token keeps its cards there. A model's **context window** (how much text it can hold at\n",
|
| 184 |
"once) is partly how big the shelf is allowed to grow.\n",
|
| 185 |
"\n",
|
| 186 |
+
"Part 5 shows the shelf in twelve lines of code. Two honest notes: the shelf is emptied at the\n",
|
| 187 |
+
"start of every new story (it is a memory *within* one piece of writing, not between stories),\n",
|
| 188 |
+
"and Momo's own `generate` in Part 6 does not use it, to keep the code short. It redoes the\n",
|
| 189 |
+
"whole journey for every word, which is fine for 200-word stories.\n",
|
| 190 |
"\n",
|
| 191 |
"## 7. The strange names, decoded\n",
|
| 192 |
"\n",
|
|
|
|
| 239 |
},
|
| 240 |
{
|
| 241 |
"cell_type": "markdown",
|
| 242 |
+
"id": "4d7312e3",
|
| 243 |
"metadata": {},
|
| 244 |
"source": [
|
| 245 |
"## Live flow diagram\n",
|
|
|
|
| 254 |
{
|
| 255 |
"cell_type": "code",
|
| 256 |
"execution_count": null,
|
| 257 |
+
"id": "cdae01ca",
|
| 258 |
"metadata": {},
|
| 259 |
"outputs": [],
|
| 260 |
"source": [
|
|
|
|
| 379 |
},
|
| 380 |
{
|
| 381 |
"cell_type": "markdown",
|
| 382 |
+
"id": "94499493",
|
| 383 |
"metadata": {},
|
| 384 |
"source": [
|
| 385 |
"## 0. Setup\n",
|
|
|
|
| 389 |
{
|
| 390 |
"cell_type": "code",
|
| 391 |
"execution_count": null,
|
| 392 |
+
"id": "0fe52b75",
|
| 393 |
"metadata": {},
|
| 394 |
"outputs": [],
|
| 395 |
"source": [
|
|
|
|
| 399 |
{
|
| 400 |
"cell_type": "code",
|
| 401 |
"execution_count": null,
|
| 402 |
+
"id": "cf74d97b",
|
| 403 |
"metadata": {},
|
| 404 |
"outputs": [],
|
| 405 |
"source": [
|
|
|
|
| 416 |
},
|
| 417 |
{
|
| 418 |
"cell_type": "markdown",
|
| 419 |
+
"id": "30cd04b6",
|
| 420 |
"metadata": {},
|
| 421 |
"source": [
|
| 422 |
"## 1. Tensors and gradients: the two building blocks\n",
|
|
|
|
| 435 |
{
|
| 436 |
"cell_type": "code",
|
| 437 |
"execution_count": null,
|
| 438 |
+
"id": "7fd75d97",
|
| 439 |
"metadata": {},
|
| 440 |
"outputs": [],
|
| 441 |
"source": [
|
|
|
|
| 478 |
},
|
| 479 |
{
|
| 480 |
"cell_type": "markdown",
|
| 481 |
+
"id": "6d9343cc",
|
| 482 |
"metadata": {},
|
| 483 |
"source": [
|
| 484 |
"### How matrix multiplication actually happens\n",
|
|
|
|
| 500 |
{
|
| 501 |
"cell_type": "code",
|
| 502 |
"execution_count": null,
|
| 503 |
+
"id": "88849be7",
|
| 504 |
"metadata": {},
|
| 505 |
"outputs": [],
|
| 506 |
"source": [
|
|
|
|
| 557 |
{
|
| 558 |
"cell_type": "code",
|
| 559 |
"execution_count": null,
|
| 560 |
+
"id": "c1522ad3",
|
| 561 |
"metadata": {},
|
| 562 |
"outputs": [],
|
| 563 |
"source": [
|
|
|
|
| 570 |
},
|
| 571 |
{
|
| 572 |
"cell_type": "markdown",
|
| 573 |
+
"id": "59188275",
|
| 574 |
"metadata": {},
|
| 575 |
"source": [
|
| 576 |
"### The gradient: which way to turn each dial\n",
|
|
|
|
| 593 |
{
|
| 594 |
"cell_type": "code",
|
| 595 |
"execution_count": null,
|
| 596 |
+
"id": "4e4aef04",
|
| 597 |
"metadata": {},
|
| 598 |
"outputs": [],
|
| 599 |
"source": [
|
|
|
|
| 633 |
},
|
| 634 |
{
|
| 635 |
"cell_type": "markdown",
|
| 636 |
+
"id": "b4ec1642",
|
| 637 |
"metadata": {},
|
| 638 |
"source": [
|
| 639 |
"### Momo in the foggy jungle: thorn bushes, marks, and the slope\n",
|
|
|
|
| 646 |
"dials. One step is one dial turn.\n",
|
| 647 |
"\n",
|
| 648 |
"**A thorn bush is a step that made things worse.** Momo tried a direction and the mistake\n",
|
| 649 |
+
"went up. In the widget he steps back and marks the spot with a red X. Real training is blunter: it\n",
|
| 650 |
+
"never steps back. Momo stays where he landed, reads the slope again, and the slope now points\n",
|
| 651 |
+
"back downhill. The correction comes from the next reading, not from undoing the step.\n",
|
| 652 |
"\n",
|
| 653 |
"**What the gradient adds.** A real monkey learns a thorn bush is there by walking into it.\n",
|
| 654 |
"The gradient is better than that. It is the slope under the feet, felt *before* stepping.\n",
|
|
|
|
| 662 |
"- The reading was noisy. Each step uses one batch of stories, so the slope is an estimate.\n",
|
| 663 |
"\n",
|
| 664 |
"**The marks on the map are real, in two forms.**\n",
|
| 665 |
+
"- *The dials themselves.* Every step is written into the dials. There is no separate map;\n",
|
| 666 |
+
" after training Momo *is* the map. (Later lessons can partly overwrite earlier ones, which\n",
|
| 667 |
+
" is why the stories are shuffled and why the last steps are tiny.)\n",
|
| 668 |
"- *The optimizer's memory.* The dial-turning rule we use, **AdamW**, keeps a running average\n",
|
| 669 |
" of recent slopes. That is Momo remembering \"the last ten readings all said left, so one odd\n",
|
| 670 |
" reading saying right is probably a bump; keep going left\". One bush does not fool him.\n",
|
|
|
|
| 679 |
{
|
| 680 |
"cell_type": "code",
|
| 681 |
"execution_count": null,
|
| 682 |
+
"id": "73a8941e",
|
| 683 |
"metadata": {},
|
| 684 |
"outputs": [],
|
| 685 |
"source": [
|
|
|
|
| 789 |
},
|
| 790 |
{
|
| 791 |
"cell_type": "markdown",
|
| 792 |
+
"id": "a6a84861",
|
| 793 |
"metadata": {},
|
| 794 |
"source": [
|
| 795 |
"### How does Momo feel the slope without walking? The blame game\n",
|
|
|
|
| 812 |
"numbers are the gradient, found for all dials in one backward trip.\n",
|
| 813 |
"\n",
|
| 814 |
"Grown-up words: the tape is **autograd**, reading it backwards is **backpropagation**, and\n",
|
| 815 |
+
"\"multiply by how hard I push\" at each step is the **chain rule**. One detail the game leaves\n",
|
| 816 |
+
"out: when one step feeds *two* later steps (our residual connections do this), the two blames\n",
|
| 817 |
+
"are added together. And the game's mistake is a squared gap; the real Momo uses cross-entropy.\n",
|
| 818 |
+
"Same game, different first step. Press each stage below. The\n",
|
| 819 |
"slow-way check lets you see that the backward trip tells the truth."
|
| 820 |
]
|
| 821 |
},
|
| 822 |
{
|
| 823 |
"cell_type": "code",
|
| 824 |
"execution_count": null,
|
| 825 |
+
"id": "acb78f06",
|
| 826 |
"metadata": {},
|
| 827 |
"outputs": [],
|
| 828 |
"source": [
|
|
|
|
| 923 |
{
|
| 924 |
"cell_type": "code",
|
| 925 |
"execution_count": null,
|
| 926 |
+
"id": "39d72d64",
|
| 927 |
"metadata": {},
|
| 928 |
"outputs": [],
|
| 929 |
"source": [
|
|
|
|
| 941 |
},
|
| 942 |
{
|
| 943 |
"cell_type": "markdown",
|
| 944 |
+
"id": "24e1da8f",
|
| 945 |
"metadata": {},
|
| 946 |
"source": [
|
| 947 |
"## 2. Data: Ella's bedtime stories (TinyStories)\n",
|
|
|
|
| 957 |
{
|
| 958 |
"cell_type": "code",
|
| 959 |
"execution_count": null,
|
| 960 |
+
"id": "ebb5d3e6",
|
| 961 |
"metadata": {},
|
| 962 |
"outputs": [],
|
| 963 |
"source": [
|
|
|
|
| 975 |
},
|
| 976 |
{
|
| 977 |
"cell_type": "markdown",
|
| 978 |
+
"id": "b9bf532d",
|
| 979 |
+
"metadata": {},
|
| 980 |
+
"source": [
|
| 981 |
+
"### Ella's own stories about Momo\n",
|
| 982 |
+
"\n",
|
| 983 |
+
"TinyStories is full of Lily, Tom and their mums. If we want Momo and Ella to show up when the\n",
|
| 984 |
+
"model writes, the model has to *read* about them. So we add a few hundred short stories about\n",
|
| 985 |
+
"our two characters, built from sentence pools in the same simple style (every story has an\n",
|
| 986 |
+
"opening, Ella's introduction, a small problem, Ella helping, a resolution and an ending). We\n",
|
| 987 |
+
"repeat them three times so they are not drowned out by the 20,000 other stories. This is\n",
|
| 988 |
+
"exactly how a real model is taught a company's own documents: mix them into the training text."
|
| 989 |
+
]
|
| 990 |
+
},
|
| 991 |
+
{
|
| 992 |
+
"cell_type": "code",
|
| 993 |
+
"execution_count": null,
|
| 994 |
+
"id": "40a20bc2",
|
| 995 |
+
"metadata": {},
|
| 996 |
+
"outputs": [],
|
| 997 |
+
"source": [
|
| 998 |
+
"# Momo and Ella stories, built from sentence pools. Same code as scripts/momo_stories.py in the repo.\n",
|
| 999 |
+
"import random\n",
|
| 1000 |
+
"\n",
|
| 1001 |
+
"PLACES = [\"by the river\", \"under the big mango tree\", \"in the green jungle\", \"at the waterfall\",\n",
|
| 1002 |
+
" \"on the sunny hill\", \"near the little pond\", \"in the tall grass\", \"by the old rock\"]\n",
|
| 1003 |
+
"THINGS = [\"a shiny red ball\", \"a yellow banana\", \"a big green leaf\", \"a round grey stone\",\n",
|
| 1004 |
+
" \"a blue feather\", \"a little drum\", \"a brown coconut\", \"a soft pink flower\",\n",
|
| 1005 |
+
" \"a long stick\", \"a red kite\"]\n",
|
| 1006 |
+
"FRIENDS = [\"Pip the parrot\", \"Tilly the turtle\", \"Bo the bear cub\", \"Lulu the little lion\"]\n",
|
| 1007 |
+
"FOODS = [\"bananas\", \"mangoes\", \"sweet berries\", \"coconuts\", \"crunchy leaves\"]\n",
|
| 1008 |
+
"\n",
|
| 1009 |
+
"OPENINGS = [\n",
|
| 1010 |
+
" \"Once upon a time, there was a little monkey named Momo.\",\n",
|
| 1011 |
+
" \"Momo was a little monkey who lived {place}.\",\n",
|
| 1012 |
+
" \"One day, Momo the monkey woke up very early.\",\n",
|
| 1013 |
+
" \"Momo was a small monkey with a big smile.\",\n",
|
| 1014 |
+
" \"In the jungle there lived a little monkey called Momo.\",\n",
|
| 1015 |
+
" \"Every morning, Momo the monkey jumped out of his tree.\",\n",
|
| 1016 |
+
"]\n",
|
| 1017 |
+
"ELLA_INTRO = [\n",
|
| 1018 |
+
" \"His best friend was Ella, a big grey elephant.\",\n",
|
| 1019 |
+
" \"Ella the elephant was his best friend. Ella never forgot anything.\",\n",
|
| 1020 |
+
" \"He loved his friend Ella. Ella was an elephant, and she remembered everything.\",\n",
|
| 1021 |
+
" \"Ella the elephant was big and kind and very wise.\",\n",
|
| 1022 |
+
" \"His friend Ella was an elephant with a long trunk and a good memory.\",\n",
|
| 1023 |
+
"]\n",
|
| 1024 |
+
"# Each scene: (problem, Ella helps, resolution). They always go together.\n",
|
| 1025 |
+
"SCENES = [\n",
|
| 1026 |
+
" (\"Momo wanted to play with {thing}, but he could not find it. He looked {place}. It was not there. He felt sad.\",\n",
|
| 1027 |
+
" \"Ella came slowly. \\\"Do not worry, Momo,\\\" she said. \\\"I remember. You left it {place2}.\\\"\",\n",
|
| 1028 |
+
" \"Momo ran and found {thing} right where Ella said. He hugged her trunk.\"),\n",
|
| 1029 |
+
" (\"Momo climbed very high to get {thing}. Then he looked down and felt scared. \\\"I cannot get down!\\\" he cried.\",\n",
|
| 1030 |
+
" \"Ella walked under the tree and lifted her trunk. \\\"I am here,\\\" she said. \\\"You are safe. Come down slowly.\\\"\",\n",
|
| 1031 |
+
" \"Momo climbed down step by step and jumped into Ella's arms.\"),\n",
|
| 1032 |
+
" (\"It started to rain. Momo got wet and cold. He hid {place} and shivered.\",\n",
|
| 1033 |
+
" \"Ella held a big leaf over Momo like an umbrella. \\\"Stay dry, my friend,\\\" she said.\",\n",
|
| 1034 |
+
" \"The rain stopped. The sun came out. Momo and Ella walked home together.\"),\n",
|
| 1035 |
+
" (\"Momo met {friend} {place}. {friend_short} had {thing} and did not want to share. Momo felt sad.\",\n",
|
| 1036 |
+
" \"Ella walked over and said, \\\"Let us all play together. Sharing makes everyone happy.\\\"\",\n",
|
| 1037 |
+
" \"Momo and {friend_short} became friends and played with {thing} all day.\"),\n",
|
| 1038 |
+
" (\"Momo tried to count his {food}. \\\"One, two, three...\\\" Then he forgot the next number.\",\n",
|
| 1039 |
+
" \"Ella said, \\\"After three comes four. I will count with you.\\\" They counted together.\",\n",
|
| 1040 |
+
" \"Momo counted all the way to ten. Ella was very proud.\"),\n",
|
| 1041 |
+
" (\"Momo had a bad dream. He woke up scared and ran to find Ella.\",\n",
|
| 1042 |
+
" \"Ella sat with Momo until he felt better. \\\"Being scared is okay,\\\" she said. \\\"I am right here.\\\"\",\n",
|
| 1043 |
+
" \"Momo fell asleep next to Ella and had happy dreams.\"),\n",
|
| 1044 |
+
" (\"Momo wanted to tell a story, but he did not know how to start. He sat down {place} and thought and thought.\",\n",
|
| 1045 |
+
" \"Ella said, \\\"Start with 'Once upon a time'. Then say what happens next. One word at a time.\\\"\",\n",
|
| 1046 |
+
" \"Momo told his first story. It was about {thing}. Ella clapped her big ears.\"),\n",
|
| 1047 |
+
" (\"Momo saw a big shadow {place}. He thought it was a monster. He hid behind {thing}.\",\n",
|
| 1048 |
+
" \"Ella laughed softly. \\\"That shadow is only me,\\\" she said. Momo peeked out and laughed too.\",\n",
|
| 1049 |
+
" \"They played shadow games until the sun went down.\"),\n",
|
| 1050 |
+
" (\"Momo was sad because he could not swim like {friend}. He sat {place} with his feet in the water.\",\n",
|
| 1051 |
+
" \"Ella said, \\\"Try again, little one. Every time you try, you learn a little more.\\\" She held him up with her trunk.\",\n",
|
| 1052 |
+
" \"Momo kicked and kicked. Soon he could swim all by himself.\"),\n",
|
| 1053 |
+
" (\"Momo and Ella went {place} to look for {food}. They looked and looked, but they found none.\",\n",
|
| 1054 |
+
" \"Ella thought for a moment. Elephants never forget. \\\"I know a secret place,\\\" she said.\",\n",
|
| 1055 |
+
" \"They found lots of {food} and ate them together under the stars.\"),\n",
|
| 1056 |
+
" (\"Momo broke {thing} that belonged to {friend}. He hid it and felt bad all day.\",\n",
|
| 1057 |
+
" \"Ella said, \\\"A true friend says sorry. Go and tell {friend_short}.\\\"\",\n",
|
| 1058 |
+
" \"Momo said sorry. {friend_short} smiled and said, \\\"We can fix it together.\\\"\"),\n",
|
| 1059 |
+
" (\"Momo wanted to be big like Ella. He stood on {thing} and stretched, but he was still small.\",\n",
|
| 1060 |
+
" \"Ella smiled. \\\"You are small, but you can climb and jump and I cannot,\\\" she said. \\\"We are different, and that is good.\\\"\",\n",
|
| 1061 |
+
" \"Momo climbed to the top of the tree and threw {food} down to Ella. They both laughed.\"),\n",
|
| 1062 |
+
"]\n",
|
| 1063 |
+
"ENDINGS = [\n",
|
| 1064 |
+
" \"The end.\",\n",
|
| 1065 |
+
" \"Momo was happy. Ella was happy. The end.\",\n",
|
| 1066 |
+
" \"And they were best friends forever. The end.\",\n",
|
| 1067 |
+
" \"\\\"Thank you, Ella,\\\" said Momo. \\\"You always remember.\\\" The end.\",\n",
|
| 1068 |
+
" \"That night, Momo dreamed about his friend Ella. The end.\",\n",
|
| 1069 |
+
"]\n",
|
| 1070 |
+
"\n",
|
| 1071 |
+
"\n",
|
| 1072 |
+
"def make_story(rng: random.Random) -> str:\n",
|
| 1073 |
+
" friend = rng.choice(FRIENDS)\n",
|
| 1074 |
+
" place, place2 = rng.sample(PLACES, 2)\n",
|
| 1075 |
+
" slots = dict(place=place, place2=place2, thing=rng.choice(THINGS), friend=friend,\n",
|
| 1076 |
+
" friend_short=friend.split(\" the \")[0], food=rng.choice(FOODS))\n",
|
| 1077 |
+
" problem, helps, resolution = rng.choice(SCENES)\n",
|
| 1078 |
+
" parts = [rng.choice(OPENINGS), rng.choice(ELLA_INTRO), problem, helps, resolution, rng.choice(ENDINGS)]\n",
|
| 1079 |
+
" return \" \".join(p.format(**slots) for p in parts)\n",
|
| 1080 |
+
"\n",
|
| 1081 |
+
"\n",
|
| 1082 |
+
"def momo_stories(n: int = 1000, seed: int = 0) -> list[str]:\n",
|
| 1083 |
+
" rng = random.Random(seed)\n",
|
| 1084 |
+
" return [make_story(rng) for _ in range(n)]\n",
|
| 1085 |
+
"\n",
|
| 1086 |
+
"momo = momo_stories(1000, seed=0)\n",
|
| 1087 |
+
"stories = stories + momo * 3 # 20,000 TinyStories + 3,000 Momo stories (1,000 unique)\n",
|
| 1088 |
+
"import random; random.Random(42).shuffle(stories)\n",
|
| 1089 |
+
"print(f\"{len(stories):,} stories in total, {len(momo):,} unique Momo stories\")\n",
|
| 1090 |
+
"print(\"-\" * 60)\n",
|
| 1091 |
+
"print(momo[0])"
|
| 1092 |
+
]
|
| 1093 |
+
},
|
| 1094 |
+
{
|
| 1095 |
+
"cell_type": "markdown",
|
| 1096 |
+
"id": "1b3fc1b7",
|
| 1097 |
"metadata": {},
|
| 1098 |
"source": [
|
| 1099 |
"## 3. Momo's first trick: the bigram\n",
|
|
|
|
| 1114 |
{
|
| 1115 |
"cell_type": "code",
|
| 1116 |
"execution_count": null,
|
| 1117 |
+
"id": "d7c45f72",
|
| 1118 |
"metadata": {},
|
| 1119 |
"outputs": [],
|
| 1120 |
"source": [
|
|
|
|
| 1145 |
{
|
| 1146 |
"cell_type": "code",
|
| 1147 |
"execution_count": null,
|
| 1148 |
+
"id": "3a50e68a",
|
| 1149 |
"metadata": {},
|
| 1150 |
"outputs": [],
|
| 1151 |
"source": [
|
|
|
|
| 1165 |
{
|
| 1166 |
"cell_type": "code",
|
| 1167 |
"execution_count": null,
|
| 1168 |
+
"id": "942d14ad",
|
| 1169 |
"metadata": {},
|
| 1170 |
"outputs": [],
|
| 1171 |
"source": [
|
|
|
|
| 1214 |
},
|
| 1215 |
{
|
| 1216 |
"cell_type": "markdown",
|
| 1217 |
+
"id": "55fb61d0",
|
| 1218 |
"metadata": {},
|
| 1219 |
"source": [
|
| 1220 |
"Momo learned *something* (the loss dropped, and he produces word-ish shapes with spaces), but\n",
|
|
|
|
| 1224 |
},
|
| 1225 |
{
|
| 1226 |
"cell_type": "markdown",
|
| 1227 |
+
"id": "b287c96b",
|
| 1228 |
"metadata": {},
|
| 1229 |
"source": [
|
| 1230 |
"## 4. A real tokenizer: how Momo decides where to bite\n",
|
|
|
|
| 1249 |
{
|
| 1250 |
"cell_type": "code",
|
| 1251 |
"execution_count": null,
|
| 1252 |
+
"id": "6cc8a788",
|
| 1253 |
"metadata": {},
|
| 1254 |
"outputs": [],
|
| 1255 |
"source": [
|
|
|
|
| 1279 |
{
|
| 1280 |
"cell_type": "code",
|
| 1281 |
"execution_count": null,
|
| 1282 |
+
"id": "9edae39b",
|
| 1283 |
"metadata": {},
|
| 1284 |
"outputs": [],
|
| 1285 |
"source": [
|
|
|
|
| 1305 |
{
|
| 1306 |
"cell_type": "code",
|
| 1307 |
"execution_count": null,
|
| 1308 |
+
"id": "07134162",
|
| 1309 |
"metadata": {},
|
| 1310 |
"outputs": [],
|
| 1311 |
"source": [
|
|
|
|
| 1319 |
},
|
| 1320 |
{
|
| 1321 |
"cell_type": "markdown",
|
| 1322 |
+
"id": "435e5e35",
|
| 1323 |
"metadata": {},
|
| 1324 |
"source": [
|
| 1325 |
"## 5. Attention, by hand: the story circle in numbers\n",
|
|
|
|
| 1341 |
{
|
| 1342 |
"cell_type": "code",
|
| 1343 |
"execution_count": null,
|
| 1344 |
+
"id": "98f928a1",
|
| 1345 |
"metadata": {},
|
| 1346 |
"outputs": [],
|
| 1347 |
"source": [
|
|
|
|
| 1365 |
},
|
| 1366 |
{
|
| 1367 |
"cell_type": "markdown",
|
| 1368 |
+
"id": "dd9059e3",
|
| 1369 |
"metadata": {},
|
| 1370 |
"source": [
|
| 1371 |
"### Ella's shelf (the KV cache), in twelve lines\n",
|
|
|
|
| 1379 |
{
|
| 1380 |
"cell_type": "code",
|
| 1381 |
"execution_count": null,
|
| 1382 |
+
"id": "807c906b",
|
| 1383 |
"metadata": {},
|
| 1384 |
"outputs": [],
|
| 1385 |
"source": [
|
|
|
|
| 1409 |
},
|
| 1410 |
{
|
| 1411 |
"cell_type": "markdown",
|
| 1412 |
+
"id": "e7557457",
|
| 1413 |
"metadata": {},
|
| 1414 |
"source": [
|
| 1415 |
"## 6. A tiny GPT: Momo's whole head\n",
|
|
|
|
| 1426 |
"3. **Blocks**, repeated `n_layer` times (6 branches of the tree). Each block has:\n",
|
| 1427 |
" - **multi-head attention**: the story circle, run 4 times at once with different cards;\n",
|
| 1428 |
" - a **feed-forward network**: after listening to everyone, each token goes off to its own\n",
|
| 1429 |
+
" branch and thinks alone (a small two-layer network; research suggests many facts end up\n",
|
| 1430 |
+
" stored here);\n",
|
| 1431 |
" - **LayerNorm** (Ella keeping the numbers at a steady volume) and **residual connections**\n",
|
| 1432 |
" (each block *adds* its thoughts to what came in instead of replacing it, so nothing is\n",
|
| 1433 |
" lost on the way up the tree).\n",
|
|
|
|
| 1442 |
{
|
| 1443 |
"cell_type": "code",
|
| 1444 |
"execution_count": null,
|
| 1445 |
+
"id": "40b8d767",
|
| 1446 |
"metadata": {},
|
| 1447 |
"outputs": [],
|
| 1448 |
"source": [
|
|
|
|
| 1486 |
{
|
| 1487 |
"cell_type": "code",
|
| 1488 |
"execution_count": null,
|
| 1489 |
+
"id": "d79f1d74",
|
| 1490 |
"metadata": {},
|
| 1491 |
"outputs": [],
|
| 1492 |
"source": [
|
|
|
|
| 1597 |
},
|
| 1598 |
{
|
| 1599 |
"cell_type": "markdown",
|
| 1600 |
+
"id": "4e8831e7",
|
| 1601 |
"metadata": {},
|
| 1602 |
"source": [
|
| 1603 |
"## 7. Training: Ella's bedtime lessons\n",
|
|
|
|
| 1626 |
{
|
| 1627 |
"cell_type": "code",
|
| 1628 |
"execution_count": null,
|
| 1629 |
+
"id": "882b3bdb",
|
| 1630 |
"metadata": {},
|
| 1631 |
"outputs": [],
|
| 1632 |
"source": [
|
|
|
|
| 1668 |
{
|
| 1669 |
"cell_type": "code",
|
| 1670 |
"execution_count": null,
|
| 1671 |
+
"id": "481c902a",
|
| 1672 |
"metadata": {},
|
| 1673 |
"outputs": [],
|
| 1674 |
"source": [
|
|
|
|
| 1735 |
},
|
| 1736 |
{
|
| 1737 |
"cell_type": "markdown",
|
| 1738 |
+
"id": "944ca70e",
|
| 1739 |
"metadata": {},
|
| 1740 |
"source": [
|
| 1741 |
"**How to read the numbers.** The loss is Ella's average \"how surprised were you\" per token.\n",
|
|
|
|
| 1746 |
},
|
| 1747 |
{
|
| 1748 |
"cell_type": "markdown",
|
| 1749 |
+
"id": "387f64a3",
|
| 1750 |
"metadata": {},
|
| 1751 |
"source": [
|
| 1752 |
"## 8. Momo tells a story: the use case\n",
|
|
|
|
| 1764 |
{
|
| 1765 |
"cell_type": "code",
|
| 1766 |
"execution_count": null,
|
| 1767 |
+
"id": "b545d4c1",
|
| 1768 |
"metadata": {},
|
| 1769 |
"outputs": [],
|
| 1770 |
"source": [
|
| 1771 |
"def tell_story(prompt, max_new_tokens=200, temperature=0.8):\n",
|
| 1772 |
" model.eval()\n",
|
| 1773 |
+
" ids = tokenizer(prompt)[\"input_ids\"] or [tokenizer.eos_token_id] # empty prompt: start from the story marker\n",
|
| 1774 |
+
" idx = torch.tensor([ids], device=device)\n",
|
| 1775 |
" out = model.generate(idx, max_new_tokens, temperature=temperature)\n",
|
| 1776 |
" return tokenizer.decode(out[0].tolist(), skip_special_tokens=True)\n",
|
| 1777 |
"\n",
|
|
|
|
| 1782 |
},
|
| 1783 |
{
|
| 1784 |
"cell_type": "markdown",
|
| 1785 |
+
"id": "455a433e",
|
| 1786 |
"metadata": {},
|
| 1787 |
"source": [
|
| 1788 |
"## 9. Put Momo's book in the library: the Hugging Face Hub\n",
|
|
|
|
| 1801 |
{
|
| 1802 |
"cell_type": "code",
|
| 1803 |
"execution_count": null,
|
| 1804 |
+
"id": "00878bab",
|
| 1805 |
"metadata": {},
|
| 1806 |
"outputs": [],
|
| 1807 |
"source": [
|
|
|
|
| 1842 |
{
|
| 1843 |
"cell_type": "code",
|
| 1844 |
"execution_count": null,
|
| 1845 |
+
"id": "45371319",
|
| 1846 |
"metadata": {},
|
| 1847 |
"outputs": [],
|
| 1848 |
"source": [
|
|
|
|
| 1863 |
},
|
| 1864 |
{
|
| 1865 |
"cell_type": "markdown",
|
| 1866 |
+
"id": "9c85c1d9",
|
| 1867 |
"metadata": {},
|
| 1868 |
"source": [
|
| 1869 |
"## Loading it back later\n",
|
|
|
|
| 1874 |
{
|
| 1875 |
"cell_type": "code",
|
| 1876 |
"execution_count": null,
|
| 1877 |
+
"id": "dd50896e",
|
| 1878 |
"metadata": {},
|
| 1879 |
"outputs": [],
|
| 1880 |
"source": [
|
|
|
|
| 1895 |
},
|
| 1896 |
{
|
| 1897 |
"cell_type": "markdown",
|
| 1898 |
+
"id": "c107a885",
|
| 1899 |
"metadata": {},
|
| 1900 |
"source": [
|
| 1901 |
"## What we built, in one paragraph\n",
|