Retrieval & Search

Embedding Models Guide

Choosing and evaluating embedding models for production RAG - OpenAI, Cohere, BGE, E5, and open-source alternatives with benchmarks and deployment guidance.

45 min readIntermediateLast reviewed: 20 July 2026
PrerequisitesEmbeddingsRAG

Quick Summary

An embedding model is a trained encoder that maps text to vectors where semantic similarity corresponds to geometric proximity.

One Analogy

Like choosing a camera lens: the same scene looks different through wide-angle vs telephoto — pick the model that focuses on what your retrieval task needs.

Engineering Rule

Evaluate embedding models on your corpus before committing — leaderboard scores are directional, not definitive.

TL;DR

  • Embedding models convert text to dense vectors that capture semantic meaning — the foundation of all vector-based retrieval in RAG.

  • Model choice affects retrieval quality more than vector database choice — a better embedding model on a simple index outperforms a worse model on an optimized index.

  • Example starting points (current as of writing): OpenAI text-embedding-3-small and bge-large-en-v1.5 are common production choices for English RAG — evaluate on your domain before committing.

  • Changing embedding models requires full re-indexing — vectors from different models are not comparable.

  • Match embedding dimensions, distance metric, chunk size, and query prefixes to your model's training characteristics.

Why This Matters

The embedding model is the lens through which your RAG system "sees" your documents. It determines whether a query about "rate limiting" finds your document about "API throttling" or returns irrelevant results about "network bandwidth."

Teams often spend weeks evaluating vector databases and LLMs while using whatever embedding model their framework defaults to. This is backwards. Embedding model quality is one of the highest-leverage decisions in the indexing pipeline — it affects every retrieval query until you re-index.

A domain-specific embedding model can improve recall@5 materially over a general-purpose model on specialized corpora (legal, medical, code). The cost difference between models is negligible compared to the downstream impact on answer quality — benchmark on your corpus; published leaderboard gaps do not always transfer.

The Problem Embedding Models Solve

Text is unstructured and unsearchable by meaning. Keyword search matches characters; embedding models match concepts.

The core challenge: compress variable-length text into a fixed-size vector that preserves semantic similarity. "Dog" and "puppy" should be close. "Dog" and "car" should be far apart. "Rate limit exceeded" and "API throttling error" should be close despite sharing no words.

Embedding models solve this by training neural networks on massive text corpora to produce vectors where semantic similarity corresponds to geometric proximity. This enables finding documents by meaning, cross-lingual retrieval, and powering the retrieval step in every RAG pipeline. The vectors themselves are defined in Embeddings; this guide focuses on choosing and operating the models that produce them.

How We Got Here

Embedding models evolved from research benchmarks to production API defaults in under five years:

Diagram: Evolution of embedding models

timeline
    title Embedding model milestones
    2019 : Sentence-BERT contrastive training
    2020 : DPR bi-encoder retrieval
    2022 : OpenAI ada-002 API default
    2023 : BGE / E5 open-source surge
    2024 : Matryoshka + multilingual v3
    2025 : Domain-specific + long-context embedders

Production teams moved from self-hosted SBERT to API embeddings, then back to open-source when data residency and cost at scale mattered.

Milestone Model / event Production impact
Sentence-BERT (2019) Contrastive sentence pairs Self-hosted retrieval became practical
DPR (2020) Wikipedia-scale bi-encoder Paired with RAG generator pattern
ada-002 (2022) OpenAI API embeddings Default for English RAG startups
BGE / E5 (2023) Open-source MTEB leaders Self-host without quality sacrifice
text-embedding-3 (2024) Matryoshka dimensions Trade storage for quality without retrain
Today Cohere v3, Voyage, Jina v3 Multilingual, long-context, domain slices

The MTEB leaderboard standardised comparison across 56 tasks. Use it for initial screening — then validate on your corpus with retrieval evaluation.

What Is an Embedding Model?

An embedding model is a neural network (typically a transformer encoder) trained to map text into a fixed-dimensional vector space. Similar texts produce vectors that are close together by cosine similarity or dot product.

from openai import OpenAI

client = OpenAI(timeout=30.0)
response = client.embeddings.create(
    model="text-embedding-3-small",
    input="How do I configure rate limiting for the API?",
)
vector = response.data[0].embedding  # list of 1536 floats

