Оценка RAG: как учесть несколько правильных наборов источников
В тесте RAG есть вопрос: «Можно ли вернуть оплату после начала услуги?» Разметчик выбрал полную инструкцию и записал её ID как правильный источник. Новая версия поиска нашла два других раздела: общее правило и исключение для уже начавшейся услуги. Вместе они позволяют дать такой же обоснованный ответ, но тест сообщает о провале: ожидаемого ID в выдаче нет.
Прежде чем откатывать поиск, нужно проверить сам эталон. Иногда достаточно любого одного из нескольких документов. Иногда требуются два текста одновременно. Если хранить оба случая обычным списком правильных ID, оценка потеряет смысл: она будет требовать лишние дубликаты или разрешать ответ по половине необходимых оснований.
Что означает список релевантных документов
Классический recall по ID делит число найденных релевантных документов на число всех размеченных релевантных. Такая метрика полезна, когда задача действительно состоит в полноте списка. Например, пользователь просит найти все решения комиссии за период. Для ответа на конкретный вопрос несколько документов могут быть взаимозаменяемыми, и получение каждого из них не является обязательным.
В метриках context recall Ragas есть расчёт по ID и проверка поддержки утверждений эталонного ответа. Они отвечают на разные вопросы. ID позволяют быстро контролировать известные источники. Проверка утверждений помогает оценить содержание, но требует собственного контроля качества оценщика. Сначала сформулируйте критерий успеха, затем выбирайте инструмент для его расчёта.
Опишите альтернативные достаточные наборы
Для нашего вопроса зададим две допустимые комбинации. Первая содержит только полную инструкцию. Вторая содержит одновременно правило и исключение. Каждый набор сам по себе достаточен. Между наборами действует «или», внутри набора — «и». Так разметка явно отражает, какие документы взаимозаменяемы, а какие дополняют друг друга.
Полноту покрытия посчитаем для каждого варианта и возьмём максимальную. Наличие достаточного основания проверим отдельно: хотя бы один допустимый набор должен целиком войти в выдачу. Назовём первый показатель coverage, второй — sufficient. Это собственная прикладная проверка, поэтому в отчёте рядом с названием должна лежать формула, а не только знакомое слово recall.
def evaluate(retrieved, alternatives):
if not alternatives or any(not group for group in alternatives):
raise ValueError("Нужен непустой список непустых оснований")
found = set(retrieved)
coverage = max(len(found & group) / len(group)
for group in alternatives)
sufficient = any(group <= found for group in alternatives)
return coverage, sufficient
# Полная инструкция либо два раздела, вместе закрывающие вопрос.
alternatives = [{"full-guide"}, {"rule", "exception"}]
cases = {
"другая полная инструкция": ["full-guide"],
"оба раздела": ["rule", "exception"],
"только правило": ["rule", "unrelated"],
"ничего нужного": ["unrelated"],
}
for name, retrieved in cases.items():
coverage, sufficient = evaluate(retrieved, alternatives)
print(name, f"coverage={coverage:.2f}", f"sufficient={sufficient}")
assert evaluate(["rule"], alternatives) == (0.5, False)
assert evaluate(["rule", "exception"], alternatives) == (1.0, True)
assert evaluate(["full-guide", "full-guide"], alternatives) == (1.0, True)
assert evaluate([], alternatives) == (0.0, False)
Полная инструкция и пара разделов дают coverage 1.00 и sufficient=True. Один раздел с правилом даёт 0.50 и False. Посторонний текст даёт 0.00 и False. Повтор одного ID ничего не прибавляет: множества убирают дубли. Пустые эталонные наборы запрещены, потому что пустое множество оказалось бы формально найденным в любой выдаче.
Как разметить варианты без бесконечного каталога
Начните с вопросов, по которым старый тест уже спорит с экспертной оценкой. Для каждого сохраните ожидаемый ответ, минимальные утверждения, которые нужно подтвердить, и источники этих утверждений. Попросите предметного специалиста проверить достаточность комбинаций. Для возврата денег важны не только совпадающие слова, но и условия, сроки, исключения. Похожий по теме раздел не становится альтернативой автоматически.
Размечайте ту единицу, которую получает генератор. Если индекс выдаёт фрагменты, ID документа целиком слишком груб: один чанк содержит нужное исключение, соседний — только оглавление. Закрепите устойчивый идентификатор фрагмента или версионируемую связь с разделом. После изменения разбиения перенесите разметку и проверьте спорные соответствия, прежде чем сравнивать числа двух прогонов.
Когда новый поиск приносит неизвестный источник, отправляйте такой случай на разбор разметки. Не добавляйте найденный документ в эталон только потому, что система его вернула. Эксперт должен подтвердить, какие утверждения он обосновывает и с какими другими текстами совместим. После принятия новой версии разметки пересчитайте обе сравниваемые версии поиска на одном эталоне.
Где проходит граница достаточности
Нельзя собирать удачную комбинацию из противоречащих документов разных периодов или продуктов. Перед добавлением варианта зафиксируйте дату применимости и предмет вопроса. Если два источника допустимы только при разных условиях, это разные тестовые ситуации. Иначе критерий начнёт одобрять контекст, по которому невозможно выбрать действующее правило.
В итоговом отчёте покажите долю вопросов с sufficient=True и распределение частичного покрытия. Сохраняйте coverage для диагностики: оно помогает отличить отсутствие всей темы от потери одного необходимого раздела. Успешное извлечение основания ещё не проверяет формулировку ответа, поэтому следующим тестом проверьте, что генератор использовал найденные условия и исключения. Связанный пример — проверка смысла цитат в RAG.
В платном курсе LLMOps & Evaluation: из песочницы в продакшн вы соберёте тестовые наборы, настроите автоматическую оценку RAG и добавите проверки качества в процесс выпуска. Это продолжение работы над эталоном: превращение спорных примеров в воспроизводимый отчёт для изменений системы. Откройте программу и пробный урок по Ragas.
