Окружения, бенчмарки и генерация данных

Hermes Agent включает в себя полноценный каркас окружений, который включает в себя его возможности инструментов с фреймворком RL-обучения Atropos. Это позволяет реализовать три рабочих процесса:

  1. RL-обучение — обучение языковых моделей на многих клиентских агентских задачах с помощью GRPO.
  2. Бенчмарки — оценка моделей на стандартизированных агентских бенчмарках.
  3. Генерация данных — создание SFT-обучающих данных из развёртывания агента.

Все три основаны на одном и том же: класс окружения, который определяет задачу, запускает цикл агента и измеряет результат.:::информация Окружения репозитория vs инструменты RL-обучения Фреймворк окружения на Python, описанный здесь, находится в каталоге environments/, репозиторий и представляет собой реализацию уровня API для руководителей Hermes/Atropos. Он отделён от инструментов rl_*, которые работают как оркестрационный слой для удаленных рабочих процессов RL-обучения.:::

💡 Tip

Быстрые ссылки - Хотите запустить тесты? Переходите к Доступные тесты - Хотите обучаться с RL? См. Инструменты RL-обучения для интерфейса, управляемого агентом, или Запуск окружений для ручного выполнения - Хотите создать новое окружение? См. Создание окружений

Архитектура

Система окружения построек на трехуровневой цепочке наследия:

classDiagram
    class BaseEnv {
      Server management
      Worker scheduling
      Wandb logging
      CLI: serve / process / evaluate
    }

    class HermesAgentBaseEnv {
      Terminal backend configuration
      Tool resolution
      Agent loop engine
      ToolContext access
    }

    class TerminalTestEnv {
      Stack testing
    }

    class HermesSweEnv {
      SWE training
    }

    class TerminalBench2EvalEnv {
      Benchmark evaluation
    }

    class TBLiteEvalEnv {
      Fast benchmark
    }

    class YCBenchEvalEnv {
      Long-horizon benchmark
    }

    BaseEnv <|-- HermesAgentBaseEnv
    HermesAgentBaseEnv <|-- TerminalTestEnv
    HermesAgentBaseEnv <|-- HermesSweEnv
    HermesAgentBaseEnv <|-- TerminalBench2EvalEnv
    TerminalBench2EvalEnv <|-- TBLiteEvalEnv
    TerminalBench2EvalEnv <|-- YCBenchEvalEnv

BaseEnv (Атропос)

Основа из атропослиб. Предоставляет: - Управление сервером — подключение к API, совместимым с OpenAI (VLLM, SGLang, OpenRouter) - Планирование рабочих процессов — координация параллельных разворотов. - Интеграция с Wandb — логирование метрик и визуализация развёртывания - CLI-интерфейс — три подкоманды: «обслуживать», «обрабатывать», «оценивать» - Логирование evalevaluate_log() сохраняет результаты в формате JSON + JSONL.

HermesAgentBaseEnv

Слой hermes-agent (environments/hermes_base_env.py). Добавляет: - Настройка терминального бэкенда — задаёт TERMINAL_ENV для изолированного выполнения (local, Docker, Modal, Daytona, SSH, Singularity) - Разрешение инструментов_resolve_tools_for_group() вызывает get_tool_definitions() из hermes-agent для соответствующих инструментов схем в зависимости от включенных/отключенных наборов инструментов - Цикл интеграции агентаcollect_trajectory() запускает HermesAgentLoop и оценивает результат - Двухфазная операция — Фаза 1 (сервер OpenAI) для eval/SFT, Фаза 2 (VLLM ManagedServer) для качественного RL с logprobs - Патчи для асинхронной безопасности — мои патчи бэкенда Модальный для работы внутри цикла событий Atropos

Конкретные окружения

Окружение тела наследуется от HermesAgentBaseEnv и реализуется пятью методами:

Метод Назначение
настройка() Загрузка набора данных, инициализация состояния
get_next_item() Возвращает следующий элемент для развёртывания
format_prompt(элемент) Преобразует элемент в сообщение пользователя
compute_reward(предмет, результат, ctx) Оценивает развёртывание (0,0–1,0)
оценить() Логика периодической оценки

