Офлайн-оценка LLM-агентов: фреймворк для тестирования недетерминированных систем | AiManual
AiManual Logo Ai / Manual.
24 Мар 2026 Гайд

Фреймворк офлайн-оценки для продакшен-готовых LLM-агентов: как тестировать недетерминированные системы

Полное руководство по созданию фреймворка офлайн-оценки для LLM-агентов. Тестируйте многоагентные и недетерминированные системы перед продакшеном с помощью прак

Вы выпускаете в продакшен хаос. Давайте это исправим

Вы настраиваете цепочку из трех LLM-агентов. Один анализирует запрос, второй ищет данные в базе, третий генерирует ответ. В демо все работает идеально. В продакшене первый агент иногда решает, что запрос - это шутка, и передает второму мусор. Система ломается, а вы не понимаете почему. Классика.

Традиционные юнит-тесты здесь бесполезны. LLM недетерминированы по своей природе. Один и тот же промпт может дать разные результаты. Добавьте сюда взаимодействие нескольких агентов - и вы получаете систему, которую невозможно отладить стандартными методами.

Главная проблема: вы не можете написать assert agent.run(input) == expected_output. Потому что agent.run(input) каждый раз возвращает что-то новое. Иногда лучше, иногда хуже, иногда совсем не то. Как оценить, готов ли такой агент к продакшену?

Офлайн-оценка: тестируем, когда все спят

Офлайн-оценка (offline evaluation) - это прогон вашего LLM-агента на заранее собранном наборе тестовых данных без подключения к реальным пользователям или внешним API. Вы симулируете работу системы в контролируемой среде.

Зачем? Потому что запускать A/B тест на реальных пользователях с сырым агентом - это профессиональное самоубийство. Офлайн-оценка дает вам цифры. Не "вроде работает", а конкретные метрики: на 87% запросов агент выбирает правильный инструмент, заполнение параметров стабильно на 92%, задержка не превышает 2.3 секунды.

В 2026 году это уже не опционально. Это обязательный этап пайплайна ML-инженерии для любого серьезного продукта на основе LLM.

💡
В статье "Тестируем недетерминированные LLM" мы разбирали основы. Сейчас пойдем глубже - на уровень системы из нескольких агентов.

Из чего строится фреймворк

Хороший фреймворк офлайн-оценки для LLM-агентов состоит из четырех взаимосвязанных компонентов. Если пропустить один - вся конструкция рухнет.

КомпонентЧто делаетКритичность
Контролируемая среда выполненияЗапускает агентов в изоляции, подменяет внешние API, логирует все шагиВысокая. Без этого вы тестируете не агента, а весь интернет.
Эталонный датасетСодержит входные запросы и "правильные" последовательности действий агентовМаксимальная. Мусор на входе - мусор на выходе.
Набор метрикИзмеряет не только правильность, но и стабильность, стоимость, скоростьВысокая. Одна метрика - слепота.
Аналитический движокАгрегирует результаты, находит паттерны ошибок, генерирует отчетыСредняя. Без него вы утонете в данных.

Звучит сложно? Это потому, что так и есть. Тестирование многоагентных систем сложнее тестирования одного LLM в разы. Но деваться некуда - либо вы строите этот фреймворк, либо ваш агент в продакшене ведет себя как пьяный сотрудник.

1Собираем датасет, который не стыдно показать

Первая ошибка - использовать 10-20 примеров из головы. Вторая - скрестить руки и сказать "нужны тысячи размеченных данных". Истина посередине.

Для старта хватит 100-200 разнообразных сценариев. Но разнообразие - ключевое слово. Если ваш агент бронирует столики, нужны не только "забронируй на двоих на 19:00", но и "мой кот хочет поужинать в вашем ресторане, что посоветуете?", и "отмени бронь номер 54812", и запросы с пропущенными параметрами, и с противоречивыми инструкциями.

Как получить эти данные? Три пути:

  • Синтетика: Генерация с помощью другой LLM (например, GPT-4.5 Turbo, актуальной на март 2026). Да, вы используете одну модель для тестирования другой. Это нормально, если валидировать результаты.
  • Пользовательские логи: Берите реальные запросы из логов (если есть). Очищайте от персональных данных. Размечайте вручную или полуавтоматически.
  • Краудсорсинг: Сервисы вроде Scale AI или Appen. Дорого, но качественно.
💡
Для разметки "правильного" поведения агента используйте стандартные промпты-шаблоны. Это сократит время и повысит консистентность.

Формат датасета? JSON Lines (.jsonl). Каждая строка - объект с полями: уникальный id, входной запрос, ожидаемая последовательность вызовов инструментов (или конечный ответ), метаданные (сложность, категория).

{
  "id": "booking_042",
  "query": "Перенеси мою бронь с сегодня 20:00 на завтра 19:30",
  "expected_actions": [
    {"tool": "find_reservation", "args": {"date": "2026-03-24", "time": "20:00"}},
    {"tool": "update_reservation", "args": {"new_date": "2026-03-25", "new_time": "19:30"}}
  ],
  "metadata": {"category": "update", "complexity": "medium"}
}

2Строим контролируемую песочницу

Ваши агенты вызывают внешние API? Работают с базой данных? Отправляют письма? В офлайн-режиме все это должно быть заглушено (mocked).

Цель: полная детерминированность окружения. Вызов инструмента send_email(to, body) не должен реально отправлять письмо, а должен возвращать заранее заданный ответ ("ok", "error") и записывать факт вызова в лог.

Реализация на Python с помощью паттерна Dependency Injection:

from abc import ABC, abstractmethod
from typing import Any, Dict

class ToolMock(ABC):
    """Абстрактная заглушка для инструмента агента."""
    @abstractmethod
    def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
        pass

class EmailToolMock(ToolMock):
    def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
        # Логируем вызов для последующего анализа
        ExecutionLogger.log_tool_call("send_email", args)
        # Всегда возвращаем успех в тестах
        return {"status": "sent", "message_id": "mock_123"}

# Внедряем заглушку в агента
agent.email_tool = EmailToolMock()
# Теперь агент работает в изоляции

Песочница также должна контролировать случайность (randomness) в самих LLM. Установите seed для генератора случайных чисел в начале каждого теста. Для облачных моделей типа OpenAI API используйте параметр seed в запросе (поддерживается в GPT-4.5 Turbo и новее). Это не сделает ответы полностью идентичными, но значительно снизит вариативность.

Предупреждение: Даже с установленным seed ответы LLM могут отличаться между прогонами, особенно при изменении температуры (temperature). Для оценки стабильности запускайте каждый тестовый сценарий несколько раз (например, 5) и смотрите на распределение результатов. Один прогон - статистически ничто.

3Выбираем метрики, которые имеют смысл

Accuracy (точность) для LLM-агентов - почти бессмысленная метрика. Вместо нее используйте набор специализированных метрик, каждая из которых отвечает на конкретный вопрос.

МетрикаЧто измеряетКак считать
Success RateДоля сценариев, где агент выполнил задачу полностью и правильноСравнение итогового состояния системы с ожидаемым
Tool Selection AccuracyНасколько часто выбирается правильный инструментF1-score по названиям вызванных инструментов
Argument FidelityТочность заполнения параметров инструментовCosine similarity или точное совпадение ключевых значений
Stability ScoreКонсистентность результатов при многократном запускеДоля сценариев, где результат не менялся в N запусках
Cost per TaskСредняя стоимость выполнения одного сценария (в токенах или деньгах)Сумма токенов вход/выход по всем вызовам моделей
Latency 95th percentileВремя выполнения для 95% самых быстрых сценариевЗамер от начала запроса до финального ответа

Для подсчета метрик вроде Success Rate часто используют LLM-судью - еще одну модель, которая оценивает, выполнил ли агент задачу. В 2026 году для этого есть специализированные модели с улучшенным критическим мышлением, такие как Claude 3.7 Sonnet или специально дообученные версии Llama-4. Но будьте осторожны: судья тоже может ошибаться. Всегда делайте выборочную проверку человеком.

💡
Подробнее о метриках и пайплайнах автоматической оценки читайте в нашем руководстве "LLM-судья".

4Автоматизируем прогон и анализ

Ручной запуск 200 тестов по 5 раз каждый - это ад. Нужен скрипт или система, которая делает все сама.

Базовый пайплайн на Python с использованием асинхронности для скорости:

import asyncio
import json
from typing import List
from your_agent_module import MultiAgentSystem
from sandbox import MockEnvironment

