中文翻译暂不可用,显示俄语原文。

Как вы тестируете RAG-систему на новых документах без реальных пользователей?

Краткий тезис

Тестирование RAG-системы на новых документах без реальных пользователей строится на трёх столпах: генерация синтетического датасета (вопросы + эталонные ответы), автоматическая оценка метриками (RAGAS) и непрерывный пайплайн (CI/CD + shadow-режим). Такой подход даёт до 80% уверенности в качестве до выкатки на продакшен, а оставшиеся 20% снимаются A/B-тестированием и мониторингом на реальных данных.


1. Термин: Тестирование RAG без реальных пользователей (offline testing)

Offline-тестирование — это процесс оценки качества RAG-системы на фиксированном наборе документов и синтетических запросов, без участия живых пользователей. Оно необходимо, когда:

  • Документы добавляются в базу знаний в первый раз
  • Изменяются эмбеддинги, чанкинг, промпты или модель генерации
  • Нужно быстро проверить регресс перед релизом

Без пользователей мы не можем опираться на онлайн-метрики (CTR, время ответа, отзывы), поэтому используем синтетические данные и автоматические метрики.


2. Синтетический датасет: генерация вопросов по документам

2.1. Зачем это нужно

  • Реальные пользовательские запросы недоступны на этапе добавления новых документов
  • Нужен test set, который покрывает все ключевые факты из документов

2.2. Метод: вопросно-ответная генерация через LLM

Берём фрагменты (чанки) документа и просим LLM сгенерировать вопросы, на которые этот чанк отвечает.

Пример реализации на Python (с использованием LangChain):

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from typing import List

class QAPair(BaseModel):
    question: str = Field(description="Вопрос по тексту")
    answer: str = Field(description="Ответ, основанный на тексте")

template = """Ты — ассистент для создания синтетического датасета.
На основе следующего текста придумай {num_questions} вопросов, 
на которые можно ответить, используя только этот текст.
Вопросы должны быть разнообразными: фактические, уточняющие, сравнительные.

Текст:
{chunk}

Формат ответа: JSON список {{"question": ..., "answer": ...}}"""

parser = PydanticOutputParser(pydantic_object=List[QAPair])
prompt = ChatPromptTemplate.from_template(template)

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
chain = prompt | llm | parser

chunk = "Глубокое обучение — это подмножество машинного обучения, которое использует нейронные сети с тремя и более слоями."
qa_pairs = chain.invoke({"chunk": chunk, "num_questions": 3})
print(qa_pairs)

Важные нюансы

  • Не генерить вопросы, выходящие за пределы текста (можно задать констрейнт в промпте)
  • Перемешать вопросы из разных чанков, чтобы симулировать реальные запросы
  • Оценить качество синтетических вопросов: они должны быть осмысленными, разнообразными и покрывать разные уровни сложности

2.3. Поиск эталонных ответов

Для каждого синтетического вопроса нужно указать ground truth (правильный ответ). Лучший подход:

  • Ответ берётся из того же чанка, который использовался для генерации вопроса (автоматически)
  • Или LLM дополнительно проверяет, что ответ действительно содержится в документе (самопроверка)
  • Для оценки retrieval достаточно знать, какие чанки релевантны (gold standard)

Итог получаем датасет {question, ground_truth_answer, relevant_chunks}.


3. Автоматическая оценка метриками (RAGAS)

RAGAS (Retrieval Augmented Generation Assessment) — фреймворк для автоматической оценки RAG без участия человека. Основные метрики:

МетрикаЧто измеряетФормула / подход
Faithfulness (правдивость)Все ли утверждения ответа подтверждаются документамиДоля утверждений, которые можно вывести из контекста
Answer Relevance (релевантность ответа)Насколько ответ соответствует вопросуКосинусная схожесть эмбеддинга вопроса и сгенерированного ответа
Context Precision (точность контекста)Насколько все релевантные чанки находятся в топеСредняя точность по рангам
Context Recall (полнота контекста)Сколько релевантных чанков было найденоДоля найденных релевантных чанков среди всех релевантных

Пример вычисления Faithfulness с помощью RAGAS (код):

from ragas import evaluate
from datasets import Dataset
from ragas.metrics import faithfulness, answer_relevancy

# Подготовка данных
dataset = Dataset.from_dict({
    "question": ["Что такое глубокое обучение?"],
    "answer": ["Глубокое обучение использует нейронные сети с тремя и более слоями."],
    "contexts": [["Глубокое обучение — это подмножество машинного обучения, которое использует нейронные сети с тремя и более слоями."]],
    "ground_truth": ["Глубокое обучение использует нейронные сети с тремя и более слоями."]
})