Основные компоненты

Цикл агента

HermesAgentLoop (environments/agent_loop.py) — это многократно повторяющийся многопользовательский движок-агента. Он выполняет тот же шаблон вызова инструментов, что и основной цикл hermes-agent:

  1. Отправляет сообщения + схемы инструментов в API через server.chat_completion()
  2. Если ответ содержит tool_calls, каждый отправляется через handle_function_call()
  3. Добавляет инструменты в разговор, возвращается к шагу 1.
  4. Если tool_calls нет, агент завершён

Вызовы инструментов выполняются в пуле потоков (ThreadPoolExecutor(128)), чтобы асинхронные бэкенды (Modal, Docker) не вызывали взаимную блокировку внутри событий цикла Atropos.

Возвращает AgentResult:

@dataclass
class AgentResult:
    messages: List[Dict[str, Any]]       # Полная история разговора
    turns_used: int                       # Количество сделанных LLM-вызовов
    finished_naturally: bool              # True, если модель остановилась сама
    reasoning_per_turn: List[Optional[str]]  # Извлечённое содержимое рассуждений
    tool_errors: List[ToolError]          # Ошибки, возникшие при отправке инструментов
    managed_state: Optional[Dict]         # Состояние VLLM ManagedServer (Фаза 2)

Контекстные инструменты

ToolContext (environments/tool_context.py) обеспечивает функцию вознаграждения прямого доступа к тому же изолированному окружению, модель которого использовалась во время развёртывания. Область максимального task_id обеспечивает сохранение всего состояния (файлы, процессы, вкладки браузера).

async def compute_reward(self, item, result, ctx: ToolContext):
    # Запуск тестов в терминальном изолированном окружении модели
    test = ctx.terminal("pytest -v")
    if test["exit_code"] == 0:
        return 1.0

    # Проверка, был ли создан файл
    content = ctx.read_file("/workspace/solution.py")
    if content.get("content"):
        return 0.5

    # Загрузка файлов для локальной проверки
    ctx.download_file("/remote/output.bin", "/local/output.bin")
    return 0.0

Доступные методы:

Категория Методы
Терминал терминал(команда, тайм-аут)
Файлы read_file(путь), write_file(путь, содержимое), поиск (запрос, путь)
Передача upload_file(), upload_dir(), download_file(), download_dir()
Веб web_search(запрос), web_extract(urls)
Браузер browser_navigate(url), browser_snapshot()
Общее call_tool(name, args) — аварийный люк для любого инструмента hermes-agent
Очистка cleanup() — освобождение всех ресурсов

Парсеры вызовов инструментов

Для Фазы 2 (VLLM ManagedServer) сервер получает необработанный текст без инструментов структурированных вызовов. Парсеры на стороне клиента в environments/tool_call_parsers/ извлекают tool_calls из необработанного результата:

from environments.tool_call_parsers import get_parser

parser = get_parser("hermes")  # или "mistral", "llama3_json", "qwen", "deepseek_v3" и т.д.
content, tool_calls = parser.parse(raw_model_output)

Доступные парсеры: hermes, mistral, llama3_json, llama4_json, qwen, qwen3_coder, deepseek_v3, deepseek_v3_1 (псевдоним deepseek_v31), kimi_k2, longcat, glm45, glm47.

В Фазе 1 (тип сервера OpenAI) парсеры не нужны — сервер обрабатывает инструменты синтаксического анализа вызовов изначально.

Доступные бенчмарки

ТерминалBench2

89 сложных терминальных задач с изолированными Docker-окружениями для каждой задачи.

Что тестирует Способность к выполнению одношаговых задач по программированию/администрированию
Оценка Бинарный проход/непроход (проверка набора тестов)
Изоляция Облачные изолированные окружения Модальные (Docker-образы для каждой задачи)
Инструменты терминал + файл
Задачи 89 задач по различным категориям
Стоимость ~$50–200 за полную оценку (параллельное выполнение)
Время ~2–4 часа
python environments/benchmarks/terminalbench_2/terminalbench2_env.py evaluate \
    --config environments/benchmarks/terminalbench_2/default.yaml

