AILLMметрикианалитика

LLM-метрики: как оценивать качество ответов модели

2026-07-11 11 мин

Качество ответа языковой модели нельзя измерить одной цифрой «accuracy» — в задачах генерации и в RAG-системах работает связка из нескольких метрик, каждая из которых ловит свой тип ошибки. Главные четыре: faithfulness (насколько ответ опирается на переданный контекст, а не на фантазию модели), answer relevance (отвечает ли модель именно на заданный вопрос), context recall и context precision (насколько хорошо поисковый модуль достал нужные документы). Отдельно считают hallucination rate — долю ответов с выдуманными фактами. Дальше разберу, что каждая метрика значит, как посчитать её в Python, как собрать честную выборку для оценки и почему «модель звучит уверенно» и «модель отвечает правильно» — это два совершенно разных события.

Тема сейчас всплывает на собеседованиях всё чаще: продуктовых аналитиков зовут оценивать чат-ботов поддержки, внутренние поисковики по документации, ассистентов внутри продукта. И первый же вопрос от интервьюера звучит просто: «Как ты поймёшь, что бот стал отвечать лучше?». Если ответить «посмотрю на точность» — собеседование считай провалено.

Почему привычные метрики точности здесь не работают?

Классический аналитик привык к миру, где есть правильный ответ и предсказание модели. Есть таблица «предсказали / факт», из неё считаем precision, recall, F1, ROC-AUC. Для классификации оттока или скоринга это идеально.

С языковой моделью так не выйдет по одной причине: правильных ответов на открытый вопрос бесконечно много. На вопрос «Как отменить подписку?» модель может ответить пятью разными формулировками, и все пять будут корректны. Строгое сравнение строк (exact match) провалит четыре из пяти. Метрики вроде BLEU и ROUGE, которые пришли из машинного перевода, считают пересечение n-грамм с эталоном — они чуть терпимее, но всё равно наказывают за синонимы и перефраз, а главное — вообще не проверяют, правда ли то, что написала модель.

Поэтому в оценке LLM происходит сдвиг: мы перестаём спрашивать «совпал ли текст с эталоном» и начинаем спрашивать «обладает ли ответ нужными свойствами». Свойства — это и есть метрики: правдивость, релевантность, полнота контекста. Каждое свойство можно оценить отдельно, часто по шкале от 0 до 1, и уже эти числа агрегировать так же, как вы привыкли агрегировать любую продуктовую метрику — по срезам, по времени, с доверительными интервалами.

Что такое RAG и где в нём ломается качество?

RAG (retrieval-augmented generation) — это архитектура, где модель отвечает не «из головы», а на основе документов, которые ей подложили. Схема из трёх шагов: пользователь задаёт вопрос → поисковый модуль (retriever) достаёт из базы несколько релевантных фрагментов → генератор (LLM) пишет ответ, опираясь на эти фрагменты. Так делают почти все корпоративные боты по внутренней базе знаний: это дешевле дообучения и позволяет обновлять знания, просто добавив документ.

Ключевой вывод для аналитика: в RAG есть две независимые точки поломки, и их нельзя мерить одной метрикой.

Первая — retriever достал не те документы. Тогда генератор при всём желании не ответит правильно, потому что нужного факта просто нет в контексте. Вторая — retriever достал правильные документы, но генератор их проигнорировал или переврал. Это разные болезни с разным лечением: в первом случае чинят поиск и эмбеддинги, во втором — промпт и саму модель. Если у вас одна общая метрика «хорошо/плохо», вы не поймёте, куда копать. Поэтому метрики RAG делят на две группы: оценка ретривера (context recall, context precision) и оценка генерации (faithfulness, answer relevance).

Мысленно держите это как воронку — примерно как вы разбиваете конверсию на этапы. Разберётесь, где именно теряется качество, и половина работы сделана. Если хотите потренировать саму логику декомпозиции воронок на данных, это ровно тот навык, что качается на SQL-задачах и в кейсах.

Как измерить hallucination rate и faithfulness?

Галлюцинация — это когда модель уверенно сообщает факт, которого нет в источниках (или который прямо им противоречит). faithfulness — зеркальная метрика: доля утверждений в ответе, которые подтверждаются переданным контекстом.

Считается так. Берём ответ модели и разбиваем его на отдельные атомарные утверждения (claims). Например, ответ «Подписку можно отменить в разделе Настройки, деньги вернут в течение 14 дней» — это два утверждения. Дальше для каждого проверяем: есть ли ему подтверждение в контексте, который получил генератор. Формула простая:

faithfulness = (число утверждений, подтверждённых контекстом) / (всего утверждений в ответе)
hallucination_rate = 1 - faithfulness

