軌跡格式
Hermes Agent 以 ShareGPT 兼容的 JSONL 格式保存對話軌跡,用於訓練數據、調試工件以及強化學習數據集。
源文件: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),幷包含額外的元數據字段。
可通過 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_stats 和 tool_error_counts 字典已歸一化,包含所有可能的工具(來自 model_tools.TOOL_TO_TOOLSET_MAP),並以零值作為默認值,確保 HuggingFace 數據集加載時的模式一致性。
對話數組(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_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": "<think>\nThe user wants to know the Python version. I should run python3 --version.\n</think>\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": "<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
}
歸一化規則
推理內容標記
軌跡轉換器將所有推理內容統一歸一化為 <think> 標籤,無論模型原始生成方式如何:
-
原生思考令牌(來自 Anthropic、OpenAI o 系列等 Provider 的
msg["reasoning"]字段):包裹為<think>\n{reasoning}\n</think>\n,並前置到內容之前。 -
REASONING_SCRATCHPAD XML(當禁用原生思考且模型通過 System Prompt 指定的 XML 進行推理時):通過
convert_scratchpad_to_think()將<REASONING_SCRATCHPAD>標籤轉換為<think>。 -
空 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>塊
工具響應歸一化
所有在助手消息之後的工具結果都會合併為單個 tool 輪次,並以 XML 包裹的 JSON 響應形式呈現:
<tool_response>
{"tool_call_id": "call_abc123", "name": "terminal", "content": "output here"}
</tool_response>
- 若工具內容看起來像 JSON(以
{或[開頭),則解析為對象/數組,而非字符串 - 多個工具結果通過換行符連接在一條消息中
- 工具名稱通過與父級助手的
tool_calls數組位置匹配
系統消息
系統消息在保存時生成(而非從對話中獲取)。它遵循 Hermes 函數調用提示模板,包含:
- 說明函數調用協議的前言
- 包含 JSON 工具定義的
<tools>XML 塊 FunctionCall對象的模式引用<tool_call>示例
工具定義包含 name、description、parameters 和 required(設為 null 以匹配標準格式)。
加載軌跡
軌跡為標準 JSONL 格式——可使用任意 JSON 行讀取器加載:
import json
def load_trajectories(path: str):
"""Load trajectory entries from a JSONL file."""
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 # 默認值:假
或通過 --save-trajectories 標誌。當 Agent 初始化時設置 save_trajectories=True,將在每個對話回合結束時調用 _save_trajectory() 方法。
批處理運行器始終保存軌跡(這是其主要目的)。
批處理運行器會自動丟棄所有回合中均無推理內容的樣本,以避免非推理示例汙染訓練數據。