| --- |
| license: mit |
| tags: |
| - gpt |
| - language-model |
| - text-generation |
| - tinystories |
| - pytorch |
| - from-scratch |
| - slm |
| library_name: pytorch |
| pipeline_tag: text-generation |
| datasets: |
| - roneneldan/TinyStories |
| --- |
| |
| # scribe |
|
|
| A **~30M-parameter small language model built from scratch in PyTorch** and trained on |
| [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories). It's a decoder-only GPT β |
| hand-written multi-head causal attention, pre-LayerNorm blocks, GELU MLP, tied LM head β with no |
| `transformers`/`nanoGPT` modelling code. The architecture is deliberately **GPT-2-compatible**, so |
| these weights load directly into [`ember`](https://github.com/mbsdeepak/ember), a from-scratch |
| LLM inference server. |
|
|
| π¦ **Code, training, and full write-up (incl. the maths):** https://github.com/mbsdeepak/scribe |
|
|
| ## What it does |
|
|
| Give it a prompt and it continues it as a simple, coherent children's story: |
|
|
| > **"Once upon a time"** β *there was a little girl named Lily. She loved to read magazines. One |
| > day, she found a magazine in her mom's room... "Mommy, look at that magazine!" Lily said... Her |
| > mom looked at the magazine and smiled. "That's very nice, Lily. But be careful with it, it might |
| > break."* |
| > |
| > **"One day, a boy named Deepak"** β *went to the park every day. He saw a large tree and wanted to |
| > climb it. He started to climb it, but it was too heavy for him. He tried to jump, but he fell.* |
|
|
| ## Model |
|
|
| | | | |
| | :-- | :-- | |
| | Architecture | decoder-only transformer (GPT-2 family) | |
| | Parameters | ~30.0M (19.3M of it the tied 50257-token embedding) | |
| | Layers / heads / width | 6 / 6 / 384 | |
| | Context length | 256 tokens | |
| | Tokenizer | GPT-2 BPE (`tiktoken`) | |
| | Training | TinyStories, AdamW + warmup/cosine, ~3.4h on Apple-Silicon MPS | |
| | Validation loss | **1.74** (cross-entropy) | |
|
|
| ## Files |
|
|
| - `model.safetensors` β the weights (fp32) |
| - `config.json` β architecture config to rebuild the model |
|
|
| ## Usage |
|
|
| ```python |
| from huggingface_hub import hf_hub_download |
| from safetensors.torch import load_file |
| import json, torch |
| |
| # get the code: git clone https://github.com/mbsdeepak/scribe |
| from config import GPTConfig |
| from src.model import GPT |
| from src.tokenizer import Tokenizer |
| |
| cfg_json = json.load(open(hf_hub_download("mbsdeepak/scribe", "config.json"))) |
| gc = GPTConfig(n_layer=cfg_json["n_layer"], n_head=cfg_json["n_head"], |
| n_embd=cfg_json["n_embd"], block_size=cfg_json["max_position"]) |
| model = GPT(gc).eval() |
| model.load_state_dict(load_file(hf_hub_download("mbsdeepak/scribe", "model.safetensors"))) |
| |
| tok = Tokenizer() |
| ids = torch.tensor([tok.encode("Once upon a time")]) |
| out = model.generate(ids, max_new_tokens=120, temperature=0.8, top_k=200)[0].tolist() |
| print(tok.decode(out)) |
| ``` |
|
|
| Or serve it with [ember](https://github.com/mbsdeepak/ember) for a streaming, OpenAI-compatible API. |
|
|
| ## Limitations |
|
|
| A 30M model on TinyStories writes simple, coherent children's-story English β not general-purpose |
| text. It's a learning/portfolio project: the goal is understanding an LLM end-to-end (architecture, |
| training, serving), not competing with production models. Context is 256 tokens; architecture is |
| vanilla GPT-2 (no RoPE/RMSNorm/SwiGLU). |
|
|
| ## License |
|
|
| MIT |
|
|