Vector Similarity Search: Metrics & Approximate Methods › Worked Example: Metrics in Action
Language AI HandbookAll chapters Vector Similarity Search: Metrics & Approximate Methods › Worked Example: Metrics in ActionOne section · Sections in this chapter5 / 11 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Let's make these metrics concrete with a small example that illustrates the key differences between direction-based and position-based measures. Suppose we have a query vector and four document vectors, all in for visualization simplicity. The low dimensionality lets us reason about the geometry directly, and the principles we observe generalize straightforwardly to the hundreds of dimensions used in real embeddings.
These four vectors were chosen deliberately to illustrate specific geometric relationships. Notice that , so it points in exactly the same direction but has 3 times the magnitude. This makes it a perfect test case for the distinction between direction-based and position-based metrics: any direction-based metric will consider identical to , while any position-based metric will see them as far apart. Meanwhile, , pointing in the exact opposite direction, which should produce the worst possible cosine similarity. The vector is the subtlest case: it is close to in both direction and magnitude, differing only by small perturbations in each component. Finally, points in a substantially different direction, with a large component in the third dimension where has only a small value.
Before computing anything, we can reason geometrically about what to expect. Cosine similarity between and should be 1.0 (identical direction), while cosine similarity between and should be (opposite direction). Meanwhile, is close to in both direction and magnitude, so it should also have high cosine similarity, though not a perfect 1.0.
Euclidean distance between and should be small (they are nearby), while the distance between and will be large despite their identical directions (because is far away in absolute terms). This is the signature behavior that distinguishes position-based from direction-based metrics.
import numpy as np
# Define query and document vectors
q = np.array([1.0, 2.0, 0.5])
v1 = np.array([1.1, 1.9, 0.6])
v2 = np.array([3.0, 6.0, 1.5])
v3 = np.array([0.0, 1.0, 3.0])
v4 = np.array([-1.0, -2.0, -0.5])
vectors = {"v1": v1, "v2": v2, "v3": v3, "v4": v4}
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def euclidean_distance(a, b):
return np.linalg.norm(a - b)
def manhattan_distance(a, b):
return np.sum(np.abs(a - b))
def dot_product(a, b):
return np.dot(a, b)
# Calculate metrics for all vectors
results = []
for name, v in vectors.items():
results.append(
{
"name": name,
"cos": cosine_similarity(q, v),
"dot": dot_product(q, v),
"euc": euclidean_distance(q, v),
"man": manhattan_distance(q, v),
}
)Vector Cosine Sim Dot Product Euclidean Manhattan ------------------------------------------------------------ v1 0.997 5.200 0.173 0.300 v2 1.000 15.750 4.583 7.000 v3 0.483 3.500 2.872 4.500 v4 -1.000 -5.250 4.583 7.000

The results confirm our predictions. By cosine similarity, scores a perfect 1.0 (same direction as the query) while scores (opposite direction). But by Euclidean distance, is the closest neighbor (only 0.1732 away), while is much farther despite its perfect directional alignment.
This example highlights the core difference between direction-based metrics (cosine) and position-based metrics (Euclidean). Cosine similarity asks, "Which document is most topically aligned with the query?" Euclidean distance asks, "Which document is closest to the query in the embedding space?" For normalized vectors these questions have the same answer, but for unnormalized vectors they can diverge significantly.
Now let's see what happens when we normalize the vectors:
# Normalize all vectors to unit length
q_norm = q / np.linalg.norm(q)
vectors_norm = {name: v / np.linalg.norm(v) for name, v in vectors.items()}
# Calculate metrics for normalized vectors
results_norm = []
for name, v in vectors_norm.items():
results_norm.append(
{
"name": name,
"cos": cosine_similarity(q_norm, v),
"dot": dot_product(q_norm, v),
"euc": euclidean_distance(q_norm, v),
}
)Vector Cosine Sim Dot Product Euclidean ------------------------------------------------ v1 0.997 0.997 0.076 v2 1.000 1.000 0.000 v3 0.483 0.483 1.017 v4 -1.000 -1.000 2.000
After normalization, cosine similarity and dot product produce identical values, confirming the mathematical relationship we derived earlier: for unit vectors, . And the rankings from all three metrics now agree: the vectors with higher cosine similarity also have smaller Euclidean distance, exactly as the identity predicts. Notice in particular that , which was far from the query before normalization, now sits at exactly the same point as the normalized query, with Euclidean distance 0.0. Normalization collapsed the magnitude information and left only direction.
This is the practical reason why normalizing embeddings before indexing is so common: it makes the choice of metric irrelevant. Once all vectors lie on the unit sphere, cosine similarity, dot product, and Euclidean distance all induce the same ranking over candidates. You can then choose whichever metric your library computes most efficiently, typically the dot product, without worrying about whether it matches the conceptual notion of similarity your model was trained with.
Visualizing the Metric Distribution
Another way to understand how metrics differ is to examine their distribution over a realistic embedding collection. When you compute all pairwise similarities in a real embedding collection, the distribution reveals the geometry of the embedding space: how tight the clusters are, how much separation exists between topics, and what similarity values to expect for relevant versus irrelevant documents.

The distribution shows how vector search works at scale. Most documents in the collection are only weakly similar to any given query: the bulk of cosine similarities cluster near zero. The relevant documents (simulated here as vectors near the query direction) form a distinct right tail. A retrieval system needs to identify this tail efficiently, which is why even small differences in the similarity metric can affect which documents make it into the retrieved set.