AgentDepthAgent 工程学习指南
输入概念或问题,检索正文和待编写目录。
第一次学习?从 L0 总览开始 →

可观察轨迹:看清动作、结果和回答的来源

我的学习 →

正在读取学习记录…

1. 一条轨迹保存什么

轨迹是按时间顺序保存的事件记录。一次查询任务可以记录:收到目标、选择工具、执行查询、取得资料、生成答复、停止。每个事件都带同一任务编号,读记录的人就能把它们串起来。

这像快递查询:你查看包裹在哪个站点、何时离开、谁签收。Agent 的轨迹关注可观察的动作和结果,帮助解释它查过什么、为什么得出这条答复、卡在哪个环节。

同一任务r1先查询policy,再观察退款7天,最终回答引用policy;通过来源连回观察
沿任务编号找到事件,再沿来源字段把回答连回实际取得的资料。

动作表示发出了什么请求,观察表示工具返回什么,最终回答表示用户看到什么。来源字段负责把回答连接到观察。更完整的来源可包含文档编号、段落位置和版本。

2. 从事件列表整理出一个可回查结果

想象这次助手做了三件事:请求退款政策,收到“退款7天”,把这条资料用于回答。我们按发生顺序保存三条事件。它们是本程序的过程记录,字段含义如下:

事件字段含义示例
run_id整次任务的编号r1,三条记录属于同一次任务
kind发生的事情action 发出查询、observation 收到资料、final 生成回答
source查询或引用的资料标识policy 表示退款政策资料
text收到的资料正文或最终回答退款7天

先在 PowerShell 创建并进入学习目录:

Bash
mkdir "F:\学习\l3-evidence" -Force
cd "F:\学习\l3-evidence"

保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。

在新目录创建 evidence.py:

先在 PowerShell 创建并进入学习目录:

Bash
mkdir "F:\学习\l3-evidence" -Force
cd "F:\学习\l3-evidence"

保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。

Python
"""沿动作、观察和回答的记录,找出回答所依据的资料。"""
import json

def summarize(events):
    actions = 0
    observed = {}
    run_id = events[0]["run_id"] if events else None
    answer = None
    for event in events:
        if event["run_id"] != run_id:
            raise ValueError("同一轨迹包含多个任务")
        if event["kind"] == "action":
            actions += 1
        elif event["kind"] == "observation":
            # 按来源保存原文,后续回答可回查。
            observed[event["source"]] = event["text"]
        elif event["kind"] == "final":
            if observed.get(event["source"]) != event["text"]:
                raise ValueError("回答缺少对应的资料观察")
            answer = {"actions": actions, "answer": event["text"], "source": event["source"]}
    if answer is None:
        raise ValueError("轨迹尚无回答")
    return answer

if __name__ == "__main__":
    events = [
        {"run_id": "r1", "kind": "action", "source": "policy"},
        {"run_id": "r1", "kind": "observation", "source": "policy", "text": "退款7天"},
        {"run_id": "r1", "kind": "final", "source": "policy", "text": "退款7天"},
    ]
    print(json.dumps(summarize(events), ensure_ascii=False))
Bash
ls
python evidence.py

输出:

TXT
{"actions": 1, "answer": "退款7天", "source": "policy"}

这份汇总表示:助手发出过1次动作(actions),最终回答为“退款7天”(answer),引用的资料是退款政策(source: policy)。actions 数的是事件列表中的动作记录,source 则让你回到相应的资料事件核对正文。

代码遍历事件列表,动作增加计数,观察按来源保存原文,最终回答按来源回查。示例使用原文完全相同的短答复,因此能直接比较字符串。

run_id 是任务编号;kind 是事件类型;source 是资料来源;text 是返回或回答内容。调用多次工具时,各次动作还可以带 call_id,把请求和响应一一对应。

3. 改变来源,观察回查失败

把最后事件的来源从 policy 改为 other,运行会出现“回答缺少对应的资料观察”。恢复来源,再把最后文本改为“退款14天”,同样会失败。因为已保存观察是7天。

接着把最后事件的 run_id 改为 r2,会出现“同一轨迹包含多个任务”。这个修改说明任务编号也参与一致性检查。恢复所有改动后再运行测试。

