Similarity and Distance
Once your text is a set of vectors, "find the most relevant document" becomes "find the nearest vector" β a geometry problem. The whole value of embeddings depends on one measurement: how close are two vectors? Get the distance metric right and semantic search just works; get it wrong and your retrieval silently degrades.

Nearby vectors mean similar meaning
The embedding model was trained to place similar text close together, so proximity in vector space is similarity in meaning. To answer a question, you embed the question, then look for the stored chunks whose vectors sit nearest to it. Those nearest chunks are your best candidates for a grounded answer β which is exactly what the AI Tutor does before it writes a response.
The standard way to measure "nearness" for text embeddings is cosine similarity.
Cosine similarity vs. cosine distance
Cosine similarity measures the angle between two vectors, ignoring their length:
- +1.0 β vectors point the same direction β meanings are very similar.
- 0.0 β perpendicular β unrelated.
- β1.0 β opposite directions β opposite meaning (rare with text).
Because angle ignores magnitude, a short question and a long paragraph about the same topic still score as highly similar β which is what you want.
In practice databases work with cosine distance, which is just 1 β cosine similarity:
- 0.0 distance β identical meaning (smaller is better).
- 1.0 distance β unrelated.
- 2.0 distance β opposite.
So when you search, you sort by distance ascending and take the smallest values. SQL Server
2025 exposes this directly as VECTOR_DISTANCE('cosine', a, b).
Searching in SQL Server 2025
A semantic search is conceptually a single ordered query. In LyraLearn the AI Tutor embeds your question into a 768-dim vector, then asks SQL Server for the closest lesson chunks:
SELECT TOP (5) chunk_text,
VECTOR_DISTANCE('cosine', embedding, @question_vector) AS dist
FROM LessonChunks
ORDER BY dist ASC;
The TOP (5) is the k in k-nearest-neighbor search β you keep the few closest chunks, not
everything. Those become the grounding context fed to the model.
Practical pitfalls
A few things that trip up real systems:
- Mismatched models β distances are only meaningful between vectors from the same model.
A
nomic-embed-textvector and an Azure vector have no comparable geometry. - Near-duplicate flooding β the top results can all be the same passage chunked differently; de-duplicate or diversify so the model sees varied evidence.
- A "nearest" match can still be irrelevant β there is always a closest vector even when nothing truly answers the question. Apply a distance threshold: if the best match is still far away, treat it as "no good evidence" and let the system refuse rather than answer from a weak match. That threshold is grounding's safety valve.