Skip to main content
Articles/AI/tokenization-explained-how-llms-understand-text
Series: AI Product Engineeringβ€’Part 2 of 10
Scenario Article

Tokenization Explained: How LLMs Understand Text

Why LLMs Can't Just Read Words

Abstract Algorithmsβ€’Feb 11, 2026
XLinkedInReddit
Tokenization Explained: How LLMs Understand Text
πŸ’‘ Executive Summary

LLMs don't read words β€” they read tokens.

🎯 System Scenario & Requirements

System Goal

LLMs don't read words β€” they read tokens.

Actors & Components

  • Application or API tier
  • Core service under design
  • Operator or SRE observer

Functional Requirements

  • TLDR: LLMs don't read words β€” they read tokens.
  • A token is roughly 4 characters.
  • Byte Pair Encoding (BPE) builds an efficient subword vocabulary by iteratively merging frequent character pairs.

Constraints & Assumptions

  • All modern subword algorithms solve the same core problem differently: balance vocabulary size, sequence length, and handling of unseen (OOV) words.

⚑ Execution Stages & Decision Trace

1

Stage 1 β€” How Byte Pair Encoding Builds a Vocabulary

Action / Decision:

BPE starts with individual characters and iteratively merges the most frequent adjacent pair, growing the vocabulary until a target size is reached.

Component Behavior:

Step-by-step trace on "low lower lowest": Result: Common words stay whole ( the , in , is ).

Observable Output: Rare or new words are split into known subword pieces ( tokenization β†’ token , ization ).
Read Full Stage in Deep Dive ↓
πŸ“–

Deep Dive

Detailed Architectural Analysis

Deep Dive: Stage 1 β€” How Byte Pair Encoding Builds a Vocabulary

  • BPE starts with individual characters and iteratively merges the most frequent adjacent pair, growing the vocabulary until a target size is reached.
  • Step-by-step trace on "low lower lowest": Result: Common words stay whole ( the , in , is ).
  • Rare or new words are split into known subword pieces ( tokenization β†’ token , ization ).
Initial characters: ['l','o','w',' ','l','o','w','e','r',' ','l','o','w','e','s','t']

Round 1: Most frequent pair = ('l','o') β†’ merge to 'lo'
β†’ ['lo','w',' ','lo','w','e','r',' ','lo','w','e','s','t']

Round 2: Most frequent pair = ('lo','w') β†’ merge to 'low'
β†’ ['low',' ','low','e','r',' ','low','e','s','t']

Round 3: Most frequent pair = ('low','e') β†’ merge to 'lowe'
β†’ ['low',' ','lowe','r',' ','lowe','s','t']

...continues until vocabulary size target is reached
graph TD
    A[All characters in training corpus] --> B[Find most frequent adjacent pair]
    B --> C[Merge pair into a new token]
    C --> D[Update frequency counts]
    D --> E{Vocabulary size reached?}
    E -->|No| B
    E -->|Yes| F[Final vocabulary]

Observable outcome: Rare or new words are split into known subword pieces ( tokenization β†’ token , ization ).

Deep Dive: Stage 2 β€” What a Token Actually Looks Like in Practice

  • Key observations: - tokenization β†’ 2 tokens - The space before is is part of the is token - !
  • is its own token - Cost = number of tokens , not number of words Token counting rule of thumb (English): 1 token β‰ˆ 4 characters β‰ˆ 0.75 words.
import tiktoken                    # OpenAI's tokenizer library

enc = tiktoken.encoding_for_model("gpt-4o")

text = "Tokenization is fascinating!"
tokens = enc.encode(text)
print(tokens)
# β†’ [8908, 2065, 374, 41353, 0]   (5 tokens)

decoded = [enc.decode([t]) for t in tokens]
print(decoded)
# β†’ ['Token', 'ization', ' is', ' fascinating', '!']
sequenceDiagram
    participant T as Text Input
    participant TZ as Tokenizer
    participant M as LLM
    participant D as Detokenizer
    T->>TZ: raw string
    TZ->>M: token ID sequence
    M->>D: output token IDs
    D-->>T: decoded text output

