Обновить

Идеальная база знаний, а RAG возвращает мусор — проблема не там, где кажется

Продолжение предыдущего поста про микрочанки, где 3 мусорных документа отравили весь RAG. Тогда проблема была в данных. Сейчас — данные идеальные, а поиск всё равно не работает.

Контекст

Строю локальную мультиагентную систему. Собрал базу знаний: 85 архитектурных блоков, 160 чанков в ChromaDB, реальный опыт — не синтетика. Embedding модель — стандартная all-MiniLM-L6-v2. Документы на русском с вкраплениями английских терминов (DPO, LoRA, VRAM — как у всех).

Симптом

Спрашиваю: "DPO патч для OOM" — в базе есть целый блок про это. RAG возвращает документ про права доступа к Project Context. Вообще мимо.

Спрашиваю: "positive feedback loop" — в базе есть блок №57 ровно с таким названием. RAG его не находит, dist=0.746.

Диагностика

Подозрение — embedding модель не понимает русский текст. Проверяю: один и тот же смысл, три формулировки.

queries = [
    ("positive feedback loop", "английский"),
    ("петля положительной обратной связи", "русский"),
    ("цикл доверие данные результат", "русский контекст"),
]

for q, lang in queries:
    results = col.query(query_texts=[q], n_results=1, include=["documents", "distances"])
    dist = results['distances'][0][0]
    print(f"[{lang}] dist={dist:.3f} | '{q}'")
[английский]       dist=0.746 | 'positive feedback loop'
[русский]           dist=0.566 | 'петля положительной обратной связи'
[русский контекст]  dist=0.504 | 'цикл доверие данные результат'

Один смысл — разница в полтора раза. При этом документы в базе на русском. Английский запрос к русским документам — модель не может их сопоставить.

Почему так

all-MiniLM-L6-v2 обучалась на английских текстах. Она превращает текст в вектор из 384 чисел. Для английского — вектор осмысленный, семантически правильный. Для русского — видит буквы, но не понимает смысл. Вектор получается случайный.

Это как нанять переводчика, который знает только английский, и попросить его искать по русской библиотеке.

А может перевести всё на английский?

Первая мысль — перевести все документы на английский, запросы тоже переводить на лету, а результат обратно на русский. Английские embedding модели объективно лучше отточены, больше данных, больше бенчмарков.

Но для локальной системы с русскими документами это плохой вариант. Технические термины с контекстом теряются при переводе. Появляется двойная задержка — перевод запроса туда, результата обратно. Нужен ещё один сервис (переводчик), а задача — держать всё локально. И главное — ошибки накапливаются: плохой перевод → плохой вектор → плохой результат.

Для чисто английских доков — да, держите всё на английском. Но когда документы изначально на русском с кучей специфики — мультиязычная модель проще. Меньше движущихся частей.

Решение

Заменил all-MiniLM-L6-v2 на paraphrase-multilingual-MiniLM-L12-v2. Модель обучена на 50+ языках, включая русский. Понимает смешанный текст типа “DPO обучение на LoRA адаптере” — то, что в локальных ML-проектах встречается на каждом шагу.

Пересоздал все коллекции с новой моделью. Результат:

# Было (all-MiniLM-L6-v2):
# 'positive feedback loop' → dist=0.746, нашёл мусор

# Стало (multilingual):
# 'positive feedback loop' → dist=0.35, нашёл именно блок про Feedback Loop

Поиск заработал сразу. На все запросы — и русские, и английские, и смешанные.

Вывод

Если строите RAG на русском (или любом не-английском) — не берите all-MiniLM-L6-v2 по дефолту. Она стоит первой в каждом туториале, но для нелатинских языков это ловушка. Данные могут быть идеальными, чанкинг правильным, а поиск будет возвращать мусор — потому что “переводчик” не знает ваш язык.

Замена embedding модели на мультиязычную — одна строчка кода и пересоздание коллекций. Пять минут работы, которые сэкономят дни дебага.

# Было
ef = SentenceTransformerEmbeddingFunction(model_name="all-MiniLM-L6-v2")

# Стало
ef = SentenceTransformerEmbeddingFunction(model_name="paraphrase-multilingual-MiniLM-L12-v2")
Теги:
+3
Комментарии5

Публикации