# Запуск конкретных задач
python environments/benchmarks/terminalbench_2/terminalbench2_env.py evaluate \
    --config environments/benchmarks/terminalbench_2/default.yaml \
    --env.task_filter fix-git,git-multibranch

Набор данных: NousResearch/terminal-bench-2 на HuggingFace.

TBLite (OpenThoughts Terminal Bench Lite)

100 задач с калиброванной сложностью — более быстрый прокси для TerminalBench2.

Что тестирует То же, что и TB2 (программирование/администрирование), калиброванные уровни сложности
Оценка Бинарный проход/непроход
Изоляция Облачные изолированные окружения Модальный
Инструменты терминал + файл
Задачи 100 задач: Лёгкие (40), Средние (26), Сложные (26), Экстремальные (8)
Корреляция r=0,911 с полным TB2
Скорость В 2,6–8 раз быстрее TB2
python environments/benchmarks/tblite/tblite_env.py evaluate \
    --config environments/benchmarks/tblite/default.yaml

TBLite — тонкий подкласс TerminalBench2 — учитывает только набор данных и тайм-ауты. Создано командой OpenThoughts Agent (Snorkel AI + Bespoke Labs). Набор данных: NousResearch/openoughts-tblite.

YC-Скамейка

Стратегический ориентир длительного горизонта — роль агента выполняет генеральный директор AI-стартапа.

Что тестирует Стратегическое согласие на протяжении сотен шагов
Оценка Составная: 0,5 × выживание + 0,5 × нормализованные_средства
Изоляция Локальный терминал (Модальный режим не требуется)
Инструменты Только терминал
Запуски 9 по умолчанию (3 пресета × 3 сида), последовательно
Стоимость ~$50–200 за полную оценку
Время ~3–6 часов
# Установка yc-bench (опциональная зависимость)
pip install "hermes-agent[yc-bench]"

# Запуск оценки
bash environments/benchmarks/yc_bench/run_eval.sh

# Или напрямую
python environments/benchmarks/yc_bench/yc_bench_env.py evaluate \
    --config environments/benchmarks/yc_bench/default.yaml

# Быстрый тест с одним пресетом
python environments/benchmarks/yc_bench/yc_bench_env.py evaluate \
    --config environments/benchmarks/yc_bench/default.yaml \
    --env.presets '["fast_test"]' --env.seeds '[1]'

YC-Bench использует collinear-ai/yc-bench — детерминированную симуляцию с 4 областями навыков (исследования, выводы, данные по окружающей среде, обучение), формой престижа, управлением сотрудниками и потенциальным испытанием. В отличие от бинарной оценки по задаче в TB2, измерения YC-Bench позволяют агенту поддерживать согласованную реакцию на протяжении всех сотен взаимозависимых решений.

Обучающие окружения

ТерминалТестЭнв

Минимальное самодостаточное окружение с различными задачами (без внешнего набора данных). Используется для сквозной проверки полного стека. каждая задача требует от модели создать файл известным способом; верификатор последних стандартов.

# Режим process (сохраняет развёртывания в JSONL, не требуется сервер обучения)
python environments/terminal_test_env/terminal_test_env.py process \
    --env.data_path_to_save_groups terminal_test_output.jsonl

# Режим serve (подключается к API Atropos для RL-обучения)
python environments/terminal_test_env/terminal_test_env.py serve

HermesSweEnv

Обучающее окружение в стиле SWE-bench. Модель получает задание по программированию, использованию терминальных, файловых и веб-инструментов для решения ее, функция вознаграждения за запуск тестов в том же изолированном модальном режиме.

python environments/hermes_swe_env/hermes_swe_env.py serve \
    --openai.model_name ВашаМодель \
    --env.dataset_name bigcode/humanevalpack \
    --env.terminal_backend modal

Запуск окружения

Каждое окружение — это автономный Python-скрипт с ситуациями CLI-подкомандами:

evaluate — Запуск бенчмарка

Для окружений, предназначенных только для оценки (бенчмарки). Запускает все элементы, вычисляет метрики, логирует в wandb.

