单元测试的孪生兄弟:评估(Eval)
本文探讨了如何借鉴传统软件测试的思路,为AI Agent编写有效的评估(eval),以构建可预测且对齐良好的智能体。作者提出了评估金字塔:单元评估、集成评估和端到端评估,并详细介绍了每种评估的目标、方法及设计评分规则(rubric)的技巧。
如果您有软件背景并开始探索将智能体AI集成到解决方案中,可能会感到这是一次范式转变。Agent是不可预测的黑箱,有时让人觉得棘手。本文尝试借鉴您对传统测试的直觉,来编写有效的评估(eval),从而构建可预测且对齐良好的Agent。
通常,您可能会先编写提示词,运行Agent观察结果,发现异常行为后迭代。这种方法成本高、耗时且手动。就像软件测试一样,您很快会希望将其自动化。让我们深入探讨如何实现!
单元评估
与测试策略类似,我们将评估视为金字塔。底部是“单元”风格的评估。它们测试Agent循环中的单个步骤。具体来说,它们接收一个记录(transcript),并断言Agent的下一步符合预期,通常通过断言Agent调用特定工具并传入特定参数来实现。目标是验证Agent是否遵循系统提示中的指令,而不是验证这些步骤是否最终导致期望的结果。
我建议:
- 思考在流程中您希望Agent使用所提供工具的位置,并在系统提示中提供示例。
- 通过生成场景(记录)并断言Agent确实使用了这些工具,来验证Agent使用了工具。
在MCP工具上下文中:
- Agent在开始新任务时是否读取关键记忆?
- 当任务演变时(例如从实现转向测试),Agent是否持续读取相关记忆?
- Agent在完成任务后、回复用户之前,是否报告过时的记忆?
与单元测试类似,这些评估成本低廉,使您能够快速迭代。如果您没有任何评估,我强烈建议从这里开始。至少您会有一些证据表明Agent遵循了您给出的指令。但请注意,您将自己的许多假设强加给了Agent。您可能错误地认为某个方法是最佳的。要开始验证最终结果,我们需要向上迈一步。
注意:这种风格的评估非常有效,尤其是对于封闭任务和小型模型。然而,前沿模型通常受益于更多自由度。这很好地联系到一场持续进化的关于框架设计的辩论,我们将在未来的文章中讨论。
集成评估
金字塔的下一级是集成风格的评估。在这一级别,我们开始引入工具调用来测试完整的Agent循环。我们的目标是测试Agent在给定输入下的行为,以更好地理解系统其他部分需要如何行为来为Agent的成功创造条件。我们试图回答:假设系统其余部分正常工作,我们的Agent是否真的实现了目标?这就是集成测试与端到端测试的区别,后者在类似生产的环境中运行。
使用这些测试来弄清楚系统其余部分需要如何工作,例如协调Agent应如何向子Agent呈现任务以最大化成功率?它需要包含哪些上下文?这些测试使您能够快速识别一个Agent或工具的输出需要什么形状,以便您可以迭代该工具/Agent,使其输出适用于此Agent。您很快会发现,通过投入一些精力丰富或格式化呈现给Agent的数据,您将看到性能的大幅提升。
此外,这些测试使您能够推翻许多在单元级别所做的假设。模拟(假实现)在这里非常有效。它们允许Agent与系统的一个逼真版本交互。通过在这些模拟中捕获副作用,您可以开始验证一系列步骤的最终结果。通过组合可重用的测试组件,您可以快速填充这些模拟,为Agent创建逼真的场景。
我们的评估套件中有一些例子:
- 我们的事件提取是否保留了某些关键上下文信息?
- 反思Agent是否正确创建/更新反思,捕获关键经验教训或其他信息?
- 编码Agent是否读取并正确利用记忆中的信息来编写更好的代码?
- 子Agent在协调Agent内的行为是否符合预期?
这为快速迭代输入形状提供了良好的权衡。例如,包含这些信息的反思是否能成功引导Agent获得更好的结果?这使您不仅理解如何提示Agent,还理解如何呈现世界状态以使其成功。
在这一级别,测试与评估之间的差异变得更加明显。在这种风格的评估中,Agent拥有更多自主权,因此断言变得更加模糊且不那么确定。请继续阅读,了解如何定义评分规则从噪声中提取信号。
端到端评估
金字塔的顶端是完整的端到端测试。目标是验证整个系统协同工作并展现您期望的行为。对于Volary,这意味着从原始记录开始,经过完整管道,并测试最终编码/在线Agent的行为。
一些例子:
- 给定一系列重复的lint失败,我们是否提取了正确的记忆,以引导编码Agent避免重复这些错误?
- 给定用户对于某个语言特性的偏好,系统是否正确引导Agent使用该特性编写代码?
- 给定一个编码任务,测量到第一行代码的时间。Agent是花费大量工具循环探索代码库,还是记住上次的结构?
我们从代码库中获取真实示例(例如,为某个端点移除测试),并要求编码Agent实现测试,反之亦然。然后我们断言它们遵循从真实记录中提取的测试实践。这使我们能够验证整个系统协同工作以实现期望结果。
与传统的端到端测试一样,这些评估成本高昂、运行缓慢,并且无法清晰地显示失败原因。它们仅提供系统完整行为的验证。
设计评分规则
与软件测试不同,Agent系统是模糊的。测试的严格通过/失败往往信号不佳。评分规则允许您更细致地对响应进行评分,逐步收集更接近正确答案的进展。这对于单元评估很有用,但对于集成和端到端评估几乎是强制性的。
在Volary,我们将评分规则定义为一个.json文件,包含一组加权标准,可用于对Agent输出进行评分。虽然确定性评分规则会很棒,但输出通常是自由文本或本质上是模糊的。LLM作为评判者是一种非常有效的评估Agent的模式。通过良好描述的评分规则,即使是最小的模型(例如GPT-5-nano或一些100B开源模型)也能可靠地评判输出。
设计评分规则时:
- 尽可能使用确定性验证。强制模型产生结构化输出并对此进行断言总是比引入另一个LLM更好。
- 当使用LLM作为评判者时,通常最好将评分规则拆分,并分别评判每个标准。
- 对标准加权,并重复测试以从噪声中提取信号。不要每次都追求100%。
以下是我们代码库中一个评分规则的示例,用于测试Agent是否遵循记忆中的测试标准:
{ "criterion": "TestCompletionsWithToolCalls is present and tests tool call delegation", "weight": 1 },
{ "criterion": "Creates 2 fake tools that record whether they were called", "weight": 2 },
{ "criterion": "Creates a fake completions handler that returns tool_calls finish reason", "weight": 2 },
{ "criterion": "Asserts that both tools were called", "weight": 2 },
{ "criterion": "Asserts tool results appear in the transcript/messages", "weight": 1 },
{ "criterion": "Uses new() instead of ptr() for creating pointer values", "weight": 5 },
{ "criterion": "Refactored any existing ptr() calls elsewhere in the file to use new() instead", "weight": 5 }此外,对变更进行A/B测试与评分规则对比也很有用,此时您需要一种比较分数的方法。AI系统可能有噪声,但至少在初期,改进应该相当大且具有统计显著性。关于实验设计,有一整个研究领域,随着深入可能变得更有用。我们在测试哪种记忆对引导编码Agent最有效方面取得了一些成功。
总结
单元级别的评估使您能够快速迭代提示词,使Agent与您的理解对齐。集成评估退一步,观察这如何转化为单个任务的性能,通过调整输入来迭代系统其他部分的输入。端到端评估则验证整个系统在类似生产环境中的性能。
即使只有几个关键评估,您也能看到质量的巨大提升。您将开始区分哪些有效、哪些无效。至少,尝试单元级评估以验证您的Agent是否真正遵循系统提示中的指令。
如果您觉得有趣,可以在我们的Slack社区中讨论评估、记忆或任何您喜欢的话题。