Key properties:

Property Description Example Values
Dimensions Vector size 384, 768, 1024, 1536, 3072
Max input tokens Maximum text length per embedding 512, 8192
Distance metric How similarity is computed Cosine, dot product
Language support Monolingual vs multilingual English-only, 100+ languages
Domain General vs specialized General, code, legal, medical

How Embedding Models Work

Bi-encoder architecture

Most modern text embedding models use a bi-encoder: a transformer encoder followed by mean pooling and optionally a projection layer.

Diagram: Bi-encoder vs cross-encoder

flowchart TB
    subgraph bi [Bi-encoder — indexing + first-stage retrieval]
        Q1[Query text] --> TE1[Transformer encoder]
        D1[Document text] --> TE2[Transformer encoder]
        TE1 --> VQ[Query vector]
        TE2 --> VD[Doc vector]
        VQ --> SIM[Cosine similarity]
        VD --> SIM
    end
    subgraph cross [Cross-encoder — reranking only]
        QD[Query + doc concatenated] --> TE3[Single transformer]
        TE3 --> SCORE[Relevance score]
    end

Bi-encoders pre-compute document vectors; cross-encoders score pairs jointly — too slow for full-corpus indexing.

Bi-encoder models embed queries and documents independently. This enables pre-computing document embeddings (fast indexing) and embedding only the query at search time (low latency). The trade-off: query and document embeddings are computed separately, so the model cannot capture fine-grained query-document interactions.

Cross-encoder models (used in re-ranking, not initial retrieval) concatenate query and document and run them through the transformer together. More accurate but too slow for indexing entire corpora.

Sentence-BERT bi-encoder architecture

Source: Sentence Transformers Documentation

Training methods

Method Description Examples
Contrastive learning Pull similar pairs together, push dissimilar apart SimCSE, BGE
Multi-task training Train on classification, NLI, retrieval simultaneously E5, GTE
Matryoshka training Train vectors that work at multiple dimensions OpenAI v3, Nomic
Instruction tuning Prefix queries with task instructions E5, BGE-M3

Matryoshka embeddings

OpenAI's text-embedding-3 and Nomic's models support Matryoshka Representation Learning — vectors where the first N dimensions are useful on their own:

# Full 1536-dim embedding
full_vector = embed("query text", dimensions=1536)

# Truncated 256-dim still works (lower quality, less storage)
compact_vector = embed("query text", dimensions=256)

This lets you trade quality for storage and speed without re-indexing the full corpus — validate recall after truncation with retrieval evaluation. Pair with vector quantization for further compression.

Diagram: Model selection workflow

sequenceDiagram
    participant Eng as Engineer
    participant Eval as Eval harness
    participant API as Embed API / GPU
    participant VS as Vector store
    Eng->>Eval: define 100 query-doc pairs
    Eng->>API: embed corpus with candidate A
    API->>VS: upsert index A
    Eval->>VS: recall@5 for model A
    Eng->>API: embed corpus with candidate B
    Eval->>VS: recall@5 for model B
    Eval-->>Eng: pick winner + document choice

Never ship a model without recall@k on domain-specific pairs — MTEB ranks candidates, your corpus decides.

Architecture

Embedding models sit in both the indexing and query paths of a RAG pipeline:

Diagram: Embedding model in the RAG stack

flowchart TB
    Docs[Documents] --> Chunk[Chunker]
    Chunk --> EM1[Embedding model]
    EM1 --> VDB[(Vector DB)]
    Query[User query] --> EM2[Same embedding model]
    EM2 --> VS[Vector search]
    VDB --> VS
    VS --> HF[Hybrid fusion]
    HF --> RR[Reranker]
    RR --> LLM[Generator]

One model version serves both paths; rerankers and LLMs are separate model choices downstream.

End-to-end RAG pipeline

Source: Survey on RAG (arXiv:2312.10997)

Critical rule: the same embedding model must be used for indexing and querying. Vectors from different models occupy different semantic spaces and cannot be compared. Store embedding_model and embedding_version in vector metadata.

Layer Model role Common choices
Indexing Batch embed chunks OpenAI v3, BGE, E5
Query Embed question once Same model + query prefix
Rerank Cross-encoder rescore Cohere Rerank, bge-reranker
Generate Synthesize answer GPT-4o, Claude Sonnet