python environments/benchmarks/tblite/tblite_env.py evaluate \
    --config environments/benchmarks/tblite/default.yaml \
    --openai.model_name anthropic/claude-sonnet-4.6

Не требуется обучающий сервер или «run-api». Окружение обрабатывает всё самостоятельно.

process — Генерация SFT-данных

Запускает развёртывания и сохраняет оценённые траектории в JSONL. Полезно для создания обучающих данных без полного RL-цикла.

python environments/terminal_test_env/terminal_test_env.py process \
    --env.data_path_to_save_groups output.jsonl \
    --openai.model_name anthropic/claude-sonnet-4.6

Формат вывода: собственная строка — это оценённая траектория с полным историческим разговором, вознаграждением и метаданными.

serve — Подключение к Атропос для RL-обучения

Подключает окружение к рабочему серверу API Atropos (run-api). Используется во время живого RL-обучения.

# Терминал 1: Запуск API Atropos
run-api

# Терминал 2: Запуск окружения
python environments/hermes_swe_env/hermes_swe_env.py serve \
    --openai.model_name ВашаМодель

Окружение получает элементы от Атропоса, запускает агенты развёртывания, получает вознаграждение и отправляет оценённые траектории обратно для обучения.

Двухфазная операция

Фаза 1: Сервер OpenAI (Eval/SFT)

Использует server.chat_completion() с параметром tools=. Сервер (VLLM, SGLang, OpenRouter, OpenAI) обрабатывает инструменты синтаксического анализа вызовов изначально. Возвращает объекты ChatCompletion со структурированнымиtool_calls.

Фаза 2: VLLM ManagedServer (Полное RL)

Использует ManagedServer для точных идентификаторов токенов + logprobs через /generate. Парсер вызовов инструментов на стороне клиента организует структурированные tool_calls из необработанного результата.

Создание окружений

Обучающее окружение

from environments.hermes_base_env import HermesAgentBaseEnv, HermesAgentEnvConfig
from atroposlib.envs.server_handling.server_manager import APIServerConfig

class MyEnvConfig(HermesAgentEnvConfig):
    my_custom_field: str = "default_value"

class MyEnv(HermesAgentBaseEnv):
    name = "my-env"
    env_config_cls = MyEnvConfig

    @classmethod
    def config_init(cls):
        env_config = MyEnvConfig(
            enabled_toolsets=["terminal", "file"],
            terminal_backend="modal",
            max_agent_turns=30,
        )
        server_configs = [APIServerConfig(
            base_url="https://openrouter.ai/api/v1",
            model_name="anthropic/claude-sonnet-4.6",
            server_type="openai",
        )]
        return env_config, server_configs

    async def setup(self):
        from datasets import load_dataset
        self.dataset = list(load_dataset("my-dataset", split="train"))
        self.iter = 0

    async def get_next_item(self):
        item = self.dataset[self.iter % len(self.dataset)]
        self.iter += 1
        return item

    def format_prompt(self, item):
        return item["instruction"]

    async def compute_reward(self, item, result, ctx):
        # ctx предоставляет полный доступ к инструментам изолированного окружения развёртывания
        test = ctx.terminal("pytest -v")
        return 1.0 if test["exit_code"] == 0 else 0.0

    async def evaluate(self, *args, **kwargs):
        # Периодическая оценка во время обучения
        pass

if __name__ == "__main__":
    MyEnv.cli()

Бенчмарк только для оценок

Для бенчмарков следуйте шаблону, используемому в TerminalBench2, TBLite и YC-Bench:

  1. Создайте в environments/benchmarks/ваш-бенчмарк/
  2. Настроить конфигурацию только для eval: eval_handling=STOP_TRAIN, steps_per_eval=1, total_steps=1
  3. Заглушите методы обучения: collect_trajectories() возвращает (None, []), score() возвращает None
  4. Реализовать rollout_and_score_eval(eval_item) — цикл агента + оценка для каждого элемента
  5. Реализовать evaluate() — управляющий всеми запусками вычисляет агрегированные метрики.
  6. Добавьте потоковый JSONL для сохранения результатов, связанных с боями.
  7. Добавить очистку: обработка KeyboardInterrupt, cleanup_all_environments(), _tool_executor.shutdown()
  8. Запускайте с подкомандой оценить

