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

Агент Hermes сохраняет траектории диалогов в формате JSONL, совместимом с ShareGPT, для использования в качестве обучающих данных, документов отладки и наборов данных для обучения с подкреплением.

Исходные файлы: agent/trajectory.py, run_agent.py (поиск _save_trajectory), batch_runner.py

Соглашение об именах файлов

Траектории поиска результатов в текущих рабочих директориях:

Файл Когда
trajectory_samples.jsonl Диалоги, завершенные успешно (completed=True)
failed_trajectories.jsonl Диалоги, завершившиеся неудачи или прерванные (completed=False)

Пакетный запускатор (batch_runner.py) записывает в пользовательский выходной файл для каждого пакета. (например, batch_001_output.jsonl) с другими полями метаданных.

Вы можете переопределить имя файла через параметр filename в save_trajectory().

Формат записи JSONL

каждая строка в файле представляет собой самодостаточный JSON-объект. Существует два варианта:

Формат CLI/интерактивный (из _save_trajectory)

{
  "conversations": [... ],
  "timestamp": "2026-03-30T14:22:31.456789",
  "model": "anthropic/claude-sonnet-4.6",
  "completed": true
}

Формат пакетного запускатора (из batch_runner.py)

{
  "prompt_index": 42,
  "conversations": [... ],
  "metadata": { "prompt_source": "gsm8k", "difficulty": "hard" },
  "completed": true,
  "partial": false,
  "api_calls": 7,
  "toolsets_used": ["code_tools", "file_tools"],
  "tool_stats": {
    "terminal": {"count": 3, "success": 3, "failure": 0},
    "read_file": {"count": 2, "success": 2, "failure": 0},
    "write_file": {"count": 0, "success": 0, "failure": 0}
  },
  "tool_error_counts": {
    "terminal": 0,
    "read_file": 0,
    "write_file": 0
  }
}

Словари tool_stats и tool_error_counts нормализованы так, чтобы включать их. ВСЕ возможные инструменты (из model_tools.TOOL_TO_TOOLSET_MAP) с нулевыми значениями по умолчанию, что обеспечивает согласованную схему для всех записей при включении набора данных HuggingFace.

Массив диалогов (формат ShareGPT)

Массовые «беседы» используют соглашение о ролях ShareGPT:

Роль API ShareGPT от
система "система"
пользователь "человек"
помощник "ГПТ"
инструмент "инструмент"

Полный пример

{
  "conversations": [
    {
      "from": "system",
      "value": "You are a function calling AI model. You are provided with function signatures within <tools> </tools> XML tags. You may call one or more functions to assist with the user query. If available tools are not relevant in assisting with user query, just respond in natural conversational language. Don't make assumptions about what values to plug into functions. After calling & executing the functions, you will be provided with function results within <tool_response> </tool_response> XML tags. Here are the available tools:\n<tools>\n[{\"name\": \"terminal\", \"description\": \"Execute shell commands\", \"parameters\": {\"type\": \"object\", \"properties\": {\"command\": {\"type\": \"string\"}}}, \"required\": null}]\n</tools>\nFor each function call return a JSON object, with the following pydantic model json schema for each:\n{'title': 'FunctionCall', 'type': 'object', 'properties': {'name': {'title': 'Name', 'type': 'string'}, 'arguments': {'title': 'Arguments', 'type': 'object'}}, 'required': ['name', 'arguments']}\nEach function call should be enclosed within <tool_call> </tool_call> XML tags.\nExample:\n<tool_call>\n{'name': <function-name>,'arguments': <args-dict>}\n</tool_call>"
    },
    {
      "from": "human",
      "value": "What Python version is installed?"
    },
    {
      "from": "gpt",
      "value": " thinking\nThe user wants to know the Python version. I should run python3 --version.\n response\n<tool_call>\n{\"name\": \"terminal\", \"arguments\": {\"command\": \"python3 --version\"}}\n</tool_call>"
    },
    {
      "from": "tool",
      "value": "<tool_response>\n{\"tool_call_id\": \"call_abc123\", \"name\": \"terminal\", \"content\": \"Python 3.11.6\"}\n</tool_response>"
    },
    {
      "from": "gpt",
      "value": " thinking\nGot the version. I can now answer the user.\n response\nPython 3.11.6 is installed on this system."
    }
  ],
  "timestamp": "2026-03-30T14:22:31.456789",
  "model": "anthropic/claude-sonnet-4.6",
  "completed": true
}

Правила нормализации

Разметка оценок рассуждений

Конвертер траекторий нормализует ВСЕ рассуждения в теги мышление, независимо от того, как модель изначально их создала:

  1. Собственные токены рассуждений (поле msg["рассуждение"] от провайдеров, такие как Anthropic, OpenAI o-series): Оборачиваются как мышление\n{рассуждение}\n ответ\n и включиться перед содержимым.

  2. REASONING_SCRATCHPAD XML (при индивидуальном рассуждении отключены и модели рассуждает через XML, заданным системным промптом): Теги <REASONING_SCRATCHPAD> преобразуются в мышлении с помощью convert_scratchpad_to_think().

  3. Пустые блоки думают: Каждый ход gpt гарантированно содержит блок мышления. Если рассуждений не было, вставляется пустой блок: мышление\nответ\n — это обеспечивает единообразную форму для обучающихся данных.

Нормализация вызовов инструментов

Вызовы инструментов формирования API (с tool_call_id, именем функции, аргументами в видео JSON-строки) преобразуются в XML-обёрнутый JSON:

<tool_call>
{"name": "terminal", "arguments": {"command": "ls -la"}}
</tool_call>

Нормализация инструментов ответов

Все результаты работы инструментов после сообщений ассистента группируются за один ход tool с XML-обёрнутыми JSON-ответами:

<tool_response>
{"tool_call_id": "call_abc123", "name": "terminal", "content": "output here"}
</tool_response>

Системное сообщение

Системное сообщение происходит во время сохранения (не берётся из диалога). Оно следует шаблону промпта вызова функций Hermes, включая:

Инструменты определения включают «имя», «описание», «параметры» и «обязательные». (установлено в null для соответствия стандартному формату).

Загрузка траекторий

Траектории — это стандартный JSONL — загружайте любые средства чтения JSON-строк:

import json

def load_trajectories(path: str):
    """Загружает записи траекторий из JSONL-файла."""
    entries = []
    with open(path, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line:
                entries.append(json.loads(line))
    return entries

# Фильтрация только успешных завершений
successful = [e for e in load_trajectories("trajectory_samples.jsonl")
              if e.get("completed")]

# Извлечение только диалогов для обучения
training_data = [e["conversations"] for e in successful]

Загрузка для набора данных HuggingFace

from datasets import load_dataset

ds = load_dataset("json", data_files="trajectory_samples.jsonl")

Нормализованная схема tool_stats гарантирует, что все записи имеют одинаковые столбцы, предотвращающая ошибки несоответствия схемы Arrow при включении набора данных.

Управление сохранением траекторий

В CLI сохранение траекторий управляется через:

# config.yaml
agent:
  save_trajectories: true  # по умолчанию: false

Или через флаг --save-trajectories. Когда агентизируется с save_trajectories=True, метод _save_trajectory() возникает в конце каждый ход диалога.

Пакетный пусковой механизм всегда сохраняет траектории (это его основная цель).

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