# Five core ideas, or: what is actually happening inside a clanker

> Source: <https://latentheat.dev/blog/five-core-ideas>
> Published: 2026-08-02 23:00:00+00:00

03 Aug 2026

by flirp

# Five core ideas, or: what is actually happening inside a clanker

Before the great clanker war of 2037 begins, wouldn't it be nice to know what drives these incomprehensible black boxes? Well, today I'll endeavour to break it down til even Qwen's weakest model can understand it.

## Five core ideas

- Token embedding and the corpus, what is latent space?
~~My little pony~~~~multi~~tri layer perceptrons- The mixologists: attention heads. A wise man once said that's all you need.
- Decoding and hyperparameters
- Training and inference quirks

With these five core ideas, you too can stare into the cold eyes of a clanker, and empathise.

## 1. Token embedding and the corpus

So how do we make a machine talk? First, it must recognise words. But words are fairly arbitrary. Token 4823 is "dog". Token 4824 is "quantum". They are, numerically, next door neighbours, and that fact tells you absolutely nothing about either of them. So we need to find an embedding for tokens (words, or more often bits of words, which will matter later) into vectors, somewhere that distance actually means something.

Enter the matrix.

It's a lookup table. Token 4823? Fetch row 4823. That is the whole trick. A textbook will tell you it's a matrix multiply against a one hot vector, and technically it is, but nobody has ever implemented it that way and nobody should.

This is the first layer of the transformer, and its job is exactly that embedding, into d dimensions (ranging from 768 to 16k).

Initially the assigned vectors are random, but with enough training (trying to predict from a stupidly large training corpus), slowly, patterns emerge. Words used in similar ways drift to similar positions. Nobody wrote that rule down anywhere; it falls out of trying to predict the next word.

### The residual stream

So we have a space. But it isn't just where tokens start; it's where everything happens.

Once a token has its vector, that vector goes on the bus. Every component from here on reads from the bus and writes back to it, and the bus never resets and never changes width. Same d, top to bottom.

Here is the entire architecture, and I do mean the entire thing:

```
x = x + Attn(LayerNorm(x))
x = x + MLP(LayerNorm(x))
```

Look at what those lines actually do. Nothing flows *through* a block. Each sublayer takes a copy of the stream, has a think about it, and adds its answer back on. Both of them only ever add.

That unbroken addition path is why you can stack eighty layers and still train the thing. Gradients get a clear run from the top to the bottom without being put through eighty matrix multiplies on the way down. Hence "residual": a block isn't computing the answer, it's writing a correction to whatever is already there.

If you've played Factorio you already understand this, and I'm sorry to be the one to tell you that your four hundred hours were research. It's a main bus. Fixed lanes running the length of the base, assemblers tapping off what they need and merging their output back on, nothing routed through anything. The analogy holds right up until belt compression, at which point it stops, and so does the comparison, and so did my last base.

One difference though. Reading the stream copies rather than removes. Nothing is consumed and nothing is ever erased. The residual stream is append-only, which makes it the only well-behaved log file in the entire system.

And that last bit is the part I actually care about. If every component only ever adds, then the vector you end up with is a *sum*. Layer 40 head 3 put this in. Layer 12's MLP put that in. You can pull the final vector apart and ask who contributed what, which is a very odd thing for a black box to let you do. Working out who put what on the bus is, more or less, the whole field of interpretability.

Then the round trip. After the last layer a matrix maps the vector back to a score for every token in the vocabulary, and in a lot of models that matrix is just the embedding table transposed, the same one from the start, run backwards. Token into the space, work happens, space back to token.

## 2. ~~Multi~~ Tri layer perceptrons

Most readers will be familiar with MLPs by now, so I'll summarise quickly.

A multi layer perceptron is a feed forward neural network: input dimension, expand into a larger hidden dimension, back down to an output dimension. Each line has a weight and each node an activation function.

An MLP can, in theory, learn anything. This is the universal approximation theorem, and like most things with "universal" in the name it turns up with an asterisk you could park a datacentre on.

Each MLP section only modifies each token's own part of the residual stream, one at a time (or just once during auto regression). There is no cross over; that comes at the next step, attention.

These layers transform the latent space representation and do the non linear work required for any complex patterns to emerge.

One final essential note before we move on. There are multiple MLP sections and attention heads and they interleave.

MLPs make up around 2/3rds of a transformer's weights. The standard interpretation is that the up projection looks for patterns and the down projection puts them back into the latent space format. Two thirds of the weights, and "the standard interpretation" is as good as it currently gets. We are still largely guessing what is in there.

## 3. Attention: pull a rabbit out of a KV cache

Watch closely, magic happens here. Here's where your VRAM goes to die.

What is attention? Attention is where previous tokens affect the current token's latent state. This is the only place inter-token mixing happens.

As each token passes an attention head, three things happen.

The head builds a query, a key and a value for the token. All three are just its bit of the residual stream pushed through a learned matrix, one matrix each. The query is the question it's asking. The key is what it's advertising to everyone else. The value is what it actually hands over if it gets picked.

That query gets compared against the key of every token behind it, one dot product per position. Big number means "you're relevant to me", small number means "you're not". Squash the lot through a softmax and you've got weights that sum to 1.

Those weights pull a blend of the values, and the blend gets added back onto the residual stream.

That's also why it's a KV cache and not a QKV cache. The keys and values of old tokens get consulted again at every future step, so they're worth hanging onto. The query gets used once and binned.

