知识引擎/Hermes 知识引擎/轨迹格式(Trajectory Format)

原文链接:Trajectory Format Hermes Agent 以 ShareGPT 兼容的 JSONL 格式保存对话轨迹(Trajectory),用作训练数据、调试产物和强化学习数据集。 源文件:agent/trajectory.py、run agent.py(搜索 save trajectory)、batc

> 原文链接:Trajectory Format

轨迹格式(Trajectory Format)

Hermes Agent 以 ShareGPT 兼容的 JSONL 格式保存对话轨迹(Trajectory),用作训练数据、调试产物和强化学习数据集。

源文件:agent/trajectory.pyrun_agent.py(搜索 _save_trajectory)、batch_runner.py

文件命名约定

轨迹写入当前工作目录中的文件:

文件时机
trajectory_samples.jsonl成功完成的对话(completed=True
failed_trajectories.jsonl失败或中断的对话(completed=False

批量运行器(batch_runner.py)写入每个批次的自定义输出文件(例如 batch_001_output.jsonl),带有额外的元数据字段。

你可以通过 save_trajectory() 中的 filename 参数覆盖文件名。

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_statstool_error_counts 字典被标准化为包含所有可能的工具(来自 model_tools.TOOL_TO_TOOLSET_MAP),默认为零值,确保各条目之间 Schema 一致,便于 HuggingFace 数据集加载。

conversations 数组(ShareGPT 格式)

conversations 数组使用 ShareGPT 角色约定:

API 角色ShareGPT from
system"system"
user"human"
assistant"gpt"
tool"tool"

完整示例

{
  "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_results> </tool_results> 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_call> </tool_call_call> XML tags.\\nExample:\\n<tool_call_call>\\n{'name': <function-name>,'arguments': <args-dict>}\\n</tool_call_call>\\n"
    },
    {
      "from": "human",
      "value": "What Python version is installed?"
    },
    {
      "from": "gpt",
      "value": "<think_call>\\nThe user wants to know the Python version. I should run python3 --version.\\n</think_call>\\n<tool_call_call>\\n{\\\"name\\\": \\\"terminal\\\", \\\"arguments\\\": {\\\"command\\\": \\\"python3 --version\\\"}}\\n</tool_call_call>"
    },
    {
      "from": "tool",
      "value": "<tool_results>\\n{\\\"tool_call_id\\\": \\\"call_abc123\\\", \\\"name\\\": \\\"terminal\\\", \\\"content\\\": \\\"Python 3.11.6\\\"}\\n</tool_results>"
    },
    {
      "from": "gpt",
      "value": "<think_call>\\nGot the version. I can now answer the user.\\n</think_call>\\nPython 3.11.6 is installed on this system."
    }
  ],
  "timestamp": "2026-03-30T14:22:31.456789",
  "model": "anthropic/claude-sonnet-4.6",
  "completed": true
}

标准化规则

推理内容标记

轨迹转换器将所有推理内容标准化为 &lt;think_call&gt; 标签,无论模型最初如何生成:

  1. 原生思考 token(来自 Anthropic、OpenAI o 系列等 Provider 的 msg["reasoning"] 字段):包装为 &lt;think_call&gt;\n&#123;reasoning&#125;\n&lt;/think_call&gt;\n 并前置到内容之前。

  2. REASONING_SCRATCHPAD XML(当原生思考被禁用且模型通过系统提示词指示的 XML 推理时):&lt;REASONING_SCRATCHPAD&gt; 标签通过 convert_scratchpad_to_think() 转换为 &lt;think_call&gt;

  3. 空思考块:每个 gpt 轮次保证有一个 &lt;think_call&gt; 块。如果没有生成推理内容,则插入一个空块:&lt;think_call&gt;\n&lt;/think_call&gt; — 这确保训练数据格式一致。

工具调用标准化

来自 API 格式的工具调用(带有 tool_call_id、函数名、JSON 字符串参数)被转换为 XML 包装的 JSON:

<tool_call_call>
{"name": "terminal", "arguments": {"command": "ls -la"}}
</tool_call_call>
  • 参数从 JSON 字符串解析回对象(非双重编码)
  • 如果 JSON 解析失败(不应发生 — 对话期间已验证),使用空 &#123;&#125; 并记录警告
  • 一个 Assistant 轮次中的多个工具调用在单个 gpt 消息中生成多个 &lt;tool_call_call&gt;

工具响应标准化

Assistant 消息之后的所有工具结果被分组到一个带有 XML 包装 JSON 响应的 tool 轮次中:

<tool_results>
{"tool_call_id": "call_abc123", "name": "terminal", "content": "output here"}
</tool_results>
  • 如果工具内容看起来像 JSON(以 &#123;[ 开头),它会被解析,使 content 字段包含 JSON 对象/数组而非字符串
  • 多个工具结果在一条消息中用换行符连接
  • 工具名称按位置匹配父级 Assistant 的 tool_calls 数组

系统消息

系统消息在保存时生成(不从对话中获取)。它遵循 Hermes 函数调用提示模板,包含:

  • 解释函数调用协议的前导说明
  • 包含 JSON 工具定义的 &lt;tools&gt; XML 块
  • FunctionCall 对象的 Schema 参考
  • &lt;tool_call_call&gt; 示例

工具定义包括 namedescriptionparametersrequired(设为 null 以匹配规范格式)。

加载轨迹

轨迹是标准 JSONL — 使用任何 JSON Lines 读取器加载:

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 Schema 确保所有条目具有相同的列,防止数据集加载时的 Arrow Schema 不匹配错误。

控制轨迹保存

在 CLI 中,轨迹保存由以下配置控制:

# config.yaml
agent:
  save_trajectories: true  # 默认:false

或通过 --save-trajectories 标志。当 Agent 以 save_trajectories=True 初始化时,_save_trajectory() 方法在每个对话轮次结束时调用。

批量运行器始终保存轨迹(这是其主要目的)。

所有轮次中零推理的样本会被批量运行器自动丢弃,以避免用非推理样本污染训练数据。

Continue Exploring

继续探索

这不是课程式的上一篇下一篇,而是从当前节点向外继续漫游。

开发者指南

架构

本页面是 Hermes Agent 内部结构的顶层地图. 使用它来了解代码库的整体结构,然后深入子系统文档获取实现细节。 如果你是首次接触此代码库: 1. 本页面 — 了解整体结构 2. Agent 循环内部机制 — AIAgent 如何工作 3. 提示词组装 — 系统提示词构建

开发者指南

贡献指南

感谢你对 Hermes Agent 的贡献!本指南涵盖开发环境设置、理解代码库以及如何让你的 PR 被合并。 我们按以下顺序重视贡献: 1. Bug 修复 — 崩溃、不正确行为、数据丢失 2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2 3. 安全加固 — Shell 注入、Prompt 注入、路

开发者指南

Agent 循环内部机制

sidebar position: 3 title: "Agent 循环内部机制" description: "AIAgent 执行、API 模式、工具、回调和回退行为的详细解析" 核心编排引擎是 run agent.py 中的 AIAgent 类——大约 10,700 行代码,负责从 Prompt(提示词)组装到工具

开发者指南

提示词组装

sidebar position: 5 title: "提示词组装" description: "Hermes 如何构建系统提示词、保持缓存稳定性和注入临时层" Hermes 刻意将以下两者分离: - 缓存的系统提示词状态 - 临时的 API 调用时添加内容 这是项目中最关键的设计决策之一,因为它影响:

开发者指南

上下文压缩与缓存

Hermes Agent 使用双重压缩系统和 Anthropic 提示词缓存,在长对话中高效管理上下文窗口的使用。 源文件:agent/context engine.py(ABC)、agent/context compressor.py(默认引擎)、agent/prompt caching.py、gateway/run

开发者指南

网关内部机制

sidebar position: 7 title: "网关内部机制" description: "消息网关如何启动、授权用户、路由会话和投递消息" 消息网关是一个长运行进程,通过统一架构将 Hermes 连接到 14+ 个外部消息平台。 当消息从任何平台到达时: 1. 平台适配器 接收原始事件,将其规范化为 Mess

Developer Guide

开发者指南

面向二次开发者,解释架构、运行时、上下文引擎、插件、工具与扩展机制。

20 篇文档20 个节点

当前节点

轨迹格式(Trajectory Format)

同主题继续探索

架构

本页面是 Hermes Agent 内部结构的顶层地图. 使用它来了解代码库的整体结构,然后深入子系统文档获取实现细节。 如果你是首次接触此代码库: 1. 本页面 — 了解整体结构 2. Agent 循环内部机制 — AIAgent 如何工作 3. 提示词组装 — 系统提示词构建

贡献指南

感谢你对 Hermes Agent 的贡献!本指南涵盖开发环境设置、理解代码库以及如何让你的 PR 被合并。 我们按以下顺序重视贡献: 1. Bug 修复 — 崩溃、不正确行为、数据丢失 2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2 3. 安全加固 — Shell 注入、Prompt 注入、路

Agent 循环内部机制

sidebar position: 3 title: "Agent 循环内部机制" description: "AIAgent 执行、API 模式、工具、回调和回退行为的详细解析" 核心编排引擎是 run agent.py 中的 AIAgent 类——大约 10,700 行代码,负责从 Prompt(提示词)组装到工具

提示词组装

sidebar position: 5 title: "提示词组装" description: "Hermes 如何构建系统提示词、保持缓存稳定性和注入临时层" Hermes 刻意将以下两者分离: - 缓存的系统提示词状态 - 临时的 API 调用时添加内容 这是项目中最关键的设计决策之一,因为它影响:

上下文压缩与缓存

Hermes Agent 使用双重压缩系统和 Anthropic 提示词缓存,在长对话中高效管理上下文窗口的使用。 源文件:agent/context engine.py(ABC)、agent/context compressor.py(默认引擎)、agent/prompt caching.py、gateway/run

网关内部机制

sidebar position: 7 title: "网关内部机制" description: "消息网关如何启动、授权用户、路由会话和投递消息" 消息网关是一个长运行进程,通过统一架构将 Hermes 连接到 14+ 个外部消息平台。 当消息从任何平台到达时: 1. 平台适配器 接收原始事件,将其规范化为 Mess

相关节点

架构

本页面是 Hermes Agent 内部结构的顶层地图. 使用它来了解代码库的整体结构,然后深入子系统文档获取实现细节。 如果你是首次接触此代码库: 1. 本页面 — 了解整体结构 2. Agent 循环内部机制 — AIAgent 如何工作 3. 提示词组装 — 系统提示词构建

贡献指南

感谢你对 Hermes Agent 的贡献!本指南涵盖开发环境设置、理解代码库以及如何让你的 PR 被合并。 我们按以下顺序重视贡献: 1. Bug 修复 — 崩溃、不正确行为、数据丢失 2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2 3. 安全加固 — Shell 注入、Prompt 注入、路

Agent 循环内部机制

sidebar position: 3 title: "Agent 循环内部机制" description: "AIAgent 执行、API 模式、工具、回调和回退行为的详细解析" 核心编排引擎是 run agent.py 中的 AIAgent 类——大约 10,700 行代码,负责从 Prompt(提示词)组装到工具

提示词组装

sidebar position: 5 title: "提示词组装" description: "Hermes 如何构建系统提示词、保持缓存稳定性和注入临时层" Hermes 刻意将以下两者分离: - 缓存的系统提示词状态 - 临时的 API 调用时添加内容 这是项目中最关键的设计决策之一,因为它影响:

上下文压缩与缓存

Hermes Agent 使用双重压缩系统和 Anthropic 提示词缓存,在长对话中高效管理上下文窗口的使用。 源文件:agent/context engine.py(ABC)、agent/context compressor.py(默认引擎)、agent/prompt caching.py、gateway/run

网关内部机制

sidebar position: 7 title: "网关内部机制" description: "消息网关如何启动、授权用户、路由会话和投递消息" 消息网关是一个长运行进程,通过统一架构将 Hermes 连接到 14+ 个外部消息平台。 当消息从任何平台到达时: 1. 平台适配器 接收原始事件,将其规范化为 Mess