Tokenization

How raw text becomes model inputs, and why tokenizer design affects cost, quality, and multilingual behavior.

Why Tokenization Exists

Neural networks operate on fixed vocabularies of discrete symbols. Raw Unicode text must be split into tokens, mapped to integer IDs, and converted to embeddings. Tokenization defines the interface between human-readable text and model computation. A poor tokenizer inflates sequence length, increases inference cost, and can degrade performance on code, math, or non-English text.

The fundamental tension is vocabulary size vs sequence length. Word-level tokenizers have huge vocabularies and out-of-vocabulary problems. Character-level tokenizers have tiny vocabularies but very long sequences. Subword methods balance both.

Subword Algorithms

Byte Pair Encoding (BPE)

BPE starts with byte or character units and iteratively merges the most frequent pairs until the vocabulary reaches a target size. GPT-2, GPT-3, and many open models use BPE. It handles rare words by composing frequent subword pieces.

WordPiece and Unigram

WordPiece (BERT) selects merges that maximize likelihood under a language model. Unigram (SentencePiece) starts large and prunes tokens to optimize a probabilistic objective. Both are common in multilingual and production pipelines.

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-1B")
text = "Retrieval-augmented generation (RAG) grounds LLM answers."
tokens = tokenizer.encode(text)
print(tokens)                          # [128000, 27420, ...]
print(tokenizer.decode(tokens))        # round-trip text
print(len(tokens))                     # billable / context length

SentencePiece

SentencePiece treats text as a raw byte stream and can train without language-specific pre-tokenization. This makes it strong for multilingual models and consistent handling of whitespace and punctuation across scripts.

Special Tokens and Chat Templates

Production tokenizers include special tokens beyond ordinary subwords:

Chat templates are string patterns (often Jinja-based) that wrap messages with the correct special tokens before tokenization. Using the wrong template causes silent quality degradation even when the base model is correct.

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Explain tokenization in one sentence."},
]
prompt = tokenizer.apply_chat_template(
    messages, tokenize=False, add_generation_prompt=True
)
Engineering rule: Always pair a model with its native tokenizer and chat template. Swapping tokenizers between checkpoints breaks vocabulary alignment and special token semantics.

Bytes, Unicode, and Edge Cases

Byte-level BPE (used in GPT-2) represents any UTF-8 string without UNK tokens by falling back to individual bytes. This is robust but can split non-Latin scripts into many tokens, raising cost for those languages.

Tokenization affects:

Vocabulary Design Tradeoffs

Practical Pipeline Integration

In serving systems, tokenization runs on every request. Batch tokenization, caching of frequent prefixes, and streaming decode (incremental detokenization) all affect latency. For RAG, chunk sizes are often defined in tokens, not characters, because the model context window is token-bounded. Counting tokens accurately before sending requests prevents truncation and surprise billing on API providers.