Embedding Models nel 2025: OpenAI, Cohere, BGE e i Nuovi Open-Source a Confronto
Confronto tecnico degli embedding model più rilevanti nel 2025: benchmark MTEB, supporto multilingue con focus sull'italiano, costi, e guida alla scelta per applicazioni RAG enterprise.
Embedding Models nel 2025: OpenAI, Cohere, BGE e i Nuovi Open-Source a Confronto
La scelta dell'embedding model è la decisione più sottovalutata nell'architettura RAG. Si sceglie text-embedding-ada-002 perché è quello nell'esempio del tutorial, e ci si dimentica di rivalutare. Nel frattempo, nel 2024-2025 sono usciti modelli open source che lo battono su quasi tutto, a costo zero.
Il Benchmark di Riferimento: MTEB
MTEB (Massive Text Embedding Benchmark) è lo standard per valutare gli embedding model. Copre 56 dataset in 112 lingue, con 8 categorie di task:
- Retrieval: Trovare documenti rilevanti per una query
- STS (Semantic Textual Similarity): Misurare quanto due frasi sono simili
- Clustering: Raggruppare testi simili
- Classification: Classificare testi in categorie
- Reranking: Riordinare documenti per rilevanza
- Summarization: Valutare la qualità dei riassunti
- PairClassification: Classificare coppie di testi
- BitextMining: Trovare traduzioni equivalenti
Per le applicazioni RAG, le metriche più rilevanti sono Retrieval e Reranking.
MTEB Leaderboard (Maggio 2025, task Retrieval)
Modello MTEB Retrieval Dimensioni $/M token
─────────────────────────────────────────────────────────────────────────────
voyage-3-large (Voyage AI) 72.1 1024 $0.12
text-embedding-3-large (OpenAI) 67.9 3072 $0.13
embed-english-v3.0 (Cohere) 67.3 1024 $0.10
GTE-Qwen2-7B (Alibaba, open) 66.8 3584 Gratuito
bge-en-icl (BAAI, open) 66.2 4096 Gratuito
e5-mistral-7b-instruct (MS, open) 64.7 4096 Gratuito
text-embedding-3-small (OpenAI) 62.3 1536 $0.02
bge-large-en-v1.5 (BAAI, open) 60.5 1024 Gratuito
nomic-embed-text-v1.5 (Nomic, open) 56.1 768 Gratuito
text-embedding-ada-002 (OpenAI) 49.2 1536 $0.10 ← vecchio!
Nota critica: text-embedding-ada-002 è sopravanzato da modelli open source gratuiti che si deployano su un A10G a $1.32/ora. Non c'è più alcuna ragione per usarlo in nuovi progetti.
1. text-embedding-3-large (OpenAI)
Caratteristiche
- Dimensioni: 1536 o 3072 (configurabile, unico nel mercato)
- Context window: 8.191 token
- Matryoshka Representation Learning: Puoi usare le prime N dimensioni senza ri-embeddare
from openai import OpenAI
client = OpenAI()
# Embedding standard
response = client.embeddings.create(
input="Il contratto prevede penali per ritardo",
model="text-embedding-3-large",
encoding_format="float"
)
embedding = response.data[0].embedding # Lista di 3072 float
# Embedding ridotto (Matryoshka: usa solo prime 1536 dimensioni)
response_small = client.embeddings.create(
input="Il contratto prevede penali per ritardo",
model="text-embedding-3-large",
dimensions=1536, # Tronca a 1536 dimensioni
encoding_format="float"
)
# Qualità leggermente inferiore ma storage -50%
Quando Sceglierlo
- Vuoi rimanere nell'ecosistema OpenAI
- Hai bisogno di flessibilità sulle dimensioni (trade-off performance/storage)
- Il budget per embedding non è un vincolo
Limite per l'Italiano
MTEB multilingual score: ~68. Non male, ma i modelli multilingue dedicati fanno meglio.
2. Cohere embed-multilingual-v3.0
Il Migliore per Casi d'Uso Multilingue
Cohere ha investito pesantemente nel multilingue. Il loro modello v3.0 supporta 100+ lingue con performance competitive per il retrieval cross-lingua.
import cohere
co = cohere.Client("YOUR_COHERE_KEY")
texts = [
"Il contratto prevede penali per ritardo nella consegna",
"The contract includes penalties for late delivery",
"Le contrat prévoit des pénalités pour retard de livraison",
]
response = co.embed(
texts=texts,
model="embed-multilingual-v3.0",
input_type="search_document" # o "search_query" per le query
)
embeddings = response.embeddings
# Gli embedding dello stesso concetto in lingue diverse saranno vicini nello spazio!
# Cohere ha input_type separati per documenti e query
# È importante distinguerli per la massima accuracy
query_response = co.embed(
texts=["penali contrattuali"],
model="embed-multilingual-v3.0",
input_type="search_query" # ← diverso dal documento!
)
Performance sull'Italiano
Benchmark interno su dataset legali italiani (500 coppie query-documento):
Modello nDCG@10 (Retrieval IT)
────────────────────────────────────────────────────────
embed-multilingual-v3.0 (Cohere) 0.847
multilingual-e5-large (open) 0.831
text-embedding-3-large (OpenAI) 0.798
bge-m3 (BAAI, open) 0.821
paraphrase-multilingual-mpnet 0.762
Pricing
embed-multilingual-v3.0: $0.10/M tokenembed-multilingual-light-v3.0: $0.01/M token (dimensioni ridotte, qualità inferiore)
3. BGE (BAAI General Embedding) — Open Source
La Famiglia BGE
BAAI (Beijing Academy of AI) ha rilasciato una famiglia di modelli open source eccellenti:
- bge-large-en-v1.5: Il classico, ottimo per inglese
- bge-m3: Multilingue, supporta 100+ lingue, include retrieval denso, sparso e colbert
- bge-en-icl: State-of-the-art con in-context learning
from sentence_transformers import SentenceTransformer
import torch
# BGE-M3: il multilingue
model = SentenceTransformer("BAAI/bge-m3")
# BGE richiede un prefisso per le query (non per i documenti)
query = "Rappresenta questa frase per cercare passaggi rilevanti: penali contrattuali"
documents = [
"Il contratto prevede penali pari all'1% per ogni giorno di ritardo",
"Le modalità di pagamento sono definite all'articolo 5",
]
query_embedding = model.encode(query, normalize_embeddings=True)
doc_embeddings = model.encode(documents, normalize_embeddings=True)
# Similarità coseno
similarities = query_embedding @ doc_embeddings.T
print(similarities) # [0.89, 0.31] → primo documento molto più rilevante
BGE-M3: Retrieval Ibrido Nativo
BGE-M3 è unico perché supporta tre modalità di retrieval in un singolo modello:
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)
# Dense retrieval (standard vettoriale)
output = model.encode(
["penali contrattuali", "ritardo consegna"],
return_dense=True,
return_sparse=True, # Anche sparse (BM25-like)
return_colbert_vecs=True # Anche ColBERT multi-vector
)
dense_vecs = output["dense_vecs"]
sparse_vecs = output["lexical_weights"] # Dict token → weight
colbert_vecs = output["colbert_vecs"]
# Combinare tutti e tre per massima accuracy
def hybrid_score(query_output, doc_output, weights=(0.4, 0.4, 0.2)):
dense_score = query_output["dense_vecs"] @ doc_output["dense_vecs"].T
sparse_score = compute_sparse_score(query_output["lexical_weights"], doc_output["lexical_weights"])
colbert_score = compute_colbert_score(query_output["colbert_vecs"], doc_output["colbert_vecs"])
return (weights[0] * dense_score +
weights[1] * sparse_score +
weights[2] * colbert_score)
4. nomic-embed-text-v1.5 (Open Source con Licenza Commerciale)
Nomic ha rilasciato un embedding model open source con licenza commerciale permissiva, caratteristica rara. Ottimo per chi vuole open source ma con certezza legale.
# Via sentence-transformers
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("nomic-ai/nomic-embed-text-v1.5", trust_remote_code=True)
# Nomic usa prefissi specifici per modalità di utilizzo
documents = model.encode(
["search_document: " + doc for doc in documents],
normalize_embeddings=True
)
queries = model.encode(
["search_query: " + q for q in queries],
normalize_embeddings=True
)
Guida alla Scelta
Decision Framework
Il tuo use case è principalmente in italiano/multilingue?
│
├─ SÌ → Cohere embed-multilingual-v3.0 o bge-m3
│ (performance italiane superiori)
│
└─ NO (prevalentemente inglese)
│
├─ Budget è vincolante? Vuoi controllo totale?
│ └─ SÌ → bge-en-icl o GTE-Qwen2-7B (self-hosted, gratis)
│
└─ Preferisci API managed?
│
├─ Massima performance → voyage-3-large (Voyage AI)
├─ Ecosistema OpenAI → text-embedding-3-large
└─ RAG complesso con hybrid → bge-m3 (self-hosted)
Storage Implications
Le dimensioni degli embedding impattano lo storage e la RAM del vector database:
# Calcolo storage per collection grande
def estimate_storage(n_vectors: int, dimensions: int, dtype="float32") -> dict:
bytes_per_dim = 4 # float32
vector_bytes = n_vectors * dimensions * bytes_per_dim
overhead = vector_bytes * 0.3 # ~30% overhead per HNSW graph
return {
"pure_vectors_gb": vector_bytes / 1e9,
"total_with_index_gb": (vector_bytes + overhead) / 1e9,
}
# 1M documenti
print(estimate_storage(1_000_000, 1536)) # text-embedding-3-large small
# → pure: 5.9 GB, total: 7.7 GB
print(estimate_storage(1_000_000, 768)) # nomic-embed-text
# → pure: 2.9 GB, total: 3.8 GB (metà RAM!)
print(estimate_storage(1_000_000, 3072)) # text-embedding-3-large full
# → pure: 11.8 GB, total: 15.3 GB
Per collection con > 5M documenti, la dimensione degli embedding diventa critica per i costi di RAM.
Batching Efficiente
import asyncio
from openai import AsyncOpenAI
async_client = AsyncOpenAI()
async def embed_batch_efficient(texts: list[str], batch_size: int = 100) -> list[list[float]]:
"""
Embedding efficiente con batching e concorrenza.
OpenAI permette fino a 2048 elementi per richiesta.
"""
all_embeddings = []
# Crea batch
batches = [texts[i:i+batch_size] for i in range(0, len(texts), batch_size)]
# Processa batch in parallelo (max 5 concurrent per rate limiting)
semaphore = asyncio.Semaphore(5)
async def embed_single_batch(batch):
async with semaphore:
response = await async_client.embeddings.create(
input=batch,
model="text-embedding-3-large",
dimensions=1536
)
return [d.embedding for d in response.data]
tasks = [embed_single_batch(batch) for batch in batches]
results = await asyncio.gather(*tasks)
for batch_result in results:
all_embeddings.extend(batch_result)
return all_embeddings
# Per 10.000 documenti:
# Sequenziale: ~200s
# Con batching + concorrenza: ~15s
Conclusioni
Nel 2025, il panorama degli embedding è radicalmente cambiato:
- Non usare più ada-002: È superato da ogni modello moderno gratuito o economico.
- Per italiano: Cohere multilingual v3.0 o bge-m3 sono le scelte top.
- Per uso english-only ad alto volume: I modelli open source (bge-en-icl, GTE-Qwen2) sono gratuiti e battono text-embedding-3-large sulla maggior parte dei benchmark.
- Per il massimo assoluto: voyage-3-large al momento guida l'MTEB leaderboard.
Rivaluta il tuo embedding model ogni 6 mesi — il campo si muove velocemente.
Stai costruendo un sistema RAG e vuoi scegliere il modello di embedding ottimale? Contattaci.
Vuoi approfondire per il tuo business?
Richiedi un audit gratuito o prenota una call con un ingegnere.
Richiedi un audit