Перейти к содержимому

Оценка

Эта страница описывает, что именно оценивается в репозитории, как это измеряется и где проходят границы. Здесь нет leaderboard’а и нет сравнения провайдеров: закоммиченная поверхность оценки — это офлайн-фикстура плюс runtime-оценщики, не живой бенчмарк конкретной модели.

Детерминированный путь, который проходит один поддерживаемый вопрос end-to-end, — на странице Воспроизвести E20.

Фикстура на 12 кейсов

evaluation/test_cases.json содержит 12 вопросов по шести категориям: error_codes, reset_password, warranty, installation, billing, general. У каждого кейса поля question, expected_keywords, expected_answer и category.

Офлайн-оценщик

evaluation/ragas_eval.py реализует RAGEvaluator с четырьмя keyword-метриками без зависимости от пакета ragas: faithfulness, answer_relevancy, context_precision, context_recall. Fallback детерминированный и работает без платного embeddings-API.

Бенчмарк-раннер

evaluation/benchmark_runner.py читает фикстуру, скорит каждый кейс против expected_answer через RAGEvaluator и пишет агрегаты плюс per-question результаты в data/evaluation/benchmark_results.json. Флаг —use-embeddings переключает answer_relevancy на embedding-вариант.

Онлайн-оценщики

evaluation/online_evaluators.py скорит живое состояние трейса на момент запроса: покрытие цитатами, аномалия длины ответа по z-score, hit-rate поиска по relevance_score, эффективность использования инструментов, совпадение паттерна отказа, детектор PII по config/evaluator_patterns.yml.

  • Нет cross-provider чисел по живому графу. Репозиторий гоняет офлайн-путь, не multi-model bake-off, и документация не заявляет сравнительных результатов между провайдерами.
  • Нет leaderboard’а. Нет закоммиченного output вида «модель A обходит модель B на этих двенадцати вопросах», и фикстура слишком мала, чтобы такое заявление было осмысленным, даже если бы output был.
  • Нет paid-API-базовой линии. RAGEvaluator работает без ragas и без embeddings-сервиса; embedding-вариант answer_relevancy включается явно через --use-embeddings у бенчмарк-раннера.

Засеянная демо-база содержит три документа (demo/seed_docs.py): гарантия, возвраты и errors_e10_e30.md. Фикстура на 12 кейсов покрывает шесть категорий, поэтому для трёх из них (installation, billing, reset_password) в демо-базе нет поддерживающего документа. Эти кейсы всё равно проходят через граф, но шаг retrieve, как ожидается, вернёт фрагменты с низкой релевантностью, и оценки оценщика это отражают — по дизайну, не случайно.

Если нужен детерминированный trust-путь на поддерживаемом сценарии, страница Воспроизвести E20 проводит ingest, ask и инспекцию трейса end-to-end на засеянном источнике.

Раннера два. Базовый гоняет с пустым контекстом (осмыслен только answer_relevancy); второй кормит каждому кейсу засеянный демо-документ по mapping’у категории — это поднимает все четыре метрики.

Окно терминала
cd D:\RAG_Support_Assistant
python -m demo.seed_docs # пишет demo/docs/*.md
# Базовый: пустой контекст, считает только answer_relevancy.
python evaluation/benchmark_runner.py
# С документами: category->doc mapping для трёх поддерживаемых категорий.
python evaluation/benchmark_offline_with_docs.py
# Или в кастомный output:
python evaluation/benchmark_runner.py --output data/evaluation/my_run.json

Оба раннера пишут data/evaluation/benchmark_results.json. Закоммиченный файл — это output benchmark_offline_with_docs.py, поэтому числа ниже воспроизводятся с чистого чекаута.

Числа ниже — output evaluation/benchmark_offline_with_docs.py против засеянной демо-базы demo/docs/. Три категории имеют поддерживающий документ, три — нет; этот gap и есть доминирующий сигнал в агрегате.

МетрикаAggregate (n=12)
faithfulness0.042
answer_relevancy0.549
context_precision0.190
context_recall0.250

Per-category mean scores:

КатегорияnЕсть документ?faithfulnessanswer_relevancycontext_precisioncontext_recall
error_codes3да0.1670.5280.3170.333
warranty2да0.0000.1670.5000.833
billing2да (returns_policy.md, частичный overlap)0.0000.8330.1670.167
reset_password2нет0.0000.6670.0000.000
installation2нет0.0000.5000.0000.000
general1нет0.0000.6670.0000.000

faithfulness низкий, потому что ответы в фикстуре написаны прозой, которая не всегда совпадает дословно с текстом демо-документа; context_precision/recall равны нулю для категорий без документа — по дизайну, не случайно. Это честные числа, не leaderboard.

Структура data/evaluation/benchmark_results.json — это то, что offline-with-docs раннер пишет после прогона; именно этот файл закоммичен:

{
"aggregate": {
"faithfulness": 0.0417,
"answer_relevancy": 0.5486,
"context_precision": 0.1905,
"context_recall": 0.25
},
"per_question": [
{
"question": "Что означает ошибка E401?",
"category": "error_codes",
"scores": {
"faithfulness": 0.0,
"answer_relevancy": 0.75,
"context_precision": 0.1429,
"context_recall": 0.0
}
}
],
"num_cases": 12,
"context_source": "demo/docs (category->doc mapping)",
"category_coverage": { "error_codes": 3, "warranty": 2, "billing": 2,
"reset_password": 2, "installation": 2, "general": 1 },
"supported_categories": ["billing", "error_codes", "warranty"],
"timestamp": ""
}

benchmark_runner.py без документов кладёт ту же структуру, но агрегат сводится к keyword-only answer_relevancy ≈ 0.549 и нулям остальные — это baseline, относительно которого прогон с демо-документами является честным улучшением.