Оценка RAG: извлечение и верность ответа

Нельзя улучшить то, что не измеряешь. Учимся оценивать обе половины RAG отдельно.

Оценка RAG делится надвое: качество извлечения (нашли ли нужные чанки) и качество генерации (верен ли ответ контексту и без выдумок).

Две независимые половины

RAG может ошибаться в двух местах, и лечатся они по-разному:

Что измеряемВопросМетрики
Извлечениенашли ли нужные чанки?recall@k, precision@k, MRR
Генерацияверен ли ответ контексту?faithfulness, релевантность

Если плох retrieval — чините чанкинг/эмбеддинги/k. Если retrieval хорош, а ответ плохой — чините промпт и генерацию. Поэтому их меряют раздельно.

Recall@k своими руками

Recall@k — доля действительно релевантных чанков, попавших в top-k. Это главная метрика извлечения: если нужного чанка нет в top-k, LLM просто нечем ответить.

queries = [
    {"q": "q1", "gold": {"c2"},       "retrieved": ["c2", "c5", "c1"]},
    {"q": "q2", "gold": {"c4", "c7"}, "retrieved": ["c1", "c4", "c9"]},
    {"q": "q3", "gold": {"c3"},       "retrieved": ["c8", "c6", "c0"]},
]

def recall_at_k(gold, retrieved, k):
    topk = set(retrieved[:k])
    return len(gold & topk) / len(gold)

k = 3
recalls = [recall_at_k(it["gold"], it["retrieved"], k) for it in queries]
for it, r in zip(queries, recalls):
    print(f"{it['q']}: recall@{k} = {r:.2f}")
print(f"Средний recall@{k} = {sum(recalls) / len(recalls):.2f}")

Вывод:

q1: recall@3 = 1.00
q2: recall@3 = 0.50
q3: recall@3 = 0.00
Средний recall@3 = 0.50

Для q3 ни один релевантный чанк не попал в top-3 — это провал извлечения, и никакой умный промпт его не спасёт. Средний recall@3 = 0.50 говорит: половина нужного не доходит до модели. Это первое, что надо чинить.

Верность контексту (faithfulness)

Даже при идеальном извлечении модель может добавить от себя. Faithfulness проверяет: каждое утверждение ответа подтверждается контекстом? Если в ответе есть факт, которого нет в поданных чанках, — это галлюцинация. Оценивают людьми или «LLM-судьёй», который сверяет ответ с контекстом.

Триада метрик качества

  • Context relevance — релевантен ли извлечённый контекст вопросу.
  • Faithfulness — опирается ли ответ строго на контекст.
  • Answer relevance — отвечает ли ответ на сам вопрос.

Инструменты вроде RAGAS автоматизируют эти метрики с помощью LLM-судьи.

Итог

  • Меряйте извлечение и генерацию раздельно — у них разные лекарства.
  • Recall@k: попал ли нужный чанк в top-k (основа извлечения).
  • Faithfulness: подтверждён ли каждый факт ответа контекстом.
Проверьте себя
1. Что показывает метрика recall@k в RAG?
AСкорость ответа
BДолю релевантных чанков, попавших в top-k результатов
CРазмер контекстного окна
DСтоимость запроса
2. Что проверяет метрика faithfulness?
AГрамотность ответа
BПодтверждается ли каждое утверждение ответа поданным контекстом
CДлину ответа
DСкорость эмбеддинга
3. Почему извлечение и генерацию оценивают раздельно?
AТак быстрее
BУ ошибок разные причины и лечения: чанкинг/k против промпта/генерации
CЭтого требует Python
DЧтобы увеличить recall
Поддержать проект