Softmax, for the uninitiated, takes a list of arbitrary numbers and converts them into a set of weights that are all positive and sum to exactly one. It does this by exponentiating each element and then dividing by the sum of all the exponentiated elements, which has the effect of

no. I'm not doing this. I'm not your first year CS lecturer and you have a search engine. Big numbers become big weights, small numbers become small weights, they all add up to 1. Onwards.

There are often multiple attention heads in between MLP layers, front loaded, as attention is used to mix for grammar and syntax more than latent reasoning.

### Types of heads

Head types are not built. They form on their own during training, and get worked out after the fact by researchers staring at heatmaps, which is also how constellations happened.

- Previous token head
- Positional head
- Syntactic heads
- Duplicate token head
- Induction head
- Copy suppression head
- Name mover head
- S-inhibition head
- Backup head
- Attention sink

My favourite is the sink. Softmax insists the weights sum to 1, so a head with nothing to say is legally obliged to have an opinion anyway, and it dumps the whole lot on the first token in the sequence. Then, and this is the good bit, if you tidy that up the model gets worse. The shrug is load bearing.

## 4. Decoding and hyperparameters

End of the road; what happens when the residual stream hits the last layer?

Well, the same as the first layer in reverse (with caveats).

We end with a latent representation that could be representing any one of many tokens, a superposition if you will. We need to decode. Pick one token from this distribution of possible tokens.

To get an interesting output (sometimes not) we don't always want the most likely token. Always taking it would make the transformer deterministic.

This is where temperature comes into play. Temp 0 means always take the most likely token. As we increase T, we flatten the curve. T divides the logits before softmax ever sees them, which means temp 0 is a division by zero. Every implementation quietly special cases it to "just take the biggest one". The most popular temperature setting is the one the maths forbids.

This one simple value moves us from static to dynamic. Push it too high and you'll get nonsense, too low and you get boring output. As it often is in life, the interesting stuff lives in the middle. At a critical point for you chaos theory nerds.

## 5. Training and inference quirks

Here's the thing that took me an embarrassingly long time to get straight: training is not autoregressive.

I had a picture in my head of the model writing out a sentence one word at a time, checking each guess against the real text, getting told off, and shuffling on to the next word. Reasonable picture. Completely wrong.

In training, the model sees the whole sequence at once and predicts every position simultaneously. Position 1 predicts token 2, position 2 predicts token 3, and so on to the end of the document, all in a single forward pass. It never generates anything, because the real text is already sitting right there. The text is both the input and the answer key.

The causal mask is what makes this legal. Every position can look left and nothing can look right, so no position can cheat by reading the token it is supposed to be predicting. Without the mask this would be the world's most expensive way to learn the identity function.

And that's why training is so much more efficient than it has any right to be. One pass over a four-thousand-token document doesn't give you one training example. It gives you four thousand.

The loop you were imagining does exist. It just isn't here. It only turns up at generation time. Same objective, completely different execution. That is where the quirks come from.

### Prefill and decode

Generation happens in two phases, and they behave nothing alike.

**Prefill** is the prompt. Every token of it goes through at once, exactly like training, and the K and V for the whole lot get written into the cache. This is your GPU doing the thing it is actually good at: one enormous matmul, all cores busy, compute-bound and happy.

**Decode** is everything after. One token at a time, each one appending a single new K and V and reading the entire history back out. There is almost no arithmetic here. The GPU spends decode shuffling the cache in and out of memory and waiting, which is a memory-bandwidth problem wearing a compute problem's clothes.

Once you've seen that split, a lot of things that looked arbitrary suddenly make sense:

**Time-to-first-token scales with prompt length. Tokens-per-second barely does.** Those are two different phases and only one of them cares how long your prompt was.**A long prompt costs you VRAM before you've seen a single output token.** That's prefill filling the cache, and it's the bill from part 3 arriving.**Batching helps enormously.** Decode is memory-bound and mostly idle, so running eight conversations at once costs barely more than running one. Your tokens per second per user drops a little; your tokens per second in total goes up a lot.

### Three quirks that fall straight out of all this

**It cannot count the letters in "strawberry".** Nothing to do with intelligence. It has never seen a letter in its life. It saw `str`

, `aw`

, `berry`

, three arbitrary integers standing in for three chunks of text, and you have asked it how many times a shape appears inside a shape it cannot look at. Ask it to spell the word out with spaces first and the accuracy jumps, because now the letters are actually tokens and it can finally see the thing you're asking about.

**Temperature 0 is not reproducible.** Deterministic, yes. Reproducible, no. Floating-point addition isn't associative, GPU kernels reduce in whatever order is fastest, and the fastest order depends on your batch size, which depends on how many other people happen to be talking to the same server at the same moment. Set temperature to 0, ask twice, get two different answers, and the reason is that a stranger in another timezone changed your batch size. Your determinism depends on people you will never meet.

**It does not remember your conversation.** There is no state between calls. The KV cache is the closest thing the model has to a memory and it lives for exactly one request. Everything that feels like memory is your chat app quietly re-sending the entire conversation, from the top, every single message. The context window is not the model's attention span, it's how much of the transcript your client can afford to post back every single time.

I find that one a bit grim, honestly. Every message you send, it reads the entire conversation start to finish, for the first time, and then forgets you again.

With these five core ideas, you too can stare into the cold eyes of a clanker, and empathise.

### Get the next one

New experiments, negative results included. No schedule, no spam, unsubscribe by replying.

### Comments

Found a hole in this? Say so. Corrections and replications are the whole point, and a comment pointing at a mistake is worth more to me than a compliment.
