LABS · 02  /  TOKENIZATION

The Tokenizer.

A language model can't read letters or words — it reads tokens. Before a single neuron fires, your text is shattered into sub-word chunks and turned into numbers. You'll watch it happen, race three ways to do it, then build the real algorithm by hand.

THE GIST · 20 SECONDS

An LLM only understands token IDs — integers. A tokenizer maps text to those IDs and back. Modern tokenizers use sub-word units: common words become a single token, rare words split into reusable pieces, so nothing is ever truly unknown. The algorithm that finds those pieces is Byte-Pair Encoding — merge the most frequent pair, over and over.

  • Tokena sub-word chunk — the unit a model reads
  • Vocabularythe fixed set of tokens the model knows
  • BPEmerge the most common pair, repeatedly
  • Token IDthe integer each token maps to

Watch text become tokens  →  Char vs word vs sub-word  →  Build BPE by merging pairs  →  Tune the vocabulary size  →  Cost, context & the 'strawberry' bug

one token just merged word boundary ·

Each colored chip is one token — the unit the model reads. The number under it is its token ID. Notice tokens don't line up with words.

UNDER THE HOOD

What you just played, written down

You shattered text, raced three tokenizers, grew a vocabulary by merging pairs, and felt the cost. Here's the same thing as the algorithm inside every LLM tokenizer.

Byte-Pair Encoding — four steps

  1. Start from characters. Split every word into single characters plus an end-of-word marker. The vocabulary is just the alphabet.
  2. Count pairs. Across the whole corpus, count every adjacent pair of symbols. Find the most frequent one.
  3. Merge it. Replace that pair everywhere with a new single token, and add the merge to the vocabulary. Every sequence gets a little shorter.
  4. Repeat for a fixed number of merges (e.g. ~50,000). Common words collapse to one token; rare words stay split into reusable pieces.
WHY SUB-WORDS WIN

Characters make sequences too long; whole words make the vocabulary huge and choke on anything new. BPE lands in between — frequent = one token, rare = a few pieces — so it's compact and never hits a word it can't represent.

Encoding a word, once trained

text  → "lowest"
chars → l o w e s t </w>      # start split

apply learned merges, in order:
  (l,o)   → lo w e s t         # merge #1
  (lo,w)  → low e s t          # merge #2
  (e,s)   → low es t           # ...
  (es,t)  → low est
tokens → [ low ][ est ]        # 2 tokens, not 6
TINY VOCABlong seqschar-level · model relearns spelling
HUGE VOCABrare tokensword-level · unknowns & sparsity

Solved by hand — BPE on a tiny corpus

Corpus: low · low · lower · newest · widest. Each row is one merge: the most frequent pair, and the new token it becomes. Watch the vocabulary grow and the token count fall.

⚠ Where it bites

Models miscount letters (the r's in strawberry) because they see tokens, not characters. Numbers, code, and rare names split into many tokens — more cost, less context.

↔ Its cousins

WordPiece (BERT) and Unigram (SentencePiece) are alternative sub-word schemes. Modern GPT-style models use byte-level BPE, which never hits an unknown byte.

★ Where you've met it

Every prompt you've ever sent. Token counts drive your bill, your context limit, and even multilingual fairness — some languages cost 2–3× the tokens for the same sentence.

RUN IT YOURSELF

Train BPE yourself

The lab above, in code: real Byte-Pair Encoding training on a small corpus — CPython in your browser. It repeatedly merges the most frequent pair. Change the number of merges and watch the vocabulary grow. Hit Run (or ⌘/Ctrl + Enter).

HOW TO READ THE CODE — 4 IDEAS
  1. Each word starts as a tuple of characters ending in </w>.
  2. Count every adjacent pair across the corpus, weighted by word frequency.
  3. Merge the most frequent pair into one symbol — that's one new vocab token.
  4. Repeat num_merges times: common sequences collapse into single tokens.
CPython · WebAssembly
QUICK CHECK

Did it stick?

FAQ

Tokenization, answered

What is tokenization in an LLM?

Turning raw text into tokens — usually sub-word chunks — each mapped to an integer ID. The model only ever sees those IDs. Context limits, cost, and some model quirks all trace back to it.

What is Byte-Pair Encoding (BPE)?

The algorithm behind most LLM tokenizers: start from characters, then repeatedly merge the most frequent adjacent pair into a new token. Common words end up as one token; rare words stay split into reusable pieces.

Why not just use words as tokens?

A word vocabulary is huge, chokes on typos, names, and new words (all become 'unknown'), and wastes capacity on run/runs/running. Sub-words are the sweet spot — compact and never truly unknown.

Why does token count matter?

You're billed per token and the context window is measured in tokens. Fewer tokens = cheaper and more room. Rare words, code, numbers, and many languages split into more tokens for the same meaning.

Why do LLMs miscount letters like the r's in 'strawberry'?

The model sees tokens, not letters. The characters are hidden inside tokens, so counting them means reasoning about spelling the model can't directly see — a tokenization artifact, not a reasoning failure.

RUN CARD

Next → these token IDs become vectors, and every token learns to look at every other one: that's attention.

Finished this one? 0 / 12 Labs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More Labs