Cosine similarity and the dot product
I wrote part one of this series assuming you were comfortable with dot products and cosine similarity. Someone read it and said, fairly: “I’m useless at maths, and none of that landed.” So this is the version I should have handed them first — the same ideas, built from zero, no maths background assumed. If you can multiply two numbers and add them, you already have everything you need.
The whole trick behind a model’s sense of meaning fits in one sentence: meaning becomes geometry. Words turn into positions in space, and “close in space” is engineered to mean “close in meaning.” Everything below is just unpacking that sentence.
1. Words become coordinates
A computer can’t read the word cat. It only does arithmetic on numbers. So the first move is to hand every word a list of numbers — a coordinate, a spot on a map. The part that makes it useful: the map is arranged so that words with similar meaning land near each other, and unrelated words land far apart.

Real encoders don’t use two dimensions like my drawing — they use hundreds (384 and 1536 are common). You can’t picture 384 axes, but the idea doesn’t change: it’s still a map, just with far more directions to spread meaning across.
2. Similarity is an angle, not a ruler
Here is the one upgrade that unlocks the rest. Draw each word as an arrow from the centre of the map out to its dot. Now you can ask a sharper question than “how far apart are they?” — you can ask “do these two arrows point the same way?”

Modern encoders stretch every arrow to the same length first — that’s what “L2-normalised” means, every vector pinned to a unit sphere. Once all arrows are the same length, length can no longer tell them apart, so direction is the only thing left that carries meaning. That is precisely why we measure the angle and ignore the distance.
3. Cosine turns the angle into one number
An angle in degrees is an awkward thing to compute with. We want a single number where bigger simply means more similar. Cosine is exactly that translator: give it the angle, it hands back a number between −1 and 1.

That’s the entire scale. It has a name, cosine similarity, and it is the number every retrieval system in the world ranks by.
4. The dot product: how a computer actually does it
A CPU doesn’t own a protractor — it never measures an angle. It has the two coordinate lists and nothing else. So how does it get a cosine out of them? With the cheapest operation there is: multiply the matching slots, then add the results. That is the dot product, start to finish.

In code it’s a one-liner:
import numpy as np
# two unit-length embeddings (already normalised)
cat = np.array([0.6, 0.8])
dog = np.array([0.8, 0.6])
print(cat @ dog) # 0.96 -> very similar
print(cat @ np.array([-0.8, 0.6])) # 0.0 -> unrelated (a right angle)
No trigonometry, no angle measured anywhere — just one multiply and one add per dimension.
5. Why the dot product is the cosine
This is the part I care about most, because it’s where the “scary formula” quietly dissolves. The textbook definition of the dot product is this:

Read it in plain words: multiply-and-add equals (length of a) × (length of b) × (cosine of the angle). The whole formula is just bookkeeping for the two lengths. And once you’ve normalised every vector to length 1, those lengths are both 1 — they disappear, and you’re left with a · b = cos θ. That is the entire reason production systems normalise their embeddings: it makes similarity free — a single dot product, with nothing to divide afterwards.
6. Where the coordinates come from
One question I skipped: who decided that cat = [0.6, 0.8]? Nobody. The model invents every coordinate during training, through a process with a wonderfully blunt name.

Start with random coordinates — pure noise, cat might sit next to pizza by accident. Then repeatedly show the model a pair that should be similar (a caption and its image, a question and its answer) and nudge those two vectors closer; take unrelated things and shove them apart. The objective has a name, InfoNCE, but the property that matters is that it’s relative: it only insists that related things score higher than unrelated ones, never that a pair hits a specific number. That’s also why you can’t compare a 0.8 from one model against a 0.8 from another — each score only ranks meaningfully inside its own space.
Why any of this matters
Because comparing two meanings collapses to one multiply-and-add over a couple of coordinate lists, a database can score a query against millions of stored vectors in milliseconds. The elegant geometry is why the number is meaningful; the embarrassingly cheap arithmetic is why it’s usable at scale. Every semantic search box and every RAG pipeline you’ve touched is, underneath, this one dot product run a few million times.
Next I’ll build on these vectors and get into attention — how a model lets words look at each other and shift their meaning in context. Same spirit as here: intuition first, symbols last.