4. 用测试保存判断规则

在同目录创建 test_evidence.py:

下面的测试检查回答能否找到对应观察,以及任务编号和资料正文是否一致。

测试代码:test_evidence.py
Python
"""检查evidence示例的正常路径和边界结果。"""
import unittest
from evidence import summarize
class Tests(unittest.TestCase):
    def test_trace(self):
        events=[{"run_id":"r1","kind":"action","source":"policy"},{"run_id":"r1","kind":"observation","source":"policy","text":"退款7天"},{"run_id":"r1","kind":"final","source":"policy","text":"退款7天"}]
        self.assertEqual(summarize(events),{"actions":1,"answer":"退款7天","source":"policy"})
    def test_missing(self):
        with self.assertRaises(ValueError): summarize([{"run_id":"r1","kind":"final","source":"policy","text":"退款7天"}])

if __name__ == "__main__":
    unittest.main()
Bash
python -m unittest test_evidence -v

正常路径与改动后的边界都在测试中检查。若结果不同,先定位失败的断言,再回到对应的字段与分支。

5. 扩展轨迹时,先想清排查问题

要排查的问题需要记录的字段
一次请求等了多久开始时间、结束时间、耗时
调用了哪个工具工具名、调用编号、必要参数
答复依据在哪里文档编号、片段和版本
任务为何停下状态和停止原因
费用为何增加模型调用次数、输入输出用量
谁批准了写入审批者、提案版本和回执

长答复通常是对原文的归纳,不能简单用字符串相等判断。可以先保存引用片段和对应句子,再人工或程序辅助核对支持关系。轨迹提供回查入口,资料质量与结论支持仍需检查。

记录也有成本:完整对话可能很大,敏感字段需要脱敏,访问权限和保留期限需要配置。优先记录排查需要的最小信息,原始资料按受控地址回查;凭据用占位符或字段删除处理。

并行工具的事件可能交错,所以任务编号与调用编号比打印先后更重要。每个调用保存起止事件,按编号聚合后再计算耗时。对照 OpenTelemetry 的追踪概念,可以进一步理解多个组件之间的关联。

模型内部思维与可观察事件有不同的数据来源。工程排查先查看真实请求、工具返回、状态变化和引用,读者能够逐项核对。总结:同一任务串事件,同一调用配响应,来源连资料,停止原因说明出口。回到 L3总览把这些部件组合成完整循环。

从事件列表读出处理过程

位置kindsource读者能确认什么
1actionpolicy程序发起政策查询
2observationpolicy工具返回退款7天
3finalpolicy答复引用该次资料

当前程序比较短答复与原文是否相等,因此最后事件换成14天会直接失败。长答复通常包含归纳,可保存“回答句子→引用片段”的关系,再检查片段是否支持该句。

多个来源时,观察可以按来源与调用编号一起存。两个查询都叫policy,也可能使用不同过滤条件;编号能进一步区分它们。任务编号把整次运行连起来,调用编号把某次请求和响应配起来。

轨迹可以帮助复盘卡点:重复动作的参数是否一致,失败是否发生在同一来源,等待时间耗在哪里,最终回答采用哪份资料。必要的字段比单纯打印“开始、结束”更容易定位因果。敏感正文可用受控资源地址回查,用户界面展示必要片段。

课后练习展开习题收起习题

4 道练习 · 客观题规则评分 · 其余题目待批改

正在读取本地记录…

不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。

练习 1 / 4 · v1.0.1

选择题 · 先判断边界

关于“保存可观察轨迹而非索取私密思维链”,哪种做法更稳妥?

对应知识点:L3-evidence

选择一个答案
练习 2 / 4 · v1.0.0

简答题 · 解释失败

写出一个失败输入并说明记录字段。

对应知识点:L3-evidence

练习 3 / 4 · v1.0.0

代码题 · 边界测试

补充正常、边界、失败三组输入和预期结果。

对应知识点:L3-evidence

练习 4 / 4 · v1.0.0

场景题 · 结果未知

证据不足时如何设计状态和人工接管?

对应知识点:L3-evidence

图片查看器
100%

文章配图 · 按 Esc 关闭