T1 · Intermediate · 7 minStable · Last reviewed: 2026-08-19Early draft

Measuring Vector Similarity

In one line · To tell how close two texts are in meaning, you measure the distance or angle between their vectors — most commonly with cosine similarity.

Glossary:EmbeddingModelReranking
Why it matters

This is the core that ranks every semantic-search result: the metric decides what rises to the top and what sinks, so getting it wrong breaks the whole search.

Cosine looks at direction, not length: two vectors pointing the same way are similar even if one is longer. The score runs from -1 (opposite) to 1 (same meaning).

An analogy

Like two compass needles: you don't care that one is longer, only whether both point the same way. Cosine measures exactly that direction and ignores the length.

The query 'how do I restart the server' scores high cosine with an article on 'rebooting the host' and low with 'koshari recipe' — so you show the first and drop the second.

How it works

Cosine similarity is the dot product of the two vectors divided by the product of their lengths — that strips out magnitude and keeps only direction. Other metrics exist: raw dot product (sensitive to length) and Euclidean distance (straight-line gap). Many models output normalized vectors (length 1), in which case cosine and dot product give the exact same ranking. Practical rule: use the metric the model was trained for — the model card tells you.

// Cosine similarity between two vectors
function cosine(a: number[], b: number[]): number {
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na += a[i] * a[i];
    nb += b[i] * b[i];
  }
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
// Near 1 = same meaning, near 0 = unrelated
Practice

🧪 Try it: write one query and 5 sentences (2 close to it, 2 unrelated, 1 borderline). Embed them all with the same model, compute cosine between the query and each sentence using the function above, and sort descending. Check whether the ranking matches your intuition — the surprises are what teach you the model's limits.

Common mistakes

The biggest mistake: reading cosine as an absolute percentage — '0.8 means 80% similar.' Scores are relative per model: 0.8 can be a strong match in one model and mediocre in another; tune your threshold empirically on your own data. Second: mixing metrics — storing in an index configured for cosine and querying with Euclidean. Third: comparing similarity scores produced by two different models.

When to use it

Use cosine as the default for text similarity — it fits when meaning matters more than 'intensity,' and most embedding models are trained for it (or for dot product with normalization).

When NOT to use it

If your model was trained on unnormalized dot product (as some recommendation models are), the magnitude itself carries signal — use dot product as the model expects. And for things that aren't embeddings at all (coordinates, physical measurements), Euclidean distance is usually the better fit.

LET'S BUILD ITDone reading — now build it yourself.Rank 5 sentences by cosine to a query