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

设置

配置环境

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

下载数据库

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

定义客户支持智能体

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

退款智能体

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

查询智能体

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

父智能体

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

试用一下

让我们试试我们自定义的支持智能体!

评估

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

最终响应评估器

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

轨迹评估器

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

单步评估器

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

参考代码

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