Skip to main content
在本教程中,您将学习如何构建一个能够回答关于 SQL 数据库问题的代理。您将以两种方式构建代理:
  1. 使用最少代码构建代理
  2. 使用 LangGraph 构建自定义工作流
从高层次来看,该代理将执行以下步骤:
1

从数据库中获取可用的表和模式

2

确定哪些表与问题相关

3

根据问题和模式信息生成查询语句

4

对查询语句进行安全检查,以限制 LLM 生成查询语句可能带来的影响

5

执行查询并返回结果

6

根据数据库引擎反馈的错误修正查询语句,直到查询成功

7

基于查询结果生成最终回复

构建基于 SQL 数据库的问答系统需要执行模型生成的 SQL 查询语句,这本身存在固有风险。请确保您的数据库连接权限始终尽可能严格地限制在代理所需的最小范围内。这虽然不能完全消除风险,但可以显著降低构建模型驱动系统所带来的潜在威胁。

开始之前

  1. 安装依赖项:
  2. 设置 LangSmith,以便检查链或代理内部的运行情况。然后设置以下环境变量:

使用最少代码构建代理

1. 选择一个 LLM

选择一个支持工具调用的模型:
👉 Read the OpenAI integration docs
以下示例中的输出使用的是 OpenAI 模型。

2. 配置数据库

在本教程中,您将创建一个 SQLite 数据库。SQLite 是一种轻量级数据库,易于设置和使用。我们将加载 chinook 数据库,这是一个代表数字媒体商店的示例数据库。 为方便起见,我们已将数据库文件 (Chinook.db) 托管在公共 GCS 存储桶上。

3. 添加用于数据库交互的工具

使用 langchain_community 包中提供的 SQLDatabase 封装器与数据库交互。该封装器提供了一个简单的接口用于执行 SQL 查询并获取结果:
您将提取有助于 LLM 生成查询语句的数据库信息,并将其存储在 LLM 提示中。

4. 执行 SQL 查询

在执行命令前,先通过 _safe_sql 函数检查 LLM 生成的命令:
然后,使用 SQLDatabaserun 方法配合 execute_sql 工具执行命令:

5. 使用 create_agent

使用 create_agent 以最少代码构建一个 ReAct 代理。该代理将解析请求并生成 SQL 命令。工具将检查命令的安全性,然后尝试执行命令。如果命令出错,错误消息将返回给模型。模型随后可以检查原始请求和新的错误消息,并生成一个新的命令。此过程可以持续进行,直到 LLM 成功生成命令或达到最大尝试次数。这种向模型提供反馈(在此处为错误消息)的模式非常强大。 使用描述性的系统提示初始化代理,以自定义其行为:
现在,使用模型、工具和提示创建代理:

5. 运行代理

在示例查询上运行代理并观察其行为:
代理正确地编写了查询语句,检查了查询语句,并执行了查询以生成最终回复。
您可以在 LangSmith 跟踪 中检查上述运行的所有细节,包括所采取的步骤、调用的工具、LLM 接收到的提示等。

(可选)使用 Studio

Studio 提供了“客户端侧”循环以及内存功能,因此您可以将其作为聊天界面运行并查询数据库。您可以提出诸如“告诉我数据库的模式”或“显示前 5 名客户的发票”之类的问题。您将看到生成的 SQL 命令及其输出结果。有关如何启动的详细信息如下。
除了之前提到的包之外,您还需要:
在您要运行的目录中,您需要一个包含以下内容的 langgraph.json 文件:
请创建一个文件 sql_agent.py 并插入以下内容:

构建自定义工作流

预构建的代理让我们可以快速上手,但在每一步中,代理都可以访问完整的工具集。我们可以通过在 LangGraph 中自定义代理来实现更高级别的控制。下面,我们将实现一个简单的 ReAct 代理设置,为特定任务设置专用节点。我们将把客户信息添加到 状态 中。 你将构建一个专用节点,用于为特定客户设置数据库。客户节点将获取客户 ID 并将其存储到状态中。 将步骤放入专用节点中,可以让你(1)控制工作流,以及(2)自定义与每个步骤关联的提示。

1. 初始化模型和数据库

如上所述,我们初始化模型和数据库。

2. 定义状态

你将创建一个图(graph)。该图的状态如前所述包含消息,但新增了用于在各节点间跟踪客户信息的字段。这些字段将在工具中被引用,因此现在需要先对其进行定义。

3. 定义工具

在本示例中,你将对客户可访问的内容施加限制。LLM 提示词将反映这一限制,但实际的强制执行将在调用工具时进行。此模型扩展了 _safe_sql 的作用范围。
现在,让我们更新 execute_sql 工具。请注意一个有趣的点:工具会在 ToolNode 中执行时,由图 注入 图状态到该函数中。这免除了 LLM 需要知道该参数的负担。在此情况下,我们不会将客户 ID 传递给 LLM。
让我们定义 LLM 生成 SQL 时将使用的系统提示词:

4. 添加节点和边

现在,让我们构建图,从节点和边开始。
identify 节点接收客户的姓名作为输入,在数据库中查找客户 ID,并将其存储在状态中。如果客户不在数据库中,则返回一条消息。
我们假设客户姓名是从 invoke 函数传入图的输入。未来可扩展此图,例如加入用户登录和身份验证功能。
如果用户未知,该节点将为用户生成一条消息。此节点未来可扩展为记录非客户尝试访问的日志。
以下节点构成一个标准的 ReAct 循环。
最后,我们构建并编译图。
我们可在下方可视化该应用:
SQL agent graph 现在我们可以像之前一样调用图:
请参阅 LangSmith 跟踪记录 以查看上述运行详情。

后续步骤

请参阅评估图指南,了解如何使用 LangSmith 评估 LangGraph 应用程序,包括像这样的 SQL 代理。