Учебник

Как проверить, не врёт ли ваш ИИ-помощник, за вечер без программиста

Ваш ИИ-помощник может терять 38% нужных документов и выдумывать каждый третий факт. Вы этого не видите, а клиенты жалуются. Разбираем, как за 4 часа собрать тестовый набор вопросов и запустить автоматическую проверку качества. Никаких программистов - всё делается через готовые библиотеки, которые настраиваются за час.

Макс Космов··9 мин чтения

Ваш ИИ-помощник может тихо терять треть нужных документов и придумывать каждый четвёртый факт. Без цифр об этом никто не узнает. Жалобы пойдут от клиентов, а вы будете думать, что система работает нормально.

Разберём на примере стройфирмы. У вас есть база знаний: прайс на работы, типовой договор подряда, техзадания. Вы запустили ИИ-бота для менеджеров, чтобы они быстро находили условия и цены. Бот отвечает, но иногда выдаёт неверные цифры или пропускает важные пункты. Метрики - единственный способ увидеть эти дыры и закрыть их.

RAG (Retrieval-Augmented Generation, поиск с дополнением ответа) - это связка из двух частей. Сначала система ищет в базе знаний фрагменты, относящиеся к вопросу. Потом большая языковая модель пишет ответ на основе найденного. Если показатель context recall равен 0,62, а faithfulness 0,71, это значит: 38% важных данных не находится, 29% утверждений в ответе ничем не подтверждены.

Метрики превращают такие ощущения в цифры. По цифрам уже можно принимать решения: дорабатывать поиск, менять модель, переделывать разбивку документов.

Почему старые метрики не работают для RAG

Если качество ИИ-помощника оценивать неправильными метриками, цифры будут красивые, а пользователи всё равно недовольны. Тратятся деньги на улучшения, которые не улучшают то, что важно клиенту. Правильная метрика снимает спор о том, стало лучше или хуже после изменения.

До появления RAG качество ответов измеряли по сходству с эталонным текстом. BLEU и ROUGE - это классические метрики из машинного перевода. BLEU сравнивает слова ответа со словами эталона. ROUGE делает то же самое, но смотрит с другой стороны. Для RAG они не подходят по трём причинам.

Первая причина: совпадение слов не означает правильность. Ответ "Выручка составила 52 миллиарда" и "Выручка составила 52,7 миллиарда" дают BLEU около 0,9. При этом первый ответ содержит неточное число.

Вторая причина: нет проверки источника. Большая языковая модель может ответить правильно из собственной памяти, а не из загруженных документов. BLEU этого не заметит. В RAG-системе такой ответ опасен. База знаний обновится, а модель продолжит выдавать старые данные из памяти.

Третья причина: BLEU требует точного эталонного ответа. В корпоративных задачах эталон обычно звучит так: "любое утверждение, подтверждённое найденными документами". Точной фразы для сравнения просто нет.

RAG-специфичные метрики оценивают три вещи. Нашли ли нужные документы. Соответствует ли ответ найденному. Относится ли ответ к вопросу.

Четыре метрики Ragas: что считают и зачем

Эти четыре метрики дают понятную картину работы системы за 30 минут. Без них улучшения превращаются в гадание: одно поменяли, что-то изменилось, но непонятно, в какую сторону. С метриками каждое изменение становится проверяемым и обратимым.

Ragas (Retrieval Augmented Generation Assessment, оценка поиск-дополненной генерации) - библиотека для оценки RAG без эталонных ответов. Бизнес-смысл каждой метрики простой.

Context Precision (точность контекста) показывает, не тащит ли система мусорные документы.

Context Recall (полнота контекста) показывает, не упускает ли система нужные документы.

Faithfulness (достоверность) показывает, не выдумывает ли модель факты.

Answer Relevancy (релевантность ответа) показывает, отвечает ли система на вопрос, а не уходит в сторону.

Формулы простые. Context Precision равен количеству нужных фрагментов, делённому на все найденные. Context Recall равен количеству эталонных утверждений, найденных в контексте, делённому на все эталонные утверждения. Faithfulness равен количеству утверждений ответа, подтверждённых контекстом, делённому на все утверждения ответа.

Пример из практики. Клиент спрашивает об условиях договора. Система находит три документа, один из них нерелевантный. Context Precision получится 0,67. Если при этом система забыла найти пункт о штрафах, Context Recall тоже окажется ниже 1,0.

Следующий блок кода запускает оценку по всем четырём метрикам сразу. Для этого готовится набор тестовых вопросов с ответами, найденными фрагментами и эталонными ответами. Этот код выполняет ваш менеджер или фрилансер за час.

