Skip to content

为什么要评估智能体

python_only

在传统软件开发中,单元测试和集成测试提供了代码按预期运行并在变更中保持稳定的信心。这些测试提供了明确的"通过/失败"信号,指导进一步的开发。然而,LLM 智能体引入了一定程度的变异性,使得传统的测试方法不够充分。

由于模型的概率性特质,确定性的"通过/失败"断言通常不适合评估智能体性能。相反,我们需要对最终输出和智能体轨迹(达成解决方案所采取的步骤序列)进行定性评估。这涉及评估智能体决策的质量、推理过程以及最终结果。

这看起来可能需要额外的工作量来搭建,但自动化评估的投入很快就会得到回报。如果你打算超越原型阶段,这是一个强烈推荐的最佳实践。

intro_components.png

准备智能体评估

在自动化智能体评估之前,定义明确的目标和成功标准:

  • 定义成功: 什么构成了你的智能体的成功结果?
  • 识别关键任务: 你的智能体必须完成哪些基本任务?
  • 选择相关指标: 你将跟踪哪些指标来衡量性能?

这些考虑因素将指导评估场景的创建,并能够有效监控智能体在真实部署中的行为。

评估什么?

要从概念验证过渡到生产就绪的 AI 智能体,一个强大且自动化的评估框架至关重要。与评估生成式模型不同(主要关注最终输出),智能体评估需要更深入地理解决策过程。智能体评估可以分为两个组成部分:

  1. 评估轨迹和工具使用: 分析智能体达成解决方案所采取的步骤,包括其工具选择、策略以及方法的效率。
  2. 评估最终响应: 评估智能体最终输出的质量、相关性和正确性。

轨迹只是智能体在返回给用户之前所采取的步骤列表。我们可以将其与我们期望智能体采取的步骤列表进行比较。

评估轨迹和工具使用

在响应用户之前,智能体通常会执行一系列操作,我们称之为"轨迹"。它可能会将用户输入与会话历史进行比较以消除术语歧义,或查阅政策文档、搜索知识库或调用 API 来保存工单。我们称这一系列操作为行动"轨迹"。评估智能体的性能需要将其实际轨迹与预期或理想轨迹进行比较。这种比较可以揭示智能体过程中的错误和低效之处。预期轨迹代表了基准事实——我们预计智能体应该采取的步骤列表。

例如:

// 轨迹评估将比较
expected_steps = ["determine_intent", "use_tool", "review_results", "report_generation"]
actual_steps = ["determine_intent", "use_tool", "review_results", "report_generation"]

存在几种基于基准事实的轨迹评估:

  1. 精确匹配: 要求与理想轨迹完全匹配。
  2. 顺序匹配: 要求正确动作按正确顺序,允许有额外动作。
  3. 任意顺序匹配: 要求正确动作,但顺序不限,允许有额外动作。
  4. 精确度: 衡量预测动作的相关性/正确性。
  5. 召回率: 衡量预测中包含了多少必要动作。
  6. 单工具使用: 检查是否包含特定动作。

选择正确的评估指标取决于你的智能体的具体要求和目标。例如,在高风险场景中,精确匹配可能至关重要,而在更灵活的情况下,顺序匹配或任意顺序匹配可能就足够了。

ADK 中评估如何工作

ADK 提供了两种方法来根据预定义的数据集和评估标准评估智能体性能。虽然概念上相似,但它们在能处理的数据量上有所不同,这通常决定了每种方法的适用场景。

第一种方法:使用测试文件

这种方法涉及创建单独的测试文件,每个文件代表一个简单的智能体 - 模型交互(一个会话)。它在活跃的智能体开发阶段最有效,作为单元测试的一种形式。这些测试旨在快速执行,应专注于简单的会话复杂性。每个测试文件包含单个会话,而会话可能包含多个轮次。一个轮次代表用户和智能体之间的单次交互。每个轮次包括:

  • User Content: 用户发出的查询。
  • Expected Intermediate Tool Use Trajectory: 我们期望智能体为正确响应用户查询而进行的工具调用。
  • Expected Intermediate Agent Responses: 这些是智能体(或子智能体)在生成最终答案过程中产生的自然语言响应。这些自然语言响应通常是多智能体系统的产物,其中你的根智能体依赖子智能体来实现目标。这些中间响应对于终端用户来说可能并不重要,但对于系统开发者/拥有者来说至关重要,因为它们能让你确信智能体走对了生成最终响应的路径。
  • Final Response: 智能体的预期最终响应。

你可以给文件起任何名字,例如evaluation.test.json。框架只检查.test.json后缀,文件名的前面部分没有限制。以下是包含几个示例的测试文件:

