Skip to content

AI/LLM

BGE-M3 vs OpenAI Embeddings: The Free Multilingual Model That Tops MTEB

Top of MTEB, 100+ languages, MIT licensed — and it runs on your laptop.

🌐📏🆓

Spoiler: the best general-purpose embedding model in the world right now is open weights, multilingual, and free. BGE-M3 from BAAI took the top of the MTEB leaderboard and quietly made text-embedding-ada-002 look like a museum piece.

BGE-M3 vs OpenAI Embeddings: The Short Version

If you only read one section, read this one:

  • License & cost: BGE-M3 is MIT licensed and free to run locally. OpenAI embeddings are a metered API — every token has a price.
  • Benchmarks: BGE-M3 took the top of MTEB and beats the closed-source incumbents on most retrieval benchmarks.
  • Languages: 100+ languages in one shared vector space — cross-language retrieval with no translation step.
  • Dimensions: BGE-M3 outputs 1024-dim vectors, vs 1536 for ada-002 and 512 for text-embedding-3-small as commonly configured.
  • Retrieval modes: dense, sparse, and ColBERT-style from one forward pass. OpenAI embeddings are dense-only.
  • Where it runs: your laptop, your server, your VPC. OpenAI runs on OpenAI.

What Is BGE-M3?

BGE-M3 is BAAI’s general-purpose embedding model, and the “M3” stands for multi-linguality, multi-functionality, multi-granularity. In practice that means one model handles dense retrieval, sparse (lexical) retrieval, and ColBERT-style multi-vector retrieval — out of the same forward pass.

One pip install, one model load, and you’re embedding 1024-dim vectors locally on an M4 Mac. No API key, no rate limits, no per-token bill:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-m3")

docs = [
    "hail damage on a colorbond roof in Brisbane",
    "dégâts de grêle sur une toiture",
    "屋根のひょう害",
]

embeddings = model.encode(docs, normalize_embeddings=True)
print(embeddings.shape)  # (3, 1024)

The multi-granularity piece rounds it out: the same model is built to embed everything from a one-line search query to a long document, so you aren’t juggling one model for queries and another for passages. One checkpoint, one vector space, every input length your pipeline throws at it.

Dense, Sparse and ColBERT From One Forward Pass

The multi-functionality part deserves a beat, because it’s the feature the OpenAI API simply doesn’t have. Dense vectors capture semantic meaning — “roof leak” matches “water coming through the ceiling.” Sparse retrieval behaves like a learned keyword match, which rescues you when the query is an exact product code or error string that semantics would blur over.

ColBERT-style multi-vector retrieval keeps one vector per token for finer-grained matching on long documents. BGE-M3 produces all three from the same forward pass, so hybrid retrieval — the dense-plus-sparse setup most production RAG systems converge on eventually — comes from one model instead of two systems glued together.

With a dense-only API, hybrid means bolting a separate keyword engine next to your vector store and merging results yourself. With BGE-M3 it’s a flag.

The Benchmark That Matters: Top of MTEB

MTEB is the standard leaderboard for embedding quality — retrieval, classification, clustering, reranking, across a pile of datasets. BGE-M3 took the top of it, which is exactly the kind of sentence that used to require an OpenAI or Google logo in front of it.

We’re not going to invent precise scores here — the leaderboard moves, check it live before you commit. But the headline result stands: the free, open-weights model outranks the paid closed models most teams are still defaulting to, and it does it while beating them on most retrieval benchmarks specifically — which is the workload that actually matters for RAG.

The Money Pattern: Cross-Language Retrieval

Multilingual is the real flex. Same model, same vector space, cross-language retrieval that actually works. Query in English, hit documents in French, Japanese, Mandarin — no per-language pipelines, no translation step:

import numpy as np

query = model.encode("roof leak after hailstorm", normalize_embeddings=True)
corpus = model.encode([
    "claim 4421: hail damage to tiled roof",
    "fuite de toit après tempête de grêle",
    "暴風雨後の屋根からの水漏れ",
    "completely unrelated invoice text",
], normalize_embeddings=True)

# cosine similarity = dot product when normalized
scores = corpus @ query
for s, doc in sorted(zip(scores, corpus), reverse=True)[:3]:
    print(f"{s:.3f}")

If your corpus has even a handful of non-English documents — international customers, imported datasets, multilingual support tickets — this single property ends the comparison. One vector space for everything beats a per-language embedding pipeline every single time.

Where OpenAI Embeddings Still Win

1024 dimensions is bigger than ada-002’s 1536… wait, no, it’s smaller. But it’s still chunkier than the new text-embedding-3-small at 512 dims. Storage and ANN index size scale with dimensions, so if you’re cramming 100M vectors into pgvector, that math genuinely matters.

The other honest win is operations. A metered API means zero infrastructure: no model serving, no GPU sizing, no cold starts — someone else’s problem, for a fee. If your embedding volume is tiny and your team has no appetite for running models, that trade can be worth it.

Also remember that embedding costs aren’t one-off. Every re-chunk, every re-index, every new document pipeline run bills the meter again — RAG systems re-embed constantly as content changes and chunking strategies evolve. A local model turns that recurring line item into compute you already own.

Which Embedding Model Should You Use?

Building RAG over your own data, embedding at real volume, or handling a multilingual corpus? BGE-M3 — the quality is there, the cost is zero, and the vectors never leave your infrastructure. If you’re storing them in Postgres, our pgvector + Supabase semantic search guide is the natural next step.

Tiny side project, no infra appetite, already wired into an OpenAI SDK? The managed API is fine, honestly. Just know you’re paying for convenience, not quality — the leaderboard says the free model is the better model.

One migration warning before you swap: embeddings from different models live in different vector spaces. You can’t mix BGE-M3 vectors with ada-002 vectors in the same index — a switch means re-embedding the entire corpus in one batch job and cutting over. With a local model that job costs you compute time and zero API dollars, which is exactly why the swap is easier in this direction than the reverse.

The Verdict

If you’re paying OpenAI for embeddings in 2026 and you’re not on the absolute frontier, you’re lighting money on fire. BGE-M3 runs locally, beats the closed-source incumbents on most retrieval benchmarks, and costs nothing per token.

Swap it in tonight. Your retrieval gets better, your bill goes to zero, and your CFO will thank you.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.