English translation is not available yet. Showing Russian content.
RAG с мультиязычным поиском (русский/английский/китайский)
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: RAG с мультиязычным поиском (русский/английский/китайский)
1. Цель задачи
Разработать прототип RAG-системы (Retrieval-Augmented Generation), использующий мультиязычный эмбеддер BGE-M3 для индексации и поиска документов на русском, английском и китайском языках. Система должна принимать запросы на любом из трёх языков и возвращать релевантные документы из единого корпуса, содержащего документы на всех трёх языках. Ключевой результат значение метрики Recall@10 > 0.8 на каждом из трёх языков для тестового набора запросов.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Модель эмбеддингов BGE-M3 | Hugging Face: BAAI/bge-m3 (размер ~2.2 ГБ) |
| Тестовый корпус документов (минимум 100 документов на каждый язык) | Сгенерировать самостоятельно: 300 коротких текстов (100 русских, 100 английских, 100 китайских) по теме «наука и технологии» |
| Тестовые запросы (10 на каждый язык, всего 30) | Составить вручную: каждый запрос должен иметь один релевантный документ в корпусе |
| Ground truth (соответствия запрос-документ) | Определить при создании корпуса (запросы формулируются на основе содержания документа) |
| Индекс для быстрого поиска | FAISS (Facebook AI Similarity Search) — библиотека для эффективного поиска по векторным базам |
Если нет реального инструмента — симулируем:
- Для генерации корпуса документов напишите Python-скрипт, который создаёт 100 текстов на каждом языке с помощью шаблонов или случайного набора предложений (без использования LLM). Например, комбинируйте готовые фразы из технических статей.
- Тестовые запросы составляются вручную на основе первых 10 документов каждого языка. Для каждого запроса запишите ID релевантного документа в файл ground_truth.json.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык программирования | Python 3.10+ | Реализация пайплайна |
| Управление зависимостями | pip + requirements.txt или Conda | Воспроизводимость среды |
| Эмбеддинги | Hugging Face Transformers + BAAI/bge-m3 | Получение мультиязычных векторных представлений |
| Индексирование и поиск | FAISS (faiss-cpu или faiss-gpu) | Эффективный косинусный/внутренний поиск по векторам |
| Обработка данных | Pandas, NumPy, JSON | Подготовка корпуса, запросов и ground truth |
| Метрики | Scikit-learn, собственные функции | Вычисление Recall@10 |
| Среда разработки | Jupyter Notebook или Python-скрипт | Прототипирование и фиксация результатов |
4. Этапы выполнения
Этап 1: Подготовка данных и окружения (оценка времени: 1 час)
Действия
- Создайте виртуальное окружение и установите зависимости:
pip install transformers torch faiss-cpu pandas numpy scikit-learn - Загрузите модель BGE-M3:
from transformers import AutoModel, AutoTokenizer model_name = "BAAI/bge-m3" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModel.from_pretrained(model_name) model.eval() - Сгенерируйте корпус документов (corpus.json):
- Формат: список словарей {"id": int, "language": "ru"/"en"/"zh", "text": str}.
- Для каждого языка создайте 100 текстов длиной 50–150 символов. Пример шаблона для русского:
"Квантовый компьютер использует кубиты для параллельных вычислений." - Используйте комбинации тем: AI, космос, биотехнологии, физика.
- Составьте ground truth (ground_truth.json):
- Выберите первые 10 документов каждого языка (id 0–9 для ru, 100–109 для en, 200–209 для zh).
- Для каждого документа придумайте запрос на том же языке, однозначно на него указывающий. Сохраните в формате:
[ {"query": "запрос на русском", "relevant_doc_id": 0, "language": "ru"}, ... ]
Ожидаемый результат этапа Файлы corpus.json (300 документов) и ground_truth.json (30 запросов). Загруженная модель BGE-M3.
Этап 2: Получение эмбеддингов для корпуса (оценка времени: 1 час)
Действия
- Напишите функцию encode_texts(texts, batch_size=32), которая:
- Принимает список строк.
- Токенизирует с параметром padding=True, truncation=True, max_length=512, return_tensors='pt'.
- Пропускает через модель без градиентов, получает last_hidden_state, применяет mean pooling.
- Возвращает массив numpy формы (n_texts, hidden_dim) – для BGE-M3 размерность 1024.
- Примените функцию ко всем текстам корпуса, сохраните матрицу
corpus_embeddings.npy. - Нормализуйте эмбеддинги (L2-норма) – это повысит качество косинусного поиска.
Ожидаемый результат этапа Матрица эмбеддингов corpus_embeddings.npy размером (300, 1024). Векторы нормализованы.
Этап 3: Индексирование и поиск (оценка времени: 0.5 часа)
Действия
- Создайте индекс FAISS типа IndexFlatIP (скалярное произведение) или IndexFlatL2.
import faiss dim = 1024 index = faiss.IndexFlatIP(dim) # для косинусного расстояния с нормализованными векторами index.add(corpus_embeddings) - Сохраните индекс на диск: faiss.write_index(index, "bge_m3_index.faiss").
- Реализуйте функцию search(query, k=10):
- Переводит запрос в эмбеддинг через
encode_texts([Вики/Query|query). - Ищет в индексе index.search(query_emb, k).
- Возвращает id ближайших документов и расстояния.
- Переводит запрос в эмбеддинг через
Ожидаемый результат этапа Индекс bge_m3_index.faiss, функция поиска работает.
Этап 4: Оценка качества поиска (Recall@10) (оценка времени: 1 час)
Действия
- Для каждого запроса из ground_truth.json выполните поиск (k=10).
- Вычислите Recall@10 для каждого языка отдельно:
def recall_at_k(retrieved_ids, relevant_id, k=10): return 1.0 if relevant_id in retrieved_ids[:k] else 0.0 - Усредните Recall@10 по всем запросам одного языка.
- Выведите отчёт:
Recall@10 (Russian): 0.90 Recall@10 (English): 0.85 Recall@10 (Chinese): 0.95 - Если Recall@10 < 0.8 на каком-либо языке:
- Проверьте качество запросов (не слишком ли общие).
- Увеличьте корпус до 200 документов на язык.
- Попробуйте добавить префикс инструкции:
"Represent this sentence for searching relevant passages:"(для BGE-M3 рекомендуется). - Перезапустите этапы 2–4.
Ожидаемый результат этапа Значения Recall@10 для каждого языка, записанные в файл metrics.json.
Этап 5: Анализ и документирование (оценка времени: 0.5 часа)
Действия
- Оформите Jupyter Notebook с последовательным выполнением всех шагов.
- Добавьте в конец вывод метрик и примеры запросов с найденными документами.
- Зафиксируйте в README.md:
- Краткое описание задачи.
- Инструкцию по запуску.
- Достигнутые метрики.
- Наблюдения: как язык запроса влияет на поиск, какие ошибки возникли.
Ожидаемый результат этапа Notebook multilingual_rag.ipynb, файл README.md.
5. Критерии приемки (Definition of Done)
- Реализован полный пайплайн: загрузка модели → эмбеддинги → индекс → поиск → метрики.
- Recall@10 на русском языке ≥ 0.8.
- Recall@10 на английском языке ≥ 0.8.
- Recall@10 на китайском языке ≥ 0.8.
- Код воспроизводим: все зависимости указаны в
requirements.txt. - Корпус документов содержит не менее 100 уникальных текстов на каждый язык.
- Ground truth включает 30 запросов (10 на язык) с правильными релевантными ID.
- Индекс FAISS сохранён как двоичный файл и может быть переиспользован.
- Результаты метрик выведены в консоль и сохранены в JSON.
- Jupyter Notebook оформлен с пояснениями и выводами.
6. Ожидаемый результат
- Основной артефакт файл
multilingual_rag.ipynb, содержащий: - Вспомогательные файлы
corpus.json– корпус документов.ground_truth.json– тестовые запросы с релевантными ID.bge_m3_index.faiss– сериализованный индекс.corpus_embeddings.npy– эмбеддинги корпуса (опционально).metrics.json– метрики Recall@10 по языкам.requirements.txt– список зависимостей.
- Дополнительно краткий отчёт в
README.mdс анализом сильных и слабых сторон мультиязычного поиска.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Модель BGE-M3 не загружается (проблемы с Hugging Face) | Использовать зеркало hf-mirror.com или загрузить модель заранее вручную. |
| Эмбеддинги не нормализованы → низкое качество поиска | Принудительно применить L2-нормализацию после mean pooling. |
| Китайские запросы не находят релевантные документы | Убедиться, что китайские тексты токенизируются корректно (использовать китайские символы, а не пиньинь). Увеличить корпус до 200 документов. |
| Ошибка памяти при большом корпусе | Использовать faiss-gpu (если есть CUDA) или уменьшить batch_size. |
| Recall@10 ниже 0.8 на одном из языков | 1) Проверить ground truth: запрос должен быть точной парафразой части документа. 2) Добавить префикс инструкции BGE-M3: "Represent this sentence for searching relevant passages: " + query. 3) Увеличить k до 20 и проверить Recall@20. |
| Зависимости конфликтуют (torch + faiss) | Создать conda environment с Python 3.10: conda create -n multilingual python=3.10 && conda install pytorch faiss-cpu. |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Подготовка данных и окружения | 1 ч |
| Этап 2: Получение эмбеддингов | 1 ч |
| Этап 3: Индексирование и поиск | 0.5 ч |
| Этап 4: Оценка качества | 1 ч |
| Этап 5: Анализ и документирование | 0.5 ч |
| Итого | 4 ч |
Примечание Для первого выполнения задачи заложите дополнительно 1 час на отладку и настройку модели (префиксы, batch_size). Оценка дана для выполнения на CPU с корпусом 300 документов. При использовании GPU время этапа 2 сокращается в 2–3 раза.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 123 | Основы RAG: архитектура, компоненты |
| 145 | Выбор эмбеддинговой модели для многоязычных текстов |
| 267 | Метрики оценки поиска: Recall@k, MRR, NDCG |
| 345 | Использование FAISS для векторного поиска |
| 456 | Оптимизация batch-запросов к модели в Hugging Face |
| 567 | Нормализация эмбеддингов и влияние на косинусное сходство |
| 678 | Префиксы инструкций в модели BGE |
| 789 | Сравнение BGE-M3, LaBSE и sentence-transformers |
| 890 | Обработка китайского текста в NLP-пайплайне |
| 901 | Тестирование RAG-систем: создание golden-датасета |
10. Чек-лист самопроверки
- Я создал виртуальное окружение и установил все зависимости из
requirements.txt. - Я сгенерировал корпус из 300 документов (100 на каждый язык) и сохранил его в JSON.
- Я составил 30 запросов (10 на каждый язык) с точным указанием релевантного документа.
- Я загрузил модель BGE-M3 и получил эмбеддинги для всего корпуса.
- Я построил индекс FAISS и выполнил поиск по всем тестовым запросам.
- Я вычислил Recall@10 для каждого языка и убедился, что все значения ≥ 0.8.
- Я оформил код в Jupyter Notebook с подробными комментариями и выводами.
- Я проверил, что notebook воспроизводится с нуля (clean run).
- Я написал README с описанием задачи, инструкцией и результатами.