注意:评估集文件现在由正式的 Pydantic 数据模型支持。两个关键的 schema 文件是 Eval SetEval Case

# 请注意,为了使本文档可读,删除了一些字段。
{
  "eval_set_id": "home_automation_agent_light_on_off_set",
  "name": "",
  "description": "这是一个用于单元测试智能体 `x` 行为的评估集",
  "eval_cases": [
    {
      "eval_id": "eval_case_id",
      "conversation": [
        {
          "invocation_id": "b7982664-0ab6-47cc-ab13-326656afdf75", # 调用的唯一标识符。
          "user_content": { # 用户在此调用中提供的内容。这是查询。
            "parts": [
              {
                "text": "关闭卧室的 device_2。"
              }
            ],
            "role": "user"
          },
          "final_response": { # 智能体的最终响应,作为基准参考。
            "parts": [
              {
                "text": "我已将 device_2 状态设置为关闭。"
              }
            ],
            "role": "model"
          },
          "intermediate_data": {
            "tool_uses": [ # 按时间顺序排列的工具使用轨迹。
              {
                "args": {
                  "location": "Bedroom",
                  "device_id": "device_2",
                  "status": "OFF"
                },
                "name": "set_device_info"
              }
            ],
            "intermediate_responses": [] # 任何中间子智能体响应。
          },
        }
      ],
      "session_input": { # 初始会话输入。
        "app_name": "home_automation_agent",
        "user_id": "test_user",
        "state": {}
      },
    }
  ],
}

测试文件可以组织到文件夹中。可选地,文件夹还可以包含一个test_config.json文件,指定评估标准。

如何迁移未遵循 Pydantic schema 的评测集文件?

注意:如果你的评测集文件没有遵循 EvalSet schema 文件,那么本节内容与你相关。

根据谁在维护评测集数据,有两种方式:

  1. 由 ADK UI 维护的评测集数据 如果你使用 ADK UI 维护评测集数据,那么你无需采取任何操作

  2. 评测集数据由你手动开发和维护,并在 ADK eval Cli 中使用 迁移工具正在开发中,在此之前,ADK eval cli 命令会继续支持旧格式的数据。

第二种方法:使用评估集文件

评估集方法使用称为"evalset"的专用数据集来评估智能体 - 模型交互。与测试文件类似,评估集包含示例交互。但是,一个评估集可以包含多个可能较长的会话,这使它非常适合模拟复杂的多轮对话。由于能够表示复杂会话,评估集非常适合集成测试。这些测试由于其更广泛的性质,通常比单元测试运行得少。

评估集文件包含多个"evals",每个代表一个不同的会话。每个 eval 由一个或多个"轮次"组成,其中包括用户查询、预期工具使用、预期中间智能体响应和参考响应。这些字段与测试文件方法中的含义相同。每个 eval 都由唯一名称标识。此外,每个 eval 都包括相关的初始会话状态。

手动创建评估集可能很复杂,因此提供了 UI 工具来帮助捕获相关会话并轻松将它们转换为评估集中的 evals。在下面了解更多关于使用 Web UI 进行评估的信息。以下是包含两个会话的评估集示例。

注意:评估集文件现在由正式的 Pydantic 数据模型支持。两个关键的 schema 文件是 Eval SetEval Case

