Documentação oficial desta página · v0.20.6
Formato de trajetória
Formato de trajetória
O Hermes Agent salva as trajetórias de conversa em formato JSONL compatível com ShareGPT, para uso como dado de treinamento, artefato de depuração e conjunto de dados de aprendizado por reforço.
Arquivos-fonte: agent/trajectory.py, run_agent.py (procure por _save_trajectory),
batch_runner.py
Convenção de nomes de arquivo
As trajetórias são escritas em arquivos no diretório de trabalho atual:
| Arquivo | Quando |
|---|---|
trajectory_samples.jsonl | Conversas que terminaram com sucesso (completed=True) |
failed_trajectories.jsonl | Conversas que falharam ou foram interrompidas (completed=False) |
O executor em lote (batch_runner.py) escreve em um arquivo de saída próprio por lote (por exemplo,
batch_001_output.jsonl), com campos de metadados a mais.
Você pode trocar o nome do arquivo pelo parâmetro filename de save_trajectory().
Formato de entrada JSONL
Cada linha do arquivo é um objeto JSON autocontido. Existem duas variantes:
Formato da CLI/interativo (de _save_trajectory)
{### Formato do executor em lote (de `batch_runner.py`) {#batch-runner-format-from-batchrunnerpy}laude-sonnet-4.6",
"completed": true
}
Formato do executor em lote (de 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
}
}
Os dicionários tool_stats e tool_error_counts são normalizados para incluir TODAS as ferramentas
possíveis (a partir de model_tools.TOOL_TO_TOOLSET_MAP), com zero como padrão, garantindo um
esquema consistente entre as entradas na hora de carregar o conjunto de dados no HuggingFace.
O array conversations (formato ShareGPT)
O array conversations usa as convenções de papel do ShareGPT:
| Papel na API | from do ShareGPT |
|---|---|
| system | "system" |
| user | "human" |
| assistant | "gpt" |
| tool | "tool" |
Exemplo completo
{
"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": "Qual versão do Python está instalada?"
},
{
"from": "gpt",
"value": "<think>\nO usuário quer saber a versão do Python. Eu devo rodar 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>\nPeguei a versão. Agora posso responder ao usuário.\n</think>\nO Python 3.11.6 está instalado neste sistema."
}
],
"timestamp": "2026-03-30T14:22:31.456789",
"model": "anthropic/claude-sonnet-4.6",
"completed": true
}
Regras de normalização
Marcação do conteúdo de raciocínio
O conversor de trajetória normaliza TODO raciocínio para tags <think>, não importa como o modelo
o produziu originalmente:
-
Tokens de pensamento nativos (campo
msg["reasoning"], de provedores como Anthropic e a série o da OpenAI): envolvidos como<think>\n{reasoning}\n</think>\ne colocados antes do conteúdo. -
XML REASONING_SCRATCHPAD (quando o pensamento nativo está desligado e o modelo raciocina por XML instruído no prompt de sistema): as tags
<REASONING_SCRATCHPAD>são convertidas em<think>porconvert_scratchpad_to_think(). -
Blocos think vazios: todo turno
gpttem garantidamente um bloco<think>. Se nenhum raciocínio foi produzido, um bloco vazio é inserido:<think>\n</think>\n— isso garante formato consistente para dado de treinamento.
Normalização das chamadas de ferramenta
As chamadas de ferramenta do formato da API (com tool_call_id, nome da função e argumentos como
string JSON) são convertidas em JSON envolvido por XML:
<tool_call>
{"name": "terminal", "arguments": {"command": "ls -la"}}
</tool_call>
- Os argumentos são convertidos de string JSON de volta para objetos (sem codificação dupla)
- Se a leitura do JSON falhar (não deveria acontecer — é validado durante a conversa), um
{}vazio é usado e um aviso vai para o log - Várias chamadas de ferramenta em um mesmo turno de assistant produzem vários blocos
<tool_call>em uma única mensagemgpt
Normalização das respostas de ferramenta
Todos os resultados de ferramenta que vêm depois de uma mensagem de assistant são agrupados em um
único turno tool, com respostas em JSON envolvido por XML:
<tool_response>
{"tool_call_id": "call_abc123", "name": "terminal", "content": "saída aqui"}
</tool_response>
- Se o conteúdo da ferramenta parece JSON (começa com
{ou[), ele é interpretado, de modo que o campo de conteúdo carrega um objeto/array JSON em vez de uma string - Vários resultados de ferramenta são juntados com quebras de linha em uma única mensagem
- O nome da ferramenta é casado por posição com o array
tool_callsda mensagem de assistant pai
Mensagem de sistema
A mensagem de sistema é gerada na hora de salvar (não é tirada da conversa). Ela segue o modelo de prompt de chamada de função do Hermes, com:
- Preâmbulo explicando o protocolo de chamada de função
- Bloco XML
<tools>com as definições JSON das ferramentas - Referência de esquema para objetos
FunctionCall - Exemplo de
<tool_call>
As definições de ferramenta incluem name, description, parameters e required (definido como
null, para bater com o formato canônico).
Carregar trajetórias
Trajetórias são JSONL padrão — carregue com qualquer leitor de JSON por linhas:
import json
def load_trajectories(path: str):
"""Carrega as entradas de trajetória de um arquivo 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
# Filtra só as conclusões bem-sucedidas
successful = [e for e in load_trajectories("trajectory_samples.jsonl")
if e.get("completed")]
# Extrai só as conversas, para treinamento
training_data = [e["conversations"] for e in successful]
Carregar para os Datasets do HuggingFace
from datasets import load_dataset
ds = load_dataset("json", data_files="trajectory_samples.jsonl")
O esquema normalizado de tool_stats garante que todas as entradas tenham as mesmas colunas,
evitando erros de descompasso de esquema Arrow ao carregar o conjunto de dados.
Controlar o salvamento de trajetórias
Salvar trajetória é uma chave do run_agent.py / do nível de biblioteca — a CLI hermes não expõe
chave de configuração nem opção para isso:
python run_agent.py --save_trajectories --query='sua pergunta aqui'
Ou de forma programática: AIAgent(..., save_trajectories=True) /
initialize_agent(..., save_trajectories=True). Quando está ligado, o método _save_trajectory()
é chamado ao fim de cada turno de conversa.
O executor em lote sempre salva trajetórias (esse é o propósito principal dele).
Amostras com zero raciocínio em todos os turnos são descartadas automaticamente pelo executor em lote, para não poluir o dado de treinamento com exemplos sem raciocínio.