Observable outcome: is its own token - Cost = number of tokens , not number of words Token counting rule of thumb (English): 1 token β‰ˆ 4 characters β‰ˆ 0.75 words.

Deep Dive: Stage 3 β€” BPE Training and Encoding Flow

  • The BPE algorithm has two distinct phases: a one-time vocabulary training phase (offline) and a per-text encoding phase (online at inference time).
  • The critical insight is that the merge rules learned during training are applied in the same order during encoding.
  • Rule 1 (first merge) is always applied before Rule 2 (second merge).
  • This determinism ensures that the same text always tokenizes to the same integer sequence β€” a requirement for reproducible model behavior.
graph TD
    subgraph Training Phase offline
        A[Large text corpus] --> B[Initialize: each character is a token]
        B --> C[Count all adjacent token pairs]
        C --> D[Merge the most frequent pair into a new token]
        D --> E[Update pair counts]
        E --> F{Vocab size target reached?}
        F -->|No| C
        F -->|Yes| G[Final vocabulary saved]
    end
    subgraph Encoding Phase online
        H[Input text] --> I[Split into characters]
        I --> J[Apply learned merge rules in order]
        J --> K[Token sequence produced]
        K --> L[Convert tokens to integer IDs]
        L --> M[Integer sequence fed to LLM]
    end
    G --> J

Observable outcome: This determinism ensures that the same text always tokenizes to the same integer sequence β€” a requirement for reproducible model behavior.

Deep Dive: Stage 4 β€” What to Learn Next

    • LLM Terms: A Helpful Glossary - LLM Hyperparameters: Temperature, Top-p, and Top-k - RAG Explained: How to Give Your LLM a Brain Upgrade

Observable outcome: - LLM Terms: A Helpful Glossary - LLM Hyperparameters: Temperature, Top-p, and Top-k - RAG Explained: How to Give Your LLM a Brain Upgrade