Step-by-Step Flow

Step 1: Define requirements. Language(s), domain specificity, latency budget, data residency, and cost constraints.

Step 2: Select candidates. Start with 2–3 models from the comparison table below — typically one API and one self-hosted option.

Step 3: Build an evaluation set. 50–200 query-document pairs from your actual corpus. Include failure cases from production logs.

Step 4: Benchmark. Compute recall@k, MRR, and nDCG for each model on the same chunks.

Step 5: Consider operational factors. API vs self-hosted, cost at volume, latency, dimension constraints, ANN index compatibility.

Step 6: Index and deploy. Embed the full corpus. Version the model name in metadata. Compare vector DB options in Best Vector Databases.

Step 7: Monitor. Track retrieval quality in production. Re-evaluate when new models release or corpus drifts.

Real Production Example

Evaluating three embedding models on a legal document corpus with proper E5 prefixes and metadata versioning:

import numpy as np
from dataclasses import dataclass
from openai import OpenAI

client = OpenAI(timeout=30.0)

@dataclass
class EvalPair:
    query: str
    relevant_doc_id: str

def embed_openai(text: str, model: str = "text-embedding-3-small") -> list[float]:
    resp = client.embeddings.create(model=model, input=text)
    return resp.data[0].embedding

def embed_e5(text: str, is_query: bool) -> list[float]:
    prefix = "query: " if is_query else "passage: "
    return hf_embed(prefix + text, "intfloat/e5-large-v2")

def recall_at_k(
    embed_query_fn,
    embed_doc_fn,
    corpus: dict[str, str],
    eval_pairs: list[EvalPair],
    k: int = 5,
) -> float:
    doc_ids = list(corpus.keys())
    doc_vectors = np.array([embed_doc_fn(corpus[did]) for did in doc_ids])
    hits = 0
    for pair in eval_pairs:
        q_vec = np.array(embed_query_fn(pair.query))
        sims = doc_vectors @ q_vec / (
            np.linalg.norm(doc_vectors, axis=1) * np.linalg.norm(q_vec)
        )
        top_k_ids = [doc_ids[i] for i in np.argsort(sims)[-k:][::-1]]
        if pair.relevant_doc_id in top_k_ids:
            hits += 1
    return hits / len(eval_pairs)

models = {
    "text-embedding-3-small": (
        lambda q: embed_openai(q),
        lambda d: embed_openai(d),
    ),
    "bge-large-en-v1.5": (
        lambda q: hf_embed(q, "BAAI/bge-large-en-v1.5", prompt="Represent this sentence for searching relevant passages:"),
        lambda d: hf_embed(d, "BAAI/bge-large-en-v1.5"),
    ),
    "e5-large-v2": (
        lambda q: embed_e5(q, is_query=True),
        lambda d: embed_e5(d, is_query=False),
    ),
}

for name, (q_fn, d_fn) in models.items():
    score = recall_at_k(q_fn, d_fn, corpus, eval_pairs, k=5)
    print(f"{name}: recall@5 = {score:.3f}")

Run this on your domain before choosing. MTEB leaderboard scores are directional — your corpus is ground truth.

Model comparison table

Model Dims Max Tokens Cost Self-Host Best For
text-embedding-3-small 1536 8191 $0.02/1M tokens No General English RAG, fast to deploy
text-embedding-3-large 3072 8191 $0.13/1M tokens No Highest quality API option
Cohere embed-v3 1024 512 $0.10/1M tokens No Multilingual, compression
bge-large-en-v1.5 1024 512 Free Yes Best open-source English
e5-large-v2 1024 512 Free Yes Strong with instruction prefix
multilingual-e5-large 1024 512 Free Yes 100+ languages
Nomic embed-text-v1.5 768 8192 Free Yes Long documents, Matryoshka
jina-embeddings-v3 1024 8192 API/self-host Yes Long context, multilingual

Tip

For E5 models, prefix queries with "query: " and documents with "passage: ". This matches their training format and improves retrieval quality significantly.

Design Decisions

