Add scribe: 30M from-scratch GPT (TinyStories), val 1.74
Browse files- README.md +92 -0
- config.json +10 -0
- model.safetensors +3 -0
README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
tags:
|
| 4 |
+
- gpt
|
| 5 |
+
- language-model
|
| 6 |
+
- text-generation
|
| 7 |
+
- tinystories
|
| 8 |
+
- pytorch
|
| 9 |
+
- from-scratch
|
| 10 |
+
- slm
|
| 11 |
+
library_name: pytorch
|
| 12 |
+
pipeline_tag: text-generation
|
| 13 |
+
datasets:
|
| 14 |
+
- roneneldan/TinyStories
|
| 15 |
+
---
|
| 16 |
+
|
| 17 |
+
# scribe
|
| 18 |
+
|
| 19 |
+
A **~30M-parameter small language model built from scratch in PyTorch** and trained on
|
| 20 |
+
[TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories). It's a decoder-only GPT —
|
| 21 |
+
hand-written multi-head causal attention, pre-LayerNorm blocks, GELU MLP, tied LM head — with no
|
| 22 |
+
`transformers`/`nanoGPT` modelling code. The architecture is deliberately **GPT-2-compatible**, so
|
| 23 |
+
these weights load directly into [`ember`](https://github.com/mbsdeepak/ember), a from-scratch
|
| 24 |
+
LLM inference server.
|
| 25 |
+
|
| 26 |
+
📦 **Code, training, and full write-up (incl. the maths):** https://github.com/mbsdeepak/scribe
|
| 27 |
+
|
| 28 |
+
## What it does
|
| 29 |
+
|
| 30 |
+
Give it a prompt and it continues it as a simple, coherent children's story:
|
| 31 |
+
|
| 32 |
+
> **"Once upon a time"** → *there was a little girl named Lily. She loved to read magazines. One
|
| 33 |
+
> day, she found a magazine in her mom's room... "Mommy, look at that magazine!" Lily said... Her
|
| 34 |
+
> mom looked at the magazine and smiled. "That's very nice, Lily. But be careful with it, it might
|
| 35 |
+
> break."*
|
| 36 |
+
>
|
| 37 |
+
> **"One day, a boy named Deepak"** → *went to the park every day. He saw a large tree and wanted to
|
| 38 |
+
> climb it. He started to climb it, but it was too heavy for him. He tried to jump, but he fell.*
|
| 39 |
+
|
| 40 |
+
## Model
|
| 41 |
+
|
| 42 |
+
| | |
|
| 43 |
+
| :-- | :-- |
|
| 44 |
+
| Architecture | decoder-only transformer (GPT-2 family) |
|
| 45 |
+
| Parameters | ~30.0M (19.3M of it the tied 50257-token embedding) |
|
| 46 |
+
| Layers / heads / width | 6 / 6 / 384 |
|
| 47 |
+
| Context length | 256 tokens |
|
| 48 |
+
| Tokenizer | GPT-2 BPE (`tiktoken`) |
|
| 49 |
+
| Training | TinyStories, AdamW + warmup/cosine, ~3.4h on Apple-Silicon MPS |
|
| 50 |
+
| Validation loss | **1.74** (cross-entropy) |
|
| 51 |
+
|
| 52 |
+
## Files
|
| 53 |
+
|
| 54 |
+
- `model.safetensors` — the weights (fp32)
|
| 55 |
+
- `config.json` — architecture config to rebuild the model
|
| 56 |
+
|
| 57 |
+
## Usage
|
| 58 |
+
|
| 59 |
+
```python
|
| 60 |
+
from huggingface_hub import hf_hub_download
|
| 61 |
+
from safetensors.torch import load_file
|
| 62 |
+
import json, torch
|
| 63 |
+
|
| 64 |
+
# get the code: git clone https://github.com/mbsdeepak/scribe
|
| 65 |
+
from config import GPTConfig
|
| 66 |
+
from src.model import GPT
|
| 67 |
+
from src.tokenizer import Tokenizer
|
| 68 |
+
|
| 69 |
+
cfg_json = json.load(open(hf_hub_download("mbsdeepak/scribe", "config.json")))
|
| 70 |
+
gc = GPTConfig(n_layer=cfg_json["n_layer"], n_head=cfg_json["n_head"],
|
| 71 |
+
n_embd=cfg_json["n_embd"], block_size=cfg_json["max_position"])
|
| 72 |
+
model = GPT(gc).eval()
|
| 73 |
+
model.load_state_dict(load_file(hf_hub_download("mbsdeepak/scribe", "model.safetensors")))
|
| 74 |
+
|
| 75 |
+
tok = Tokenizer()
|
| 76 |
+
ids = torch.tensor([tok.encode("Once upon a time")])
|
| 77 |
+
out = model.generate(ids, max_new_tokens=120, temperature=0.8, top_k=200)[0].tolist()
|
| 78 |
+
print(tok.decode(out))
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
Or serve it with [ember](https://github.com/mbsdeepak/ember) for a streaming, OpenAI-compatible API.
|
| 82 |
+
|
| 83 |
+
## Limitations
|
| 84 |
+
|
| 85 |
+
A 30M model on TinyStories writes simple, coherent children's-story English — not general-purpose
|
| 86 |
+
text. It's a learning/portfolio project: the goal is understanding an LLM end-to-end (architecture,
|
| 87 |
+
training, serving), not competing with production models. Context is 256 tokens; architecture is
|
| 88 |
+
vanilla GPT-2 (no RoPE/RMSNorm/SwiGLU).
|
| 89 |
+
|
| 90 |
+
## License
|
| 91 |
+
|
| 92 |
+
MIT
|
config.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "scribe",
|
| 3 |
+
"n_layer": 6,
|
| 4 |
+
"n_head": 6,
|
| 5 |
+
"n_kv_head": 6,
|
| 6 |
+
"n_embd": 384,
|
| 7 |
+
"vocab_size": 50257,
|
| 8 |
+
"max_position": 256,
|
| 9 |
+
"dtype": "float32"
|
| 10 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5f9fe3effaf126382fb5a2d0d1e9454e662aa1959d55f96953e89ffa5a5924fa
|
| 3 |
+
size 120184776
|