# Оценка
result = evaluate(dataset, metrics=[faithfulness, answer_relevancy])
print(result.to_pandas())

Трактовка результатов

  • Faithfulness < 0.7 → модель галлюцинирует или не использует контекст
  • Answer Relevance < 0.8 → ответ не соответствует вопросу (проблемы с промптом или генерацией)
  • Context Recall < 0.9 → retrieval пропускает важные документы (плохая индексация или эмбеддинги)

4. Benchmark и фиксация baseline

Перед добавлением новых документов необходимо:

  1. Зафиксировать текущий baseline на старом наборе документов (метрики RAGAS)
  2. После обновления базы прогнать тот же синтетический датасет
  3. Сравнить метрики: если Faithfulness или Context Recall упали больше чем на 5% — откатить изменение или доработать

Пример отчёта

МетрикаДо обновленияПосле обновленияДельтаВердикт
Faithfulness0.910.88-0.03OK (допустимо)
Answer Relevance0.850.84-0.01OK
Context Recall0.940.78-0.16🔴 ПРОБЛЕМА

5. CI/CD пайплайн при добавлении документа

Чтобы тестирование было автоматическим и повторяемым, его встраивают в CI/CD (Continuous Integration / Continuous Deployment). Примерный flow:

  1. Триггер пуш в репозиторий с новыми документами (или загрузка через API)
  2. Этап 1 Генерация синтетического датасета по новым документам (3–5 вопросов на чанк)
  3. Этап 2 Прогон evaluation pipeline на старом датасете + новом датасете
  4. Этап 3 Сравнение метрик с заданными порогами (например, Faithfulness > 0.85, Context Recall > 0.9)
  5. Решение если все метрики в порядке → автоматический деплой новой версии RAG в staging; иначе → прервать пайплайн и уведомить команду

Инструменты GitHub Actions + RAGAS + Python скрипты.


6. Shadow-режим (сравнение на проде без влияния на пользователей)

Shadow mode — это когда новая версия RAG (с новыми документами) работает параллельно с текущей продакшен-версией, но её ответы не показываются пользователям. При каждом запросе:

  • Вызываются обе версии (старая и новая)
  • Ответы новой версии логируются вместе с контекстом и метриками (faithfulness, latency)
  • Периодически (раз в день) проводится A/B сравнение синтетических метрик между старой и новой версией

Это даёт реалистичную оценку на реальных пользовательских запросах, но без риска для пользовательского опыта. По сути, shadow-режим — это bridge между offline-тестами и полноценным A/B.


7. Ограничения и как повысить уверенность до 100%

Синтетические вопросы + RAGAS дают ~80% уверенности. Основные слабые места:

ОграничениеРешение
Синтетические вопросы могут не совпадать с реальными паттернамиДобавить датасет из реальных логов поиска (если есть хотя бы небольшой поток)
RAGAS-метрики не идеальны (например, Faithfulness может пропускать тонкие галлюцинации)Провести ручную валидацию на 50–100 случайных примерах
Метрики агрегируются по всему датасету — можно пропустить выбросыВвести мониторинг на уровне отдельных запросов и алерты при падении Confidence Score

Итог комбинируем синтетический датасет → RAGAS benchmarkshadow mode → ручная выборка. Это даёт уверенность, близкую к 95%.


8. Пет-проект для закрепления

Задача Разработать пайплайн для тестирования RAG-системы при добавлении нового PDF-документа о медицинских препаратах.

Инструменты

  • Python + LangChain + OpenAI
  • RAGAS для оценки
  • Streamlit для демонстрации отчёта
  • GitHub Actions для CI/CD

Шаги:

  1. Разбить PDF на чанки (RecursiveCharacterTextSplitter)
  2. Загрузить чанки в векторную БД (Chroma)
  3. Сгенерировать синтетический датасет (30 вопросов по всему документу)
  4. Оценить baseline на текущей базе (без нового документа)
  5. Добавить новый документ в БД
  6. Переоценить на том же датасете
  7. Вывести сравнительный отчёт (таблица метрик)
  8. Если Context Recall упал > 10% → откатить изменение

Ожидаемый результат Streamlit-приложение, которое при загрузке нового PDF автоматически прогоняет evaluation и показывает зелёный/красный сигнал для деплоя.


9. Связь с другими вопросами

ВопросТема
5Как оценивать качество retrieval в RAG
9Как обновлять документы в существующей RAG-системе
10Что такое Self-RAG и когда его использовать
15Как вы отслеживаете метрики RAG в продакшене
20Какие метрики качества генерации LLM вы знаете
30Как вы детектируете галлюцинации в RAG

10. Навигация


Навигация