Пакетная обработка

Пакетная обработка нужна, чтобы прогнать Hermes Agent сразу через сотни или тысячи промптов параллельно и получить структурированные данные траекторий. Главный сценарий — генерация обучающих данных: на выходе вы получаете траектории в формате ShareGPT со статистикой использования инструментов, которые потом идут на дообучение модели или на оценку её качества.

Обзор

Пакетный раннер (batch_runner.py) берёт JSONL-датасет с промптами и прогоняет каждый из них через полноценную сессию агента с доступом к инструментам. Под каждый промпт выделяется отдельное изолированное окружение. Результат — структурированные данные траектории: полная история диалога, статистика вызовов инструментов и метрики покрытия рассуждениями.

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

# Базовый пакетный прогон
python batch_runner.py \
    --dataset_file=data/prompts.jsonl \
    --batch_size=10 \
    --run_name=my_first_run \
    --model=anthropic/claude-sonnet-4.6 \
    --num_workers=4

# Возобновить прерванный прогон
python batch_runner.py \
    --dataset_file=data/prompts.jsonl \
    --batch_size=10 \
    --run_name=my_first_run \
    --resume

# Показать доступные дистрибуции наборов инструментов
python batch_runner.py --list_distributions
совет
Предсказуемая стоимость при масштабировании

Пакетный прогон поднимает множество параллельных сессий агента, и каждая делает вызовы модели и вызовы инструментов. Подписка на Nous Portal объединяет доступ к моделям с веб-поиском, генерацией изображений, TTS и облачными браузерами в одном счёте — удобно, когда нужна стабильная цена за траекторию и не хочется жонглировать лимитами по пяти разным аккаунтам у вендоров. Настраивается командой hermes setup --portal, после чего в --model указываете модель Nous.

Формат датасета

На вход подаётся JSONL-файл — по одному JSON-объекту на строку. В каждой записи обязательно поле prompt:

{"prompt": "Write a Python function that finds the longest palindromic substring"}
{"prompt": "Create a REST API endpoint for user authentication using Flask"}
{"prompt": "Debug this error: TypeError: cannot unpack non-iterable NoneType object"}

Дополнительно запись может содержать:

  • image или docker_image: образ контейнера для песочницы этого промпта (работает с бэкендами Docker, Modal и Singularity)
  • cwd: переопределение рабочего каталога для терминальной сессии задачи

Параметры конфигурации

ПараметрПо умолчаниюОписание
--dataset_file(обязательный)Путь к JSONL-датасету
--batch_size(обязательный)Количество промптов в пакете
--run_name(обязательный)Имя прогона (используется для каталога вывода и контрольных точек)
--distribution"default"Дистрибуция наборов инструментов, из которой берутся сэмплы
--modelclaude-sonnet-4.6Используемая модель
--base_urlhttps://openrouter.ai/api/v1Базовый URL API
--api_key(переменная окружения)API-ключ для модели
--max_turns10Максимум итераций с вызовом инструментов на один промпт
--num_workers4Число параллельных рабочих процессов
--resumefalseВозобновить с контрольной точки
--verbosefalseВключить подробное логирование
--max_samplesвсеОбработать только первые N сэмплов из датасета

Маршрутизация по провайдерам (OpenRouter)

ПараметрОписание
--providers_allowedРазрешённые провайдеры через запятую (например, "anthropic,openai")
--providers_ignoredИгнорируемые провайдеры через запятую (например, "together,deepinfra")
--providers_orderПредпочтительный порядок провайдеров через запятую
--provider_sortСортировка по "price", "throughput" или "latency"

Управление рассуждениями

ПараметрОписание
--reasoning_effortУровень усилий на рассуждения: none, minimal, low, medium, high, xhigh, max, ultra
--reasoning_disabledПолностью отключить токены рассуждений/размышлений

Дополнительные параметры

ПараметрОписание
--ephemeral_system_promptСистемный промпт, который используется при выполнении, но НЕ сохраняется в траектории
--log_prefix_charsСколько символов показывать в превью логов (по умолчанию: 100)
--prefill_messages_fileПуть к JSON-файлу с предзаполненными сообщениями для few-shot-затравки

Дистрибуции наборов инструментов

Каждому промпту достаётся случайно выбранный набор инструментов из дистрибуции. Так обучающие данные охватывают разные комбинации инструментов. Полный список дистрибуций смотрите через --list_distributions.

В нынешней реализации дистрибуция задаёт вероятность для каждого отдельного набора инструментов. Сэмплер независимо подбрасывает монетку по каждому набору, а затем гарантирует, что хотя бы один набор окажется включён. Это не то же самое, что вручную составленная таблица готовых комбинаций.

Формат вывода

Весь вывод складывается в data/<run_name>/:

