Embeddings deep dive
How text becomes searchable geometry
Embeddings are the interface between language and geometry: a retriever can only find what the embedding model places near the query. Understanding how these models are trained (contrastive learning with in-batch negatives), why bi-encoders can be indexed and cross-encoders cannot, and when cosine, dot product and Euclidean distance agree lets you choose, evaluate and even fine-tune embedding models instead of trusting a leaderboard. The same loss trained SimCLR (5.8 Self-supervised and contrastive learning) and CLIP (8.10 Multimodal models), and the same vectors power agent memory (10.4 Memory and context engineering).
You'll be able to
- Explain why raw BERT embeddings fail at similarity and how contrastive fine-tuning fixes them
- Write the InfoNCE loss with in-batch negatives and explain the roles of batch size, hard negatives and temperature
- Prove that cosine, dot product and Euclidean rankings coincide for unit vectors
- Compare bi-encoders, cross-encoders and late interaction, and place each in a retrieval pipeline
- Select an embedding model using MTEB as a shortlist and your own retrieval test set as the decider
Key ideas
- Raw BERT vectors are anisotropic and untrained for similarity; sentence embeddings come from contrastive fine-tuning on pairs that should be close.
- Bi-encoders embed query and document independently (indexable, fast); cross-encoders read them jointly (accurate, O(N) per query) and are used to rerank; ColBERT's late interaction sits between.
- InfoNCE with in-batch negatives: L = −(1/B) Σ_i log[exp(s_ii) / Σ_j exp(s_ij)], s_ij = q_i·d_j / τ — a softmax over 'which document belongs to this query'.
Show 4 more key ideas
- Quality levers in embedding training: large batches, mined hard negatives and a low temperature (≈0.01–0.05).
- For unit vectors ‖a−b‖² = 2 − 2cos θ, so cosine, dot product and Euclidean rankings coincide; use the metric the model card specifies.
- Memory is d × 4 bytes per vector in float32; Matryoshka truncation and int8/binary quantization cut it 4–32× with modest recall loss.
- MTEB shortlists models; a retrieval test set built from your own documents decides.
Suggested path through this lesson
From word vectors to sentence vectors
word2vec gave every word a fixed vector (6.3 Word embeddings); BERT gave every token a vector that depends on its sentence (7.5 Encoder-only: BERT and friends (and sentence embeddings)). A retriever needs one vector per chunk that captures what it is about. The naive approach — average BERT's token vectors or take its [CLS] vector — works badly: raw BERT embeddings are anisotropic (they crowd into a narrow cone, so every pair looks similar), and nothing in masked-language-model pretraining ever asked "do these two texts mean the same thing?". Sentence-BERT (2019) fixed this by fine-tuning with a contrastive objective on pairs of texts that should be close. Every modern embedding model — the E5, BGE and GTE families, and the API models from OpenAI, Voyage, Cohere and Google — follows the same recipe: a transformer encoder, a pooling step (mean pooling or a [CLS]/last-token vector), and contrastive training on hundreds of millions of pairs, often with an instruction prefix such as query: or passage: so the model knows which side of the retrieval it is encoding.
Bi-encoders, cross-encoders and late interaction
A bi-encoder encodes query and document independently: , , score . Because the document vectors do not depend on the query, you compute them once offline and search them with a vector index (9.3 Vector search and indexes); a query costs one forward pass plus a nearest-neighbour lookup. A cross-encoder feeds the pair [CLS] query [SEP] document through the transformer and outputs a relevance score. Query and document tokens attend to each other, so it is far more accurate — but there is nothing to precompute: scoring documents costs forward passes. The standard design therefore uses the bi-encoder to fetch 50–200 candidates and a cross-encoder to rerank them (9.5 Retrieval quality: hybrid search, reranking, query transforms and metrics). Late interaction (ColBERT) sits between: it stores one vector per token for each document and scores with , keeping much of the cross-encoder's precision while remaining indexable.
| Bi-encoder | Late interaction (ColBERT) | Cross-encoder | |
|---|---|---|---|
| Precompute documents | yes (one vector) | yes (one vector per token) | no |
| Query cost | 1 pass + ANN lookup | 1 pass + token-level MaxSim | passes |
| Accuracy | good | better | best |
| Role | first-stage retrieval | retrieval or reranking | reranking the top- |
Training embeddings: InfoNCE with in-batch negatives
Take a batch of positive pairs — a question and the passage that answers it, a title and its article, two paraphrases. Encode everything, normalize, and define similarities with a temperature . The loss treats the other documents in the batch as negatives:
This is a softmax cross-entropy (4.3 Loss functions catalog) over the question "which document in the batch belongs to query ?": it pulls toward and pushes it away from everything else. It is exactly the InfoNCE loss of SimCLR (5.8 Self-supervised and contrastive learning), and its symmetric version (also classifying documents against queries) is CLIP's objective (8.10 Multimodal models). Three practical consequences:
- Bigger batches are better. More in-batch negatives make the task harder and the embedding sharper; embedding models are trained with batches in the thousands or tens of thousands.
- Hard negatives matter. Random passages are too easy. Mine negatives that BM25 or a previous model ranks highly but that are wrong; most of the quality gap between models comes from data curation here.
- Temperature sharpens. With – a small difference in cosine becomes a large difference in probability, which trains fine-grained ranking.
Math check. With , cosines (positive) and (negative) and , the logits are and and query 1's loss is — already solved. At the same cosines give : without a low temperature the loss barely distinguishes 0.2 from 0.1.
Cosine, dot product or Euclidean?
Three similarity measures are in common use, and for unit vectors they rank documents identically. If ,
so the smallest Euclidean distance is the largest dot product is the largest cosine (1.1 Vectors, dot products and norms). Most APIs return normalized vectors, which is why "cosine" and "dot" indexes give the same results. The exception is deliberate: some models are trained with unnormalized dot products so that vector length can encode prior importance — a popular, information-dense passage gets a longer vector. Use the metric the model card specifies, and never mix normalized and unnormalized vectors in one index.
Dimension, Matryoshka and quantization
Dimension ranges from 384 (MiniLM) to 1,024–3,072 and beyond. Storage is bytes in float32: one million 1,024-dimensional vectors is about 4 GB before index overhead (9.3 Vector search and indexes). Two tricks shrink that. Matryoshka representation learning trains the model so that any prefix of the vector — the first 256 of 1,024 dimensions, say — is itself a good embedding; you truncate at query time and trade a little recall for four times less memory and faster search. Quantization stores int8 (4× smaller) or binary (32× smaller) vectors, and rescoring the top candidates with full-precision vectors recovers most of the lost accuracy.
Choosing an embedding model in 2026
The MTEB benchmark aggregates retrieval, clustering, classification and semantic-similarity tasks across many languages. Use it to shortlist, not to decide: leaderboard scores are averages over domains that are not yours, some entries overfit to the public tasks, and the cost, latency, context-length and dimension columns matter as much as the score. The procedure that works:
- Build a small retrieval test set from your documents — 50–200 queries with labelled relevant chunks (9.5 Retrieval quality: hybrid search, reranking, query transforms and metrics).
- Compare two or three candidates (a small open model you can self-host, a strong open model, an API model) on recall@ and nDCG, plus embedding latency, price per million tokens, maximum input length and dimension.
- Check language coverage (multilingual models for non-English corpora) and whether the model expects asymmetric query/passage prefixes or instructions.
- If the domain is unusual (legal, chemistry, internal jargon), fine-tune the open model on synthetic query–passage pairs generated by an LLM from your chunks; a few thousand pairs already help.
Multimodal retrieval follows the same geometry: CLIP-style models embed images and text in one space (8.10 Multimodal models), and page-image models embed whole PDF pages so you can retrieve a slide by its content without OCR (9.7 Advanced RAG patterns).
Where this shows up later
- Searching millions of vectors quickly is the job of an index — 9.3 Vector search and indexes; the chunks you embed come from 9.4 Chunking and ingestion.
- Cross-encoder reranking and hybrid search build on the bi-/cross-encoder distinction — 9.5 Retrieval quality: hybrid search, reranking, query transforms and metrics.
- The same contrastive loss trained SimCLR (5.8 Self-supervised and contrastive learning) and CLIP (8.10 Multimodal models); agent memory stores embeddings of past events — 10.4 Memory and context engineering.
Common pitfalls (4)
- Using a model's raw [CLS] vector or mean-pooled hidden states for similarity without contrastive fine-tuning — everything looks similar to everything.
- Forgetting the query/passage prefix or instruction that an embedding model was trained with; retrieval quality silently drops.
- Mixing vectors from two different embedding models (or versions) in one index — they live in unrelated coordinate systems.
- Choosing by MTEB rank alone; a model two places lower may be 10× cheaper, support your language, or handle your jargon better.
Recap: all 7 key points
- Raw BERT vectors are anisotropic and untrained for similarity; sentence embeddings come from contrastive fine-tuning on pairs that should be close.
- Bi-encoders embed query and document independently (indexable, fast); cross-encoders read them jointly (accurate, O(N) per query) and are used to rerank; ColBERT's late interaction sits between.
- InfoNCE with in-batch negatives: L = −(1/B) Σ_i log[exp(s_ii) / Σ_j exp(s_ij)], s_ij = q_i·d_j / τ — a softmax over 'which document belongs to this query'.
- Quality levers in embedding training: large batches, mined hard negatives and a low temperature (≈0.01–0.05).
- For unit vectors ‖a−b‖² = 2 − 2cos θ, so cosine, dot product and Euclidean rankings coincide; use the metric the model card specifies.
- Memory is d × 4 bytes per vector in float32; Matryoshka truncation and int8/binary quantization cut it 4–32× with modest recall loss.
- MTEB shortlists models; a retrieval test set built from your own documents decides.
Watch
How an encoder turns a passage into a vector for retrieval; the gentle entry point.
Read
Exercises
- Embed and compare
With
sentence-transformers(modelall-MiniLM-L6-v2), embed 50 sentences from your own notes withnormalize_embeddings=True. Compute the 50×50 cosine matrix with one matrix product, list the five most similar pairs, and verify numerically that holds for every pair. - See anisotropy
Mean-pool the hidden states of a raw
bert-base-uncasedfor the same 50 sentences and compute the average pairwise cosine. Compare with the sentence-transformer. Expected: raw BERT gives a high average (everything looks alike); the contrastively trained model gives a much lower one with clear structure. - Shrink the vectors
Project the 384-dimensional embeddings to 64 dimensions with PCA (3.12 Dimensionality reduction: PCA, t-SNE and UMAP), or truncate a Matryoshka-trained model's vectors. Write 20 queries for your 50 sentences and measure recall@5 at full vs reduced dimension. Expected: a few points of recall lost for a 6× memory saving.
- Model bake-off
Pick two embedding models (one small open, one API or large open). On a 50-query retrieval set over a corpus of a few hundred chunks, report recall@5, MRR, embedding latency per 1,000 chunks and price. Write three sentences on which you would deploy and why.
Quiz
Flashcards
These cards are now in your spaced-repetition queue. Review all due cards →