BPE, and Why the Model Can't Count the R's in Strawberry
AI models do not read letters. They read numbers handed to them by a compression trick from 1994 — and a surprising share of their strangest failures are that trick's fault, not the model's.
Ask a language model how many times the letter r appears in "strawberry" and it will often say two. This gets passed around as proof that AI does not really understand anything, and as far as it goes that is fair.
But there is a more precise explanation, and it is much more useful: the model never saw the letters. It saw two or three numbers, and nothing about those numbers records that one of them contains a double r.
Here is the picture. Before a model reads anything, the text passes through a translator that chops it into pieces and replaces each piece with a number. The model only ever sees the numbers. That translator is the tokenizer, and it is the least glamorous part of the whole stack and the source of a startling share of its weirdness.
1. Why chopping is necessary at all
A model needs a fixed, finite list of pieces it knows about, because its final step is a score for every piece on that list, and that list has to have a size.
So text must become a bounded set of symbols. There are two obvious ways, and both fail.
One number per word. Natural and useless. There is no end to words — every name, typo, invention and mashed-together compound is a new one. So you cap the list, and everything past the cap becomes a shrug. The model then cannot read, write or reason about any rare word, which is most of the words carrying actual information in a technical document.
One number per letter. Complete: nothing is ever unknown. But now sequences are five to ten times longer, and the cost of relating everything to everything grows with the square of the length. You have also handed the model the extra job of relearning that c-a-t is one thing, spending its capacity on something you could have told it for free.
The escape is to learn the list from real text. Frequent chunks become single pieces; rare ones break into smaller pieces. Common text is short. Unusual text is still spellable. Nothing is ever unknown.
2. A compression trick, borrowed
Philip Gage published byte pair encoding in 1994 as a way of compressing files. Rico Sennrich, Barry Haddow and Alexandra Birch adapted it for machine translation in Neural Machine Translation of Rare Words with Subword Units at ACL 2016, and it has dominated ever since.
The whole training algorithm is four lines:
- Start with the list containing only individual characters.
- Count every pair of neighbours in your text.
- Glue the most common pair into a single new piece. Add it to the list.
- Repeat until the list is as big as you wanted.
That is genuinely all of it. Run on English, the first glued pairs are things like th, he, in, er. A few thousand steps later you have whole common words and useful endings like ing, tion, ness.
The output is an ordered list of glue instructions, and the order is the algorithm. Chopping up new text means replaying those instructions in the same sequence they were learned. It is not a dictionary lookup. It is a replay of a history.
Watching it run
Take a tiny text: low low low lower lowest. Split into characters, with _ marking where a word ends:
l o w _ l o w _ l o w _ l o w e r _ l o w e s t _
Count neighbouring pairs. l o appears five times, more than anything else. Glue it:
lo w _ lo w _ lo w _ lo w e r _ lo w e s t _
Now lo w appears five times. Glue it:
low _ low _ low _ low e r _ low e s t _
Then low _ — the complete word — appears three times and becomes one piece, while e r _ and e s t _ eventually become ending-pieces.
Notice what the algorithm discovered without being told: a stem and two endings. Nobody taught it grammar. It fell out of counting. That is why this generalises — a word it has never seen, lowness, still breaks into low plus something, rather than into unrelated rubble.
Notice also what it did not discover. The glue is driven purely by counting, so it is only as good as the text it counted. A stem that is rare in the training text never gets glued and stays fragmented forever, however meaningful it is.
3. Why "strawberry" wins
Run a typical tokenizer over strawberry and you get something like str + aw + berry. The model receives roughly [2536, 707, 15717].
Now think about what counting rs would require. The model must know that 2536 contains one r, that 707 contains none, and that 15717 contains two.
Those facts appear nowhere in the input. There is no letter-structure inside a number. The model can only know spelling to the extent it has memorised which pieces contain which letters — from text that happened to discuss spelling.
It has memorised some, which is why the failure is inconsistent rather than total. But that is remembered trivia, not seeing, and it falls apart exactly where you would expect: rare words, odd capitalisation, and words that get chopped differently depending on what is next to them.
The same mechanism explains several other reliable failures. Reversing a word needs letter access the model does not have. Arithmetic is erratic partly because numbers get chopped inconsistently — 1234 might be one piece while 1235 is two, so the model cannot rely on the structure. Rhyming is hard in some languages because rhyme is about final sounds and the pieces do not line up with them.
4. Chopping is a fairness problem
The list is learned from a pile of text, and that pile is mostly English. The consequences are concrete and almost never mentioned in model documentation.
English runs at roughly four characters per piece. Languages in other scripts do far worse — the glue instructions that would have compressed them were never learned, so the text falls back toward one piece per character, sometimes several.
Three real costs follow, all of them paid by people not writing English:
- Money. These services bill per piece. The same sentence costs several times more in Hindi, Thai or Burmese.
- Room. A model can only hold so many pieces at once, so it fits far less actual content.
- Quality. Longer sequences mean more distance between related words, so the model has more work to do to connect them.
None of this was a decision anyone made. It emerged from where the training text came from, which is exactly why it goes unnoticed.
5. The practical details that bite
The space is inside the piece. In most tokenizers " the" and "the" are different pieces. This is why a prompt ending in a trailing space can produce noticeably worse output — you have forced the model to continue from a piece that rarely appears in that position. Do not end prompts with a space.
Counts do not transfer. Every model family has its own list. A prompt that is 1,000 pieces for one model may be 1,300 for another. Estimate cost and room using the tokenizer of the model you are actually calling.
Structured formats are expensive. JSON spends pieces on braces, quotes and repeated field names, and every one is billed and takes up room. Short field names are meaningfully cheaper at scale.
The list is frozen forever. Any word invented after training breaks into awkward fragments, and the model has to cope without ever having had a piece of its own for it.
6. Other ways of doing it
Three alternatives are in wide use, and the differences change the failure modes.
WordPiece, used by BERT, changes which pair gets glued. Instead of the most frequent pair, it picks the pair whose gluing best explains the text — roughly, it prefers pairs that appear together more often than you would expect by chance. In practice this favours gluings that are genuinely one thing rather than two common pieces that happen to be adjacent.
Unigram, from Kudo, works backwards. Start with a huge list of candidate pieces and repeatedly remove whichever ones you would miss least, until the list is the right size. Because it keeps a probability for each piece, it can produce several valid ways to chop the same word — which lets you deliberately vary the chopping during training as a kind of practice.
SentencePiece is often listed alongside these but is a different sort of thing: a tool that runs either method directly on raw text, treating the space character as just another symbol. Its real contribution is removing the "split on spaces first" step, which quietly assumes a language that uses spaces — false for Chinese, Japanese and Thai. It is language-agnostic and perfectly reversible: decoding gives you back the original text exactly, spacing included.
7. What if we removed it?
There is active work on making the tokenizer disappear — models that read raw bytes and learn their own chunking as they go.
The appeal is obvious: no bias in the list, no spelling blindness, no unfair cost across languages, no frozen vocabulary. The obstacle is the one from section 1: byte sequences are long, and the cost grows with the square of the length.
That is why this line of work tends to appear alongside architectures that handle long sequences better. The two problems are the same problem.
8. The framing that makes this click
The tokenizer is a lossy compression scheme sitting between your text and the model, tuned to make average English short — not to preserve anything you might care about.
Read the failure list again with that in mind and it stops being a list of quirks. Spelling, counting letters, reversing words, arithmetic on digits, cross-language cost, sensitivity to a trailing space: every one is a direct consequence of a compression decision made before the model saw a single example.
The model is not failing to count. It is answering a question about letters using an input that contains none.
Sources
- Sennrich, Haddow, Birch — Neural Machine Translation of Rare Words with Subword Units, ACL 2016
- Gage — A New Algorithm for Data Compression, The C Users Journal, 1994
- Radford et al. — Language Models are Unsupervised Multitask Learners (GPT-2, byte-level BPE), 2019