Проверку «подтверждается ли утверждение» на масштабе делают не руками, а моделью-судьёй (об этом ниже) или через natural language inference. Но принцип от этого не меняется. Вот заготовка на Python, которая считает faithfulness, если у вас уже есть функция-верификатор:

def faithfulness(claims, context, verify):
    """claims — список утверждений из ответа,
    context — текст, который видел генератор,
    verify(claim, context) -> True, если контекст подтверждает утверждение."""
    if not claims:
        return 1.0  # пустой ответ ничего не выдумывает
    supported = sum(1 for c in claims if verify(c, context))
    return supported / len(claims)

# на выборке:
scores = [faithfulness(ex["claims"], ex["context"], verify) for ex in dataset]
mean_faithfulness = sum(scores) / len(scores)
hallucination_rate = 1 - mean_faithfulness

Важная деталь: faithfulness проверяет верность контексту, а не верность реальному миру. Если в базе знаний лежит устаревший документ, а модель честно его пересказала — faithfulness будет высоким, хотя ответ фактически неверен. Поэтому её всегда смотрят в паре с context recall, который как раз ловит проблему на стороне источников. Потренировать сам синтаксис агрегаций и группировок для таких расчётов можно в Python-тренажёре, а свериться по функциям — в Python-справочнике.

Как понять, отвечает ли модель на вопрос?

Это метрика answer relevance. Проблема, которую она ловит: ответ может быть на 100% правдивым и при этом бесполезным. Спросили «Сколько стоит подписка?» — модель выдала абзац про историю компании, ни одного выдуманного факта, faithfulness идеальный, а пользователь в ярости.

Стандартный трюк для оценки relevance без ручной разметки — обратная генерация вопросов. Берём ответ модели и просим модель-судью придумать, на какой вопрос этот ответ мог бы отвечать (несколько вариантов). Потом считаем семантическую близость этих сгенерированных вопросов к исходному — через косинусное сходство эмбеддингов. Если ответ по делу, восстановленные вопросы будут близки к настоящему; если модель ушла в сторону — далеки.

import numpy as np

