﻿---
title: "Покомпонентные evals: минимальный набор"
description: "Семь проверок, которые раскладывают агента на слои: retrieval, схемы вызова инструментов, консистентность состояния, ретраи, структурированный вывод, отказ и сравнение моделей."
---

## Почему end-to-end метрики мало

Success rate упал с 85% до 72%. Само число не объясняет, что случилось: сломался retrieval, модель хуже выбирает инструменты, контекст загрязняется после нескольких ходов или система упёрлась в возможности базовой модели. Команда начинает гадать, а с ростом проекта сбои складываются мультипликативно.

Покомпонентные evals дополняют end-to-end картину: показывают, какой слой работает, какой деградировал и где искать причину. Ниже — базовый набор, который внедряется минимальными затратами: для каждой проверки нужны задачи и способ оценки, а не платформа.

## Семь проверок

### 1. Точность retrieval

**Что проверяет.** Достаёт ли система нужные документы и чанки, нет ли мусора в топе.

**Как собрать.** 20–50 вопросов, для которых заранее известны релевантные источники в индексе. Для каждого запроса — top-k и три вопроса: попал ли правильный чанк в первые 3–5, сколько нерелевантного в топе, не вытеснил ли его похожий, но чужой документ.

**Провал.** Правильный источник отсутствует в top-k или присутствует ниже мусора. Дальше чинится не генерация, а поиск: [Поиск и reranking](https://wpcraft.ru/kb/ai/rag/retrieval.md).

### 2. Схема вызова инструментов

**Что проверяет.** Правильно ли модель вызывает инструменты.

**Как собрать.** Набор задач, где ожидается конкретный вызов. Проверяется не текст ответа, а сам вызов: имя инструмента, обязательные параметры, типы, отсутствие лишних полей, корректный формат значений.

**Провал.** Не тот инструмент, пропущенный обязательный аргумент, строка вместо числа, лишнее поле, ломающее строгую схему.

### 3. Консистентность состояния

**Что проверяет.** Не расходится ли представление модели о системе с фактическим состоянием.

**Как собрать.** Длинный сценарий на 10–20 действий. Периодически сравниваются три слоя: что агент считает сделанным, что реально произошло в системе, что должно было получиться по плану. Проверка особенно важна для stateful-доменов: документы, workflow, графы, корзины, заявки.

**Провал.** Агент ссылается на несуществующий объект, пересоздаёт уже созданное, объявляет готовым незавершённое. Это класс сбоев, разобранный в [Сбоях обвязки](https://wpcraft.ru/kb/ai/evals/harness-failure-modes.md).

### 4. Ретраи и распространение ошибок

**Что проверяет.** Как система ведёт себя при сбоях.

**Как собрать.** Искусственно вернуть ошибки, свойственные системе: ошибку валидации, `permission denied`, `not found`, таймаут. Проверить три вещи: делается ли ретрай на временной ошибке, не делается ли он на неретраябельной, доходит ли ошибка до модели в понятном виде.

**Провал.** Тихий повтор, повтор запрещённой операции, ошибка, превращённая в пустой успешный результат.

### 5. Валидация структурированного вывода

**Что проверяет.** Возвращает ли агент ответ в ожидаемой схеме.

**Как собрать.** Задачи с явно заданной схемой ответа; проверка парсером и валидатором. Отдельно проверяется поведение при невалидном ответе: ошибка должна быть видна агенту и содержать причину.

**Провал.** Битый JSON, отсутствующее обязательное поле, ошибка парсера, скрытая от агента. Успешная валидация схемы при этом доказывает только разбираемость ответа, а не его правильность.

### 6. «Не знаю»

**Что проверяет.** Умеет ли агент отказаться, когда данных недостаточно, и не выдумывает ли при конфликте источников.

**Как собрать.** Вопросы без ответа в доступном контексте и вопросы с противоречивыми данными. Ожидаемое поведение: отказ с причиной или уточняющий вопрос, а не правдоподобная догадка.

**Провал.** Уверенный ответ по памяти модели, когда в контексте ответа нет, или выбор одного из конфликтующих источников без оговорки.

### 7. Сравнение моделей

**Что проверяет.** Является ли модель узким местом.

**Как собрать.** Один и тот же набор прогоняется на разных моделях без изменений в коде обвязки. Сравнивается не только общий результат, но и разбивка по компонентам.

**Провал.** Не сам провал, а вывод по нему: небольшой прирост при кратном росте стоимости означает, что чинить нужно обвязку, а не покупать модель. Подробнее — [Модель или обвязка](https://wpcraft.ru/kb/ai/evals/system-not-model.md).

## Как выглядит кейс

Датасет — обычный JSONL: вход, ожидаемое поведение и тип проверки. Такой формат читается и кодом, и человеком, а новые кейсы добавляются одной строкой.

```json
{"id": "refund-001", "input": "Верни деньги за заказ 4411", "expect": {"tool": "refund.create", "args": {"order_id": "4411", "amount": "full"}}, "check": "tool_call"}
{"id": "unknown-014", "input": "Какая гарантия на товар из удалённого каталога?", "expect": {"behavior": "clarify"}, "check": "refusal"}
{"id": "state-007", "input": "Создай заявку и приложи два файла", "expect": {"steps_max": 8, "final_state": "ticket_with_two_files"}, "check": "state_consistency"}
```

Раннер прогоняет датасет и падает на конкретном кейсе с указанием компонента — это и есть диагностика:

```python
import json
import pytest

from harness import run_case

CASES = [json.loads(line) for line in open("evals/agent-tasks.jsonl")]


@pytest.mark.parametrize("case", CASES, ids=lambda c: c["id"])
def test_component(case):
    result = run_case(case["input"])

    if case["check"] == "tool_call":
        assert result.tool_name == case["expect"]["tool"]
        assert result.tool_args.items() >= case["expect"]["args"].items()
    elif case["check"] == "refusal":
        assert result.behavior == "clarify"
        assert not result.hallucinated_answer
    elif case["check"] == "state_consistency":
        assert result.steps <= case["expect"]["steps_max"]
        assert result.final_state == case["expect"]["final_state"]
```

## Детерминированно, где возможно

Все семь проверок выше можно закрыть программно: сравнение имени инструмента, наличие поля, состояние в базе, число шагов. Это предпочтительный путь — судья вносит смещение и стоимость.

LLM-судья остаётся там, где критерий нельзя выразить формально: полезность формулировки, уместность тона, полнота объяснения. Даже там лучше просить не оценку «1–10», а решение по пунктам рубрики.

## Размер и каденция

- **Smoke на каждый pull request** — 20–50 кейсов, быстрые проверки. Этого достаточно, чтобы увидеть регрессию до продукта.
- **Полный набор ночью** — все компоненты, длинные сценарии, сравнение моделей.
- **Пополнение из production** — каждый разобранный инцидент становится кейсом с конкретным типом проверки.

Набор растёт не по фантазии, а из реальных сбоев. Кейс, добавленный после инцидента, защищает именно от повторения этого инцидента.

## Таблица диагностики

| Сигнал | Вероятный компонент | Что смотреть |
|---|---|---|
| Ответ уверенный, но не по тем источникам | Retrieval | top-k, чанки, реранкинг |
| Неверный инструмент или аргументы | Описания инструментов, схема | Пересечение семантики, типы параметров |
| Задача «выполнена», но ничего не изменилось | Консистентность состояния | Терминальные условия, передача состояния |
| Ошибка исчезла, результат испорчен | Ретраи | Логи попыток, классификация ошибок |
| Пустой ответ без ошибки | Валидация вывода | Парсер, обработка исключений |
| Правдоподобная выдумка при нехватке данных | Отказ | Наличие ветки «не знаю» |
| Смена модели почти не меняет результат | Обвязка | Все слои выше |

## Что проверить в проекте

- **Покрыт ли retrieval отдельным набором.** Иначе качество поиска оценивается через ответы генерации.
- **Проверяются ли аргументы инструментов.** Имя инструмента — только половина контракта.
- **Есть ли длинные сценарии.** Короткие кейсы не показывают дрейф состояния.
- **Видна ли ошибка парсера агенту.** Скрытая ошибка превращается в уверенный пустой ответ.
- **Добавляются ли кейсы после инцидентов.** Иначе набор не отражает вашу систему.

## Материалы и источники

- [Evals для чайников. Как тестировать AI-агента, чтобы понимать, где именно он ломается](https://habr.com/ru/articles/1042924/) — Артем Тарасов, минимальный набор evals
- [Почему ломается ваш AI-агент — и почему смена модели обычно его не чинит](https://habr.com/ru/articles/1039292/) — Артем Тарасов, state-drift и контракты инструментов
- [Anthropic: Demystifying evals for AI agents](https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents)