The first edition of The Computer Science Book finished with compilers because I felt they represented the perfect capstone project: a complex application that drew together multiple computer science topics to deliver seemingly magical results. In the six years since I wrote the first edition, advances in large language models (LLMs) have made compilers seem almost trivially simple.
In this chapter, we’ll cover how LLMs work at a deep level and then explore how they generalise to artificial intelligence systems. In the sense I’ll use throughout this chapter, artificial intelligence means a system that can perceive some part of the world, build useful internal representations, choose actions toward a goal, and improve those choices from data or feedback.
For the first time in history, humans aren’t the only things that can talk. We’re at the very beginning of working out what this means for humanity. Prosaically for software engineers, this is both a huge opportunity and a possible threat. We can now build capabilities that were previously impossible or comparatively limited, including intelligent assistants, semantic search, and automated code generation. But LLMs are different from the programs we’ve seen before. We don’t “design” LLMs. We “grow” them and there is much we don’t understand about them. Yet LLMs are still programs. They are an abstraction, hiding an enormous amount of machinery behind a deceptively simple “text in, text out” interface.
This chapter is in two parts. The first traces the inside of a working LLM: the history that led from symbolic AI to deep learning, a step-by-step walk through a GPT-2-style model, and how post-training turns a next-token predictor into an aligned assistant capable of tool use and multi-step reasoning.
There are already many excellent introductions to LLMs (included in the further reading, of course) and so I don’t want to repeat old ground. I want to use this final chapter of the book to point you towards the many exciting capabilities that are just coming into view. Therefore the second part looks outward at where AI systems are heading. We’ll look at multimodal perception, action models, world models, and the tools we’re only beginning to develop to evaluate and understand what these systems are actually doing inside.
I’m unashamedly pro-AI and excited by its potential when used in the correct context. Understanding how an LLM works under the surface helps us to evaluate lurid claims about what AI is doing and what it’s capable of. I hope to disabuse you of the notion that LLMs are “glorified autocomplete”. Nevertheless, people are right to be unsure and, dare I say, even fearful of what the future might hold.
May you live in interesting times!
AI has long had two competing instincts (or, less kindly, squabbling factions). The older one is symbolic AI, often called “Good Old-Fashioned AI” (GOFAI). It assumes that intelligence comes from manipulating symbols according to explicit rules, much as we do with logical reasoning. Under this approach, if you wanted a system to diagnose diseases, prove theorems, or plan routes through a network, you would interview experts, write down the rules, and let the machine search through combinations of symbolic states. That produced expert systems which did well at things such as theorem provers and planning systems.
GOFAI worked best when the world could be described cleanly. Tasks like playing chess, solving algebra problems, and scheduling resources have explicit states and clear rules for moving between them. However, this approach fell over when it came to handling messy inputs. Recognising a face or understanding human language don’t begin with neat symbols. They begin with messy data. Writing all the relevant rules down by hand turned out to be painfully hard, and maintaining those rule bases was harder still. This became known as the knowledge-acquisition bottleneck. GOFAI was strongest when the symbols were already there. It was weakest when the system had to discover them for itself.
Of course, we already know a mechanism for automatically discovering features. The rival instinct is known as connectionism (or “neural”) and forms the intellectual hinterland of deep learning. Instead of hand-writing the rules, you build networks of simple units, spin up the GPUs and let them learn from reams of data. For decades the symbolic camp argued that “real” intelligence required explicit reasoning over symbols and that connectionist systems were just fancy pattern matchers with no real insight. Connectionists argued that useful representations should be learned rather than hand-coded. Both sides were true to some extent. Symbolic systems were interpretable and precise in narrow domains. Neural systems were flexible but, for a long time, too small and too hard to train to compete broadly.
As the deep learning section on scaling and the Bitter Lesson showed, the balance shifted when data, compute, and training methods finally lined up. Larger datasets, GPUs, better optimisers, better activations, and better architectures let neural networks learn representations that hand-crafted systems struggled to match. AlexNet’s ImageNet win in 2012 was the emblematic moment in vision. Remember Rich Sutton’s “Bitter Lesson” from the previous chapter. Methods that efficiently scale with more data and more compute do better than hand-crafted approaches. Connectionism has delivered vastly more than symbolic AI did.
The language side of the story has its own watershed. In 2017, Vaswani et al. published “Attention Is All You Need”, introducing the transformer architecture. The key idea–replacing recurrent connections with a technique called self-attention–turned out to be both more parallelisable and more capable than the recurrent networks that had until then dominated natural language processing. Within two years, early transformers (Google’s BERT, which first appeared in 2018) had broken records on nearly every language benchmark. Not long after, a variant known as generative pre-trained transformers (GPTs) showed that simply scaling up next-token prediction produced surprisingly capable text generation. AlexNet had shown that learned representations could win on images. The transformer showed the same was true for language, and at a scale that quickly outpaced anything built before it.
I think it’s fair to say that connectionism has been decisively more successful than symbolic approaches at creating AI. As late as 2023-24 you would still occasionally see symbolic AI researchers complaining online “these GPT models are only probabilistic! They hallucinate and get obvious things wrong so there’s no intelligence there!” but these voices have become quieter as LLM reasoning capabilities advanced rapidly. Still, modern AI systems are an intriguing mixture of very clever and still sometimes very dumb. So it isn’t correct to say that symbolic ideas disappeared or that the whole approach is totally discredited. Modern systems are often connectionist at the core and symbolic around the edges. The model learns representations from data, but the surrounding system may still use search, planning, tools, external memory, code, or formal constraints to keep it grounded and talking sense.
An LLM is a deep neural network, usually a foundation model built on the transformer architecture, trained on broad data and then adapted to many tasks. When people say “LLM” today they usually mean a large decoder-style language model plus some form of post-training that makes it useful as an assistant.
Let’s find out what all of that means!
GPT-2 was released in 2019 but it’s still a good starting point because many later LLMs follow the same broad recipe: tokenise text, map tokens to vectors, pass them through a stack of masked transformer blocks, and project the final state into next-token probabilities.
Let’s start with the name: generative pre-trained transformer. “Generative” obviously means that it’s designed to generate text. That implies certain architectural choices. Modern chat LLMs are decoder-style models (explained further below) that generate one token at a time. “Pre-trained” means that the model goes through an initial training period where it’s given a very large text corpus and learns to predict the next token at every point. That gives the model an overall understanding of the world. What’s so cool about LLMs is that they have so much knowledge. You don’t need to give them thousands of examples of your own training data. Finally, “transformer” means that it uses transformer blocks, which we’ll cover shortly.
The first step is tokenisation of the input text. As in the machine-learning chapter, we need to take messy raw input and turn it into a representation the model can work with. LLMs don’t process text directly. They work with tokens, pieces of text that might be whole words, parts of words, punctuation marks, or bytes. Since computers fundamentally work with numbers, tokenisation converts text into a sequence of integer IDs that the model can process.
Splitting words into these integer IDs isn’t straightforward. Character-level input is flexible but inefficient. The model would have to learn “c-a-t” character by character. At the other extreme, a whole-word vocabulary captures more meaning per unit but explodes in size if you want to handle every possible word. Subword tokenisation strikes a balance between keeping the total vocabulary size reasonable and being flexible enough to handle all inputs. With this approach, common strings get their own tokens but rare strings are broken down to their constituent pieces.
A common family of tokenisation algorithms is Byte Pair Encoding (BPE). The algorithm starts with small units and repeatedly merges frequent pairs into larger ones until it reaches a pre-defined vocabulary size. That vocabulary size is itself an important hyperparameter. A smaller vocabulary keeps things compact, but it makes sequences longer because more words get split apart. A larger vocabulary makes sequences shorter, but it costs more memory and gives you more rare entries that are hard to train well. The idea behind merging is that it naturally discovers patterns in language. If “th” appears constantly in the corpus, it’s a good candidate to merge. If “the” is even more common, that can become a token too. The result reflects patterns in the input corpus rather than any linguistic theory. Some concrete examples are shown in Listing 1.
"Hello, world!" : ["Hello", ",", " world", "!"]
"hello, world!" : ["hello", ",", " world", "!"]
"The cat sat" : ["The", " cat", " sat"]
"computational" : ["comput", "ation", "al"]
"defenestration" : ["def", "enestr", "ation"]
Several practical consequences are evident in the example. Capitalisation can matter, so “Hello” and “hello” may become different tokens. Common words often stay intact, while technical or rare words get chopped into reusable pieces. The whole motivation of BPE is to keep frequent patterns whole when possible, but fall back to smaller fragments when necessary.
Remember the actual token IDs the LLM sees are numbers, not string fragments as in the example. LLM skeptics liked to point out that LLMs couldn’t correctly answer “how many ’r’s are in ‘strawberry’?” The model only sees numerical representations of chunks like “straw” and “berry”. It doesn’t actually see the characters in the input and so it can’t trivially count them as we can. It’s confusing for us because we see the tokens converted back to strings, but the model doesn’t. The fact that many powerful models failed to answer correctly is therefore not proof that they’re actually really dumb. It does show that models are constrained by their architecture, and understanding those architectures improves our understanding of LLMs.
Once we have token IDs, the model looks each one up in an embedding table. A token ID is just an index into the embedding table, nothing more. The embedding table maps that bare integer to a long vector (i.e. array) of floating-point numbers. GPT-2 uses vectors of between 768 and 1600 numbers, depending on the variant, while newer models use thousands. This dimensionality, often called
, is one of the most important hyperparameters in the whole design. A single integer can’t represent the whole range of meaning present in a single token. For example, whether “bank” means a financial institution or a river bank. A 768-dimensional vector has room for such nuance–and for the word’s grammatical role, its relationship to nearby words, and much else besides. The embedding table itself is trained jointly with the rest of the model, but you can also get specialist embedding models which are useful for text analysis.
So, the token ID is a number uniquely identifying each token. We map each ID to an embedding vector of length
. Through the pre-training process, the model has learned to encode lots of relevant semantic information in each token’s embedding vector. From the input prompt we generate a sequence of embedding vectors. These will pass through the whole model, gradually picking up more meaning as they work through the layers. From this point onwards, if I refer to the model operating on “tokens”, I mean the token’s embedding vector.
Up to this point there has been no notion of ordering. Transformers operate on sets of vectors and so once we pass in the embedded input we lose all sense of tokens’ relative position. You might think that we could just provide the index of each token’s position in the input sequence, but then we’re back to single integers that don’t encode much information. Instead, GPT-2 adds another learned vector of length
, known as positional embeddings, so the network knows where each token sits in the sequence and can express complex, useful concepts like “previous clause”. A token embedding says what kind of symbol the token is. The positional information says where it appeared in the input.
The sequence of embeddings then passes through a stack of transformer blocks. Each block has two main parts. First comes the real magic of transformers: self-attention. Then comes a small feedforward network, more commonly referred to as multi-layer perceptrons (MLP) in this context. Residual connections and layer normalisation hold the whole stack together and keep it trainable.
Inside the complete chapter
Continue reading
Get the complete chapter in The Computer Science Book, along with twelve more chapters covering the foundations from computer architecture to modern AI.
Buy the ebook - $19.99The ebook includes PDF and EPUB formats and a 28-day money-back guarantee.
Not ready to buy yet?
Subscribe and I'll send you a free, 45-page roadmap through computer science — what to learn, in what order, and what to skip — plus the occasional CS deep dive.
No spam. Unsubscribe anytime.