Skip to content

dobryakov/eval-harness

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

eval-harness — release gate для моделей и RAG-агентов

Минимальный eval перед релизом: два автоматизируемых слоя в CI. Exit code 0 — можно релизить; non-zero — блок.

Exit code Значение
0 Все проверки пройдены
1 Layer 1 (regression): хотя бы один кейс упал
2 Layer 2 (distribution): значимый drift относительно снапшота

Три слоя методики

Layer 1 — Regression (non-negotiable). Фиксированный набор reference-кейсов с известным ожидаемым выводом: edge-кейсы прошлых инцидентов, одобренные демо-кейсы, adversarial-входы (prompt injection, пустой, malformed). Любой новый фейл блокирует релиз. Реализован в layers/regression.py.

Layer 2 — Distribution check. 20–50 свежих реальных входов через новую версию. Сравнение не с «идеалом», а с diff против снапшота прошлого релиза: длина ответа, число retrieved-чанков, сдвиг confidence (рост std >20% — сигнал хрупкости; сдвиг длины >30% — drift). Реализован в layers/distribution.py.

Layer 3 — Human spot-check. Обязателен перед первым проддеплоем нового вида вывода: доменный эксперт читает 10–20 реальных выводов. Это процесс, не код; в харнесс не входит.

Owner. Один человек подписывает sign-off на релиз. Если владельца нельзя назвать до выката — это уже красный флаг.

Быстрый старт

pip install -r requirements.txt

python run_eval.py --layer regression
python run_eval.py --layer distribution --inputs inputs.jsonl
python run_eval.py --all --inputs inputs.jsonl

После успешного релиза обновите baseline распределения:

python run_eval.py --layer distribution --inputs inputs.jsonl --update-snapshot

Подключение своей модели

Реализуйте контракт в adapter.py:

def run(input: dict) -> dict:
    # input — поле input из YAML-кейса или строка JSONL
    # return:
    return {
        "output": str,       # текст ответа
        "chunks": list,      # retrieved chunks (любая структура)
        "confidence": float,  # 0..1
    }

Демо-стаб в репозитории проходит bundled regression-кейсы; замените его на вызов API, локальной модели или агента.

Добавление regression-кейса из инцидента

  1. Создайте cases/<short-id>.yaml:
id: rag-stale-corpus
origin: incident-2026-03
input:
  query: "действующая ставка по тарифу X"
expected:
  must_contain:
    - "актуальный документ"
  must_not_contain:
    - "archived"
  retrieved_chunks:
    min_count: 1
    must_contain:
      - '"status": "active"'
    must_not_contain:
      - '"status": "archived"'
pass_criteria:
  - no_archived_docs
  - answer_grounded
  1. must_contain / must_not_contain — подстроки в тексте ответа (output).
  2. retrieved_chunks — подстроки в сериализованных чанках (dict/list → JSON, как в adapter.py). Подбирайте needle под реальный формат вашего RAG, иначе тест пройдёт vacuously. Пример для {"doc_id": "…", "status": "active"}: в кейсе указано '"status": "active"', а не "status: archived" (лог-формат) — последнее в JSON-чанках не встретится и ничего не проверит.
    • min_count / max_count — границы числа чанков;
    • must_contain / must_not_contain — хотя бы один / ни один чанк;
    • each_must_contain — в каждом чанке.
  3. pass_criteria — документация для ревью; в CI не исполняется.
  4. Прогоните python run_eval.py --layer regression локально, затем в CI.

Каждый инцидент, который не должен повториться, должен стать permanent regression-кейсом.

Distribution: inputs и snapshot

  • inputs.jsonl — по одному JSON-объекту на строку (те же поля, что передаёте в adapter.run).
  • snapshots/latest.json — метрики прошлого релиза; создаётся/обновляется флагом --update-snapshot.

Флаги drift (Layer 2):

  • средняя длина output изменилась >30% относительно снапшота;
  • confidence std вырос >20% (ответы стали «рванее» по уверенности);
  • среднее число chunks изменилось >30%;
  • mean confidence сместился к краям (<0.35 или >0.85) при заметном отличии от baseline.

CI (пример)

- run: pip install -r requirements.txt
- run: python run_eval.py --all --inputs inputs.jsonl

Не передавайте --update-snapshot в release pipeline — только после выката, когда метрики приняты.

Структура

eval-harness/
  run_eval.py
  adapter.py
  layers/
    regression.py
    distribution.py
  cases/
    *.yaml
  snapshots/
    latest.json
  inputs.jsonl          # пример; подставьте свои 20–50 входов
  requirements.txt

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages