Рейтинг умер. Да здравствуют метрики.
Откройте любой AI-новостной сайт. GPT-5.1 набрал 92.7 баллов в MMLU. Claude 4.5 — 94.3. Gemini Ultra 3.0 — 96.1. Цифры, цифры, цифры. И ни одного ответа на простой вопрос: а как эта модель поведет себя в вашем приложении?
Проблема в том, что бенчмарки типа MMLU или HumanEval измеряют модель в вакууме. А ваше приложение живет в реальном мире, где пользователи задают странные вопросы, ожидают конкретных ответов и терпеть не могут галлюцинации. Вот почему тестирование AI-приложений требует другого подхода — не "насколько умна модель", а "насколько хорошо она решает ваши задачи".
Актуальность на 18.02.2026: В этой статье используются только самые свежие данные и инструменты, доступные на текущую дату. Мы рассматриваем метрики, которые реально работают с моделями 2025-2026 годов выпуска.
Почему традиционные метрики не работают для LLM
Представьте, что вы тестируете поисковую систему на ИИ. Пользователь спрашивает: "Как испечь яблочный пирог без духовки?". Традиционная метрика точности (precision) проверит, содержит ли ответ слова "яблочный", "пирог", "духовка". Но она пропустит:
- Ответ, который предлагает использовать микроволновку вместо духовки (релевантно, но метрика точности не поймет)
- Ответ с рецептом шарлотки вместо пирога (частично релевантно)
- Ответ, который начинает с истории яблочного пирога в Древнем Риме (нерелевантно, но содержит все ключевые слова)
Вот почему для AI-приложений нужны специальные метрики. Они измеряют не точность совпадения слов, а семантическую релевантность, согласованность и полезность.
Метрики релевантности: от простого к сложному
Начнем с основ. Релевантность — это мера того, насколько ответ соответствует запросу по смыслу, а не по букве. И здесь есть несколько уровней сложности.
1 Токенные метрики (устарели, но все еще используются)
BLEU, ROUGE, METEOR — все эти метрики родились в эпоху машинного перевода и до сих пор кочуют из статьи в статью. Проблема в том, что они сравнивают тексты на уровне токенов (слов или их частей).
# Пример расчета BLEU через nltk (как НЕ надо делать)
from nltk.translate.bleu_score import sentence_bleu
reference = ["Как испечь яблочный пирог без духовки?".split()]
candidate = "История яблочного пирога начинается в Древнем Риме".split()
score = sentence_bleu(reference, candidate) # Получим около 0.4!
# Ответ исторический, а не кулинарный, но метрика показывает неплохой результат
Токенные метрики мертвы для LLM-приложений. Они не понимают смысла, только слова. Перестаньте их использовать — серьезно.
2 Семантические метрики (современный стандарт)
Здесь мы сравниваем не слова, а их смысловые представления (эмбеддинги). Самый популярный подход — косинусное сходство между эмбеддингами запроса и ответа.
# Современный подход с использованием эмбеддингов
import numpy as np
from sentence_transformers import SentenceTransformer
# Используем современную модель для эмбеддингов (актуально на 2026 год)
model = SentenceTransformer('all-mpnet-base-v3')
query = "Как испечь яблочный пирог без духовки?"
answer_good = "Используйте мультиварку или микроволновку вместо духовки"
answer_bad = "Яблочный пирог был любимым десертом Наполеона"
# Получаем эмбеддинги
query_emb = model.encode(query)
good_emb = model.encode(answer_good)
bad_emb = model.encode(answer_bad)
# Считаем косинусное сходство
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
print(f"Хороший ответ: {cosine_similarity(query_emb, good_emb):.3f}") # ~0.78
print(f"Плохой ответ: {cosine_similarity(query_emb, bad_emb):.3f}") # ~0.32
Но и у семантического сходства есть ограничения. Оно хорошо определяет явно нерелевантные ответы, но плохо различает степени релевантности. Ответ "Используйте микроволновку" и "Вот 15 рецептов яблочного пирога без духовки с пошаговыми фото" получат примерно одинаковые баллы.
3 LLM как судья (state-of-the-art на 2026 год)
Самый продвинутый подход — использовать одну LLM для оценки ответов другой. Звучит как рекурсия, но работает неожиданно хорошо, особенно с большими моделями типа GPT-5.1 или Claude 4.5.
# Пример использования GPT-5.1 Turbo в качестве судьи
import openai
from tenacity import retry, stop_after_attempt, wait_exponential
client = openai.OpenAI(api_key="your-key")
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def evaluate_with_llm_judge(query, answer, reference=None):
"""Оценка ответа LLM-судьей"""
prompt = f"""Ты эксперт по оценке качества ответов AI-систем.
Запрос пользователя: {query}
Ответ системы: {answer}
Оцени ответ по следующим критериям (от 1 до 5):
1. Релевантность: насколько ответ соответствует запросу
2. Полнота: покрывает ли ответ все аспекты запроса
3. Полезность: можно ли использовать ответ для решения задачи
4. Точность: нет ли фактических ошибок
5. Ясность: понятен ли ответ
Верни JSON с оценками и кратким объяснением."""
response = client.chat.completions.create(
model="gpt-5.1-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
Этот подход дорогой (каждый вызов стоит денег), но дает наиболее человеко-подобные оценки. На практике его используют для калибровки более дешевых метрик или для финальной проверки спорных случаев.
Метрики для поисковых систем на ИИ
Если ваше приложение — поисковая система или RAG (Retrieval-Augmented Generation), вам нужны специальные метрики. Здесь важно не только качество одного ответа, но и правильность ранжирования.
| Метрика | Что измеряет | Когда использовать | Ограничения |
|---|---|---|---|
| nDCG@K | Качество ранжирования с учетом позиции | Поисковые системы, рекомендации | Требует human-оценки релевантности |
| MRR (Mean Reciprocal Rank) | На какой позиции первый релевантный результат | Когда важен первый хороший ответ | Игнорирует качество других результатов |
| MAP (Mean Average Precision) | Средняя точность по всем релевантным документам | Когда важны все релевантные результаты | Сложно считать для больших K |
| Recall@K | Доля найденных релевантных документов | Когда нельзя пропустить ни одного важного документа | Не учитывает позицию или точность |
Вот как выглядит расчет nDCG на практике:
import numpy as np
def ndcg_at_k(relevance_scores, k=10, ideal_scores=None):
"""Normalized Discounted Cumulative Gain at K"""
# relevance_scores - список оценок релевантности [3, 2, 0, 1, ...]
# где 0 - нерелевантно, 3 - максимально релевантно
# DCG: сумма (relevance / log2(position + 1))
dcg = 0
for i, rel in enumerate(relevance_scores[:k]):
dcg += rel / np.log2(i + 2) # +2 потому что позиции с 1
# Идеальный DCG (отсортированные оценки)
if ideal_scores is None:
ideal_scores = sorted(relevance_scores, reverse=True)
ideal_dcg = 0
for i, rel in enumerate(ideal_scores[:k]):
ideal_dcg += rel / np.log2(i + 2)
return dcg / ideal_dcg if ideal_dcg > 0 else 0
# Пример: наш поиск выдал документы с такой релевантностью
our_results = [3, 1, 2, 0, 1, 3, 0, 2]
print(f"nDCG@5: {ndcg_at_k(our_results, k=5):.3f}") # Оценим первые 5 результатов
Статистические метрики для недетерминированных систем
LLM по своей природе недетерминированы. Один и тот же промпт может давать разные ответы. Как это измерить?
Стабильность ответов
Запустите один и тот же запрос 100 раз. Посчитайте, насколько похожи ответы. Самый простой способ — Jaccard similarity между множествами ключевых слов:
def calculate_stability(responses, n_runs=100):
"""Измеряем стабильность ответов LLM"""
# responses - список из n_runs ответов на один и тот же промпт
# Извлекаем ключевые слова из каждого ответа
keyword_sets = []
for resp in responses:
# Простая токенизация и фильтрация стоп-слов
words = set(resp.lower().split())
stop_words = {"the", "a", "an", "and", "or", "but", "in", "on", "at", "to"}
keywords = words - stop_words
keyword_sets.append(keywords)
# Считаем попарное сходство Jaccard
similarities = []
for i in range(len(keyword_sets)):
for j in range(i+1, len(keyword_sets)):
intersection = len(keyword_sets[i] & keyword_sets[j])
union = len(keyword_sets[i] | keyword_sets[j])
if union > 0:
similarities.append(intersection / union)
return np.mean(similarities) if similarities else 0
# Стабильность 1.0 - идеальные идентичные ответы
# Стабильность 0.0 - совершенно разные ответы
# На практике хорошие системы дают 0.7-0.9
Внимание: Высокая стабильность — не всегда хорошо. Для творческих задач (генерация историй, идей) нужна вариативность. Для фактологических (ответы на вопросы, классификация) — стабильность критична.
Согласованность (consistency)
Более сложная метрика — проверка логической согласованности ответов. Например, если модель в одном ответе говорит "Python — интерпретируемый язык", а в другом — "Python компилируется в байт-код", это проблема.
Измеряем так: задаем серию связанных вопросов, проверяем, не противоречат ли ответы друг другу. Для этого тоже можно использовать LLM-судью.
Практический пайплайн оценки: шаг за шагом
Теория — это хорошо, но как собрать все вместе? Вот рабочий пайплайн, который мы используем в продакшене.
1 Собираем тестовый датасет
Не пытайтесь оценивать систему на абстрактных примерах. Соберите реальные запросы пользователей. 1000 разнообразных запросов лучше, чем 100 идеальных.
- 20% простых фактологических вопросов ("Сколько планет в Солнечной системе?")
- 30% сложных многоступенчатых вопросов ("Как настроить CI/CD для Python проекта с Docker?")
- 25% творческих задач ("Напиши начало детективной истории про AI")
- 15% edge-кейсов (бессмысленные запросы, провокационные вопросы)
- 10% запросов на других языках (если ваша система мультиязычная)
2 Размечаем эталонные ответы
Для каждого запроса создаем "идеальный" ответ. Это может быть:
- Ответ эксперта в предметной области
- Консенсус нескольких экспертов
- Ответ из проверенного источника (документация, учебник)
Размечаем не только текст, но и метаданные: релевантность (0-3), полнота, точность, полезность. Это пригодится для расчета nDCG и других метрик.
3 Запускаем автоматическую оценку
Создаем скрипт, который:
# Псевдокод пайплайна оценки
class EvaluationPipeline:
def __init__(self):
self.metrics = {
'semantic_similarity': SemanticSimilarityMetric(),
'bleu': BLEUMetric(), # Только для сравнения
'rouge': ROUGEMetric(), # Только для сравнения
'answer_length': AnswerLengthMetric(),
'hallucination_score': HallucinationDetector(),
}
# LLM-судья для сложных случаев
self.llm_judge = LLMJudge(model="gpt-5.1-turbo")
def evaluate_batch(self, queries, references, candidates):
results = {}
# Быстрые автоматические метрики
for name, metric in self.metrics.items():
results[name] = metric.compute_batch(queries, references, candidates)
# LLM-судья для 10% случайных выборок (чтобы сэкономить)
sample_indices = np.random.choice(len(queries),
size=max(10, len(queries)//10),
replace=False)
llm_scores = []
for idx in sample_indices:
score = self.llm_judge.evaluate(
queries[idx],
candidates[idx],
references[idx]
)
llm_scores.append(score)
results['llm_judge_mean'] = np.mean(llm_scores)
results['llm_judge_std'] = np.std(llm_scores)
return results
4 Анализируем результаты и ищем паттерны
Не просто смотрите на средние баллы. Ищите паттерны:
- На каких типах запросов система работает хуже всего?
- Есть ли корреляция между длиной запроса и качеством ответа?
- Становится ли система лучше/хуже со временем (регрессионное тестирование)?
- Как влияет температура (temperature) на стабильность ответов?
Распространенные ошибки и как их избежать
Ошибка 1: Тестирование на слишком маленьком датасете. 100 запросов недостаточно. Нужны тысячи, чтобы покрыть все возможные сценарии.
Ошибка 2: Использование только автоматических метрик. BLEU и ROUGE дешевы, но бесполезны для смысловой оценки. Всегда добавляйте человеческую оценку или LLM-судью.
Ошибка 3: Игнорирование стоимости оценки. LLM-судья на GPT-5.1 стоит денег. Рассчитайте бюджет заранее. Иногда дешевле нанять нескольких асессоров.
Ошибка 4: Отсутствие бейзлайна. Нельзя сказать "наша система имеет nDCG 0.85". Нужно сравнить с чем-то: предыдущей версией, конкурентами, простым BM25.
Ошибка 5: Забыть про edge-кейсы. Система может прекрасно работать на 95% запросов и полностью ломаться на оставшихся 5%. Ищите эти 5%.
Инструменты и библиотеки (актуально на 2026 год)
Не изобретайте велосипед. Вот что стоит использовать:
| Инструмент | Для чего | Плюсы | Минусы |
|---|---|---|---|
| DeepEval | Комплексная оценка LLM | Много встроенных метрик, интеграция с LLM-судьями | Требует обучения |
| RAGAS | Оценка RAG-систем | Специализированные метрики для retrieval | Ограниченная гибкость |
| TruLens | Мониторинг и оценка LLM | Хорошие инструменты для production | Коммерческий продукт |
| BERTScore | Семантическое сходство | Бесплатно, быстро, лучше BLEU | Требует модели BERT |
Что дальше? Будущее метрик LLM
Метрики эволюционируют вместе с моделями. Вот что будет важно в ближайшие годы:
Мультимодальные метрики
GPT-5.1, Claude 4.5, Gemini Ultra 3.0 — все они мультимодальны. Как оценить, насколько хорошо модель описывает изображение или создает его по тексту? Нужны новые метрики, которые понимают связь между текстом и визуальным контентом.
Метрики для агентов
Современные LLM — не просто чат-боты. Это агенты, которые выполняют действия: вызывают API, управляют устройствами, совершают транзакции. Метрики должны оценивать не только текст ответа, но и правильность действий. Если вам интересна эта тема, посмотрите мою статью про тестирование недетерминированных LLM.
Персонализированные метрики
Один и тот же ответ может быть хорошим для новичка и плохим для эксперта. Будущие метрики будут учитывать контекст пользователя: его знания, цели, предпочтения.
Главный секрет, который никто не говорит
После 20 лет в QA я понял одну вещь: идеальных метрик не существует. Все они ломаются на edge-кейсах. Все они имеют слепые зоны.
Но есть один трюк, который работает всегда: комбинация метрик + человеческое суждение.
Создайте свою собственную систему оценки. Возьмите 3-4 автоматические метрики. Добавьте LLM-судью для сложных случаев. Раз в месяц проводите ручную проверку на 100 случайных запросах. Сравнивайте результаты с предыдущими месяцами.
И помните: метрики — не самоцель. Они инструмент для принятия решений. "Наша система улучшила nDCG с 0.82 до 0.85" — это не результат. Результат — это "пользователи стали на 15% чаще находить нужную информацию".
Метрики должны связываться с бизнес-показателями. Иначе вы просто играете с цифрами.
Самый важный навык AI-QA инженера в 2026 году — не знание конкретных метрик, а понимание, какие метрики использовать в каждой конкретной ситуации. И когда нужно отложить все метрики и просто поговорить с пользователями.
Потому что в конце концов, мы строим системы для людей. А люди редко думают в терминах nDCG и BLEU.