def cosine(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

def answer_relevance(original_q, answer, embed, gen_questions, n=3):
    # gen_questions(answer, n) -> список из n вопросов, восстановленных из ответа
    generated = gen_questions(answer, n)
    q_vec = embed(original_q)
    sims = [cosine(q_vec, embed(g)) for g in generated]
    return float(np.mean(sims))  # ближе к 1 — ответ по теме

На практике answer relevance хорошо коррелирует с раздражением пользователей: боты, которые «льют воду», набирают низкий скор ещё до того, как вы посмотрите на реальные жалобы. Держите её рядом с faithfulness: первая штрафует за уход от темы, вторая — за выдумки. Вместе они закрывают большую часть провалов генерации.

Context recall и context precision: как оценить поиск?

Эти две метрики отвечают за retriever — то есть за то, достал ли поиск нужные документы до того, как генератор начал писать.

context recall — из всех фактов, необходимых для правильного ответа, сколько реально оказалось в извлечённом контексте. Если для ответа нужны три факта, а retriever принёс документы только с двумя, recall = 2/3. Это самый коварный показатель: при низком recall никакая доработка промпта не спасёт, потому что информации физически нет. context precision — из всех извлечённых фрагментов сколько действительно релевантны, и, что важно, стоят ли релевантные фрагменты в начале списка. Мусор в контексте не только раздувает расходы на токены, но и сбивает генератор.
context_recall = (нужные факты, попавшие в контекст) / (все нужные факты для ответа)
context_precision = (релевантные фрагменты) / (все извлечённые фрагменты)

Логика тут абсолютно та же, что в классических метриках информационного поиска, — если вы когда-нибудь оценивали качество ранжирования, вам знакомо. Разница лишь в том, что «релевантность» фрагмента к вопросу опять же размечает либо человек, либо модель-судья. Для аналитика удобно, что recall и precision retriever'а можно снимать вообще без генератора — прогнали поиск по тестовым вопросам, сравнили с эталонными документами, получили числа. Это дешёвый способ ловить деградацию поиска отдельно от модели.

Как собрать эти метрики на практике?

Здесь на сцену выходит RAGAS — популярная open-source библиотека, которая считает как раз faithfulness, answer relevance, context recall и context precision по вашему датасету. Идея та же, что я описал выше: она использует модель-судью, чтобы разбить ответы на утверждения и проверить подтверждения. Вам нужно подготовить таблицу из четырёх колонок: вопрос, ответ модели, извлечённый контекст и (для recall) эталонный правильный ответ.

Мыслите этим как обычным ETL-пайплайном оценки:

# псевдокод пайплайна оценки RAG
rows = []
for q in eval_questions:
    contexts = retriever.search(q)          # что достал поиск
    answer = generator.generate(q, contexts)  # что ответила модель
    rows.append({
        "question": q,
        "contexts": contexts,
        "answer": answer,
        "ground_truth": gold[q],            # эталон для recall
    })

# дальше метрики (RAGAS или свои функции) прогоняются построчно,
# а агрегаты вы считаете как любую продуктовую метрику:
# среднее, срезы по категориям вопросов, динамика по дням

Дальше это чистая аналитика, к которой вы привыкли. Результаты складываете в таблицу и режете по срезам: по типу вопроса, по разделу базы знаний, по версии промпта. Тут спокойно работает обычный SQL — сгруппировали по prompt_version, посчитали AVG(faithfulness), сравнили релизы. Никакой магии, те же оконные функции и агрегаты, что вы отрабатываете в SQL-тренажёре и на курсе SQL. Отслеживать метрики во времени и по когортам версий — ровно тот же навык, что и следить за DAU продукта, только вместо активности пользователей у вас качество ответов.

SELECT
  prompt_version,
  COUNT(*)                        AS n,
  ROUND(AVG(faithfulness), 3)     AS faithfulness,
  ROUND(AVG(answer_relevance), 3) AS relevance,
  ROUND(AVG(context_recall), 3)   AS recall
FROM llm_eval_runs
WHERE created_at >= DATE('now', '-14 days')
GROUP BY prompt_version
ORDER BY faithfulness DESC;

Как выбрать эталонную выборку и не обмануть себя?

Метрики врут ровно настолько, насколько плоха выборка, на которой вы их считаете. Самая частая ошибка — брать 10 удобных вопросов, на которых бот и так отвечает хорошо, и радоваться цифре 0.95.

Что делаю я. Во-первых, собираю набор из реальных пользовательских вопросов, а не придуманных — логи бота дают их бесплатно. Во-вторых, специально добавляю тяжёлые случаи: вопросы, ответа на которые в базе нет вообще (правильное поведение — честно сказать «не знаю», и это отдельно проверяемое свойство), вопросы с опечатками, многосоставные вопросы «а как X и заодно Y». В-третьих, слежу за балансом категорий, чтобы средняя метрика не маскировала провал в одном важном разделе — поэтому всегда смотрю разбивку, а не только общее среднее.

Размер выборки — тот же разговор про статзначимость, что и в A/B-тестах. На 20 примерах разница метрик 0.80 против 0.83 — это шум, а не улучшение. Нужны сотни примеров и доверительные интервалы, иначе вы будете катать релизы по случайным колебаниям. Логика доверительных интервалов и проверки значимости здесь ровно та же, что вы разбираете, готовясь к вопросам по статистике на собеседовании.

LLM-as-a-judge: можно ли доверять модели-оценщику?

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

Что важно держать в голове. Модель-судья имеет систематические перекосы: она склонна выше оценивать длинные ответы, ответы, похожие по стилю на её собственные, и вариант, который стоит первым при попарном сравнении. Всё это лечится: даём судье чёткий чеклист с критериями вместо расплывчатого «оцени от 1 до 10», перемешиваем порядок при сравнении, просим сначала обоснование, потом оценку.

И главное — сам судья нуждается в валидации. Один раз берёте 100–200 примеров, размечаете руками, а потом смотрите, насколько оценки судьи совпадают с человеческими (через корреляцию или процент согласия). Если сходятся — судье можно доверять на масштабе и гонять им тысячи примеров дёшево. Если нет — правите инструкцию судьи и повторяете. По сути вы относитесь к модели-оценщику как к любому измерительному прибору: сначала калибруете по эталону, потом используете. Именно эта связка — автоматическая оценка плюс маленькая человеческая сверка — и есть промышленный стандарт, который сегодня спрашивают на собеседованиях в продуктовые команды.

Что унести с собой

Если сжать всё до одного экрана: качество LLM — это не одна цифра, а профиль из свойств. Faithfulness ловит выдумки, answer relevance — уход от темы, context recall и precision — поломки поиска. Считаете их на честной выборке из реальных вопросов с тяжёлыми случаями, агрегируете как обычную продуктовую метрику, а модель-судью перед использованием калибруете по ручной разметке. С таким ответом на собеседовании вы выглядите не как человек, прочитавший статью, а как тот, кто это измерял.

А дальше всё упирается в фундамент — SQL для нарезки метрик по срезам, Python для расчётов, статистика для значимости различий. Если хотите системно закрыть эти темы под реальные собеседования в аналитику, Pro-доступ открывает все 425 SQL-задач, 402 Python-задачи, кейсы и безлимитные AI мок-собеседования — включая разбор вопросов про метрики LLM и RAG. Начать можно бесплатно.

Готовься к собесу аналитика
Вопросы по метрикам, статистике и продукту с разбором — попробуй бесплатно.
Банк вопросов →