# 请注意,为了使本文档可读,删除了一些字段。
{
  "eval_set_id": "eval_set_example_with_multiple_sessions",
  "name": "包含多个会话的评估集",
  "description": "这个评估集是一个示例,显示评估集可以有多个会话。",
  "eval_cases": [
    {
      "eval_id": "session_01",
      "conversation": [
        {
          "invocation_id": "e-0067f6c4-ac27-4f24-81d7-3ab994c28768",
          "user_content": {
            "parts": [
              {
                "text": "你能做什么?"
              }
            ],
            "role": "user"
          },
          "final_response": {
            "parts": [
              {

                "text": "我可以掷不同大小的骰子并检查数字是否为质数。"
              }
            ],
            "role": null
          },
          "intermediate_data": {
            "tool_uses": [],
            "intermediate_responses": []
          },
        },
      ],
      "session_input": {
        "app_name": "hello_world",
        "user_id": "user",
        "state": {}
      },
    },
    {
      "eval_id": "session_02",
      "conversation": [
        {
          "invocation_id": "e-92d34c6d-0a1b-452a-ba90-33af2838647a",
          "user_content": {
            "parts": [
              {
                "text": "掷一个 19 面骰子"
              }
            ],
            "role": "user"
          },
          "final_response": {
            "parts": [
              {
                "text": "我掷出了 17。"
              }
            ],
            "role": null
          },
          "intermediate_data": {
            "tool_uses": [],
            "intermediate_responses": []
          },
        },
        {
          "invocation_id": "e-bf8549a1-2a61-4ecc-a4ee-4efbbf25a8ea",
          "user_content": {
            "parts": [
              {
                "text": "掷两次 10 面骰子,然后检查 9 是否为质数"
              }
            ],
            "role": "user"
          },
          "final_response": {
            "parts": [
              {
                "text": "我从骰子掷出了 4 和 7,9 不是质数。\n"
              }
            ],
            "role": null
          },
          "intermediate_data": {
            "tool_uses": [
              {
                "id": "adk-1a3f5a01-1782-4530-949f-07cf53fc6f05",
                "args": {
                  "sides": 10
                },
                "name": "roll_die"
              },
              {
                "id": "adk-52fc3269-caaf-41c3-833d-511e454c7058",
                "args": {
                  "sides": 10
                },
                "name": "roll_die"
              },
              {
                "id": "adk-5274768e-9ec5-4915-b6cf-f5d7f0387056",
                "args": {
                  "nums": [
                    9
                  ]
                },
                "name": "check_prime"
              }
            ],
            "intermediate_responses": [
              [
                "data_processing_agent",
                [
                  {
                    "text": "我已经掷了两次 10 面骰子。第一次掷出 5,第二次掷出 3。\n"
                  }
                ]
              ]
            ]
          },
        }
      ],
      "session_input": {
        "app_name": "hello_world",
        "user_id": "user",
        "state": {}
      },
    }
  ],
}

如何迁移未遵循 Pydantic schema 的评估集文件?

注意:如果你的评估集文件没有遵循 EvalSet schema 文件,那么本节内容与你相关。

根据谁在维护评估集数据,有两种方式:

  1. 由 ADK UI 维护的评估集数据 如果你使用 ADK UI 维护评估集数据,那么你无需采取任何操作

  2. 评估集数据由你手动开发和维护,并在 ADK eval Cli 中使用 迁移工具正在开发中,在此之前,ADK eval cli 命令会继续支持旧格式的数据。

评估标准

评估标准定义了如何根据评估集衡量智能体的性能。支持以下指标:

  • 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文件示例:

{
  "criteria": {
    "tool_trajectory_avg_score": 1.0,
    "response_match_score": 0.8
  }
}

如何在 ADK 中运行评估

作为开发者,你可以通过以下方式使用 ADK 评估你的智能体:

  1. 基于 Web 的 UI(adk web): 通过基于 Web 的界面交互式评估智能体。
  2. 编程方式(pytest: 使用pytest和测试文件将评估集成到你的测试流程中。
  3. 命令行界面(adk eval): 直接从命令行对现有评估集文件运行评估。

1. adk web - 通过 Web UI 运行评估

Web UI 提供了一种交互式方式来评估智能体并生成评估数据集。

通过 Web UI 运行评估的步骤:

  1. 运行以下命令启动 Web 服务器:bash adk web samples_for_testing
  2. 在 Web 界面中:
    • 选择一个智能体(例如,hello_world)。
    • 与智能体交互,创建你想要保存为测试用例的会话。
    • 点击界面右侧的"Eval 标签"
    • 如果你已经有现有的评估集,选择它或通过点击"创建新评估集"按钮创建新的评估集。给你的评估集一个有上下文的名称。选择新创建的评估集。
    • 点击"添加当前会话"将当前会话保存为评估集文件中的 eval。系统会要求你为此 eval 提供一个名称,同样给它一个有上下文的名称。
    • 创建后,新创建的 eval 将显示在评估集文件的可用 evals 列表中。你可以运行所有 evals 或选择特定的 evals 来运行评估。
    • 每个 eval 的状态将显示在 UI 中。

2. pytest - 以编程方式运行测试

你还可以使用pytest作为集成测试的一部分运行测试文件。

示例命令

pytest tests/integration/

示例测试代码

以下是运行单个测试文件的pytest测试用例示例:

from google.adk.evaluation.agent_evaluator import AgentEvaluator

def test_with_single_test_file():
    """通过会话文件测试智能体的基本能力。"""
    AgentEvaluator.evaluate(
        agent_module="home_automation_agent",
        eval_dataset_file_path_or_dir="tests/integration/fixture/home_automation_agent/simple_test.test.json",
    )

这种方法允许你将智能体评估集成到 CI/CD 流程或更大的测试套件中。如果你想为测试指定初始会话状态,可以通过在文件中存储会话详情并将其传递给AgentEvaluator.evaluate方法来实现。

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:在控制台上打印详细结果。