Step 1 · The tokenizer
Before a model sees language, something must chop text into pieces. Get this wrong and everything downstream is quietly worse.
In 60 seconds
Step 1 · The tokenizer
Before a model sees language, something must chop text into pieces. Get this wrong and everything downstream is quietly worse.
| Approach | Vocabulary | Problem |
|---|---|---|
| One token per character | ~100 | Sequences become enormously long; the model wastes capacity on spelling |
| One token per word | Millions, and still incomplete | Every typo and rare name is an unknown token |
| Subword (BPE) | 30k–200k | None serious — this is why everyone uses it |
Byte-pair encoding, in one paragraph
from collections import Counter
def get_pairs(ids):
return Counter(zip(ids, ids[1:]))
def merge(ids, pair, new_id):
out, i = [], 0
while i < len(ids):
if i < len(ids) - 1 and (ids[i], ids[i+1]) == pair:
out.append(new_id); i += 2
else:
out.append(ids[i]); i += 1
return out
def train_bpe(text, vocab_size=512):
ids = list(text.encode("utf-8")) # start: raw bytes, 0-255
merges = {}
for new_id in range(256, vocab_size):
pairs = get_pairs(ids)
if not pairs: break
best = max(pairs, key=pairs.get) # most frequent adjacent pair
ids = merge(ids, best, new_id)
merges[best] = new_id
return merges
def encode(text, merges):
ids = list(text.encode("utf-8"))
for pair, new_id in merges.items(): # apply in training order
ids = merge(ids, pair, new_id)
return ids
def decode(ids, merges):
vocab = {i: bytes([i]) for i in range(256)}
for (a, b), new_id in merges.items():
vocab[new_id] = vocab[a] + vocab[b]
return b"".join(vocab[i] for i in ids).decode("utf-8", errors="replace")Why tokenizer decisions haunt you
- 1
Vocabulary size is a trade
Bigger vocabulary means shorter sequences and faster inference, but a larger embedding matrix and more rarely-seen tokens. 32k to 128k is the normal range today. - 2
Language coverage is political and practical
If your corpus was mostly English, Hindi or Tamil text costs three to five times as many tokens to say the same thing. That is a real price and latency penalty for those users, baked in at tokenizer time. - 3
Numbers and code need care
Splitting "12345" into odd chunks damages arithmetic. Most modern tokenizers split digits individually on purpose. - 4
You cannot change it later
The embedding table is indexed by token id. Change the tokenizer and every weight you trained is meaningless. Decide once.
Watch and read more
Lab
A BPE tokenizer you wrote, benchmarked against a real one.
The problem
# Measure the fertility gap that decides who pays more per request
for lang, text in samples.items():
n_tokens = len(encode(text, merges))
n_words = len(text.split())
print(f"{lang:10} {n_tokens/n_words:.2f} tokens/word")You are done when
Hard questions
Try to answer before you reveal. If you can answer these, you understood the lesson.
Q1Your tokenizer needs 3.5 tokens per Hindi word and 1.3 per English word. State every consequence.Reveal
Questions people ask
How many tokens is a word?
English averages roughly 1.3 tokens per word, or about 4 characters per token. Code, non-Latin scripts and unusual names cost more. Always measure on your actual data rather than trusting the rule of thumb.
What are special tokens?
Reserved ids the text can never produce naturally: end-of-text, padding, and chat-role markers like beginning-of-turn. They give the model unambiguous structure. Get them wrong in fine-tuning and the model will not know when to stop generating.
Why do some models use SentencePiece?
SentencePiece treats the input as a raw stream including whitespace, which avoids language-specific pre-tokenisation rules. It suits multilingual models. Byte-level BPE and SentencePiece unigram are the two dominant families.
Can I extend a vocabulary?
Yes — add new tokens and grow the embedding matrix, initialising new rows sensibly (often the mean of the sub-token embeddings). Useful for adding a domain vocabulary or a new script. It requires further training to be worth anything.
Lesson test
5 questions. Get 3 right (60%) to pass and complete this lesson.
Sign in with your phone number to take the test and save your progress