BPE-Style Tokenizers: The Small Algorithm That Decides What an LLM Can See Shrijith Venkatramana, an engineer building the AI code review tool LiveReview, traces modern LLM tokenization back to Byte Pair Encoding, a 1994 data-compression algorithm by Philip Gage. The writeup explains how BPE-style subword tokenization resolves the open-vocabulary problem by balancing short sequences against vocabulary size, and notes its 2016 adoption for neural machine translation by Rico Sennrich, Barry Haddow and Alexandra Birch before it became standard in models like GPT-2. Hello, I'm Shrijith Venkatramana, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us https://github.com/HexmosTech/LiveReview/ to help devs discover the project, give it a try, and share your feedback to help improve the product. When you type: unbelievableness an LLM does not see the word. It sees something more like: "un", "believ", "ableness" Or perhaps: "un", "believe", "ness" Or, depending on the tokenizer: "un", "bel", "iev", "ab", "leness" That difference is not cosmetic. Tokenization determines the length of the model's input sequence, which affects context usage, inference cost, attention computation, vocabulary size, handling of rare words, programming-language behavior, multilingual performance, and even some model failure modes. And one of the most widely used ideas behind modern LLM tokenizers has an unusually non-LLM origin: a 1994 data-compression algorithm by a programmer named Philip Gage. The basic idea is remarkably simple: Find things that occur together often, and give them a reusable symbol. That idea eventually went from C programmers doing data compression, to neural machine translation, to GPT-2 and the tokenization machinery surrounding today's language models. This article builds the idea from intuition to implementation, then looks at the less obvious engineering consequences. A neural network wants numbers. Your input is text: The server returned HTTP 500. The model needs: the, server, returned, HTTP, 500, . which eventually becomes integer IDs such as: 464, 2126, 4710, ... The obvious question is: Why not make every word a token? Suppose the vocabulary contains: cat dog server database running ... Now consider: microarchitectural microarchitectures microarchitecturally You immediately run into the open-vocabulary problem. There are infinitely many possible strings. New product names appear. Developers invent identifiers. People misspell things. Languages generate long compounds. Users paste URLs, hashes, code, emojis and arbitrary Unicode. A word-level tokenizer therefore needs some fallback mechanism. At the other extreme, we could tokenize one character at a time: m i c r o a r c h i t e c t u r a l Now everything is representable, but sequences become much longer. That creates a fundamental tradeoff: word tokens <- shorter sequences, huge vocabulary, poor handling of unknown words character tokens <- tiny vocabulary, very long sequences subword tokens <- compromise BPE-style tokenization lives in that middle ground. Frequent sequences become single tokens. Rare sequences remain decomposable into smaller units. That is the key intuition. In 1994, Philip Gage published an article in The C Users Journal describing Byte Pair Encoding , or BPE. His original problem had nothing to do with language models. The idea was ordinary compression: Suppose data contains: ABABABABABAB and AB occurs constantly. Instead of repeatedly storing: A B A B A B A B ... we can create a new symbol representing: AB and replace occurrences of the pair. Do it repeatedly, and common sequences become increasingly compact. The original algorithm therefore looked roughly like: find the most frequent adjacent byte pair replace it with a new symbol repeat This is a compression algorithm. But the basic mechanism turns out to be useful for language. In 2016, Rico Sennrich, Barry Haddow and Alexandra Birch applied BPE to neural machine translation. Their motivation was the open-vocabulary problem : machine translation systems had to deal with names, compounds and rare words that could not reasonably all appear in a fixed word vocabulary. Consider: counterrevolutionaries A word-level vocabulary might not contain it. A subword system could represent it approximately as: counter + revolution + ar + ies The exact segmentation is learned from data rather than being supplied by a linguist. This mattered because the model could now encounter a word it had never seen as a whole while still having a representation for its pieces. Then GPT-2 made an important variation mainstream: byte-level BPE . Instead of starting from all Unicode characters, GPT-2 starts from the 256 possible byte values. That gives a tiny guaranteed base vocabulary while preserving the ability to represent arbitrary byte sequences. GPT-2 used a vocabulary of 50,257 entries, consisting of the 256-byte base plus 50,000 learned merges and a special token. OpenAI CDN https://cdn.openai.com/better-language-models/language-models.pdf So the lineage is roughly: 1994: byte compression | v 2016: subword representation for NMT | v 2019: byte-level BPE for GPT-2 | v modern LLM tokenizers The interesting part is that almost none of this requires a sophisticated linguistic theory. It is mostly frequency statistics plus a greedy merging procedure. Let's construct a tiny tokenizer. Suppose our corpus is: low low low low low lower lower widest widest widest newest newest newest newest newest newest First, pretend our base vocabulary consists of individual characters. We represent: low as: l o w and: lower l o w e r Now count adjacent pairs. For example: l, o o, w w, e e, r w, i i, d d, e e, s s, t n, e Because newest appears six times, the pair: e, s appears six times. Likewise: s, t BPE asks: Which adjacent pair is most frequent? Suppose we pick: e, s and create a new symbol: es Now: newest becomes: n e w es t The vocabulary has grown by one. Next we recount pairs and may discover: es, t is highly frequent. Merge again: est newest n e w est Continue. Eventually you might learn: st est west newest depending on corpus frequencies and the exact sequence of merges. The algorithm is therefore almost embarrassingly simple. Let the current token sequence for a corpus be made from symbols in vocabulary V . For every adjacent pair a, b , compute its frequency: f a, b = number of times a is immediately followed by b Then choose: a , b = argmax a,b f a, b Create a new token: c = a || b where || means concatenation. Then replace every occurrence of: a b with: c and repeat. If we begin with B base symbols and perform K merges: |V| = B + K + special tokens For byte-level BPE: B = 256 So with 50,000 merges: |V| ~= 50,000 + 256 plus whatever special tokens the system uses. This is a useful mental model: The tokenizer vocabulary is largely a compressed dictionary of frequently useful byte sequences. There is an important property hiding inside the greedy algorithm. Suppose these sequences are common: tion ing pre un http :// BPE will tend to discover them because they occur frequently. Eventually it may discover larger units: communicat + ion or perhaps: commun + ication or, for a very common word: communication as one complete token. This means the tokenizer automatically creates something resembling a hierarchy: php bytes - small fragments - common morpheme-like units - common words - common multi-character sequences But an important distinction: BPE does not understand morphology. It does not know that: walk walking walked walker share a linguistic stem. It only knows that certain byte sequences occur frequently enough to be worth merging. That distinction matters when people say things like "the tokenizer understands prefixes." It does not. It has learned a segmentation that is useful according to its training statistics. Imagine a corpus where: hyperparameter occurs 50,000 times. Then the tokenizer has an economic incentive, in vocabulary terms, to represent something like: hyperparameter compactly. But suppose: hyperparametrix appears once. A BPE tokenizer can still represent it: hyper + parameter + ix or some other decomposition. This is the main advantage over word-level tokenization. It gets compression for common patterns without making the vocabulary responsible for every possible word .