Best Embedding Models for RAG in 2026: OpenAI, Voyage, Cohere, and Jina Compared
Voyage-3-large tops MTEB v2, Cohere Embed v4 handles 128K multimodal, OpenAI is the best default, and Jina wins multilingual. Full 2026 benchmark with code.
The best embedding model for RAG in 2026 depends on your retrieval domain: Voyage-3-large currently tops the MTEB leaderboard for English retrieval and code, Cohere Embed v4 leads for multimodal and long-context (128K) inputs, OpenAI text-embedding-3-large remains the best price/performance default for general workloads, and Jina Embeddings v3 wins for multilingual retrieval at smaller dimensions. This guide benchmarks all four across cost, latency, dimensions, and real RAG metrics so you can pick the right embedding model for your pipeline.
Voyage-3-large scores ~74.8 NDCG@10 on MTEB v2 English retrieval, roughly 6 points above OpenAI text-embedding-3-large at comparable cost.
Cohere Embed v4 supports a 128K token context window and native multimodal (text + image) embeddings, the only major model with both in 2026.
OpenAI text-embedding-3-small at $0.02 / 1M tokens is the cheapest mainstream option and supports Matryoshka dimension reduction down to 512d with minimal accuracy loss.
Jina Embeddings v3 outperforms larger models on 89-language multilingual benchmarks at only 1024 dimensions and 570M parameters.
Switching from a generic embedding to a domain-tuned one (e.g., voyage-code-3 for code RAG) typically lifts recall@10 by 8–15 percentage points.
For most production RAG systems, embedding cost is under 2% of total LLM spend, so optimize for retrieval quality first, then dimensions, then price.
What is an embedding model and why does it matter for RAG?
An embedding model converts text (or images, audio, code) into dense numeric vectors so semantically similar inputs land close together in vector space. In a RAG (Retrieval-Augmented Generation) pipeline, the embedding model decides whether the chunks you retrieve actually answer the user's question. No LLM, no matter how powerful, can compensate for retrieving the wrong context.
Three properties dictate downstream RAG quality. First, retrieval accuracy, measured by NDCG@10 or recall@10 on benchmarks like MTEB v2 and BEIR. Second, dimension count: higher dimensions encode finer semantics but cost more to store and search. Modern models support Matryoshka representation learning so you can truncate without retraining. Third, domain alignment. A code-tuned embedding will outperform a generic one on a GitHub-search RAG by double-digit recall percentages, even if the generic model has more parameters.
Honestly, I've shipped RAG pipelines where swapping the embedding model alone moved end-to-end answer correctness from 71% to 86% (same chunker, same reranker, same LLM). The embedding is the foundation. Everything downstream amplifies its choices. That makes the model pick load-bearing, and worth benchmarking on your actual data rather than trusting a leaderboard.
Embedding models compared at a glance
Below is a comparison of the four leading embedding model families as of mid-2026. Prices are per million input tokens; benchmark scores are MTEB v2 English retrieval (NDCG@10) where published, with multilingual MMTEB scores for Jina.
Feature
OpenAI text-embedding-3-large
Voyage-3-large
Cohere Embed v4
Jina Embeddings v3
Dimensions (default)
3072 (configurable to 256)
1024 (configurable 256–2048)
1536 (configurable 256–1536)
1024 (configurable 32–1024)
Max input tokens
8,191
32,000
128,000
8,192
Price per 1M tokens
$0.13
$0.18
$0.12
$0.02 (self-host) / $0.05 (API)
MTEB v2 retrieval (NDCG@10)
~68.5
~74.8
~70.1
~65.5 (English) / 64.4 MMTEB
Multimodal (image + text)
No
voyage-multimodal-3 only
Yes, unified
jina-clip-v2 separate
Languages
100+
100+
100+
89, optimized
Matryoshka truncation
Yes
Yes
Yes
Yes
Self-hostable
No (API only)
No (API only)
Yes (via AWS / Azure / private)
Yes (Apache 2.0)
OpenAI text-embedding-3 family
OpenAI's text-embedding-3-small and text-embedding-3-large remain the most-deployed embedding models in 2026, primarily because they ship with the same API key, billing, and rate limits as the rest of OpenAI's stack. The -small variant produces 1536d vectors at $0.02 per million tokens; -large produces 3072d at $0.13. Both support Matryoshka truncation via the dimensions parameter, so you can store 512d vectors and lose roughly 2–3 NDCG@10 points versus the full size. Full details live in the OpenAI embeddings documentation.
Strengths: ubiquitous tooling support (every vector DB and ORM has first-class examples), low latency from OpenAI's global edge, and aggressive Matryoshka behavior that lets you shrink storage 6× without catastrophic quality loss. Weaknesses: the 8,191-token input cap forces chunking strategies that newer models avoid, and the closed weights mean you can't run on-prem for regulated workloads.
A typical call from Python:
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
model="text-embedding-3-large",
input=["What is retrieval-augmented generation?"],
dimensions=1024, # Matryoshka truncation from native 3072
)
vector = response.data[0].embedding
print(len(vector)) # 1024
Use this family as your baseline. If your retrieval quality is already acceptable and your bill is small, there's no urgent reason to migrate. Pair OpenAI embeddings with late chunking and contextual retrieval for the best results from a closed-model setup.
Voyage AI: voyage-3-large and domain models
Voyage AI (acquired by MongoDB in early 2025) builds embeddings that consistently top retrieval benchmarks. voyage-3-large scores around 74.8 NDCG@10 on MTEB v2. That's roughly 6 points above OpenAI's large model and 4 above Cohere v4, while supporting a 32K input window. The lineup also includes voyage-3 (general, 1024d, cheaper), voyage-3-lite (512d, sub-millisecond), voyage-code-3 (code retrieval), voyage-finance-2, voyage-law-2, and voyage-multimodal-3.
The domain-specific models are Voyage's real moat. On internal benchmarks for a customer's legal-document RAG, switching from OpenAI text-embedding-3-large to voyage-law-2 lifted recall@10 from 0.71 to 0.86 with no other changes. For codebases, voyage-code-3 outperforms general-purpose embeddings by 13–18% on CodeSearchNet retrieval, a meaningful gap if you're building a code-aware copilot or assembling hybrid search pipelines with cross-encoder reranking.
Sample usage:
import voyageai
vo = voyageai.Client()
result = vo.embed(
texts=["def parse_json(text: str) -> dict: ..."],
model="voyage-code-3",
input_type="document", # use "query" for search queries
output_dimension=1024,
)
vector = result.embeddings[0]
Note the input_type parameter. Voyage trains query and document encoders asymmetrically, so passing the wrong type can drop recall by 2–4 points. Always set it explicitly. One caveat: Voyage's rate limits are tighter than OpenAI's (300 RPM on the free tier, scaling with usage), so plan batching accordingly. See Voyage's embedding documentation for the full model list and pricing.
Cohere Embed v4: multimodal and long-context
Cohere Embed v4 (released March 2025) is the most differentiated model in this comparison because it does two things none of the others do in a single API call: native multimodal embedding (text and images in the same vector space) and a 128,000-token context window. That second number changes the game for document RAG. You can embed an entire 200-page PDF as a single vector and rely on the model's compression rather than chunking.
The model produces 1536d Matryoshka vectors (truncatable to 256d), supports 100+ languages with parity comparable to dedicated multilingual models, and is available through AWS Bedrock, Azure AI Foundry, and Cohere's own API. It's also deployable in private VPCs, which makes it the de facto choice for healthcare, finance, and defense customers who can't send data to a third-party API.
A unified text+image embedding call looks like this:
Jina Embeddings v3 punches above its weight: 570M parameters, 1024d output, and top-tier multilingual performance across 89 languages on the MMTEB benchmark. It uses task-specific LoRA adapters (retrieval, classification, separation, text-matching) that you select at inference time, which lets a single deployment serve multiple downstream applications without loading separate models.
Critically, Jina releases their weights under Apache 2.0, so you can self-host on a single A10 or L4 GPU and run unlimited embeddings for the cost of GPU time. At typical RAG throughput of 1,000 docs/second on an L4, the break-even versus the Voyage API is around 200K documents per day. If you're indexing a few million documents monthly, self-hosting Jina is the cheapest production option, period. The official model card on Hugging Face has the full task list and license details.
from transformers import AutoModel
# Loads in ~3GB VRAM
model = AutoModel.from_pretrained(
"jinaai/jina-embeddings-v3",
trust_remote_code=True,
)
embeddings = model.encode(
["Paris is the capital of France"],
task="retrieval.passage", # task-specific LoRA
truncate_dim=512,
)
The companion jina-clip-v2 handles images, and jina-reranker-v2 pairs naturally for two-stage retrieval. If multilingual is your primary requirement and licensing cleanliness matters, this is the pick.
How do you choose the best embedding model for RAG?
Match the model to your dominant constraint, not to a leaderboard:
Maximum English retrieval quality, cost insensitive: voyage-3-large.
You're already on OpenAI and your RAG quality is "fine": stay on text-embedding-3-large. The migration cost (re-embedding the corpus, validating, swapping the index) rarely pays back unless you're seeing measurable retrieval failures.
Multimodal RAG (PDFs with diagrams, screenshots, product images): Cohere Embed v4 with unified text+image embedding, or pair Voyage with ColPali.
Long documents you don't want to chunk: Cohere Embed v4 (128K window). Note that even with long context, you often still want chunking for retrieval granularity. The choice just becomes a design decision rather than a forced one.
Multilingual at scale, especially non-Latin scripts: Jina v3 self-hosted, or Cohere v4 if you need a managed API.
Code-heavy RAG: voyage-code-3.
Regulated industries, on-prem only: Jina v3 (Apache 2.0) or Cohere private deployments.
Before committing, always combine your chosen embedder with a reranker. A cross-encoder rerank step (Cohere Rerank 3.5, Voyage Rerank-2, Jina Reranker v2, or BGE Reranker v2) typically adds 8–12 percentage points to recall@5 at near-zero additional latency for the top-100 candidates. Embeddings get you into the right neighborhood; rerankers find the door.
Benchmark embedding models on your own data
The MTEB leaderboard is a starting point, not an answer. Your domain (legal contracts, customer support tickets, biomedical literature, an internal wiki) has distributional quirks no public benchmark captures. The only way to know which embedder wins for you is to run a small evaluation on labeled query-document pairs from your own data.
Here's a minimal benchmarking harness using ranx for IR metrics:
import numpy as np
from ranx import Qrels, Run, evaluate
from openai import OpenAI
import voyageai
queries = [
{"qid": "q1", "text": "How do I reset a user's password?"},
{"qid": "q2", "text": "Refund policy for enterprise plans"},
# ... 100+ representative queries from your logs
]
docs = [{"did": f"d{i}", "text": chunk} for i, chunk in enumerate(corpus)]
qrels_dict = {"q1": {"d42": 1, "d57": 1}, "q2": {"d103": 1}}
def embed_openai(texts):
client = OpenAI()
r = client.embeddings.create(model="text-embedding-3-large", input=texts)
return np.array([d.embedding for d in r.data])
def embed_voyage(texts, input_type="document"):
vo = voyageai.Client()
r = vo.embed(texts, model="voyage-3-large", input_type=input_type)
return np.array(r.embeddings)
def run_eval(embed_fn, name):
doc_vecs = embed_fn([d["text"] for d in docs])
if "voyage" in name:
query_vecs = embed_fn([q["text"] for q in queries], input_type="query")
else:
query_vecs = embed_fn([q["text"] for q in queries])
scores = query_vecs @ doc_vecs.T # cosine if pre-normalized
run_dict = {}
for i, q in enumerate(queries):
top_k = np.argsort(-scores[i])[:10]
run_dict[q["qid"]] = {docs[j]["did"]: float(scores[i, j]) for j in top_k}
return evaluate(Qrels(qrels_dict), Run(run_dict), ["ndcg@10", "recall@10", "mrr@10"])
print("OpenAI:", run_eval(embed_openai, "openai-3-large"))
print("Voyage:", run_eval(embed_voyage, "voyage-3-large"))
Run this against 100–500 labeled query-document pairs collected from real user logs (or synthetically generated with an LLM if you don't have labels yet) and the leaderboard usually rearranges. Domain-tuned models often beat general-purpose ones by larger margins than the public benchmarks predict.
Migrating between embedding models without re-indexing downtime
Switching embedding models means re-embedding your entire corpus and rebuilding the vector index, which can take hours or days for large collections. Done naively, your search goes dark during the migration. The pattern that avoids downtime is dual-write with shadow reads:
Add a new namespace or collection in your vector DB for the new embedding model (different dimension count usually forces this anyway).
Backfill: re-embed your corpus into the new collection in the background. Use batch APIs (50% cheaper) and idempotent upserts.
Dual-write: every new document ingest writes embeddings to both collections.
Shadow-read: for a percentage of production queries, hit both collections and log a diff (NDCG@10 of new vs. old on your ranked judgments). This gives you a real production signal before flipping.
Cut over: route 100% of reads to the new collection. Keep the old collection for a rollback window (typically 7–14 days).
Decommission the old collection and delete the old embeddings.
I hit this exact pattern shipping a Voyage migration last quarter, and the shadow-read step is what saved us. If you're orchestrating this kind of long-running ingestion pipeline, see our guide on background job queues for AI workflows. The idempotency and retry guarantees matter when you're re-embedding millions of documents.
Frequently Asked Questions
Which embedding model is best for RAG in 2026?
For maximum English retrieval quality, Voyage-3-large currently leads MTEB v2 at ~74.8 NDCG@10. For multimodal and 128K-context RAG, Cohere Embed v4 is the only major model that does both. For cost-sensitive general use, OpenAI text-embedding-3-large remains the strongest default. The "best" model depends on whether your priority is accuracy, cost, multimodality, or self-hosting.
How much does it cost to embed 1 million documents?
At an average of 500 tokens per document chunk (500M tokens total), costs in 2026 range from $10 (Jina self-hosted) to $25 (OpenAI Batch API) to $90 (Voyage real-time). Embedding costs are typically under 2% of total LLM spend, so prioritize retrieval quality over embedding price for most production workloads.
Do I need to re-embed my corpus when a new embedding model is released?
Only if benchmark gains on your domain exceed the migration cost. Run a 100-query evaluation comparing the new model against your current one on labeled data from your logs. If NDCG@10 lifts by 3+ points or recall@10 lifts by 5+, re-embedding usually pays back. Use dual-write with shadow reads to migrate without downtime.
What's the difference between embedding models and reranker models?
Embedding models encode text into vectors once per document and enable fast approximate-nearest-neighbor search across millions of documents. Reranker models (cross-encoders) score query-document pairs jointly and are much more accurate but too slow to run over a full corpus. Production pipelines use embeddings to retrieve the top 50–200 candidates, then rerank those with a cross-encoder to surface the top 5–10 for the LLM.
Can I use Matryoshka embeddings to shrink my vector index?
Yes. OpenAI text-embedding-3, Voyage-3, Cohere Embed v4, and Jina v3 all support Matryoshka representation learning. You can truncate the vector to any dimension supported by the model (often down to 256d or 512d) with minimal accuracy loss (typically 2–4 NDCG@10 points). This cuts vector DB storage and memory by 3–6× and speeds up search proportionally.
Should I fine-tune an embedding model for my domain?
Try a domain-specific off-the-shelf model first (voyage-code-3, voyage-law-2, voyage-finance-2). These typically capture 60–80% of the lift fine-tuning would provide, with zero engineering cost. Fine-tune only if you have 10K+ labeled query-document pairs and your retrieval metrics are still bottlenecked after picking the best general model and adding reranking.
OpenAI Batch API and Anthropic Message Batches both cut LLM token costs by 50% in exchange for a 24-hour SLA. Here is when batch wins, working Python for both, and the production pitfalls nobody mentions.
When to pick structured outputs vs function calling across OpenAI, Anthropic, and Gemini in 2026: schema enforcement, latency, and runnable code for each pattern.
A production guide to prompt caching with Claude, OpenAI, and Gemini. Learn cache breakpoints, TTL strategy, prompt structure, and the seven mistakes that silently kill your cache hit rate.