什么是评估驱动开发?如何持续改进 AI 智能体
原文出处:由 Divya Santhanam 发布于 LangChain Blog。
核心要点
- 评估驱动开发(EDD)指的是在构建智能体的同时,用一套稳定的指标衡量其表现,并朝着评估结果不断爬坡。
- EDD 的第一步,是为你想实现的行为写一份简短的规格说明,讲清楚“什么叫好”。 其中要包含智能体不应该做什么,以及哪些行为必须保持不变。
- 在迭代过程中,通过对比实验来判断你对智能体所做的某次修改。 修好一个用例的改动,可能会弄坏另一个。
- 让评估持续运行在 CI 和生产环境中,并把你发现的失败案例转化为新的数据集样本。
大多数智能体的开发起点都一样。你写一段提示词,手动试几个问题,调整一下,再试一次。这在初期很管用——那时智能体的错误很明显,改进也一眼可见。但随着时间推移,你会越来越难判断最近这次修改到底让智能体变好了还是变差了。
评估驱动开发(EDD)解决的正是这个问题:它给你一套稳定的指标,用来衡量智能体的表现并指导你的决策。在 LangChain,我们在构建最先进的智能体时就使用了 EDD(可以看看我们关于 IssueBench 的博客),并把它归纳成了一个三步流程:
- 为你的智能体定义什么叫好。
- 在动手构建之前先写评估。
- 做出修改并对比。
在这篇博客中,我们会一步步走完这个流程,让你的团队能把它应用到自己的智能体开发过程中。
什么是评估驱动开发?
评估驱动开发这个名字和概念借鉴了测试驱动开发(TDD)——先写一个会失败的测试,再写能让它通过的代码。智能体与传统代码不同,因为它们是非确定性的:
- 输出会变化。 同一个问题每次运行可能得到不同的答案。
- 正确答案不止一个。 两段自然语言结果即便措辞不同,也可能都被认为是正确的。
- 智能体自己决定步骤。 它可能调用了一个并不需要的工具,或者漏掉了一个本该使用的工具,却仍然得出了正确答案。
因此,智能体需要一种不同类型的测试。评估(eval)通过在一组样本上为智能体的多次运行打分来应对这一点。评估比传统测试更灵活。你可以对智能体运行的任何方面打分,也可以让其他 LLM 来打分(LLM-as-a-judge)。
在 EDD 中,与 TDD 类似,这些评估就成了你对成功的定义,而你朝着它们构建智能体。
第 1 步:为你的智能体定义什么叫“好”
EDD 的第一步是定义你的智能体应该做什么。然后,列出它为了做到这一点需要处理的行为。这些行为可能是回答知识库中的问题、代表用户执行某个操作,或者知道何时该追问一个澄清问题。把每种行为的需求写下来。它们共同构成了你智能体的产品需求文档(PRD)。
EDD 一次只处理一种行为。这样你就有了一个狭窄的目标可以爬坡,而不会让一次修改模糊掉另一次修改的效果。你选中的行为通常来自你即将开发的功能,或者你在智能体过往运行中发现的某个失败。在写代码之前,先定义一份简短的规格说明会很有帮助,它应覆盖:
- 该行为应该在什么时候发生
- 智能体应该做什么
- 智能体不应该做什么
- PRD 中哪些行为必须保持正常
这份规格说明要足够明确,能够按通过或失败来打分。
假设我们有一个内部文档智能体,员工会向它查询公司信息。它有两个工具:search_docs 用于内部文档,web_search 用于其他一切内容。我们计划新增一个 create_ticket 工具,让它能够提交 IT 工单。我们的规格说明是这样的:
- 何时:用户报告某样东西坏了,比如“我的笔记本电脑连不上 VPN”。
- 做什么:调用
create_ticket。 - 不做什么:不要为“如何使用”类问题提交工单,比如“怎么连接 VPN?”
- 保持不变:
search_docs和web_search仍然处理它们今天处理的问题
我们会依据这些准则来做评估,即使智能体目前还不具备这项能力。

当前文档智能体的示例实现,以及我们计划新增的工单工具。每个工具都配有一个会调用它的示例输入。
第 2 步:在动手构建之前先写评估
构建数据集。 数据集是一组测试用例(称为“样本”),它们包含输入,并且可选地包含参考的“黄金”输出。输入的来源之一是真实智能体运行记录。用户表达问题的方式往往出人意料,他们的请求里也包含你自己可能想不到要写的边缘情况。如果你的样本看起来像真实流量,那么评估得到好分数就更有可能意味着生产环境中的良好表现。在 LangSmith 中,你可以直接把真实的智能体运行添加到数据集中。如果你还没有任何运行记录,一个常见的替代做法是从零开始构建样本。
对于我们的文档智能体,少量样本就足以起步。在数据集中,我们会加入工单请求,还会加入那些仍然应该交给 search_docs 和 web_search 的问题,以便把现有行为也纳入考量。

每个样本都把输入问题与参考输出(即智能体应调用的工具)配对在一起。
你也可以扩展数据集,覆盖它尚未包含的情况。假设我们缺少“愤怒用户”的样本。我们可以把现有样本交给一个 LLM,让它把这些消息改写成更愤怒的语气,然后检查智能体是否仍然调用正确的工具。
编写评估器。 有了数据集之后,你就可以把 PRD 中对“好”的定义转化为一个测试或评估,用它为智能体在你的样本上的表现打分。编写评估器时,要选择最适合你测试的评分方式。当检查是确定性的,就用代码评估;当检查不是确定性的,就用 LLM-as-a-judge。你想看的是智能体的最终答案、它为达成目标而采取的某个动作,还是完全不同的东西?对于我们的文档智能体,我们想查看它调用了哪些工具,以确认它在每种情况下都使用了正确的工具。工具选择很容易用代码检查,所以我们可以用一个代码评估来检查每个样本是否调用了其参考输出中列出的工具。

如果智能体调用了参考输出中的工具,该样本就通过。
我们的文档智能体是一个简单聊天机器人,只有几个特定功能。随着你的智能体越来越复杂,你的评估套件很可能也需要有所不同。如果你的智能体会在某个环境中做出修改,比如沙箱中的编程智能体,那么只检查几次工具调用和最终回复是不够的。你需要检查智能体在系统中留下的状态,而且每次运行都需要一个干净的环境,这样一次运行才不会影响下一次。Harbor 是一个开源框架,用于在这类任务上运行智能体,它也是 Terminal-Bench 等行业基准测试背后的运行框架。每个任务都在自己的沙箱中运行,并附带一个对最终状态进行评分的测试脚本。
针对 Terminal-Bench 这类基准测试做优化,遵循的循环与 EDD 相同。你先写任务和测试,跑一个基线,然后在修改智能体的过程中对比实验。我们在构建 LangSmith Engine 时,就用真实和合成的智能体运行记录构建了自己的基准测试,并将其作为 Harbor 评估来运行。我们也用 Harbor 来对 Deep Agents 做基准测试。它能告诉我们,是否可以删掉运行框架的某些部分——比如待办清单中间件或系统提示词的一部分——而不会让智能体变差。
运行基线。 无论你选择如何构建数据集或评估器,你都可以让智能体在每个样本上运行,并把结果作为实验记录到 LangSmith 中。实验是你的智能体在整个数据集上的一次运行,其中每个样本的输入、输出和评估器分数都会保存在同一条记录里。拥有一个集中式系统,可以让你把不同智能体版本的结果相互对比。在对智能体做任何修改之前,先运行一个基线实验作为对比基准,这一点很重要。
对于我们的文档智能体,数据集中的工单样本会得到失败分数,因为这个工具还不存在。其他样本记录了已经正常工作的行为,这样你之后就能判断新增工具是否破坏了其他东西。
第 3 步:做出修改并对比
现在,我们构建 create_ticket 工具,并运行同一个评估。
请记住,EDD 意味着朝着评估“爬坡”。爬坡是指重复改进智能体的过程(评估、对比、调整),从而建立一个有明确目标的循环,并用客观证据证明改进。智能体的每一次后续修改都有自己的实验,而每个实验都会与上一个实验对比,以验证进展。在 LangSmith 中,你可以通过同时选中两个实验来打开对比视图。它会并排显示每个样本的分数,让你看出哪些样本变好了、哪些出现了回退。
在对比实验时,重要的是不仅要关注平均分的变化,还要关注任何回退或对正常行为的覆盖。对于我们的文档智能体,工单样本现在通过了。但“怎么连接 VPN?”现在会提交工单,而不是搜索文档。平均分上升了,但有一个用例被弄坏了。

