Skip to main content
在本教程中,我们将构建一个客户支持机器人,帮助用户在数字音乐商店中导航。然后,我们将介绍针对聊天机器人运行三种最有效的评估类型:
  • 最终响应:评估智能体的最终回复。
  • 轨迹:评估智能体是否遵循了预期路径(例如工具调用序列)以得出最终答案。
  • 单步:孤立地评估智能体的任何步骤(例如,对于给定步骤是否选择了适当的第一个工具)。
我们将使用 LangGraph 构建智能体,但此处展示的技术和 LangSmith 功能与框架无关。

环境设置

配置环境

让我们安装所需的依赖项:
让我们为 OpenAI 和 LangSmith 设置环境变量:

下载数据库

我们将为本教程创建一个 SQLite 数据库。SQLite 是一个轻量级数据库,易于设置和使用。我们将加载 chinook 数据库,这是一个代表数字媒体商店的示例数据库。有关更多信息,请参阅 Chinook 示例数据库 为了方便起见,我们将数据库托管在一个公共 GCS 存储桶中:
以下是数据库中数据的示例:
以下是数据库模式(图片来自 https://github.com/lerocha/chinook-database): Chinook 数据库

定义客户支持智能体

我们将创建一个对数据库访问权限有限的 LangGraph 智能体。出于演示目的,我们的智能体将支持两种基本类型的请求:
  • 查询:客户可以根据其他标识信息查找歌曲标题、艺术家姓名和专辑。例如:“你们有哪些 Jimi Hendrix 的歌曲?”
  • 退款:客户可以要求退还他们过去购买的款项。例如:“我叫 Claude Shannon,我想退还上周购买的一件商品,你能帮我吗?”
为了简化本演示,我们将通过删除相应的数据库记录来实现退款。我们将跳过实现用户身份验证和其他生产安全措施。 智能体的逻辑将构建为两个独立的子图(一个用于查询,一个用于退款),并带有一个将请求路由到相应子图的父图。

退款智能体

让我们构建退款处理智能体。该智能体需要:
  1. 在数据库中找到客户的购买记录
  2. 删除相关的 Invoice 和 InvoiceLine 记录以处理退款
我们将创建两个 SQL 辅助函数:
  1. 一个通过删除记录来执行退款的函数
  2. 一个查找客户购买历史记录的函数
为了简化测试,我们将为这些函数添加一个“模拟”模式。当启用模拟模式时,这些函数将模拟数据库操作,而不实际修改任何数据。
现在让我们定义我们的图。我们将使用一个包含三个主要路径的简单架构:
  1. 从对话中提取客户和购买信息
  2. 将请求路由到以下三个路径之一:
    • 退款路径:如果我们有足够的购买详细信息(发票 ID 或发票行 ID)来处理退款
    • 查询路径:如果我们有足够的客户信息(姓名和电话)来搜索他们的购买历史记录
    • 回复路径:如果需要更多信息,则回复用户请求他们提供具体的详细信息
图的状态将跟踪:
  • 对话历史记录(用户和智能体之间的消息)
  • 从对话中提取的所有客户和购买信息
  • 要发送给用户的下一条消息(后续文本)
我们可以可视化我们的退款图:
退款图

查询智能体

对于查询(即问答)智能体,我们将使用一个简单的 ReACT 架构,并为智能体提供用于根据各种过滤器查找曲目名称、艺术家姓名和专辑名称的工具。例如,您可以按特定艺术家查找专辑,按特定歌曲名称查找艺术家等。
查询图

父智能体

现在让我们定义一个结合了两个特定任务智能体的父智能体。父智能体的唯一工作是通过分类用户当前意图来路由到子智能体之一,并将输出编译为后续消息。
我们可以可视化编译后的父图,包括其所有子图:
图

试一试

让我们来试用一下我们的自定义支持智能体!

评估

现在我们有了一个可测试版本的智能体,让我们运行一些评估。智能体评估至少可以关注以下 3 个方面:
  • 最终响应:输入是一个提示和可选的工具列表。输出是智能体的最终响应。
  • 轨迹:与之前一样,输入是一个提示和可选的工具列表。输出是工具调用列表。
  • 单步:与之前一样,输入是一个提示和可选的工具列表。输出是工具调用。
让我们运行每种类型的评估:

最终响应评估器

首先,让我们创建一个数据集来评估智能体的端到端性能。为简单起见,我们将对最终响应和轨迹评估使用相同的数据集,因此我们将为每个示例问题添加真实响应和轨迹。我们将在下一节介绍轨迹。
我们将创建一个自定义的 LLM 作为评判员 评估器,使用另一个模型将我们智能体在每个示例上的输出与参考响应进行比较,并判断它们是否等价:
现在我们可以运行评估了。我们的评估器假设我们的目标函数返回一个 ‘response’ 键,所以让我们定义一个这样做的目标函数。 另外请记住,在我们的退款图中,我们使退款节点可配置,这样如果我们指定 config={"env": "test"},我们将模拟退款而不实际更新数据库。在调用我们的图时,我们将在目标 run_graph 方法中使用此可配置变量:
您可以在此处查看这些结果:LangSmith 链接

轨迹评估器

随着智能体变得越来越复杂,它们拥有更多潜在的故障点。与其使用简单的通过/失败评估,通常最好使用可以在智能体采取了一些正确步骤(即使没有得出正确的最终答案)时给予部分分数的评估。 这就是轨迹评估的用武之地。轨迹评估:
  1. 将智能体采取的实际步骤序列与预期序列进行比较
  2. 根据正确完成的预期步骤数量计算得分
对于此示例,我们的端到端数据集包含我们希望智能体采取的有序步骤列表。让我们创建一个评估器,检查智能体的实际轨迹与这些预期步骤,并计算完成了多少百分比:
现在我们可以运行评估了。我们的评估器假设我们的目标函数返回一个 ‘trajectory’ 键,所以让我们定义一个这样做的目标函数。我们需要使用 LangGraph 的流式功能 来记录轨迹。 请注意,我们正在重用与最终响应评估相同的数据集,因此我们可以同时运行两个评估器,并定义一个同时返回 “response” 和 “trajectory” 的目标函数。在实践中,为每种评估类型设置单独的数据集通常很有用,这就是我们在此分别展示它们的原因:
您可以在此处查看这些结果:LangSmith 链接

单步评估器

虽然端到端测试为您提供有关智能体性能的最多信号,但出于调试和迭代智能体的目的,查明困难的特定步骤并直接评估它们可能会有所帮助。 在我们的案例中,智能体的一个关键部分是将用户意图正确路由到“退款”路径或“问答”路径。让我们创建一个数据集并运行一些评估来直接对这一个组件进行压力测试。
您可以在此处查看这些结果:LangSmith 链接

参考代码

以下是包含上述所有代码的合并脚本: