为什么要评估智能体¶
在传统软件开发中,单元测试和集成测试能够确保代码按预期运行并在变更过程中保持稳定。这些测试提供明确的"通过/失败"信号,指导后续开发。然而,LLM 智能体引入了一定程度的可变性,这使得传统的测试方法变得不够充分。
由于模型的概率性特质,确定性的"通过/失败"断言通常不适合评估智能体性能。相反,我们需要对最终输出和智能体轨迹(达成解决方案所采取的步骤序列)进行定性评估。这涉及评估智能体决策的质量、推理过程以及最终结果。
这看起来可能需要额外的工作量来搭建,但自动化评估的投入很快就会得到回报。如果你打算超越原型阶段,这是一个强烈推荐的最佳实践。
准备智能体评估¶
在自动化智能体评估之前,定义明确的目标和成功标准:
- 定义成功: 什么构成了你的智能体的成功结果?
- 识别关键任务: 你的智能体必须完成哪些基本任务?
- 选择相关指标: 你将跟踪哪些指标来衡量性能?
这些考虑因素将指导评估场景的创建,并能够有效监控智能体在真实部署中的行为。
评估什么?¶
要从概念验证过渡到生产就绪的 AI 智能体,一个强大且自动化的评估框架至关重要。与评估生成式模型不同(主要关注最终输出),智能体评估需要更深入地理解决策过程。智能体评估可以分为两个组成部分:
- 评估轨迹和工具使用: 分析智能体达成解决方案所采取的步骤,包括其工具选择、策略以及方法的效率。
- 评估最终响应: 评估智能体最终输出的质量、相关性和正确性。
轨迹只是智能体在返回给用户之前所采取的步骤列表。我们可以将其与我们期望智能体采取的步骤列表进行比较。
评估轨迹和工具使用¶
在响应用户之前,智能体通常会执行一系列操作,我们称之为"轨迹"。它可能会将用户输入与会话历史进行比较以消除术语歧义,或查阅政策文档、搜索知识库或调用 API 来保存工单。我们称这一系列操作为行动"轨迹"。评估智能体的性能需要将其实际轨迹与预期或理想轨迹进行比较。这种比较可以揭示智能体过程中的错误和低效之处。预期轨迹代表了基准事实——我们预计智能体应该采取的步骤列表。
例如:
// 轨迹评估将比较
expected_steps = ["determine_intent", "use_tool", "review_results", "report_generation"]
actual_steps = ["determine_intent", "use_tool", "review_results", "report_generation"]
存在几种基于基准事实的轨迹评估:
- 精确匹配: 要求与理想轨迹完全匹配。
- 顺序匹配: 要求正确动作按正确顺序,允许有额外动作。
- 任意顺序匹配: 要求正确动作,但顺序不限,允许有额外动作。
- 精确度: 衡量预测动作的相关性/正确性。
- 召回率: 衡量预测中包含了多少必要动作。
- 单工具使用: 检查是否包含特定动作。
选择正确的评估指标取决于你的智能体的具体要求和目标。例如,在高风险场景中,精确匹配可能至关重要,而在更灵活的情况下,顺序匹配或任意顺序匹配可能就足够了。
ADK 中评估如何工作¶
ADK 提供了两种方法来根据预定义的数据集和评估标准评估智能体性能。虽然概念上相似,但它们在能处理的数据量上有所不同,这通常决定了每种方法的适用场景。
第一种方法:使用测试文件¶
这种方法涉及创建单独的测试文件,每个文件代表一个简单的智能体 - 模型交互(一个会话)。它在活跃的智能体开发阶段最有效,作为单元测试的一种形式。这些测试旨在快速执行,应专注于简单的会话复杂性。每个测试文件包含单个会话,而会话可能包含多个轮次。一个轮次代表用户和智能体之间的单次交互。每个轮次包括:
query:
这是用户查询。expected_tool_use
: 我们期望智能体为了正确响应用户query
而进行的工具调用。expected_intermediate_agent_responses
: 此字段包含智能体在推进到最终答案过程中产生的自然语言响应。这些响应在多智能体系统中很常见,其中根智能体依赖子智能体来完成任务。虽然这些中间响应对于终端用户通常不直接相关,但对开发者很有价值。它们提供了智能体推理路径的洞察,并帮助验证其是否遵循了正确的步骤生成最终响应。reference
: 模型的预期最终响应。
你可以给文件起任何名字,例如evaluation.test.json
。框架只检查.test.json
后缀,文件名的前面部分没有限制。以下是包含几个示例的测试文件:
[
{
"query": "hi",
"expected_tool_use": [],
"expected_intermediate_agent_responses": [],
"reference": "Hello! What can I do for you?\n"
},
{
"query": "roll a die for me",
"expected_tool_use": [
{
"tool_name": "roll_die",
"tool_input": {
"sides": 6
}
}
],
"expected_intermediate_agent_responses": [],
},
{
"query": "what's the time now?",
"expected_tool_use": [],
"expected_intermediate_agent_responses": [],
"reference": "I'm sorry, I cannot access real-time information, including the current time. My capabilities are limited to rolling dice and checking prime numbers.\n"
}
]
测试文件可以组织到文件夹中。可选地,文件夹还可以包含一个test_config.json
文件,指定评估标准。
第二种方法:使用评估集文件¶
评估集方法使用称为"evalset"的专用数据集来评估智能体 - 模型交互。与测试文件类似,评估集包含示例交互。但是,一个评估集可以包含多个可能较长的会话,这使它非常适合模拟复杂的多轮对话。由于能够表示复杂会话,评估集非常适合集成测试。这些测试由于其更广泛的性质,通常比单元测试运行得少。
评估集文件包含多个"evals",每个代表一个不同的会话。每个 eval 由一个或多个"轮次"组成,其中包括用户查询、预期工具使用、预期中间智能体响应和参考响应。这些字段与测试文件方法中的含义相同。每个 eval 都由唯一名称标识。此外,每个 eval 都包括相关的初始会话状态。
手动创建评估集可能很复杂,因此提供了 UI 工具来帮助捕获相关会话并轻松将它们转换为评估集中的 evals。在下面了解更多关于使用 Web UI 进行评估的信息。以下是包含两个会话的评估集示例。
[
{
"name": "roll_16_sided_dice_and_then_check_if_6151953_is_prime",
"data": [
{
"query": "What can you do?",
"expected_tool_use": [],
"expected_intermediate_agent_responses": [],
"reference": "I can roll dice of different sizes and check if a number is prime. I can also use multiple tools in parallel.\n"
},
{
"query": "Roll a 16 sided dice for me",
"expected_tool_use": [
{
"tool_name": "roll_die",
"tool_input": {
"sides": 16
}
}
],
"expected_intermediate_agent_responses": [],
"reference": "I rolled a 16 sided die and got 13.\n"
},
{
"query": "Is 6151953 a prime number?",
"expected_tool_use": [
{
"tool_name": "check_prime",
"tool_input": {
"nums": [
6151953
]
}
}
],
"expected_intermediate_agent_responses": [],
"reference": "No, 6151953 is not a prime number.\n"
}
],
"initial_session": {
"state": {},
"app_name": "hello_world",
"user_id": "user"
}
},
{
"name": "roll_17_sided_dice_twice",
"data": [
{
"query": "What can you do?",
"expected_tool_use": [],
"expected_intermediate_agent_responses": [],
"reference": "I can roll dice of different sizes and check if a number is prime. I can also use multiple tools in parallel.\n"
},
{
"query": "Roll a 17 sided dice twice for me",
"expected_tool_use": [
{
"tool_name": "roll_die",
"tool_input": {
"sides": 17
}
},
{
"tool_name": "roll_die",
"tool_input": {
"sides": 17
}
}
],
"expected_intermediate_agent_responses": [],
"reference": "I have rolled a 17 sided die twice. The first roll was 13 and the second roll was 4.\n"
}
],
"initial_session": {
"state": {},
"app_name": "hello_world",
"user_id": "user"
}
}
]
评估标准¶
评估标准定义了如何根据评估集衡量智能体的性能。支持以下指标:
tool_trajectory_avg_score
: 此指标将智能体在评估过程中的实际工具使用与expected_tool_use
字段中定义的预期工具使用进行比较。每个匹配的工具使用步骤得分为 1,而不匹配的得分为 0。最终得分是这些匹配的平均值,代表工具使用轨迹的准确性。response_match_score
: 此指标将智能体的最终自然语言响应与存储在reference
字段中的预期最终响应进行比较。我们使用ROUGE指标计算两个响应之间的相似度。
如果没有提供评估标准,将使用以下默认配置:
tool_trajectory_avg_score
: 默认为 1.0,要求工具使用轨迹 100% 匹配。response_match_score
: 默认为 0.8,允许智能体的自然语言响应有小误差。
以下是指定自定义评估标准的test_config.json
文件示例:
如何在 ADK 中运行评估¶
作为开发者,你可以通过以下方式使用 ADK 评估你的智能体:
- 基于 Web 的 UI(
adk web
): 通过基于 Web 的界面交互式评估智能体。 - 编程方式(
pytest
): 使用pytest
和测试文件将评估集成到你的测试流程中。 - 命令行界面(
adk eval
): 直接从命令行对现有评估集文件运行评估。
1. adk web
- 通过 Web UI 运行评估¶
Web UI 提供了一种交互式方式来评估智能体并生成评估数据集。
通过 Web UI 运行评估的步骤:
- 运行以下命令启动 Web 服务器:
bash adk web samples_for_testing
- 在 Web 界面中:
- 选择一个智能体(例如,
hello_world
)。 - 与智能体交互,创建你想要保存为测试用例的会话。
- 点击界面右侧的"Eval 标签"。
- 如果你已经有现有的评估集,选择它或通过点击"创建新评估集"按钮创建新的评估集。给你的评估集一个有上下文的名称。选择新创建的评估集。
- 点击"添加当前会话"将当前会话保存为评估集文件中的 eval。系统会要求你为此 eval 提供一个名称,同样给它一个有上下文的名称。
- 创建后,新创建的 eval 将显示在评估集文件的可用 evals 列表中。你可以运行所有 evals 或选择特定的 evals 来运行评估。
- 每个 eval 的状态将显示在 UI 中。
- 选择一个智能体(例如,
2. pytest
- 以编程方式运行测试¶
你还可以使用pytest
作为集成测试的一部分运行测试文件。
示例命令¶
示例测试代码¶
以下是运行单个测试文件的pytest
测试用例示例:
def test_with_single_test_file():
"""通过会话文件测试智能体的基本能力。"""
AgentEvaluator.evaluate(
agent_module="tests.integration.fixture.home_automation_agent",
eval_dataset="tests/integration/fixture/home_automation_agent/simple_test.test.json",
)
这种方法允许你将智能体评估集成到 CI/CD 流程或更大的测试套件中。如果你想为测试指定初始会话状态,可以通过在文件中存储会话详情并将其传递给AgentEvaluator.evaluate
方法来实现。
以下是一个示例会话 json 文件:
{
"id": "test_id",
"app_name": "trip_planner_agent",
"user_id": "test_user",
"state": {
"origin": "San Francisco",
"interests": "Moutains, Hikes",
"range": "1000 miles",
"cities": ""
},
"events": [],
"last_update_time": 1741218714.258285
}
示例代码将类似于:
def test_with_single_test_file():
"""通过会话文件测试智能体的基本能力。"""
AgentEvaluator.evaluate(
agent_module="tests.integration.fixture.trip_planner_agent",
eval_dataset="tests/integration/fixture/trip_planner_agent/simple_test.test.json",
initial_session_file="tests/integration/fixture/trip_planner_agent/initial.session.json"
)
3. adk eval
- 通过命令行运行评估¶
你还可以通过命令行界面(CLI)运行评估集文件的评估。这运行与在 UI 上运行的相同评估,但有助于自动化,即你可以将此命令添加为常规构建生成和验证过程的一部分。
以下是命令:
adk eval \
<AGENT_MODULE_FILE_PATH> \
<EVAL_SET_FILE_PATH> \
[--config_file_path=<PATH_TO_TEST_JSON_CONFIG_FILE>] \
[--print_detailed_results]
例如:
adk eval \
samples_for_testing/hello_world \
samples_for_testing/hello_world/hello_world_eval_set_001.evalset.json
以下是每个命令行参数的详细信息:
AGENT_MODULE_FILE_PATH
:包含名为"agent"的模块的init.py
文件的路径。"agent"模块包含一个root_agent
。EVAL_SET_FILE_PATH
:评估文件的路径。你可以指定一个或多个评估集文件路径。对于每个文件,默认情况下将运行所有 evals。如果你只想从评估集运行特定的 evals,首先创建一个逗号分隔的 eval 名称列表,然后将其作为后缀添加到评估集文件名中,以冒号:
分隔。- 例如:
sample_eval_set_file.json:eval_1,eval_2,eval_3
这将只运行sample_eval_set_file.json中的eval_1、eval_2和eval_3
CONFIG_FILE_PATH
:配置文件的路径。PRINT_DETAILED_RESULTS
:在控制台上打印详细结果。