Выбор и настройка Embedding-модели для RAG
Embedding-модель — один из наиболее критичных компонентов RAG-системы. Качество retrieval напрямую зависит от того, насколько хорошо модель представляет тексты в векторном пространстве. Смена embedding-модели может дать больший прирост recall, чем оптимизация чанкинга или параметров поиска.
Категории embedding-моделей
Проприетарные API-модели:
-
text-embedding-3-large(OpenAI, dim=3072): лучшее качество на большинстве бенчмарков MTEB -
text-embedding-3-small(OpenAI, dim=1536): хорошее соотношение цена/качество -
embed-v3(Cohere): сильный на retrieval задачах, поддерживает input_type параметр
Открытые модели (self-hosted):
-
BAAI/bge-m3(dim=1024): многоязычный, поддерживает dense+sparse+colbert -
BAAI/bge-large-en-v1.5(dim=1024): лучший для английского -
intfloat/multilingual-e5-large(dim=1024): хорошо на русском -
nomic-ai/nomic-embed-text-v1.5(dim=768): матрёшечный (кратные размерности)
MTEB бенчмарк: сравнение моделей
На задачах Retrieval (BEIR benchmark, усреднённый nDCG@10):
| Модель | NDCG@10 (BEIR avg) | Dim | Макс. токены | Тип |
|---|---|---|---|---|
| text-embedding-3-large | 54.9 | 3072 | 8191 | API |
| text-embedding-3-small | 51.7 | 1536 | 8191 | API |
| cohere embed-v3 | 55.0 | 1024 | 512 | API |
| BAAI/bge-m3 | 54.0 | 1024 | 8192 | Open |
| intfloat/e5-mistral-7b | 56.9 | 4096 | 32768 | Open |
| nomic-embed-text-v1.5 | 53.5 | 768 | 8192 | Open |
Для русскоязычных задач картина иная — рекомендуем тестировать на собственном домене.
Настройка Cohere Embed v3 с input_type
Cohere embed-v3 требует указания input_type — это важно для retrieval:
import cohere
co = cohere.Client(api_key="...")
def embed_documents(texts: list[str]) -> list[list[float]]:
"""Для индексации документов"""
response = co.embed(
texts=texts,
model="embed-multilingual-v3.0",
input_type="search_document", # Для документов при индексации
)
return response.embeddings
def embed_query(query: str) -> list[float]:
"""Для поискового запроса"""
response = co.embed(
texts=[query],
model="embed-multilingual-v3.0",
input_type="search_query", # Асимметричная модель — разные типы
)
return response.embeddings[0]
Использование правильного input_type повышает recall на 8–15% — модель обучена на asymmetric retrieval.
Self-hosted BGE-M3
BGE-M3 — наиболее универсальная open-source модель: поддерживает dense, sparse (SPLADE) и ColBERT-стиль multi-vector retrieval из одной модели:
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel(
"BAAI/bge-m3",
use_fp16=True, # Экономия памяти
device="cuda",
)
# Dense embeddings (для стандартного ANN поиска)
dense_embeddings = model.encode(
texts,
batch_size=32,
max_length=8192,
return_dense=True,
return_sparse=False,
return_colbert_vecs=False,
)["dense_vecs"]
# Sparse embeddings (для BM25-подобного поиска)
sparse_embeddings = model.encode(
texts,
return_dense=False,
return_sparse=True,
)["lexical_weights"] # dict {token: weight}
# Hybrid retrieval score
def compute_bge_m3_score(query_dense, doc_dense, query_sparse, doc_sparse,
alpha=0.5) -> float:
dense_score = np.dot(query_dense, doc_dense)
sparse_score = sum(
query_sparse.get(token, 0) * doc_sparse.get(token, 0)
for token in query_sparse
)
return alpha * dense_score + (1 - alpha) * sparse_score
Выбор размерности: Matryoshka Embeddings
Nomic Embed и ряд других моделей поддерживают матрёшечные embeddings — можно использовать первые N измерений без переобучения:
from openai import OpenAI
client = OpenAI()
# text-embedding-3-large с уменьшенной размерностью
# 3072 → 1536 без переиндексации (официально поддерживается OpenAI)
response = client.embeddings.create(
model="text-embedding-3-large",
input=texts,
dimensions=1536, # Уменьшаем размерность
)
Это позволяет снизить требования к RAM векторной БД в 2× при незначительной (2–5%) потере качества.
Практический выбор embedding-модели
Если данные конфиденциальны / on-premise: BGE-M3 или E5-mistral-7b (self-hosted).
Если нужен лучший русский язык: тестируем BGE-M3, multilingual-e5-large и text-embedding-3-large на своём домене. Универсального победителя нет.
Если минимальная latency: text-embedding-3-small (API) или nomic-embed-text-v1.5 (small, self-hosted).
Если нужен hybrid sparse+dense без двух моделей: BGE-M3 — единственная open-source модель с нативной поддержкой обоих режимов.
Оценка на своём домене
from ragas import evaluate
from ragas.metrics import context_recall, context_precision
# Тестирование двух моделей на вашем датасете
for model_name in ["text-embedding-3-small", "text-embedding-3-large"]:
retriever = build_retriever(model_name)
scores = evaluate(test_dataset, metrics=[context_recall, context_precision],
retriever=retriever)
print(f"{model_name}: recall={scores['context_recall']:.3f}, "
f"precision={scores['context_precision']:.3f}")
Сроки
- Настройка embedding модели и индексация: 2–5 дней
- Сравнительное тестирование 2–3 моделей: 3–5 дней
- Итого: 1–2 недели







