八段研读清单
- 115分钟
认清一条轨迹
区分模型决策、工具结果与最终回答,画出原始JSON的数据形状。
产出:用自己的话写出tasks[0]里的四个关键字段。 - 220分钟
找准程序入口
从启动脚本、YAML一路追到Runner和Agent工厂。
产出:写出一条采集命令对应的脚本、配置、调度器、Agent类。 - 325分钟
追一次工具调用
从Agent主循环追到模型文本、结构化action与MCP工具结果。
产出:画出一轮循环并注明三个停止或异常情况。 - 425分钟
回推实际目标
沿distill_task理解过滤、成功工具证据、变化摘要与任务改写。
产出:举一个三项任务只完成两项的例子,写出合理的新目标。 - 530分钟
算懂动作信用
明确评分对象,手算相邻差分,并解释best_prefix的基线更新。
产出:先手算[1.8,1.9,1.6],再到实验页修改第二个值核对。 - 620分钟
把信用贴回动作
用两个索引把工具结果上的信用对应回生成动作的模型事件。
产出:指出pending_action_index与tool_index分别索引哪一份列表。 - 725分钟
看懂批处理边界
理解并发、断点续跑、原子写回和原始数据保护。
产出:列出真正运行蒸馏前需要保留的输入与记录。 - 820分钟
划清训练与评测
区分任务运行完成、verifier评价、信用生成和论文加权训练。
产出:写一段不超过150字的端到端数据流说明,标出未公开的训练阶段。
先看一条轨迹的形状
15分钟参考从Tracer认识模型动作和工具反馈,弄清离线学习的数据从哪里来。
agentbrew/tracing
tracer.py
108行1
"""Minimal tracer compatible with migrated agents."""2
3
from __future__ import annotations4
5
import json6
import time7
import uuid8
from contextlib import contextmanager9
from pathlib import Path10
from typing import Any11
12
13
class Tracer:14
"""Collect internal spans and training-ready agent trajectory events."""15
16
def __init__(17
self,18
trace_id: str | None = None,19
*,20
include_prompts: bool = False,21
) -> None:22
self.trace_id = trace_id or str(uuid.uuid4())23
self.include_prompts = include_prompts24
self.records: list[dict[str, Any]] = []25
self.trajectory: list[dict[str, Any]] = []26
27
@contextmanager28
def sprout(self):29
child = self.__class__(30
trace_id=self.trace_id,31
include_prompts=self.include_prompts,32
)33
child.add({"type": "span_start", "timestamp": time.time()})34
try:35
yield child36
finally:37
self.records.extend(child.records)38
self.trajectory.extend(child.trajectory)39
40
def add(self, data: dict[str, Any]) -> None:41
self.records.append({"timestamp": time.time(), "data": data})42
43
def record_llm(44
self,45
parsed_response: dict[str, Any],46
*,47
messages: list[dict[str, Any]] | None = None,48
response: Any = None,49
) -> None:50
"""Record one main-agent decision."""51
event = {52
"state": "llm",53
"timestamp": time.time(),54
"parsed_response": parsed_response,55
}56
if self.include_prompts:57
event["messages"] = messages or []58
event["response"] = response59
self.trajectory.append(event)60
61
def record_tool(62
self,63
*,64
server: str,65
tool_name: str,66
arguments: dict[str, Any],67
content: str,68
is_error: bool,69
) -> None:70
"""Record one tool result."""71
self.trajectory.append(72
{73
"state": "tool",74
"timestamp": time.time(),75
"server": server,76
"tool_name": tool_name,77
"arguments": arguments,78
"content": content,79
"isError": is_error,80
}81
)82
83
def write_trajectory(84
self,85
path: str | Path,86
*,87
task_id: str,88
question: str,89
final_answer: str,90
) -> Path:91
"""Write one task trajectory in the legacy-compatible format."""92
output_path = Path(path)93
output_path.parent.mkdir(parents=True, exist_ok=True)94
payload = {95
"tasks": [96
{97
"task_id": task_id,98
"question": question,99
"final_answer": final_answer,100
"trajectory": self.trajectory,101
}102
]103
}104
output_path.write_text(105
json.dumps(payload, ensure_ascii=False, indent=2) + "\n",106
encoding="utf-8",107
)108
return output_path作者原文 / SHA256已核验L43-59
亲手改变NLL,看信用如何变化
固定同一个回推任务,用不同交互前缀预测它。NLL越低,模型越容易解释这个任务。这里使用人工数值,不调用模型。
每一项都需要0到20之间的有限数值。先修正输入,再继续推演。
| 当前步 | previous | baseline | 当前NLL | adjacent | best_prefix | 演示权重 A / B |
|---|
0/3步
从原始轨迹到成功工具证据
原始轨迹保留模型决策、成功工具与失败工具。任务回推时,筛出成功工具反馈,再交给环境提示词。
原始交错事件
工具结果的信用,贴回产生它的动作
预先给工具步骤设置0.2、0.3和0.4信用,逐个处理事件。表中的每一帧由作者原始纯函数离线生成,保留错误、缺失结果与最终回答这些边界。
| 原轨迹索引 | state | 工具 / 回答 | credit |
|---|