← All Vector search lessons

Vector search / HANDS-ON LESSON

Calculate cosine similarity by hand

Compare same, perpendicular, and opposite directions with a small executable vector example.

BeginnerAbout 15 min5 practice questionsReviewed 2026-10-05SaveMyToken editorial

WHAT YOU WILL BUILD

A similarity calculation that rejects zero-length and incompatible vectors.

Cosine similarity divides the dot product by the two vector lengths. For this nonzero real-vector example, scaling a vector without changing its direction does not change cosine similarity. The number measures a geometric relationship, not factual truth.

Before you start

Use a text editor and Node.js 22 or newer ↗. Check your version with node --version. Save the downloaded file in an empty folder, then open a terminal in that folder.

All data is included. No packages, account, or API key are required. The two-dimensional vectors are handwritten arithmetic examples. They are not embeddings produced from the policy text or scores for an AI model.

Download the lab (.mjs)

FOLLOW ALONG

Work through the example.

  1. 01

    Predict three similarities

    Compare [1,0] with [10,0], [0,1], and [-1,0]. Predict 1, 0, and -1 before running the script.

  2. 02

    Run the calculation

    Check the three printed values. Follow the dot product and normalization terms in the cosine function, especially why [10,0] has the same direction as [1,0].

  3. 03

    Inspect rejected inputs

    The assertions reject a zero vector and unequal dimensions. Try a NaN coordinate as another invalid input. A production implementation must also follow its embedding model's metric contract.

  4. 04

    Compare a fourth direction

    Add [1,1]. Its cosine with [1,0] is approximately 0.7071. Use a numeric tolerance in your assertion instead of exact equality for the rounded value.

THE COMPLETE LAB

Run it locally.

Run this command from the folder containing your downloaded file:

node vector-similarity.mjs

View or copy the complete JavaScript
// SaveMyToken local lab. Run with Node.js 22 or newer.
import assert from "node:assert/strict";

// Handwritten 2D vectors for arithmetic; not language embeddings.
function cosine(a, b) {
  if (!a.length || a.length !== b.length || ![...a, ...b].every(Number.isFinite))
    throw new Error("Invalid vectors");
  const normA = Math.hypot(...a), normB = Math.hypot(...b);
  if (normA === 0 || normB === 0) throw new Error("Zero vector");
  return a.reduce((sum, x, i) => sum + x * b[i], 0) / normA / normB;
}
assert.throws(() => cosine([0, 0], [1, 0]), /Zero vector/);
assert.throws(() => cosine([1], [1, 0]), /Invalid vectors/);
assert.equal(cosine([1, 0], [10, 0]), 1);
console.log("Same direction:", cosine([1, 0], [10, 0]).toFixed(2));
console.log("Perpendicular:", cosine([1, 0], [0, 1]).toFixed(2));
console.log("Opposite:", cosine([1, 0], [-1, 0]).toFixed(2));

Expected output for the unchanged example

Same direction: 1.00
Perpendicular: 0.00
Opposite: -1.00

The assertions also check the baseline behavior. After changing an input, predict the result and update the relevant assertion.

NOW CHANGE ONE THING

Make the example your own.

Compute raw dot products for [1,0] and [10,0]. Explain why their dot products differ even though their cosine similarities are identical.

You are done when…

The original outputs match your hand calculations, and invalid vectors are rejected rather than assigned a misleading score.

If something goes wrong

Do not mix embeddings from different models just because they have the same dimension. Their coordinate spaces need not be compatible.

EXPLAIN WHAT YOU LEARNED

Interview practice

Try answering aloud before opening the reference answer. These are original learning questions, not a record of any employer's interviews.

01How is cosine similarity calculated?

Take the dot product of two nonzero vectors and divide by the product of their lengths. Validate matching dimensions and finite coordinates first.

Watch for: The formula is undefined when either vector has zero length.

02When do dot product and cosine give the same ordering?

For vectors normalized to unit length, their dot products equal their cosine similarities. Otherwise vector magnitude can change dot-product ranking.

Watch for: Do not normalize blindly if the embedding model expects a different scoring method.

03Is a similarity score a probability of correctness?

No. It is a score under a particular representation and metric. Calibrate retrieval decisions with labeled tasks and verify answer claims separately.

Watch for: A high semantic match can retrieve an outdated or factually wrong passage.

04Can embeddings from different models be mixed?

Usually they must be regenerated or kept in separate compatible indexes. Equal vector lengths alone do not align the underlying spaces.

Watch for: Changing only the query model can silently damage retrieval.

05How should you choose an embedding model?

Evaluate representative language, document types, queries, and relevance labels. Compare retrieval quality with latency, storage, and total processing cost.

Watch for: A larger dimension alone does not prove better results for your workload.

Practice more vector search questions

Sources and further reading

The explanation and local exercises were written for SaveMyToken. These references support the underlying concepts; the sample outputs describe only the supplied examples.

Sentence Transformers: semantic textual similarity ↗