data/my_run/
├── trajectories.jsonl    # Объединённый финальный вывод (все пакеты слиты вместе)
├── batch_0.jsonl         # Результаты отдельных пакетов
├── batch_1.jsonl
├── ...
├── checkpoint.json       # Контрольная точка для возобновления
└── statistics.json       # Сводная статистика по использованию инструментов

Формат траектории

Каждая строка в trajectories.jsonl — это JSON-объект:

{
  "prompt_index": 42,
  "conversations": [
    {"from": "human", "value": "Write a function..."},
    {"from": "gpt", "value": "I'll create that function...",
     "tool_calls": [...]},
    {"from": "tool", "value": "..."},
    {"from": "gpt", "value": "Here's the completed function..."}
  ],
  "metadata": {
    "batch_num": 2,
    "timestamp": "2026-01-15T10:30:00",
    "model": "anthropic/claude-sonnet-4.6"
  },
  "completed": true,
  "partial": false,
  "api_calls": 3,
  "toolsets_used": ["terminal", "file"],
  "tool_stats": {
    "terminal": {"count": 2, "success": 2, "failure": 0},
    "read_file": {"count": 1, "success": 1, "failure": 0}
  },
  "tool_error_counts": {
    "terminal": 0,
    "read_file": 0
  }
}

Поле conversations использует формат в духе ShareGPT с полями from и value. Статистика по инструментам нормализуется: туда добавляются все возможные инструменты с нулевыми значениями по умолчанию, чтобы схема была одинаковой во всех записях и совместимой с датасетами HuggingFace.

Контрольные точки

У пакетного раннера надёжный механизм контрольных точек на случай сбоев:

  • Файл контрольной точки: сохраняется после завершения каждого пакета и хранит индексы готовых промптов
  • Возобновление по содержимому: при --resume раннер сканирует существующие файлы пакетов и сопоставляет завершённые промпты по их фактическому текстовому содержимому (а не только по индексам), так что восстановление сработает даже при изменении порядка записей в датасете
  • Неудавшиеся промпты: готовыми помечаются только успешно завершённые промпты — те, что упали, будут повторены при возобновлении
  • Слияние пакетов: по завершении все файлы пакетов (включая прежние прогоны) сливаются в единый trajectories.jsonl

Как работает возобновление

  1. Сканируем все файлы batch_*.jsonl на предмет завершённых промптов (сопоставление по содержимому)
  2. Фильтруем датасет, исключая уже завершённые промпты
  3. Заново разбиваем оставшиеся промпты на пакеты
  4. Обрабатываем только оставшиеся промпты
  5. Сливаем все файлы пакетов (старые + новые) в финальный вывод

Фильтрация по качеству

Пакетный раннер автоматически фильтрует данные по качеству:

  • Фильтр отсутствия рассуждений: сэмплы, где ни в одном ходе ассистента нет рассуждений (нет ни <REASONING_SCRATCHPAD>, ни нативных токенов размышлений), отбрасываются
  • Фильтр повреждённых записей: записи с галлюцинированными именами инструментов (которых нет в списке допустимых) отсеиваются при финальном слиянии
  • Статистика рассуждений: считается доля ходов с рассуждениями и без них по всему прогону

Статистика

По завершении раннер выводит подробную статистику:

  • Использование инструментов: число вызовов, доля успехов и неудач по каждому инструменту
  • Покрытие рассуждениями: доля ходов ассистента, содержащих рассуждения
  • Отброшенные сэмплы: сколько сэмплов отсеяно из-за отсутствия рассуждений
  • Длительность: общее время обработки

Та же статистика сохраняется в statistics.json для программного анализа.

Сценарии использования

Генерация обучающих данных

Получить разнообразные траектории использования инструментов под дообучение:

python batch_runner.py \
    --dataset_file=data/coding_prompts.jsonl \
    --batch_size=20 \
    --run_name=coding_v1 \
    --model=anthropic/claude-sonnet-4.6 \
    --num_workers=8 \
    --distribution=default \
    --max_turns=15

Оценка модели

Проверить, насколько хорошо модель пользуется инструментами на стандартизированном наборе промптов:

python batch_runner.py \
    --dataset_file=data/eval_suite.jsonl \
    --batch_size=10 \
    --run_name=eval_gpt4 \
    --model=openai/gpt-4o \
    --num_workers=4 \
    --max_turns=10

Свой образ контейнера для каждого промпта

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

{"prompt": "Install numpy and compute eigenvalues of a 3x3 matrix", "image": "python:3.11-slim"}
{"prompt": "Compile this Rust program and run it", "image": "rust:1.75"}
{"prompt": "Set up a Node.js Express server", "image": "node:20-alpine", "cwd": "/app"}

Перед запуском каждого промпта пакетный раннер проверяет, что образы Docker доступны.

перевод и редактура:

обновлено

⌕ ESC