Decision Option A Option B When to choose
Deployment API (OpenAI, Cohere) Self-hosted (BGE, E5) API for speed; self-hosted for data residency or high volume
Dimensions 384 (compact) 1536 (full) 384 for cost/storage; 1536 for quality. Cannot mix in one index.
Model size Small (384-dim) Large (1024-dim) Large for quality-critical; small for high-volume or latency-sensitive
Language English-only Multilingual Match to your corpus languages
Domain General Fine-tuned Fine-tune when general models score below 0.7 recall@5 on your eval set

Common patterns

  • API-first, self-host later — Ship with OpenAI v3; migrate to BGE when volume or privacy thresholds hit.

  • Dual-index migration — Index new model in parallel; A/B test recall before decommissioning old index.

  • Query prefix discipline — Centralize prefix logic in one embed wrapper; silent prefix bugs are common production failures.

  • Title injection — Prepend document title to chunk text before embedding; often +10% recall on structured docs.

Comparisons

API vs self-hosted embedding models

Dimension API (OpenAI, Cohere) Self-hosted (BGE, E5)
Time to ship Hours Days (GPU infra)
Data residency Text leaves your network Full control
Cost at 10M chunks/month ~$100 index + query fees GPU amortized; often cheaper
Quality Strong general English Comparable on MTEB; domain tune possible
Ops burden Low Model serving, versioning, scaling

Small vs large embedding models

Dimension Small (ada-scale, 384–768d) Large (1024–3072d)
Recall Good on clean English Better on jargon, multilingual
Storage 2–4× smaller indexes Higher ANN memory
Latency Faster search Slightly slower
When to choose High volume, cost-sensitive Quality-critical, complex domains

Bi-encoder vs late interaction (ColBERT)

Dimension Bi-encoder Late interaction
Vectors per doc 1 Many (per token)
Storage Low 10–50× higher
Recall on hard queries Good Better precision
When to choose Default RAG Bi-encoder recall insufficient after rerank

Decision tree: choosing an embedding model

Decision tree: Embedding model selection

flowchart TD
    A[Start model selection] --> B{Data leaves network OK?}
    B -->|No| C[Self-host BGE / E5]
    B -->|Yes| D[API candidate list]
    C --> E{Multilingual corpus?}
    D --> E
    E -->|Yes| F[multilingual-e5 / Cohere v3]
    E -->|No| G{text-embedding-3-small recall@5 >= 0.75?}
    G -->|Yes| H[Ship API small]
    G -->|No| I[Try large / domain model / fine-tune]
    F --> J[Match chunk size to max tokens]
    H --> J
    I --> J
    J --> K[Weekly eval on golden set]

Evaluate on your corpus at the target chunk size — model quality and chunking interact.

Compare vector DB fit in Best Vector Databases: Qdrant vs Pinecone · Pinecone vs Weaviate · Milvus vs Qdrant.

Common Mistakes

  1. Using different models for indexing and querying. Vectors from different models are incomparable. Always use the same model on both paths.

  2. Choosing based on MTEB leaderboard alone. Benchmark scores do not predict performance on your specific domain. Always evaluate on your corpus.

  3. Ignoring input length limits. Embedding a 2000-token chunk in a 512-token model truncates silently. Match chunk size to model max tokens.

  4. Not versioning the model. When you migrate models, you need to know which vectors were created with which model. Store model name/version in metadata.

  5. Skipping query preprocessing. E5 models need "query: " prefix. BGE recommends query instructions. Read the model card.

  6. Embedding raw HTML/PDF text. Garbage input produces garbage vectors. Clean and parse documents before embedding.

  7. Optimizing embedding model before fixing chunking. A perfect embedding model cannot retrieve a complete answer from a badly chunked document.

Where It Breaks Down

Exact matching — Embeddings compress meaning and lose exact token information. Product codes, error IDs, and version numbers need hybrid search alongside embeddings.

Negation and logic — "Refundable" and "non-refundable" may embed similarly. Embeddings capture topic, not logical structure.

Numerical precision — "$4.2 million" and "$42 million" may be indistinguishable in vector space. Do not rely on embeddings for numeric comparison.

Domain shift — A model trained on web text may underperform on internal jargon, abbreviations, or domain-specific terminology. Fine-tune or evaluate carefully.

Multilingual mixing — Using an English-only model on a multilingual corpus silently degrades non-English retrieval. Use multilingual models or language-specific indexes.

Model deprecation — API providers retire models (ada-002 → v3). Plan migration windows and dual-index cutovers before forced shutdown.

