跳到主要内容

轨迹格式

Hermes Agent 轨迹是标准 JSONL 格式(每行一个 JSON 对象),用于训练数据生成和评估。

概述

轨迹数据包含:

  • 完整对话历史 — 带有归一化角色的消息序列
  • 工具调用统计 — 每个工具的成功/失败计数
  • 推理覆盖 — 是否有 <think>
  • 元数据 — 模型、时间戳、批处理信息

轨迹条目格式

每个 JSONL 行是一个完整的轨迹条目:

{
"prompt_index": 0,
"conversations": [
{
"from": "system",
"value": "You are a helpful assistant...."
},
{
"from": "human",
"value": "What is Python?"
},
{
"from": "gpt",
"value": "Python is a programming language...",
"tool_calls": [
{
"name": "terminal",
"arguments": {"command": "python3 --version"}
}
]
},
{
"from": "tool",
"value": "<tool_response>\n{\"tool_call_id\": \"call_abc123\", \"name\": \"terminal\", \"content\": \"Python 3.11.6\"}\n</tool_response>"
},
{
"from": "gpt",
"value": "<think>\nGot the version. I can now answer the user.\n</think>\nPython 3.11.6 is installed on this system."
}
],
"timestamp": "2026-03-30T14:22:31.456789",
"model": "anthropic/claude-sonnet-4.6",
"completed": true
}

字段说明

conversations

对话消息数组,格式为 sharegpt 格式:

字段类型描述
fromstring角色:systemhumangpttool
valuestring消息内容
tool_callsarray(可选)GPT 消息中的工具调用
rolestring(内部)原始角色映射

tool_calls

GPT 消息中的工具调用数组:

{
"name": "terminal",
"arguments": {"command": "ls -la"}
}

tool_stats

工具使用统计(归一化模式):

{
"terminal": {"count": 2, "success": 2, "failure": 0},
"read_file": {"count": 1, "success": 1, "failure": 0},
"web_search": {"count": 0, "success": 0, "failure": 0}
}

所有工具都包含在内,零值默认值确保 HuggingFace datasets 的模式一致性。

归一化规则

推理内容标记

轨迹转换器将所有推理归一化为 <think> 标签,不管模型原始如何生成:

  1. 原生思考 token(来自 Anthropic、OpenAI o 系列等提供者的 msg["reasoning"] 字段):包装为 <think>\n{reasoning}\n</think> 并添加到内容前面。

  2. REASONING_SCRATCHPAD XML(当原生思考被禁用且模型通过系统提示指示的 XML 进行推理时):通过 convert_scratchpad_to_think() 转换为 <think>

  3. 空 think 块:每个 gpt 轮次保证有 <think> 块。如果没有生成推理,则插入空块:<think>\n </think>\n — 这确保了训练数据格式的一致性。

工具调用归一化

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

<tool_call>
{"name": "terminal", "arguments": {"command": "ls -la"}}
</tool_call>
  • 参数从 JSON 字符串解析回对象(不是双重编码)
  • 如果 JSON 解析失败(不应该发生 — 对话中已验证),使用空 {} 并记录警告
  • 一个助手消息中的多个工具调用在一个 gpt 消息中产生多个 <tool_call>

工具响应归一化

跟随助手消息的所有工具结果被分组到一个带有 XML 包装 JSON 响应的单个 tool 轮次中:

<tool_response>
{"tool_call_id": "call_abc123", "name": "terminal", "content": "output here"}
</tool_response>
  • 如果工具内容看起来像 JSON(以 {[ 开头),则解析它以便内容字段包含 JSON 对象/数组而不是字符串
  • 多个工具结果在一个消息中用换行符连接
  • 工具名称通过位置与父助手的 tool_calls 数组匹配

系统消息

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

  • 解释函数调用协议的前导文字
  • 包含 JSON 工具定义的 <tools> XML 块
  • FunctionCall 对象的 schema 引用
  • <tool_call> 示例

工具定义包含 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 Datasets

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() 方法在每个对话轮次结束时调用。

批处理运行器始终保存轨迹(这是它的主要目的)。

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