Оценка и улучшение RAG: метрики, тест-наборы, наблюдаемость
Связь с предыдущими темами курса
В предыдущих статьях вы построили почти полный локальный RAG-стек:
подготовили базу знаний (очистка, чанкинг, метаданные);
выбрали эмбеддинги и векторное хранилище;
настроили retrieval-стратегии (фильтры, hybrid search, rerank, сборка контекста);
собрали промпт и формат ответа с цитированием, чтобы снизить галлюцинации.Теперь возникает практическая проблема: RAG можно сделать работающим, но сложно сделать стабильно качественным. Качество будет плавать из-за обновления документов, смены модели, новых запросов пользователей, изменений в чанкинге и фильтрах.
Эта статья про то, как превратить улучшение RAG из «похоже стало лучше» в инженерный процесс:
какие метрики реально помогают;
как собирать тест-наборы, которые ловят регрессии;
как настроить наблюдаемость, чтобы быстро понимать, где именно сломалось: ingestion, retrieval или генерация.!Цикл «оценка → диагностика → улучшение» для RAG
Что именно нужно измерять в RAG
У RAG-пайплайна есть минимум три уровня, и у каждого свои метрики:
Качество retrieval: нашёл ли ретривер те фрагменты, на которых вообще можно ответить.
Качество генерации на найденном контексте: использует ли LLM источники, не придумывает ли лишнее, корректно ли цитирует.
Системные показатели: задержки, стабильность, доля отказов, нагрузка, безопасность.Ключевой принцип отладки:
если правильного фрагмента нет среди кандидатов, это проблема retrieval;
если фрагмент найден, но ответ плохой, это проблема контекста/промпта/LLM;
если всё правильно, но медленно или нестабильно, это проблема инфраструктуры и наблюдаемости.Тест-наборы для RAG: что собирать, чтобы это работало
Почему «просто 20 вопросов» недостаточно
Если тест-набор маленький и однотипный, вы улучшите качество на нём, но получите регрессии в реальности. Поэтому тест-набор для RAG должен:
представлять реальные классы запросов;
фиксировать права доступа и контекст пользователя (если есть ACL);
проверять не только «ответ красивый», но и «источники корректные».Минимальная структура тест-кейса
Один тест-кейс обычно содержит:
question: вопрос пользователя;
user_context: роль/группа/язык/продукт (всё, что влияет на фильтры);
expected_sources: 1–3 ожидаемых источника (например, document_id или source), чтобы оценивать retrieval;
expected_answer_points: 2–6 фактов или тезисов, которые должны быть в ответе (опционально, но полезно);
notes: комментарии, почему кейс важен.Важно: для RAG часто проще и надёжнее разметить ожидаемые источники, чем «идеальный текст ответа». Текст ответа может отличаться по стилю, но правильные источники и факты должны совпадать.
Какие типы вопросов стоит включать
Чтобы тест-набор ловил реальные провалы, в нём должны быть разные классы:
вопросы на точные формулировки (политики, регламенты);
вопросы с редкими терминами (коды ошибок, параметры конфигов);
вопросы на исключения и ограничения (условия «кроме случая…»);
вопросы, где ответа нет в базе (проверка честного «не знаю»);
вопросы с конфликтом версий (проверка свежести и поведения при противоречиях).Размер и версия тест-набора
Практичный ориентир для старта:
smoke (быстро прогонять на каждом изменении): 20–50 кейсов;
regression (ежедневно/перед релизом): 200–1000 кейсов;
domain suite (по доменам: продукт, команда): отдельные подборки по 50–300.Обязательно версионируйте тест-набор: если база знаний обновилась, ожидаемые источники тоже могут поменяться.
Метрики retrieval: как понять, что поиск приносит нужное
Hit@k и Recall@k: самый полезный старт
Если для вопроса вы знаете «правильный источник» (документ или чанк), то базовая метрика звучит так:
Hit@k: попал ли хотя бы один правильный источник в топ-k.Часто это называют Recall@k в практическом смысле «нашли ли нужное», особенно если у вопроса несколько допустимых источников.
Если всё-таки хочется формально записать Recall@k, можно использовать простую формулу:
Где:
— множество релевантных (правильных) источников для вопроса;
— множество источников, которые вернул ретривер в первых k;
— количество элементов в множестве.Интерпретация:
значение 1 означает, что все ожидаемые источники нашлись в топ-k;
0 означает, что ретривер «принёс не то», и генерация почти обречена.Precision@k: когда важно «меньше шума»
Precision@k отвечает на вопрос: какая доля топ-k реально релевантна.
Эта метрика полезна, когда retrieval приносит «много похожего», и контекст становится шумным. Но для RAG чаще сначала чинят recall (чтобы не терять нужное), а затем precision (чтобы не портить контекст).
MRR: когда важен порядок в выдаче
MRR (Mean Reciprocal Rank) важна, если вы хотите, чтобы правильный чанк был как можно ближе к началу.
Интуиция:
если правильный источник на 1 месте, это отлично;
если на 20 месте, он может не попасть в контекст после rerank и ограничений по токенам.nDCG: когда релевантность бывает «разной силы»
nDCG полезна, если вы размечаете источники градациями, например:
3 балла: «прямо отвечает на вопрос»;
2 балла: «содержит важную часть»;
1 балл: «слабосвязанный контекст»;
0 баллов: «мимо».Тогда nDCG оценивает качество ранжирования с учётом того, насколько релевантен каждый элемент и на каком месте он стоит.
Метрики по этапам: до и после rerank
Если вы используете rerank, измеряйте retrieval минимум в двух точках:
качество кандидатов на recall-этапе (до rerank, например top-50);
качество финального набора (после rerank, например top-5 или top-10).Типовой вывод диагностики:
если правильное часто есть в top-50, но пропадает в top-5, значит проблема в reranker или в правилах сборки контекста;
если правильного нет уже в top-50, значит проблема в эмбеддингах, чанкинге, фильтрах или hybrid-компоненте.Метрики генерации: как оценить «привязку к источникам»
Для локального RAG в корпоративных сценариях генерация обычно должна быть grounded: без фактов, которых нет в источниках.
Корректность цитирования
Если вы требуете ссылки вида [1], [2], то появляется измеримая вещь: корректно ли ассистент ссылается.
Практические проверки:
Citation coverage: у каждого существенного факта есть ссылка;
Citation validity: номер источника существует в контексте;
Citation support: текст источника реально подтверждает утверждение.Последний пункт часто проверяют либо вручную на выборке, либо дополнительной моделью-«судьёй». В локальных сценариях разумно начинать с ручной проверки на 30–100 примерах и постепенно автоматизировать.
Faithfulness: нет ли «придуманных деталей»
В прикладной форме faithfulness означает: ответ не добавляет фактов, которых нет в retrieved-чанках.
Сигналы, что faithfulness падает:
модель уверенно добавляет числа, сроки, названия систем, которых нет в источниках;
модель «склеивает» два источника и делает вывод, который в них не написан;
модель не умеет говорить «не знаю по источникам».Доля корректных отказов
Отдельная метрика для антигаллюцинаций:
если ответа нет в базе, ассистент должен отказать;
если ответ есть, ассистент не должен «перестраховываться» отказом.Это две разные ошибки:
ложный ответ (опаснее);
лишний отказ (хуже UX, но безопаснее).В продакшене часто задают целевой компромисс и отслеживают обе доли.
Автоматизированные фреймворки оценки
Если вы хотите ускорить автоматизацию, посмотрите:
Ragas — популярный набор метрик для RAG (качество контекста, groundedness и другие), обычно использует LLM как оценщика.
LangChain: Evaluation — концепты и подходы к оценке цепочек.
LlamaIndex: Evaluation — подходы к оценке retrieval и ответов.Важно: автоматическая оценка LLM-«судьёй» может ошибаться. В локальном RAG полезно иметь слой ручной валидации, особенно для критичных доменов.
Онлайн-метрики: что измерять в продакшене
Оффлайн тесты ловят регрессии, но реальное качество проявляется в живом трафике.
Практичный набор онлайн-метрик:
Latency по этапам: эмбеддинг запроса, поиск, rerank, генерация.
Контекстный бюджет: сколько токенов ушло на источники и инструкции.
Доля запросов с пустым/слабым retrieval: например, когда top-k ниже порога сходства.
Доля ответов с отказом: и как пользователи реагируют.
Повторные вопросы: пользователь переспрашивает сразу после ответа (сигнал плохого качества).
CTR по источникам: кликают ли на источники, открывают ли документы (если UI это позволяет).Наблюдаемость RAG: как логировать и трассировать без хаоса
Что такое наблюдаемость в RAG
Наблюдаемость — это способность по логам, метрикам и трассам восстановить:
что система сделала на конкретном запросе;
какие документы она использовала;
где потратила время;
почему ответ получился таким.Для RAG это особенно важно, потому что пайплайн многошаговый, и «просто логировать промпт» часто нельзя из-за приватности.
Что логировать на каждом запросе
Если упростить, вам нужен минимальный трассируемый след.
Обычно логируют:
request_id и время;
безопасный отпечаток вопроса (например, хэш) и язык;
применённые фильтры (продукт, ACL-группы, версии);
результаты retrieval: список document_id/chunk_id, скоринг, позиции в ранжировании;
результаты rerank: новый порядок, скоринг;
финальный список источников, который ушёл в LLM;
параметры генерации (temperature, лимит токенов);
тайминги каждого шага;
признак отказа («не знаю») и наличие цитат.По возможности не храните полный текст вопроса и источников в логах без политики безопасности. Часто достаточно хранить идентификаторы чанков и ссылку на документ.
Трассировка пайплайна
Трассировка позволяет увидеть один запрос как «цепочку спанов» (этапов): embedding, vector search, bm25 search, merge, rerank, prompt assembly, generation.
Базовый стандарт:
OpenTelemetry — спецификация и инструменты для метрик и трасс.Инструменты, которые часто используют для LLM/RAG наблюдаемости:
Langfuse — трейсинг, промпты, датасеты, оценка.
Arize Phoenix — наблюдаемость и отладка LLM-приложений.Выбор инструмента не так важен, как дисциплина: фиксировать одинаковые поля и уметь по request_id восстановить весь путь.
Дашборды и алерты: что считать «поломкой»
Полезные алерты для RAG в продакшене:
рост p95/p99 latency на retrieval или generation;
рост доли запросов, где нет релевантных источников (по порогу скоринга);
рост доли ответов без цитат (если цитаты обязательны);
рост ошибок парсинга/ингеста (если у вас регулярные обновления базы знаний).Как улучшать RAG системно: диагностическая карта
Если retrieval не находит нужное
Типовые рычаги улучшения, в порядке «дешевле → дороже»:
проверить и усилить метаданные и pre-filter (язык, продукт, ACL, свежесть);
исправить очистку и дедупликацию (часто в индексе слишком много мусора);
поменять стратегию чанкинга и overlap;
перейти на hybrid search, если много кодов/артикулов/ключевых терминов;
заменить эмбеддинг-модель или правильно включить префиксы query:/passage: (если модель их ожидает);
увеличить candidate_pool перед rerank.Если retrieval находит, но LLM отвечает плохо
Чаще всего помогают:
строгий формат источников (нумерация, границы, минимум метаданных);
жёсткое требование «только по источникам» и «иначе не знаю»;
дедуп и лимит на документ в контексте;
добавление соседних чанков для важных фрагментов;
снижение вариативности генерации (например, ниже temperature).Если качество нестабильно со временем
Проверьте:
версионность документов и удаление старых чанков при переиндексации;
дрейф базы знаний: появились новые формулировки, которых не было в тест-наборе;
изменение поведения пользователей (новые типы вопросов).Практика: часть тест-набора должна регулярно пополняться из реальных логов (после обезличивания и проверки прав).
Практический baseline: как организовать оценку как пайплайн
Ниже схема, которую удобно внедрять итеративно.
Соберите smoke-набор из 30–50 вопросов и разметьте ожидаемые источники.
Реализуйте прогон retrieval без LLM и считайте Hit@k/Recall@k.
Подключите генерацию с цитированием и начните измерять долю ответов с валидными ссылками.
Настройте логирование request_id → retrieved chunk_ids → final context chunk_ids → answer.
Перед каждым изменением (чанкинг, эмбеддинги, фильтры, rerank, промпт) прогоняйте regression-набор и сравнивайте метрики с базовой версией.Небольшой псевдокод, чтобы было ясно, что именно сравнивать:
Главная идея статьи
RAG улучшается быстрее всего, когда вы:
измеряете retrieval отдельно от генерации;
храните тест-набор с ожидаемыми источниками и контекстом пользователя;
включаете наблюдаемость, чтобы любой плохой ответ был «разбираем по косточкам»;
делаете улучшения маленькими шагами и проверяете, что нет регрессий.Это и есть переход от «локальный ассистент иногда помогает» к «локальный ассистент надёжен и поддерживаем».