from ragas import evaluate
from ragas.metrics import (
 faithfulness,
 answer_relevancy,
 context_precision,
 context_recall
)
from datasets import Dataset

# Подготовка тестового набора данных
eval_data = {
 "question": [
 "Какова выручка компании в 2024 году?",
 "Как настроить параметры поиска в Qdrant?",
 ],
 "answer": [
 "Выручка компании в 2024 году составила 52,7 млрд рублей.",
 "Параметры поиска настраиваются через hnsw_config...",
 ],
 "contexts": [
 ["Финансовые результаты 2024: выручка 52,7 млрд рублей, рост 16,6%"],
 ["hnsw_config принимает параметры m и ef_construction..."],
 ],
 "ground_truth": [
 "Выручка составила 52,7 миллиарда рублей.",
 "Нужно задать m=16 и ef_construction=200.",
 ]
}

dataset = Dataset.from_dict(eval_data)

# Запуск оценки по четырём метрикам
result = evaluate(
 dataset,
 metrics=[
 faithfulness,
 answer_relevancy,
 context_precision,
 context_recall
 ]
)

df = result.to_pandas()
print(df[["faithfulness", "answer_relevancy", "context_precision", "context_recall"]])
print(f"Faithfulness: {result['faithfulness']:.3f}")
print(f"Context Recall: {result['context_recall']:.3f}")

Как Ragas использует ИИ в роли судьи

Оценить тысячу ответов вручную - неделя работы аналитика. ИИ-судья делает это за час и стоит несколько долларов. Подвох в том, что судью тоже надо проверять, иначе он будет хвалить плохие ответы и портить картину. Знание ограничений судьи защищает от ложного оптимизма.

Ragas сам использует большую языковую модель (по умолчанию GPT-4o) для оценки. Это называется LLM-as-judge, ИИ в роли судьи. Принцип работы для faithfulness такой. Система извлекает все утверждения из ответа. Потом спрашивает модель по каждому утверждению, подтверждается ли оно найденными документами. Faithfulness равен доле подтверждённых утверждений.

Бизнес-аналогия простая. Представьте аудитора, который проверяет каждое утверждение в отчёте против первичных источников. ИИ-судья делает то же самое автоматически.

Ограничения подхода такие. Модель-судья склонна соглашаться с уверенно звучащими утверждениями. Длинные ответы оцениваются чуть выше коротких. Оценка 100 вопросов через GPT-4o обходится в 1-3 доллара.

Этот блок кода явно указывает модель-судью. Для русскоязычных текстов это важно: GPT-4o работает с русским лучше, чем более старые версии.

from langchain_openai import ChatOpenAI
from ragas.llms import LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper
from langchain_openai import OpenAIEmbeddings

# Выбор модели-судьи для русского языка
judge_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))
judge_embeddings = LangchainEmbeddingsWrapper(
 OpenAIEmbeddings(model="text-embedding-3-small")
)

result = evaluate(
 dataset,
 metrics=[faithfulness, context_recall],
 llm=judge_llm,
 embeddings=judge_embeddings
)

Пороговые значения для принятия системы в работу

Без порогов метрики превращаются в красивые цифры на дашборде, на которые никто не реагирует. С порогами появляются понятные сигналы: если показатель упал ниже планки, система не уходит в продуктивную среду. Это защищает клиентов от регресса качества.

Прежде чем запустить RAG в работу, нужно проверить минимальные показатели. Вот ориентиры из реальных систем.

Метрика Минимум Хорошо Отлично
Faithfulness 0.75 0.85 0.92
Context Precision 0.70 0.80 0.90
Context Recall 0.65 0.75 0.85
Answer Relevancy 0.80 0.88 0.95

Три частых случая неудач и что с ними делать.

Низкий faithfulness при высоком context recall. Система находит нужные документы, но модель всё равно выдумывает. Проблема в настройках генерации или в системном сообщении. Часто помогает добавить в инструкцию для модели жёсткую фразу: "отвечай только тем, что есть в контексте".

Высокий faithfulness при низком context recall. Модель честно отвечает по найденному, но находит не те документы. Проблема в поиске или в способе нарезки текста на фрагменты. Стоит проверить размер фрагмента и перекрытие между соседними.

Низкая context precision. Система тащит нерелевантные фрагменты. Нужен реранкер (инструмент переупорядочивания результатов поиска) или более строгий порог сходства.

TruLens: отслеживание каждого запроса в реальном времени

