English translation is not available yet. Showing Russian content.

Сгенерировать 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

Если нет реального инструмента — симулируем:

  1. Скачайте 3–5 статей из англоязычной Википедии (например, про «Machine learning», «Python», «RAG») в формате .txt.
  2. Разбейте их на чанки по 512 токенов (используйте langchain.text_splitter.RecursiveCharacterTextSplitter).
  3. Для эмуляции RAG‑пайплайна возьмите готовую векторную БД ChromaDB (установка chromadb).
  4. Для оценки Faithfulness используйте ragas с моделью‑judge (по умолчанию gpt-4; если нет ключа — локальная модель SentenceTransformers для эмбеддингов, но точность будет ниже; можно симулировать метрику, запустив один раз на 50 вопросах с ручной проверкой).

3. Технологический стек

КомпонентИнструментыНазначение
Генерация вопросовlangchain, openai / transformersВызов LLM для создания вопросов по чанкам
Обработка документовlangchain, unstructured / pdfplumberЗагрузка, чанкинг, очистка текста
Векторное хранилищеchromadbХранение эмбеддингов и поиск контекста
Оценка RAGASragas, datasetsВычисление Faithfulness и других метрик
Управление даннымиpandas, json, yamlСохранение датасета, конфигураций

4. Этапы выполнения

Этап 1: Подготовка корпуса и чанкинг (оценка: 1 час)

Действия

  1. Загрузите все документы из указанной директории (поддерживаемые форматы: .txt, .pdf, .md). Используйте langchain_community.document_loaders.DirectoryLoader.
  2. Очистите текст: удалите лишние пробелы, нормализуйте Unicode, приведите к нижнему регистру (если задача нечувствительна к регистру).
  3. Разбейте документы на чанки размером 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)
    
  4. Сохраните чанки в формате JSONL (каждый чанк — {"id": "chunk_001", "text": "...", "source": "file.pdf"}).

Ожидаемый результат этапа файл chunks.jsonl с 200–500 чанками (в зависимости от объёма документов).

Этап 2: Генерация синтетических вопросов (оценка: 2 часа)

Действия

  1. Настройте промпт для генерации вопроса по чанку. Пример системного сообщения:
    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.
    
  2. Для каждого чанка вызовите LLM (используйте openai.ChatCompletion или langchain.llms). Установите temperature=0.7, max_tokens=100.
  3. Повторите генерацию, пока не получите 500 уникальных вопросов. Удалите дубликаты (по схожести эмбеддингов или точному совпадению).
  4. Сохраните результат в датафрейм с колонками question, context (текст чанка), chunk_id.

Ожидаемый результат этапа файл generated_qas.jsonl (500 записей).

Этап 3: Построение RAG‑пайплайна для генерации ответов (оценка: 1.5 часа)

Действия

  1. Загрузите чанки в векторное хранилище ChromaDB (используйте эмбеддинги HuggingFaceEmbeddings от all-MiniLM-L6-v2).
  2. Создайте функцию retrieve_answer(question, k=3), которая:
    • ищет топ-3 релевантных чанка,
    • объединяет их в контекст,
    • подаёт в LLM с промптом: "Answer the question based only on the provided context. If unsure, say 'I don't know'."
  3. Для каждого из 500 вопросов сгенерируйте ответ. Ограничьте вызовы API (например, 10 параллельных потоков через ThreadPoolExecutor).
  4. Сохраните результат: датафрейм с колонками question, contexts (список чанков), answer, ground_truth (пока пустая, если нет эталонного ответа).

Ожидаемый результат этапа файл rag_responses.jsonl (500 записей).

Этап 4: Оценка RAGAS Faithfulness (оценка: 1 час)

Действия

  1. Преобразуйте датафрейм в формат Dataset Hugging Face:
    from datasets import Dataset
    data = Dataset.from_pandas(df)
    
  2. Вычислите метрику Faithfulness с помощью ragas:
    from ragas import evaluate
    from ragas.metrics import faithfulness
    result = evaluate(data, metrics=[faithfulness])
    print(result)
    
  3. Если результат < 0.85, проанализируйте причины: низкое качество генерации вопросов, плохой retrieval, шум в чанках.
  4. Итеративно улучшайте: меняйте промпт генерации вопросов, размер чанка, количество retrieved‑чанков, модель‑judge. Повторяйте оценку до достижения порога.

Ожидаемый результат этапа метрика Faithfulness ≥ 0.85.

Этап 5: Финализация датасета (оценка: 0.5 часа)

Действия

  1. Объедините файлы generated_qas.jsonl и rag_responses.jsonl в единый датасет.
  2. Добавьте колонку faithfulness_score (результат оценки для каждого вопроса, если вычисляли per‑example).
  3. Сохраните итоговый датасет в формате Parquet (быстрее для загрузки) и JSON.
  4. Сгенерируйте отчёт (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 Faithfulness1.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) со схемой пайплайна и инструкцией по запуску.