What are embedding models and semantic similarity?

Short answer: Embedding models learn to place meaning in vector space; semantic similarity is closeness of those vectors.

The model decides where each phrase lands. Distance or similarity scores then estimate related meaning. Understanding both explains why retrieval can match intent without exact keyword overlap, and why model choice shapes search quality.

The previous chapter established that a vector embedding represents meaning as coordinates in a space, with distance corresponding to difference in meaning. It didn’t explain how a model actually learns to place those coordinates correctly in the first place, or what “semantic similarity” concretely means once two vectors are sitting in that space. Both questions matter directly for anyone relying on embedding-based search, since the quality of that placement is what determines whether search actually finds what it should.

How Does an Embedding Model Actually Learn Where to Place Things in Vector Space?

Modern embedding models are typically trained using a technique called contrastive learning: the model is shown enormous numbers of paired examples, texts that are known to be related to each other, and trained with a simple objective, pull related pairs closer together in the vector space while pushing unrelated examples further apart. Repeated across hundreds of millions of such pairs, this process gradually shapes a vector space where genuinely similar meanings end up numerically close, purely as a consequence of the model being rewarded every time it grouped related things together and penalized every time it didn’t.

This is worth understanding because it explains why embedding models sometimes miss nuances that seem obvious to a person. The model never learned rules about grammar or meaning directly, it learned a geometry that happened to satisfy millions of contrastive examples, and any nuance that wasn’t well represented in that training data has no guarantee of being captured correctly in the resulting space.

Why Have Embedding Models Improved So Dramatically Over Time?

Early word-level models could only assign one fixed vector to each word, meaning a word with several distinct meanings got squeezed into a single representation that couldn’t distinguish between its different senses. Modern transformer-based models generate context-aware embeddings instead, where the same word can end up with a different vector depending on the surrounding sentence, letting the model correctly distinguish a word used in one sense from the same word used in a completely different sense elsewhere. This shift, from one fixed vector per word to context-sensitive vectors for entire passages, is largely why embedding-based search has become dramatically more reliable over the past several years.

What Does It Concretely Mean for Two Vectors to Be “Semantically Similar”?

Semantic similarity is measured by calculating a distance or similarity score between two vectors, most commonly using cosine similarity, which measures the angle between them rather than their raw magnitude. Two vectors pointing in nearly the same direction through the space score as highly similar, even if their exact numeric values differ somewhat, while vectors pointing in very different directions score as dissimilar regardless of how large or small each individual vector happens to be. This score is what actually powers ranked retrieval: every stored vector gets compared against a query vector using this same measurement, and the results with the smallest distance, or the highest similarity score, come back first.

This is a genuinely mechanical, repeatable calculation, not a subjective judgment. The “understanding” of meaning happened earlier, during training, when the model learned where to place things. Similarity search itself is just consistent, mathematical distance measurement applied to whatever positions that earlier training already established.

Why Can’t Vectors From Two Different Embedding Models Simply Be Compared to Each Other?

Each embedding model learns its own internal geometry during training, shaped by its own architecture, its own training data, and its own contrastive objective. Two different models can both produce, say, 768-dimensional vectors, but the meaning of any given dimension, and the overall shape of the space those dimensions define, is specific to each model individually. A vector from one model sitting near a vector from a different model doesn’t reliably mean anything, because there was never a shared training process that aligned the two spaces to agree on what “close” should mean between them.

This is why switching an embedding model in an existing system is a genuinely disruptive change, not a simple upgrade. Every previously stored vector was placed according to the old model’s geometry, and comparing those old vectors against new queries embedded with a different model risks producing results that look plausible but are actually meaningless, since the two sets of vectors were never trained to relate to each other at all.

How Does Weaviate Engram Rely on Consistent Embedding to Keep Memory Search Reliable?

Weaviate Engram embeds every stored memory using a consistent model, ensuring that a query embedded later lands in the exact same geometric space as everything it needs to be compared against, which is precisely what makes similarity scoring meaningful rather than arbitrary. Consider a home-brewing recipe assistant helping brewers match new recipe ideas against flavor notes from past batches, where consistent embedding is what lets genuinely similar flavor descriptions surface even when worded completely differently:

from engram import EngramClient

client = EngramClient(api_key=os.environ["ENGRAM_API_KEY"])

client.memories.add(
    "The Cascade and Centennial hop combination in this batch produced a bright, resinous citrus character with a noticeable grapefruit-pith bitterness on the finish.",
    user_id="brewer-7734",
)

Months later, the brewer describes a new idea using entirely different words:

similar_batches = client.memories.search(
    query="Which past batches had that sharp, piney, almost bitter citrus edge?",
    user_id="brewer-7734",
)

Neither “sharp, piney” nor “bitter citrus edge” appears anywhere in the original stored memory, yet because both were embedded using the same consistent model, their vectors land close enough together in the same trained geometry for the search to correctly surface the earlier Cascade and Centennial batch as a strong match. This works precisely because Engram never mixes vectors from different embedding models within the same comparison, guaranteeing the “closeness” the similarity search relies on is always measuring something the underlying model actually learned to represent, rather than an arbitrary coincidence between two unrelated geometries.

Embedding models establish where meaning lives in vector space, and similarity scoring measures distance within that space. Comparing a query against millions of stored vectors one at a time would be far too slow for any real system, which is exactly why a specialized structure exists to make that search fast at scale. Our next chapter, How do vector indexes work?, turns to exactly that structure.