См. environments/benchmarks/yc_bench/yc_bench_env.py для чистой, хорошо документированной эталонной реализации.

Справочник по конфигурации

Поля HermesAgentEnvConfig

Поле Тип По умолчанию Описание
enabled_toolsets Список[стр] Нет (все) Какие наборы инструментов Hermes включить
disabled_toolsets Список[стр] Нет Наборы инструментов для отключения
распределение ул Нет Имя вероятностного распределения набор инструментов
max_agent_turns интервал 30 Максимальное количество LLM-вызовов для развёртывания
agent_temperature плавать 1.0 Температурный сэмплирования
system_prompt ул Нет Системное сообщение для агента
terminal_backend ул "местный" local, docker, modal, daytona, ssh, singularity
terminal_timeout интервал 120 Секунда на терминале
terminal_lifetime интервал 3600 Максимальное время жизни изолированного окружения
имя_набора_данных ул Нет Идентификатор набора данных HuggingFace
tool_pool_size интервал 128 Размер пула потоков для выполнения инструментов
tool_call_parser ул "Гермес" Парсер для необработанного результата Фазы 2
extra_body Дикт Нет Дополнительные параметры для API OpenAI (например, настройки провайдера OpenRouter)
eval_handling Энум STOP_TRAIN STOP_TRAIN, LIMIT_TRAIN, NONE

Конфигурация YAML

Окружения можно настраивать через YAML-файлы, профессиональные с --config:

env:
  enabled_toolsets: ["terminal", "file"]
  max_agent_turns: 60
  max_token_length: 32000
  agent_temperature: 0.8
  terminal_backend: "modal"
  terminal_timeout: 300
  dataset_name: "NousResearch/terminal-bench-2"
  tokenizer_name: "NousResearch/Hermes-3-Llama-3.1-8B"
  use_wandb: true
  wandb_name: "my-benchmark"

openai:
  base_url: "https://openrouter.ai/api/v1"
  model_name: "anthropic/claude-sonnet-4.6"
  server_type: "openai"
  health_check: false

Значения YAML переопределяют значения по умолчанию в config_init(). Аргументы CLI переопределяют значения YAML:

python my_env.py evaluate \
    --config my_config.yaml \
    --openai.model_name anthropic/claude-opus-4.6  # переопределяет YAML

Предварительные требования

Для всех окружений

Для бенчмарков с модальной изоляцией (TB2, TBLite)

Для YC-скамейки

Для RL-обучения

См. RL-обучение для рабочего процесса RL, управляемого агентом.

Структура каталогов

environments/
├── hermes_base_env.py          # Абстрактный базовый класс (HermesAgentBaseEnv)
├── agent_loop.py               # Многопользовательский движок агента (HermesAgentLoop)
├── tool_context.py             # Доступ к инструментам для функций вознаграждения в развёртывании
├── patches.py                  # Патчи для асинхронной безопасности бэкенда Modal

├── tool_call_parsers/          # Парсеры Фазы 2 на стороне клиента
   ├── hermes_parser.py        # Формат Hermes/ChatML <tool_call>
   ├── mistral_parser.py       # Формат Mistral [TOOL_CALLS]
   ├── llama_parser.py         # Вызов инструментов Llama 3 JSON
   ├── qwen_parser.py          # Формат Qwen
   ├── deepseek_v3_parser.py   # Формат DeepSeek V3
   └──...                     # + kimi_k2, longcat, glm45/47 и т.д.

├── terminal_test_env/          # Проверка стека (встроенные задачи)
├── hermes_swe_env/             # Обучающее окружение SWE-bench

└── benchmarks/                 # Оценочные бенчмарки
    ├── terminalbench_2/        # 89 терминальных задач, изолированные окружения Modal
    ├── tblite/                 # 100 калиброванных задач (быстрый прокси TB2)
    └── yc_bench/               # Стратегический бенчмарк длительного горизонта