Тестовый набор показывает качество на синтетических вопросах. Реальные пользователи задают вопросы иначе. TruLens видит каждый запрос продуктивной среды и сразу подсвечивает проблемы. Это разница между ежеквартальным аудитом и видеонаблюдением.

Ragas запускается отдельным прогоном на тестовом наборе. TruLens от компании TruEra работает по-другому. Он встраивается в систему и оценивает каждый реальный запрос пользователя.

Этот блок кода оборачивает RAG-цепочку в TruLens. После этого каждый запрос автоматически логируется с метриками качества.

from trulens.core import TruSession, Feedback
from trulens.apps.langchain import TruChain
from trulens.providers.openai import OpenAI as TruOpenAI
import numpy as np

session = TruSession()
provider = TruOpenAI(model_engine="gpt-4o")

# Задаём функции оценки качества
f_groundedness = (
 Feedback(provider.groundedness_measure_with_cot_reasons,
 name="Достоверность")
 .on(TruChain.select_context())
 .on_output()
)

f_context_relevance = (
 Feedback(provider.context_relevance_with_cot_reasons,
 name="Релевантность контекста")
 .on_input()
 .on(TruChain.select_context())
 .aggregate(np.mean)
)

# Оборачиваем RAG-цепочку
tru_rag = TruChain(
 rag_chain,
 app_name="ProductionRAG",
 app_version="v1.2",
 feedbacks=[f_groundedness, f_context_relevance]
)

# Каждый вызов теперь автоматически оценивается
with tru_rag as recording:
 response = rag_chain.invoke({"question": user_query})

# Веб-панель с результатами на localhost:8501
session.run_dashboard()

Веб-панель TruLens показывает каждый запрос с разбивкой. Какие документы нашлись. Какая достоверность (groundedness, от английского - "заземлённость на факты"). Где модель вышла за пределы контекста.

DeepEval: автоматический стоп при снижении качества

Команда регулярно правит код RAG-системы: меняет настройки поиска, обновляет модель, переписывает разбивку документов. Без автоматического контроля одно из таких изменений однажды ухудшит качество, и это заметят только пользователи. DeepEval превращает контроль качества в часть процесса разработки, как обычные тесты.

DeepEval интегрируется в процесс проверки кода. При падении метрик ниже порога обновление не проходит. Принцип такой же, как у автоматических тестов для кода, только проверяется качество ответов.

Этот блок кода - тест, который падает если faithfulness опустится ниже 0,75 или полнота контекста ниже 0,70.

# tests/test_rag_quality.py
import pytest
from deepeval import assert_test
from deepeval.metrics import (
 FaithfulnessMetric,
 ContextualRecallMetric,
 ContextualPrecisionMetric
)
from deepeval.test_case import LLMTestCase
from deepeval.dataset import EvaluationDataset

# Загружаем эталонный набор вопросов
dataset = EvaluationDataset()
dataset.add_test_cases_from_json_file(
 file_path="tests/golden_dataset.json",
 input_key_name="question",
 actual_output_key_name="expected_answer",
 expected_output_key_name="ground_truth",
 context_key_name="golden_contexts"
)

@pytest.mark.parametrize("test_case", dataset)
def test_rag_faithfulness(test_case: LLMTestCase):
 retrieval_results = retrieve(test_case.input)
 actual_output = generate(test_case.input, retrieval_results)

 test_case.actual_output = actual_output
 test_case.retrieval_context = [r.page_content for r in retrieval_results]

 faithfulness_metric = FaithfulnessMetric(
 threshold=0.75,
 model="gpt-4o",
 include_reason=True
 )

 context_recall_metric = ContextualRecallMetric(
 threshold=0.70,
 model="gpt-4o"
 )

 assert_test(test_case, [faithfulness_metric, context_recall_metric])

# Запуск: pytest tests/test_rag_quality.py --timeout=300
# Если faithfulness < 0.75 хотя бы на одном вопросе - обновление не проходит

Следующий блок настраивает автоматический запуск этих тестов при каждом обновлении кода в GitHub. GitHub - сервис хранения и проверки исходного кода.

# .github/workflows/rag-eval.yml
name: RAG Quality Gates
on: [pull_request]

jobs:
 rag-evaluation:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4
 - name: Установка зависимостей
 run: pip install deepeval ragas
 - name: Запуск проверки качества
 env:
 OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
 run: |
 pytest tests/test_rag_quality.py --timeout=600 --tb=short -v
 - name: Сохранение результатов
 if: always()
 uses: actions/upload-artifact@v4
 with:
 name: rag-eval-results
 path: deepeval_results.json

