AI Engineer Roadmap All lessons Interactive Quiz MernStackDev GitHub

Cosine Similarity

Play the interactive lesson: Cosine similarityRead on GitHub
On this page
  1. Explain it like I'm new
  2. Watch it
  3. How it works
  4. Code example
  5. When to use it / when not to
  6. Common mistakes
  7. Recap
  8. Interview questions
  9. Go deeper

Level: Beginner · Reading time: 7 min · Phase: 1 — RAG Foundations

In one line: Cosine similarity measures how closely two vectors point in the same direction, from −1 (opposite) through 0 (unrelated) to 1 (same direction), ignoring their length.

Before you start: Embeddings. You should know that an embedding is a list of numbers (a vector) that represents the meaning of a piece of text.

Explain it like I'm new

Picture two people pointing at the sky. If they point at the same star, their arms are aligned, even if one person has longer arms. Cosine similarity only cares about the direction of the arms, not their length.

For text embeddings, direction carries the meaning. A short sentence and a long paragraph about the same topic often point in a similar direction even though their vectors may have different lengths. Cosine similarity says "these are about the same thing" without being fooled by length.

The cosine is a function from school geometry. The cosine of the angle between two arrows is 1 when the angle is 0°, 0 when the angle is 90° (a right angle), and −1 at 180°.

Words to know:

Watch it

Cosine similarity: The angle between two embedding vectors tells you how similar their meaning is.
Cosine similarity: The angle between two embedding vectors tells you how similar their meaning is.

It plays on a loop. Read the caption in the box, one step at a time. Want to go at your own pace? Step through it with Previous and Next.

How it works

  1. Compute the dot product of the two vectors.
  2. Compute the length of each vector.
  3. Divide: cos(a, b) = (a · b) / (‖a‖ × ‖b‖).
        b = [2, 4]
       /
      /   angle 0°  -> cos = 1.0   (a = [1, 2] lies on the same line)
     /
    o-------- c = [2, -1] is at 90° to a -> cos = 0.0

Worked example with a = [1, 2, 3] and b = [2, 4, 6]:

With c = [3, 0, −1]: a · c = 3 + 0 − 3 = 0, so cos(a, c) = 0 → perpendicular, "unrelated".

Shortcut: if both vectors are normalized (length 1), the denominator is 1, so cosine similarity equals the dot product. Many embedding pipelines normalize for this reason.

Cosine distance is often defined as 1 − cosine similarity, so 0 means identical. Check which one your database reports.

Worked example

A search has one query vector q = [1, 0] and three stored chunk vectors. Score each with cosine similarity.

  1. [2, 0]: dot = 2, lengths 1 and 2, so cos = 2 / (1 × 2) = 1.0. Same direction, just longer.
  2. [0, 3]: dot = 0, so cos = 0.0. At a right angle, unrelated.
  3. [-1, 0]: dot = −1, lengths 1 and 1, so cos = −1.0. Opposite direction.
  4. Ranking by highest score: [2, 0], then [0, 3], then [-1, 0].

Notice that [2, 0] ties a vector of length 1 pointing the same way. Length played no part, only direction.

Code example

From code/rag_vector_math.py:

import math

def dot(a, b):
    return sum(x * y for x, y in zip(a, b))

def norm(a):
    return math.sqrt(sum(x * x for x in a))

def cosine_similarity(a, b):
    na, nb = norm(a), norm(b)
    if na == 0 or nb == 0:
        return 0.0
    return dot(a, b) / (na * nb)

print(cosine_similarity([1, 2, 3], [2, 4, 6]))    # 1.0
print(cosine_similarity([1, 2, 3], [3, 0, -1]))   # 0.0
print(cosine_similarity([1, 0], [-1, 0]))         # -1.0

Run: cd 01-rag-foundations/code && python rag_vector_math.py

In real projects with NumPy (pip install numpy):

import numpy as np

def cosine(a, b):
    a, b = np.asarray(a, float), np.asarray(b, float)
    return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))

# Many docs at once: normalize rows, then one matrix product
docs = np.random.rand(1000, 384); q = np.random.rand(384)
docs /= np.linalg.norm(docs, axis=1, keepdims=True); q /= np.linalg.norm(q)
scores = docs @ q            # 1000 cosine similarities
top5 = np.argsort(-scores)[:5]

When to use it / when not to

Common mistakes

Recap

If you remember only three things:

Interview questions

1. Why is cosine similarity popular for text embeddings? <details><summary>Answer</summary> It compares direction only, so differences in vector length (often unrelated to meaning) do not affect the score, and many embedding models are trained with cosine-based objectives. </details>

2. How do cosine similarity and dot product relate? <details><summary>Answer</summary> Cosine is the dot product divided by both lengths. For unit-length vectors the lengths are 1, so the two are equal and rank results identically. </details>

3. What does a cosine similarity of 0 mean? <details><summary>Answer</summary> The vectors are perpendicular: no shared direction. For embeddings that usually means unrelated content, though in practice scores for unrelated text are often small positive numbers rather than exactly 0. </details>

Go deeper

Prev: Vector Databases · Next: Euclidean Distance · Back to phase: Phase 1