async def run_evaluation_pipeline(dataset_path: str, num_runs: int = 5):
    """Запускает оценку агента на датасете."""
    # Загрузка датасета
    with open(dataset_path, 'r') as f:
        scenarios = [json.loads(line) for line in f]
    
    results = []
    
    for scenario in scenarios:
        scenario_results = []
        for run_id in range(num_runs):
            # Создаем свежую песочницу для каждого запуска
            env = MockEnvironment(seed=run_id)
            agent = MultiAgentSystem(environment=env)
            
            # Запускаем агента
            start_time = asyncio.get_event_loop().time()
            agent_actions = await agent.run(scenario['query'])
            end_time = asyncio.get_event_loop().time()
            
            # Собираем результаты
            run_result = {
                'scenario_id': scenario['id'],
                'run_id': run_id,
                'actions': agent_actions,
                'latency': end_time - start_time,
                'tokens_used': env.get_token_count()
            }
            scenario_results.append(run_result)
        results.append(scenario_results)
    
    # Анализ и вывод отчета
    analyze_and_report(results, scenarios)
    return results

После прогона вы получаете гору данных. Не сваливайте все в CSV. Используйте инструменты вроде Weights & Biases, MLflow или даже простой Jupyter Notebook с Plotly для визуализации.

Что смотреть в первую очередь:

  • Корреляция ошибок со сложностью сценария: Агент стабильно падает на запросах с отрицанием? Значит, нужно доработать понимание логики.
  • Распределение задержек: Есть выбросы? Возможно, какой-то инструмент работает нестабильно.
  • Стоимость самых дорогих сценариев: Может, для простых запросов агент делает лишние вызовы LLM?

Ошибки, которые сломают вашу оценку

Я видел десятки попыток. Почти все проваливаются на одних и тех же граблях.

Ошибка 1: Тестирование в реалистичных, но неконтролируемых условиях. Вы подключаете агента к реальной тестовой базе данных. База падает - все тесты красные. Вы чините базу, но это уже не оценка агента, а оценка инфраструктуры. Заглушки. Всегда заглушки.

Ошибка 2: Игнорирование стоимости. Ваш агент решает задачу с успешностью 99%, но тратит на один запрос $0.50 из-за вызовов GPT-4.5 Turbo с огромным контекстом. В продакшене это сожжет бюджет за неделю. Считайте токены с первого дня.

Ошибка 3: Одна метрика для всех. У вас есть сценарии "простой поиск" и "сложный анализ с рассуждениями". Усредненный success rate скроет, что на сложных сценариях агент проваливается в 40% случаев. Сегментируйте результаты по категориям сложности.

Ошибка 4: Отсутствие базы знаний об ошибках. Каждый провальный тест - это золотая жила. Не просто фиксируйте "failed", а сохраняйте полную цепочку рассуждений агента, вызовы инструментов, промежуточные состояния. Это даст материал для дообучения или настройки промптов.

Что в итоге? Цифры, а не ощущения

Готовность к продакшену - это не субъективное "я думаю, он готов". Это выполнение пороговых значений по ключевым метрикам.

Установите минимальные барьеры для своей системы. Например:

  • Success Rate ≥ 95% для простых сценариев, ≥ 80% для сложных.
  • Stability Score ≥ 90% (в 9 из 10 запусков результат одинаковый).
  • Средняя задержка ≤ 3 секунды.
  • Стоимость 95-го перцентиля ≤ $0.10 за запрос.

Если ваша система проходит по всем пунктам на офлайн-датасете - у вас есть основание для cautious релиза в прод с мониторингом. Если нет - возвращайтесь к доработке промптов, архитектуры агентов или выбору моделей.

Самый неочевидный совет? Планируйте, что ваш фреймворк офлайн-оценки будет живым. Новые типы запросов появятся уже после релиза. Добавляйте их в датасет, прогоняйте оценку заново. Это не разовая акция перед запуском, а постоянный процесс, который держит ваших агентов в тонусе.

К 2026 году инструменты для такой оценки стали доступнее. Смотрите в сторону open-source решений вроде глубоко развитого к 2026 году DeepEval или коммерческих платформ типа Weights & Biases для LLM-опс. Но фреймворк, заточенный под вашу специфику, вы построите только сами. Начинайте сегодня, и ваш завтрашний продакшен-релиз не превратится в ночной кошмар поддержки.

Подписаться на канал