Сгенерировать synthetic датасет для RAG
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Сгенерировать synthetic датасет для RAG
1. Цель задачи
Разработать пайплайн синтетической генерации 500 пар «вопрос‑ответ» на основе предоставленного корпуса документов. Созданный датасет должен быть пригоден для fine‑tuning или оценки RAG‑системы. Ключевой результат метрика RAGAS Faithfulness, измеренная на синтетических данных, превышает 0.85.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Корпус документов (текстовые файлы, PDF, Markdown) | Внутренние документы компании / открытые статьи (например, датасет «Natural Questions» или собственные файлы) |
| LLM‑модель для генерации вопросов | OpenAI API (gpt-4o-mini) / Hugging Face (Llama 3) / локальная модель |
| Инструмент для оценки RAGAS | Библиотека ragas (pip install ragas) |
| Векторное хранилище (опционально, для теста RAG) | FAISS / ChromaDB |
Если нет реального инструмента — симулируем:
- Скачайте 3–5 статей из англоязычной Википедии (например, про «Machine learning», «Python», «RAG») в формате .txt.
- Разбейте их на чанки по 512 токенов (используйте langchain.text_splitter.RecursiveCharacterTextSplitter).
- Для эмуляции RAG‑пайплайна возьмите готовую векторную БД ChromaDB (установка chromadb).
- Для оценки Faithfulness используйте ragas с моделью‑judge (по умолчанию gpt-4; если нет ключа — локальная модель SentenceTransformers для эмбеддингов, но точность будет ниже; можно симулировать метрику, запустив один раз на 50 вопросах с ручной проверкой).
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Генерация вопросов | langchain, openai / transformers | Вызов LLM для создания вопросов по чанкам |
| Обработка документов | langchain, unstructured / pdfplumber | Загрузка, чанкинг, очистка текста |
| Векторное хранилище | chromadb | Хранение эмбеддингов и поиск контекста |
| Оценка RAGAS | ragas, datasets | Вычисление Faithfulness и других метрик |
| Управление данными | pandas, json, yaml | Сохранение датасета, конфигураций |
4. Этапы выполнения
Этап 1: Подготовка корпуса и чанкинг (оценка: 1 час)
Действия
- Загрузите все документы из указанной директории (поддерживаемые форматы: .txt, .pdf, .md). Используйте langchain_community.document_loaders.DirectoryLoader.
- Очистите текст: удалите лишние пробелы, нормализуйте Unicode, приведите к нижнему регистру (если задача нечувствительна к регистру).
- Разбейте документы на чанки размером 512 токенов с перекрытием 64 токена:
from langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=512, chunk_overlap=64, length_function=len # можно заменить на tiktoken ) chunks = splitter.split_documents(documents) - Сохраните чанки в формате JSONL (каждый чанк — {"id": "chunk_001", "text": "...", "source": "file.pdf"}).
Ожидаемый результат этапа файл chunks.jsonl с 200–500 чанками (в зависимости от объёма документов).
Этап 2: Генерация синтетических вопросов (оценка: 2 часа)
Действия
- Настройте промпт для генерации вопроса по чанку. Пример системного сообщения:
You are an expert at creating exam questions. Based on the provided context, generate one question that can be answered strictly from the text. The question should be specific and require factual recall. Output only the question. - Для каждого чанка вызовите LLM (используйте openai.ChatCompletion или langchain.llms). Установите temperature=0.7, max_tokens=100.
- Повторите генерацию, пока не получите 500 уникальных вопросов. Удалите дубликаты (по схожести эмбеддингов или точному совпадению).
- Сохраните результат в датафрейм с колонками
question, context (текст чанка),chunk_id.
Ожидаемый результат этапа файл generated_qas.jsonl (500 записей).
Этап 3: Построение RAG‑пайплайна для генерации ответов (оценка: 1.5 часа)
Действия
- Загрузите чанки в векторное хранилище ChromaDB (используйте эмбеддинги HuggingFaceEmbeddings от all-MiniLM-L6-v2).
- Создайте функцию
retrieve_answer(question, k=3), которая: - Для каждого из 500 вопросов сгенерируйте ответ. Ограничьте вызовы API (например, 10 параллельных потоков через ThreadPoolExecutor).
- Сохраните результат: датафрейм с колонками
question,contexts(список чанков), answer,ground_truth(пока пустая, если нет эталонного ответа).
Ожидаемый результат этапа файл rag_responses.jsonl (500 записей).
Этап 4: Оценка RAGAS Faithfulness (оценка: 1 час)
Действия
- Преобразуйте датафрейм в формат Dataset Hugging Face:
from datasets import Dataset data = Dataset.from_pandas(df) - Вычислите метрику Faithfulness с помощью ragas:
from ragas import evaluate from ragas.metrics import faithfulness result = evaluate(data, metrics=[faithfulness]) print(result) - Если результат < 0.85, проанализируйте причины: низкое качество генерации вопросов, плохой retrieval, шум в чанках.
- Итеративно улучшайте: меняйте промпт генерации вопросов, размер чанка, количество retrieved‑чанков, модель‑judge. Повторяйте оценку до достижения порога.
Ожидаемый результат этапа метрика Faithfulness ≥ 0.85.
Этап 5: Финализация датасета (оценка: 0.5 часа)
Действия
- Объедините файлы generated_qas.jsonl и rag_responses.jsonl в единый датасет.
- Добавьте колонку
faithfulness_score(результат оценки для каждого вопроса, если вычисляли per‑example). - Сохраните итоговый датасет в формате Parquet (быстрее для загрузки) и JSON.
- Сгенерируйте отчёт (Jupyter Notebook или Markdown) с распределением длин вопросов, примеров, гистограммой Faithfulness.
Ожидаемый результат этапа финальные файлы synthetic_rag_dataset.parquet, report.md.
5. Критерии приемки (Definition of Done)
- Сгенерировано не менее 500 уникальных пар «вопрос → контекст» (вопросы не пустые и не дублируются).
- Датасет содержит колонки:
question,contexts,answer,ground_truth(если есть). - Метрика RAGAS Faithfulness (усреднённая по датасету) ≥ 0.85.
- Все вызовы LLM выполняются с ограничением скорости (rate limiting) и логированием ошибок.
- Код пайплайна полностью воспроизводим (единственная точка входа —
python pipeline.py --data_dir ./docs). - В репозитории есть файл
requirements.txtс зафиксированными версиями библиотек.
6. Ожидаемый результат
Основной артефакт — папка output/, содержащая:
generated_qas.jsonl— 500 вопросов с контекстами,rag_responses.jsonl— ответы, сгенерированные RAG‑пайплайном,synthetic_rag_dataset.parquet— объединённый датасет,report.md— автоматический отчёт с метрикой и визуализациями,pipeline.py— скрипт, воспроизводящий весь процесс.
Дополнительно: файл config.yaml с параметрами (размер чанка, модель, параметры генерации).
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| LLM генерирует вопросы, на которые невозможно ответить по контексту | Ужесточить промпт: добавить требование "must be directly answerable from the context" и фильтровать вопросы с низкой схожестью ответа и контекста |
| Дубликаты вопросов (семантически похожие) | Использовать эмбеддинги и cosine similarity < 0.85 для дедупликации |
| Высокая стоимость API (500 вызовов × несколько итераций) | Использовать локальную LLM (Llama 3 70B через Ollama) для генерации вопросов и ответов |
| Faithfulness < 0.85 из‑за плохого ретривера | Увеличить k до 5, использовать Cross-encoder для реранжирования, обучить лучше эмбеддинги под домен |
| Ошибки при обработке PDF | Использовать unstructured или PyMuPDF, добавить fallback на извлечение текста через pdfplumber |
8. Бюджет времени (оценка)
| Этап | Время (часы) |
|---|---|
| Этап 1: Подготовка корпуса и чанкинг | 1.0 |
| Этап 2: Генерация синтетических вопросов | 2.0 |
| Этап 3: Построение RAG‑пайплайна | 1.5 |
| Этап 4: Оценка RAGAS Faithfulness | 1.0 |
| Этап 5: Финализация датасета | 0.5 |
| Итого | 6.0 |
Примечание: Для первого раза с учётом отладки и настройки промпта заложите дополнительно 2 часа (итого 8 часов).
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 101 | Основы RAG: ретривер, генератор, пайплайн |
| 203 | Метрики оценки RAG: Faithfulness, Answer Relevancy |
| 261 | Синтетические датасеты: генерация вопросов по тексту |
| 266 | (Текущая задача) |
| 305 | Использование langchain для чанкинга документов |
| 412 | Промпт‑инжиниринг для синтетической генерации |
| 520 | Работа с ChromaDB и FAISS |
| 677 | Оценка качества эмбеддингов для retrieval |
| 789 | Оптимизация стоимости API при генерации датасетов |
| 891 | Сравнение локальных LLM (Llama, Mistral) для синтетики |
10. Чек-лист самопроверки
- Я проверил, что все чанки уникальны и не содержат мусора (пустые строки, мусорные символы).
- Я убедился, что на каждый вопрос есть хотя бы один чанк, содержащий ответ (ручная проверка 10 примеров).
- Я выполнил оценку Faithfulness на всей выборке и получил значение ≥ 0.85.
- Я зафиксировал версии всех пакетов в
requirements.txt. - Я написал документацию (README) со схемой пайплайна и инструкцией по запуску.