新增工单工具提升了平均分,但“怎么连接 VPN?”现在失败了。
查看轨迹是理解评估为何失败的最好方式。轨迹是一次智能体运行的记录,包含每一次模型调用和工具调用。在 LangSmith 中,用你选择的任何框架构建的智能体都可以进行追踪。更多信息请查看我们的追踪快速入门。
当我们打开最新实验中失败的那条轨迹时,会看到工具描述里写着:对于“VPN 和笔记本电脑问题”应使用 create_ticket,因此任何提到 VPN 的问题都会命中它。这就覆盖了基线中正常的行为。

轨迹告诉我们,工具描述过于宽泛,所以智能体为一个文档本就能回答的问题提交了工单。
解决方案是把工具描述收窄到那些需要 IT 人员介入的请求。实施这一修改后,我们再次运行评估。现在,每个样本都通过了。

更精确的工具描述让每个样本都通过了。
在小型数据集上拿到满分是个好迹象,但 100% 并不总是正确的目标。我们是在看着这些具体样本的情况下调整工具描述的。如果你不断调整智能体,直到每个样本都通过,它可能开始过拟合你的数据集,而不是你真正关心的行为。它能通过你的评估,却仍然会漏掉那些以你的样本未覆盖的方式表述的请求。要检查这一点,请保留一组在迭代过程中不去查看的留出样本。如果你调优所用的样本分数上升,而留出集上的分数保持不变,那你很可能已经过拟合了。
多步智能体可能在任何一个步骤失败,因此 LangSmith 允许你评估的不只是最终答案。你可以为单个步骤、完整的工具调用序列,或者被归入同一个线程的多轮对话打分。
在持续交付中让 EDD 运转下去
自动化你的评估
当你开始更快地部署变更时,很容易跳过运行评估,或者弄丢较早的样本。把自动化评估加入你的工作流,可以阻止未经测试的修改到达用户,并在生产环境之前捕获回退。
创建评估套件的最佳策略取决于你的具体环境。快速的代码检查可以阻止一次糟糕的合并,而带有 LLM 评审的较慢评估可以每晚运行,或在发布前运行。迭代时,使用数据集拆分只运行你正在处理的行为对应的样本;发布前再运行完整集合。
LangSmith 集成了 pytest 和 Vitest,因此你的评估可以放在代码旁边,并在每次拉取请求时运行。每次运行都会记录为一个实验,因此你可以在与其他所有内容相同的地方查看结果。
在生产环境中评估
在部署智能体之前,你的数据集很可能只覆盖了你在开发阶段想到要测试的情况。在生产环境中,你可以用以下评估方法标记其余情况:
- 在线评估器会在实时轨迹到达时为其打分。你可以把代码检查和 LLM 评审附加到一个追踪项目上,并抽样一部分流量来控制成本。
- 标注队列让你的团队手动审查被标记的运行。在你依赖某个 LLM 评审之前,也是用它来检查该评审与人类判断是否一致。
- 仪表盘可以长期跟踪评估分数、反馈、成本和延迟,让你看出某个版本是让事情变好了还是变差了。
- Insights会把生产轨迹分组为集群,让你能在数千次运行中发现新的模式。
- LangSmith Engine则更进一步,把问题集群转化为带有断言的数据集样本,供你审查。
我们还在代码仓库中公开了我们用于 Deep Agents 的评估,你可以看到一个真实的、生产级的评估套件。
常见错误
- 把成功定义得太模糊。 前期多花力气,把成功清晰地定义出来,这样评估才能轻松地按通过或失败打分。“回答很有帮助”并不是一个定义良好的指标。
- 在修复之后才写评估。 一旦你看到了新的输出,就很容易写出一个从设计上注定会通过的评估。要先写评估,并确认它在当前有问题的版本上会失败。
- 只看平均分。 平均分的提升可能掩盖了出现回退的样本,或者覆盖了良好行为的改动。在决定保留某个修改之前,请逐个审查样本。
- 添加你并不需要的评估。 每个评估都会把智能体往某个方向推。让每个评估都对应一项具体的修改,比如你正在修复的某个失败,或者你即将构建的某个功能。
- 信任未经校验的评审。 先把你的 LLM 评审与人类评分做对比。向它提出范围明确的问题,并使用通过或失败,而不是含糊的 1 到 10 分制。
想了解更多关于构建智能体评估的信息,请查看这场关于 Agent Evals 101 的网络研讨会,以及我们免费的 LangChain Academy LangSmith 课程!