Files

172 lines
14 KiB
Markdown

# Глава 11. Оценка качества агента
«Стал ли агент лучше после твоих правок?» — самый неудобный вопрос, который задают себе люди, собирающие агентов. Неудобный, потому что интуитивно кажется: «ну, я же потыкал, посмотрел, вроде работает». А объективно сказать, что вчерашний агент хуже сегодняшнего (или наоборот, ваш новый замечательный промпт всё сломал на половине задач), — тяжело. Агенты — недетерминированные системы с разнородными задачами, и наивная метрика «точность» к ним плохо применима.
Эта глава — про то, какой практический минимум нужен, чтобы отвечать на этот вопрос, и почему его нельзя откладывать до «когда-нибудь потом».
## Две плоскости оценки
Полезно сразу различать.
**Оценка итога.** Задача решена или нет. Это то, что волнует пользователя: починили ли тест, нашли ли нужный факт, правильный ли конспект.
**Оценка траектории.** Как агент к итогу пришёл. Сколько шагов занял, какие инструменты звал, не было ли лишних вызовов, не ходил ли по кругу.
Обе важны, и измеряются они по-разному.
Результативный, но дорогой агент (правильный ответ за 50 шагов и $2) и результативный дешёвый агент (правильный ответ за 8 шагов и $0,15) с точки зрения первой метрики равны, с точки зрения второй — очень разные. Для продакшна это разница между «работает» и «окупается».
## Golden set: тестовый набор задач
Первое, что должно быть у любого агента старше двух недель жизни — фиксированный набор задач с ожидаемыми результатами. Не для одноразового теста, а как постоянный референс.
Для кодового агента такой набор — это репозиторий-фикстура с подготовленными задачами:
```
golden/
├── task_001_fix_failing_test/
│ ├── project/ # начальное состояние проекта
│ ├── task.md # формулировка задачи
│ └── check.sh # скрипт проверки, возвращает 0 при успехе
├── task_002_add_endpoint/
│ ├── project/
│ ├── task.md
│ └── check.sh
...
```
Прогон: агент запускается в копии `project/`, работает над задачей из `task.md`, потом `check.sh` говорит, получилось или нет. Результат — процент пройденных задач.
Для исследовательского агента набор более хитрый. «Правильный ответ» на «что я читал про MoE» — не один-в-один текст, а набор свойств:
- упомянута ли нужная заметка?
- процитированы ли ключевые идеи?
- не было ли галлюцинаций про факты, которых в заметках нет?
Формат:
```yaml
task: "Что я читал про MoE?"
expected:
must_cite: ["notes/llm/switch-transformer.md"]
must_mention: ["routing", "mixture of experts", "балансировка"]
must_not_hallucinate: ["Mixture-of-Recursions"] # это мы не читали
```
## Метрики для двух архетипов
### Кодовый агент
**Pass rate на golden set.** Сколько процентов задач прошло `check.sh`. Главная метрика.
**Среднее число шагов до решения.** Медиана по успешным задачам. Растущая — повод насторожиться: агент или разучился быть прямолинейным, или промпт стал многословным.
**Доля ошибок инструментов.** Сколько вызовов пришло с невалидными аргументами или попало в блоклист. Признак расхождения между тем, что модель «думает», и тем, что инструменты готовы принять.
**Стоимость задачи.** Среднее число токенов (входных + выходных) на успешную задачу. Полезно отдельно: стоимость падающих задач может превышать стоимость успешных, потому что агент долго бьётся.
### Исследовательский агент
**Citation accuracy.** Доля утверждений в ответе, которые действительно подтверждаются цитированными источниками. Вычисляется проверкой: для каждого утверждения ищем подтверждающий фрагмент в указанных заметках.
**Recall.** Нашёл ли агент релевантный материал, который у пользователя действительно есть в заметках. Частая поломка — пропустил нужную заметку, потому что порог релевантности был высоковат или формулировка запроса промахнулась.
**Hallucination rate.** Доля ответов, содержащих факты, которых нет в цитированных источниках. Главная метрика для анти-галлюцинации.
**Satisfaction.** Нефункциональная, но важная: устроил ли ответ пользователя в слепом тесте. Измеряется вручную.
## LLM-as-judge
Ручная оценка — дорогая и не масштабируется. Для большинства метрик выше можно использовать саму LLM как судью.
Принцип: для каждого ответа агента запускаем отдельный LLM-вызов с промптом вида:
```
Вот задача пользователя: <task>
Вот ответ агента: <answer>
Вот материалы, на которые агент опирался: <sources>
Оцени ответ по шкале 1-5 по следующим критериям:
- Релевантность задаче
- Фактическая корректность
- Наличие галлюцинаций
Верни JSON: {"relevance": int, "correctness": int, "hallucinations": int, "reasoning": str}
```
Важные нюансы.
**Судья должен быть отдельной моделью или отдельной сессией.** Если оценивает та же модель в той же сессии — она склонна одобрять свою же работу.
**Судья работает хуже исполнителя на сложных задачах.** Если задача на уровне самой модели — судья тоже ошибётся. Работает для слабого агента + сильного судьи; не работает наоборот.
**Оценки шумные.** Любой LLM-judge даёт разные оценки на идентичные входы. Прогоняйте каждую задачу несколько раз, берите среднее.
**LLM-judge нужна калибровка.** Сравните его оценки с ручной разметкой на небольшом наборе (50–100 задач). Если расходятся — перепишите промпт судьи.
Практически: LLM-judge — это не замена ручной оценки, а её масштабируемый спутник. Ручную держим на меньшем, но качественном срезе, LLM-judge прогоняем постоянно.
## Как не обмануться
Типичные способы сделать себе иллюзию прогресса.
**Тестировать на тех же задачах, на которых настраивали.** Если вы подкручивали промпт, глядя на 20 конкретных задач, — оценивать надо на других 20. Иначе вы измеряете не качество, а свою способность запомнить, что агенту нравится.
**Смотреть только успешные случаи.** Самая информативная часть — где агент провалился. Трасса неудачного прогона говорит больше, чем десять успешных.
**Мерить только средние.** Медиана и хвосты важнее среднего. Агент, который решает 80% задач за 5 шагов и 20% задач за 200 шагов, в среднем «решает за 44 шага» — и это число ничего не говорит.
**Тестировать только крупные правки.** Маленькие промптовые изменения часто незаметно ломают что-то. Постоянный прогон золотого набора после каждого значимого изменения ловит регрессии, пока они дешёвые.
## Регрессионное тестирование
Похоже на юнит-тесты, но для агентов:
- Есть базовая версия (main branch): `agent_baseline`.
- Есть версия с изменениями: `agent_candidate`.
- Прогоняем оба на golden set.
- Сравниваем: где candidate лучше baseline, где хуже, где равно.
- Смотрим, устраивает ли нас новая форма баланса.
Это особенно важно для изменений системного промпта. Промпт — это код. Правка промпта — это коммит. Без тестов на эту правку вы работаете с системой, которую нельзя сравнить саму с собой.
Минимальный автоматический формат:
```python
def run_suite(agent, golden_dir):
results = []
for task_dir in sorted(glob.glob(f"{golden_dir}/*/")):
task = open(f"{task_dir}/task.md").read()
outcome = run_in_sandbox(agent, task_dir, task)
check_result = subprocess.run([f"{task_dir}/check.sh"], capture_output=True)
results.append({
"task": os.path.basename(task_dir.rstrip("/")),
"pass": check_result.returncode == 0,
"steps": outcome.n_steps,
"tokens": outcome.tokens,
})
return results
baseline = run_suite(agent_baseline, "golden/")
candidate = run_suite(agent_candidate, "golden/")
compare(baseline, candidate)
```
Раз в неделю, раз в день, перед каждым коммитом — зависит от того, как активно вы меняете агента. Для каждого — сохраняйте результаты в отдельный файл, чтобы можно было проследить тренд.
## Онлайн-метрики
Всё выше — оффлайн. Отдельная тема — что мерить на живых пользователях, когда агент уже работает.
**Success signals.** Что-то, что явно говорит «задача решена». Для кодового — прошёл ли CI после merge-а агентского коммита. Для исследовательского — перешёл ли пользователь к следующему вопросу (условный признак, что предыдущим доволен) или снова спрашивает то же другими словами (не доволен).
**User feedback.** Кнопки «хорошо / плохо» рядом с ответом. Простая, но крайне ценная метрика при достаточном объёме.
**Drop-off.** На каких типах задач пользователи быстрее всего бросают сессию. Это либо слишком сложные для агента задачи, либо задачи, где агент проваливается неочевидно для себя.
Онлайн-метрики отражают реальность, но запаздывают: вы узнаёте о регрессии через дни. Оффлайн — ловят регрессии до релиза. Работает комбинация.
## Что дальше
Оценка отвечает на вопрос «правильно ли работает агент». Следующий практический вопрос — «сколько это стоит и можно ли быстрее». Глава 12 — про стоимость, латентность и кэширование промптов.