L3 Открытый урок · Стажёр

L3.7. Основы оценки: golden set и eval-скрипт

Golden set, детерминированные проверки, hit@k, eval-скрипт с порогом и списком провалов и почему разница в один кейс — не улучшение.

Объём
4 урока · 8 часов
Компетенции
EVAL-02·A, PROMPT-05·F

«Стало лучше» — это число

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

Golden set

Golden set (эталонный набор) — 15–20 кейсов на старте: вход и то, что считается правильным. Формат — JSONL, одна строка на кейс:

{"id": "q01", "question": "Какая гарантия на фильтр Аква-3?", "relevant": ["warranty"], "expected_substring": "24 месяца"}
{"id": "q07", "question": "Можно ли вернуть фильтр без чека?", "relevant": ["returns"], "expected_substring": "без чека"}
{"id": "q15", "question": "Продаёте ли вы кофемашины?", "relevant": [], "expected_substring": "нет"}

Как собрать хороший набор:

  • из реальных вопросов пользователей, а не придуманных под систему;
  • трудные случаи обязательно: синонимы, опечатки, вопрос вне базы (правильный ответ — «не знаю»), вопрос с кодом товара;
  • эталон проверяет человек, не модель;
  • набор не используется для подбора промпта и примеров (вспомните вопрос 10 квиза 1).

Детерминированные проверки

Начинайте с проверок, которые не требуют модели-судьи:

Проверка Пример Подходит для
точное совпадение category == "брак" извлечение полей, классификация
подстрока "24 месяца" in answer факт в ответе
попадание в top-k нужный doc_id среди первых 5 поиск
валидность схемы Complaint.model_validate не упал структурированный вывод
числовой допуск abs(price - 1490) < 1 извлечение чисел

hit@k — доля запросов, у которых хотя бы один релевантный документ попал в первые k результатов. Метрики полноты и порядка (recall@k, MRR, nDCG) — на L4.7.

Eval-скрипт

import json
import pathlib
import sys

THRESHOLD = 0.8      # ниже — код возврата 1: в CI это блокирует изменение (L6.2)

def hit_at_k(retrieved: list[str], relevant: set[str], k: int) -> float:
    if not relevant:                       # вопрос вне базы: поиск не оцениваем здесь
        return 1.0
    return 1.0 if relevant & set(retrieved[:k]) else 0.0

def main() -> int:
    cases = [json.loads(l) for l in pathlib.Path("evals/golden.jsonl").read_text(encoding="utf-8").splitlines() if l.strip()]
    scores, failures = [], []
    for c in cases:
        retrieved = [doc_id for doc_id, _ in search_doc_ids(c["question"], k=5)]
        s = hit_at_k(retrieved, set(c["relevant"]), k=5)
        scores.append(s)
        if s == 0:
            failures.append((c["id"], c["question"], retrieved[:3]))
    value = sum(scores) / len(scores)
    print(f"hit@5 = {value:.2f} на {len(cases)} кейсах")
    for f in failures:
        print("  FAIL", *f)
    return 0 if value >= THRESHOLD else 1

if __name__ == "__main__":
    sys.exit(main())

Что важно в этом скрипте: число на выходе, список провалов (по нему вы чините систему), порог и код возврата. Эталон референса — evals/run_evals.py.

Маленький набор — большая погрешность

На 20 кейсах один кейс — это 5 процентных пунктов. Разница 0,80 против 0,85 — это один вопрос, и она может быть случайной (особенно если модель отвечает по-разному от запуска к запуску). На L3 правило простое: изменение меньше 2 кейсов не считаем улучшением; прогоняйте генеративные проверки 2–3 раза. Доверительные интервалы — на L6.2.

Оценка промпта (PROMPT-05·F)

Цикл улучшения промпта: прогнать eval → посмотреть провалы → понять причину → изменить промпт → снова прогнать весь набор (правка для одного кейса часто ломает другой) → записать результат в CHANGELOG. Подбор «на глаз» — антипаттерн из технологического радара курса.

Практикум: eval-скрипт на 15–20 кейсах

Golden set для своего поисковика из L3.6: 15–20 кейсов, из них минимум 3 трудных и 2 вопроса вне базы. Скрипт выводит hit@1, hit@5, список провалов и возвращает код 1 ниже порога. Прогоните для двух моделей эмбеддингов из L3.6 и запишите числа. Обоснуйте порог: почему именно такой для вашего домена.

Диагностика уровня

С какого уровня начать?

Оставьте контакты — свяжемся, зададим несколько вопросов об опыте и целях и подскажем уровень входа: с нуля, с середины программы или через Fast Track для разработчиков.

Или напишите: hello@superint.ru