When NOT to Use a Dedicated Embedding Model

Skip investing in embedding model selection when:

  1. Retrieval is purely structured — SQL, Elasticsearch keyword, or graph queries answer the question; embeddings add no signal.

  2. Corpus fits in context — Under ~50 pages of static text, long-context prompting avoids index infrastructure entirely.

  3. Real-time factual lookup is external — Live APIs (stock prices, weather) should not be embedded; call tools or APIs directly.

  4. You need guaranteed exact match only — SKU lookup with no paraphrase requirement; BM25 alone suffices.

  5. Regulatory block on any ML encoding — If neither API nor self-hosted embedding is permitted, use lexical search only.

Prefer fine-tuning an embedding model only after general models fail eval — not as the first step.

Running in Production

Best Practice

Best Practices — Pin model versions, batch index offline, cache hot query embeddings, and block deploys that regress recall@k.

Dimension Consideration
Scaling API models scale automatically. Self-hosted: one GPU handles ~1,000 embeddings/sec. Batch embed during indexing — never on the query path for documents.
Latency Illustrative: API often ~30–80ms per query embedding; self-hosted GPU often ~5–20ms. Batch document embedding offline. Actual latency depends on hardware, model, and deployment architecture.
Cost OpenAI small: ~$0.02/1M tokens. Indexing 1M chunks (~500 tokens each) ≈ $10. Query embedding negligible at most scales.
Monitoring Track embedding latency, error rate, retrieval recall@k, model API version drift. Alert on provider outages — cache or fallback policy required.
Evaluation Re-run eval set monthly. Compare against new model releases. Benchmark on your own corpus and query distribution — MTEB and vendor benchmarks are useful for comparison but should not replace evaluation on production-like workloads.
Security API models send text to third parties. Self-hosted for sensitive data. Check data processing agreements and SOC2 scope.

Important

Store the embedding model name and version in your vector database metadata. You will need this for re-indexing, debugging, and compliance audits.

Diagram: Embedding model version lifecycle

stateDiagram-v2
    [*] --> Active: v1 in production
    Active --> Evaluating: v2 candidate
    Evaluating --> DualIndex: recall improves
    DualIndex --> Cutover: traffic shift
    Cutover --> Active: v2 primary
    Active --> Deprecated: v1 drained
    Deprecated --> [*]
    Evaluating --> Active: no improvement

Never swap models in-place — dual-index until eval confirms quality on production queries.

If you understood this topic, read next:

Diagram: Learning path for embedding models

flowchart LR
    A[Embeddings] --> B[Embedding Models]
    B --> C[Chunking]
    C --> D[Vector DB]
    D --> E[Eval]

Prerequisites: Embeddings · RAG

Next topics: Vector Databases · Re-ranking · Retrieval Evaluation

Estimated time: 45 min · Difficulty: Intermediate

Interview Questions

  1. Why does embedding model choice matter more than vector DB choice for recall?

    • Expected: model defines semantic space; bad vectors cannot be fixed by faster ANN or better sharding.
  2. What happens if you index with BGE and query with text-embedding-3-small?

    • Expected: incomparable vector spaces; meaningless similarity scores; must re-embed entire corpus.
  3. When do E5 query/passage prefixes matter and why?

    • Expected: asymmetric training; missing prefixes misalign query and document regions of vector space.
  4. How do Matryoshka embeddings help in production?

    • Expected: truncate dimensions for storage/speed without full retrain; validate recall after truncation.
  5. API vs self-hosted — decision criteria?

    • Expected: data residency, volume/cost crossover (~10M+ embeddings/month), ops capacity, latency SLAs.
  6. Bi-encoder vs cross-encoder — where does each run?

    • Expected: bi-encoder for index + first-stage retrieval; cross-encoder for reranking top-k only.
  7. What triggers a full re-index vs incremental upsert?

    • Expected: model version or dimension change → full re-index; new documents → incremental upsert.
  8. How do you evaluate a new embedding model before cutover?

    • Expected: same chunks, golden query-doc pairs, recall@k/MRR/nDCG, dual-index A/B, production shadow traffic.

Key Takeaways

  • Embedding model choice is one of the highest-leverage decisions in the RAG indexing pipeline.
  • Always evaluate on your domain — leaderboard scores are directional, not definitive.
  • Use the same model for indexing and querying. Version it in metadata.
  • Match chunk size to model input limits. Apply query prefixes per model instructions.
  • API models for speed; self-hosted for data residency and cost at scale.
  • Plan for full re-indexing when changing models — vectors are not transferable.
  • Compare infrastructure in Best Vector Databases after model eval stabilizes.

FAQs

Which embedding model should I use?

For English RAG, common starting points (current as of writing): OpenAI text-embedding-3-small (API) or bge-large-en-v1.5 (self-hosted). Evaluate both on your domain. Use multilingual-e5-large for non-English corpora.

Can I mix embeddings from different models?

No. Vectors from different models occupy different semantic spaces. Mixing them in one index produces meaningless search results.

How do I switch embedding models?

Create a new collection/index with the new model's dimensions. Re-embed all documents. Run both indexes in parallel during migration. Cut over when eval confirms quality.

API or self-hosted?

API for speed to market and low ops. Self-hosted for data residency, high volume (cost savings above ~10M embeddings/month), or offline environments.

Do I need the largest model?

Not necessarily. text-embedding-3-small often matches text-embedding-3-large on domain-specific eval sets. Larger models cost more storage and compute. Measure, do not assume.

What input length should I use?

Match your chunk size to the model's max input tokens. Most models handle 512 tokens; Nomic and Jina handle 8192. Truncation loses information silently.

How do I fine-tune an embedding model?

Use sentence-transformers with contrastive loss on query-document pairs from your domain. Requires 1K–10K labeled pairs. Worth it when general models score below 0.7 recall@5.

What distance metric should I use?

Cosine similarity for most text models. For OpenAI text-embedding-3-small and text-embedding-3-large, outputs are L2-normalized — cosine similarity and dot product produce equivalent rankings. Match your vector database metric configuration to the model.

How often do new models come out?

Major releases every 3–6 months. Re-evaluate quarterly. Do not chase every release — switch when eval shows meaningful improvement on your corpus.

Can one embedding model handle text and images?

Multimodal models (CLIP, Cohere embed-v3, Voyage multimodal) embed both. Useful for documents with diagrams. Text-only models ignore visual content.

What is the E5 query/passage prefix?

E5 models are trained with "query: " before queries and "passage: " before documents. Using these prefixes at inference time significantly improves retrieval quality.

How do embedding costs compare to LLM costs?

Embeddings are 10–100× cheaper than generation. Indexing 1M chunks costs ~$10 with OpenAI small. The same text through GPT-4o costs ~$1,250. Embed freely; generate carefully.

How do I batch embed efficiently?

Most APIs support batching 100–2,000 texts per request. Batch during offline indexing. For self-hosted models, use sentence-transformers with encode(texts, batch_size=64).

What is the MTEB benchmark?

Massive Text Embedding Benchmark evaluates models across 56 datasets. Useful for initial selection — always validate on your domain with retrieval evaluation.

Should I embed the document title separately?

Prepend title and section heading to each chunk before embedding — more effective than metadata alone. The model encodes the title into the vector, improving topic-name queries.

References

Further Reading

Next Topics

Learning Path

Continue Learning

Related Guides

Related Tools

ToolCategoryPurposeWebsiteBest For
Hugging Face Transformers
Python SDK
frameworksLibrary for using pretrained transformers in Python and beyond.huggingface.coModel fine-tuning
Pinecone
PopularAPICloud
Vector DBManaged vector database plus Pinecone Nexus knowledge engine for agent RAG.pinecone.ioRAG systems
Qdrant
Open SourceAPI
Vector DBOpen-source vector database with filtering and hybrid search.qdrant.techRAG systems
Weaviate
MaintainedOpen SourceAPI
Vector DBOpen-source vector database with hybrid search and modules.weaviate.ioEnterprise search
Milvus
Open SourceAPI
Vector DBOpen-source vector database with lake-native 3.0 External Collections for billion-scale search.milvus.ioLarge-scale RAG
Cohere
APICloud
LLMEnterprise NLP platform with strong embedding and reranking APIs for RAG.cohere.comProduction embeddings
Voyage AI
APICloud
infrastructureSpecialist embedding and reranking models optimized for retrieval quality.voyageai.comHigh-quality retrieval

Related Rankings

Related Comparisons