Deep Dive: Stage 5 β€” Hands-On: Explore Tokenization with tiktoken

  • The best way to build intuition for tokenization is to run experiments yourself.
  • The tiktoken library (used by OpenAI's GPT models) is available as a Python package.
  • Install and import: Experiment 1 β€” See how your prompt is tokenized: Experiment 2 β€” Compare English vs.
  • a non-Latin script: The same semantic content uses 2.4Γ— more tokens in Japanese β€” directly increasing API cost and consuming more of the context window.
pip install tiktoken
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4o")

prompt = "The quick brown fox jumps over the lazy dog."
tokens = enc.encode(prompt)
print(f"Token count: {len(tokens)}")
print([enc.decode([t]) for t in tokens])
# Token count: 10
# ['The', ' quick', ' brown', ' fox', ' jumps', ' over', ' the', ' lazy', ' dog', '.']

Observable outcome: a non-Latin script: The same semantic content uses 2.4Γ— more tokens in Japanese β€” directly increasing API cost and consuming more of the context window.

Deep Dive: Stage 6 β€” HuggingFace Tokenizers: BPE and WordPiece in Two Lines of Code

  • HuggingFace Tokenizers is the open-source Python library that powers tokenization for GPT-2, BERT, LLaMA, Mistral, and virtually every modern LLM β€” it exposes both the tokenizers (Rust-backed, fast) and transformers (hi…
  • The library makes every concept in this post directly observable: you can load real BPE (GPT-2) and WordPiece (BERT) tokenizers, inspect split boundaries, count tokens, and measure the cost difference between languages…
  • The prefix in BERT WordPiece tokens marks a continuation sub-word (part of a longer word), while GPT-2 BPE uses the Δ  prefix to mark a token that follows a space.
  • Both are subword algorithms but produce different split boundaries β€” a subtle source of model-specific behavior differences.
# pip install transformers tokenizers

from transformers import AutoTokenizer

# ── BPE tokenizer (GPT-2 style) ───────────────────────────────────────────────
gpt2_tok = AutoTokenizer.from_pretrained("gpt2")

text = "Tokenization is fascinating!"
gpt2_ids   = gpt2_tok.encode(text)
gpt2_split = gpt2_tok.convert_ids_to_tokens(gpt2_ids)
print("GPT-2 BPE:")
print("  IDs:    ", gpt2_ids)       # β†’ [30642, 1634, 318, 17049, 0]
print("  Tokens: ", gpt2_split)     # β†’ ['Token', 'ization', 'Δ is', 'Δ fascinating', '!']
print("  Count:  ", len(gpt2_ids))  # β†’ 5

# ── WordPiece tokenizer (BERT style) ──────────────────────────────────────────
bert_tok = AutoTokenizer.from_pretrained("bert-base-uncased")

bert_ids   = bert_tok.encode(text, add_special_tokens=False)
bert_split = bert_tok.convert_ids_to_tokens(bert_ids)
print("\nBERT WordPiece:")
print("  IDs:    ", bert_ids)       # β†’ [19204, 3989, 2003, 18895, 999]
print("  Tokens: ", bert_split)     # β†’ ['token', '##ization', 'is', 'fascinating', '!']
print("  Count:  ", len(bert_ids))  # β†’ 5
# Note: '##' prefix marks continuation sub-words in WordPiece

# ── Token cost comparison: English vs. Japanese ───────────────────────────────
english  = "Artificial intelligence is transforming software."
japanese = "δΊΊε·₯ηŸ₯θƒ½γ―γ‚½γƒ•γƒˆγ‚¦γ‚§γ‚’γ‚’ε€‰ι©γ—γ¦γ„γΎγ™γ€‚"

print("\nToken counts (GPT-2 BPE):")
print(f"  English:  {len(gpt2_tok.encode(english))} tokens")   # β†’ ~8
print(f"  Japanese: {len(gpt2_tok.encode(japanese))} tokens")  # β†’ ~25+ (2-3Γ— more)

# ── Reproduce the "strawberry" counting problem ───────────────────────────────
word = "strawberry"
pieces = gpt2_tok.convert_ids_to_tokens(gpt2_tok.encode(word))
print(f"\n'strawberry' splits to: {pieces}")
# β†’ ['straw', 'berry']  β€” model sees 2 tokens, not 10 characters

# ── Count prompt tokens before sending to API ────────────────────────────────
# Use the model-specific tokenizer to get an accurate count
system_prompt = "You are a helpful assistant. Always answer concisely."
user_message  = "Explain the difference between SQL and NoSQL databases."
full_prompt   = system_prompt + "\n" + user_message

token_count = len(gpt2_tok.encode(full_prompt))
cost_usd    = token_count / 1_000_000 * 5.00  # GPT-4o input pricing
print(f"\nPrompt token count: {token_count}")
print(f"Cost per 1 call: ${cost_usd:.6f}")

Observable outcome: Both are subword algorithms but produce different split boundaries β€” a subtle source of model-specific behavior differences.

πŸ“Š System Outcome & Trade-offs

End-to-End Result: Computers only work with numbers.

Observed User & Operator Behavior

User: Computers only work with numbers.

Operator: Operators can verify stage outcomes against the scenario requirements.

Key Architectural Trade-offs

  • All modern subword algorithms solve the same core problem differently: balance vocabulary size, sequence length, and handling of unseen (OOV) words.

πŸ”„ Evaluated Alternatives

Decision Guide: Practical Tokenization Guidelines

Decision Guide: Practical Tokenization Guidelines

⚠️ Failure Modes & Degraded Operation

Trade-offs & Failure Modes: Comparing Tokenization Algorithms

All modern subword algorithms solve the same core problem differently: balance vocabulary size, sequence length, and handling of unseen (OOV) words.

Series Navigation β€’ Part 2 of 10

AI Product Engineering

View Full Series Overview β†’
NEXT LEARNING STEPApply & Defend Decisions

Apply Concepts from this Scenario

Test your understanding of the architecture decisions and trade-offs presented in this case study.

Share this case study

Discuss architecture trade-offs and lessons with your team.

Share:XLinkedInReddit