cd .. / course
Part 1 · Lesson 15/15

Why it can't count the r's in "strawberry"

The model never sees letters. Once text is tokenized it reads a handful of opaque token IDs — row numbers, not spelling. So a question about the letters inside a token is invisible to it. Here's exactly what gets lost.

⏱ ~4 min 🎚 interactive math: none

Back on lesson 1, text became token IDs and the letters were dropped on the floor. Every page since has worked on vectors keyed by those IDs — never once on characters. This page shows the cost of that.

To the model, "strawberry" isn't one letter-by-letter thing — it's a few chunks, each an opaque ID. The spelling is gone the moment it's tokenized; all that survives is a short list of integers.

So "how many r's in strawberry?" asks about letters sitting inside chunks the model can't see into. It's not being dumb — the information literally isn't in its input.

What you see vs. what the model sees
Try one of the four — this toy only knows those words.
What the human sees raw letters — you can count them
What the model sees opaque IDs — letters removed

the model gets the bottom row. The r's live inside chunks it reads as single IDs.

Illustrative data — not computed

The chunk split and these ID numbers are hard-coded for the lesson. A real BPE tokenizer chunks by frequency and assigns entirely different IDs — "strawberry" might split as ["str","aw","berry"] or not, with its own vocabulary numbers. The opacity is the real point, not these exact values. (The letter count, by contrast, is computed live from the actual word string.)

TRY → Click strawberry (the default): the top row highlights all 3 of its r's and counts them; the bottom row is three IDs with no letters left to count. Now click cat, unbelievable, or GPT — or type a word — and watch the two rows drift apart.

Show me the actual numbers (word = strawberry)

"strawberry" → chunks ["str", "aw", "berry"] → IDs [1618, 707, 15717] (illustrative — not a real vocabulary).

A human reads the string letter by letter: s·t·r·a·w·b·e·r·r·y and counts the r's = 3. That count on this page is computed from the real word string, so it's always right.

The model's input is the three integers [1618, 707, 15717]. Nothing in those numbers encodes "how many r's" — the embedding for each chunk was learned from how the chunk is used, not from its spelling. The struck line letter count: unavailable is honest: there are no letters in an ID to tally.

This is why letter puzzles, rhyme edge-cases, and character counts trip models up: it's a tokenization blind spot, not a reasoning failure. Real tokenizers (BPE) chunk by frequency, so the exact split and IDs differ — but the opacity is real, and it's why "how many r's in strawberry" is a genuinely hard question for a model that never sees the letters.

MythThe model can obviously see the letters in a word it just read — it read the word, didn't it?
RealityIt reads opaque token IDs, not characters. Once "strawberry" becomes three chunk-IDs, the individual letters are gone — so it can't reliably count them, spell backwards, or rhyme by ending.
Takeaway

The model reads token IDs, not letters. Once "strawberry" is [1618, 707, 15717], the spelling is gone — so per-letter questions ask about information its input no longer contains.

Why do models miscount the letters in a word like "strawberry"?
Why: tokenization replaces letters with chunk IDs; a per-letter question asks about information the model's input no longer contains — a tokenization blind spot, not a reasoning failure.