Как собрать эталонный набор вопросов за 4 часа

Без эталонного набора метрики нельзя сравнивать между версиями. Сборка набора вручную растягивается на недели. Автоматическая генерация даёт 80% результата за день. Это снимает главное препятствие к запуску оценки качества.

Эталонный набор (golden dataset) - это 50-100 вопросов с правильными ответами и нужными фрагментами документов. Без такого набора нельзя стабильно измерять качество при изменениях системы. Хорошая новость: Ragas умеет генерировать вопросы автоматически из ваших документов.

Этот блок кода автоматически создаёт 100 вопросов разных типов по загруженным документам.

from ragas.testset import TestsetGenerator
from langchain_community.document_loaders import DirectoryLoader
from langchain_openai import ChatOpenAI, OpenAIEmbeddings

# Шаг 1: загружаем базу знаний
loader = DirectoryLoader("./knowledge_base/", glob="**/*.pdf")
documents = loader.load()

# Шаг 2: генерируем вопросы через Ragas
generator_llm = ChatOpenAI(model="gpt-4o")
critics_llm = ChatOpenAI(model="gpt-4o")
emb = OpenAIEmbeddings(model="text-embedding-3-small")

generator = TestsetGenerator.from_langchain(
 generator_llm, critics_llm, emb
)

# 100 вопросов: простые, требующие рассуждений, требующие нескольких фрагментов
testset = generator.generate_with_langchain_docs(
 documents,
 test_size=100,
 distributions={
 "simple": 0.5,
 "reasoning": 0.3,
 "multi_context": 0.2
 }
)

df = testset.to_pandas()
df.to_json("tests/golden_dataset.json", orient="records", force_ascii=False)

Шаг третий - ручная проверка за 1-2 часа. Эксперт по предметной области просматривает сгенерированные вопросы. Убирает некорректные. Добавляет специфичные для вашего бизнеса. Без проверки в наборе будет 10-20% ошибочных примеров, которые сломают всю метрику.

Типичные ошибки

Запускать оценку без ручной проверки эталонного набора. Автогенерация даёт артефакты, которые искажают все метрики.

Ориентироваться только на faithfulness. Система может быть честной, но неполной. Будет отвечать строго по найденному, но упускать половину нужных документов.

Не устанавливать пороговые значения. Без порогов метрики просто числа, на которые никто не реагирует.

Экономить на размере тестового набора. Меньше 30 вопросов не дают статистически надёжных результатов.

Оставлять одну модель-судью на годы. ИИ-судья тоже устаревает: появляются новые версии, старые становятся менее точными.

Частые вопросы

Ragas, TruLens или DeepEval - что выбрать для начала?

Ragas нужен для первоначальной оценки и понимания метрик. У него хорошая документация, работает без эталонных ответов. TruLens нужен, когда система уже в продуктивной среде и важен мониторинг каждого запроса в реальном времени. DeepEval нужен, когда система активно развивается и нужен автоматический стоп при деградации качества. Зрелая система использует все три инструмента: Ragas для разового аудита, TruLens для мониторинга, DeepEval для контроля при обновлениях.

Как понять низкий context recall при высоком faithfulness?

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

Как добавить ручную оценку к автоматической?

Оцените 50-100 вопросов вручную по шкале от 1 до 5. Сравните с оценками Ragas. Если корреляция выше 0,7, метрики надёжны для вашей предметной области. Если ниже, ИИ-судью нужно настраивать или менять.

Сколько вопросов минимально достаточно для значимой оценки?

Для разовой оценки 30-50 вопросов, точность плюс-минус 0,05. Для сравнения двух версий нужно 85 вопросов и больше. Для постоянного контроля при обновлениях около 100 вопросов.

Можно ли доверять оценке от ИИ-судьи?

Да, если откалибровать. Сравните с ручной разметкой на вашем корпусе. Без калибровки это ориентир, а не истина в последней инстанции.

Что дальше и выводы

Метрики выстроены - это фундамент управления качеством ИИ-системы. Без них любое обновление RAG превращается в угадывание. С ними каждое изменение проверяемо и обратимо.

Следующий шаг - взять Ragas, сгенерировать 100 вопросов из ваших документов, запустить оценку. На это уйдёт 4 часа. Пороги для старта: faithfulness не ниже 0,75, context recall не ниже 0,65. Если показатели ниже - сначала правите поиск и промпты.

AI Компас (t.me/kosmoslab_ai) - канал для предпринимателей в РФ и СНГ, которые применяют AI в своём бизнесе без программиста. Разбираем инструменты и схемы - без курсов и теории.