Skip to main content
在本教程中,我们将构建一个检索代理。当您希望大语言模型(LLM)自主决定是否从向量数据库中检索上下文,或直接回应用户时,检索代理非常有用。 在本教程结束时,我们将完成以下步骤:
  1. 获取并预处理用于检索的文档。
  2. 为这些文档建立索引以支持语义搜索,并为代理创建一个检索器工具。
  3. 构建一个代理式 RAG 系统,能够自主决定何时使用检索器工具。
混合式 RAG

设置

让我们先下载所需的包并设置 API 密钥:
注册 LangSmith,可快速发现并提升您的 LangGraph 项目性能。LangSmith 允许您使用跟踪数据来调试、测试和监控基于 LangGraph 构建的 LLM 应用。

1. 预处理文档

  1. 获取将在我们的 RAG 系统中使用的文档。我们将使用 Lilian Weng 的优秀博客 中最近的三篇文章。首先,使用 WebBaseLoader 工具获取页面内容:
  1. 将获取的文档分割成更小的块,以便索引到我们的向量存储中:

2. 创建检索器工具

现在我们有了分割好的文档,可以将它们索引到一个用于语义搜索的向量存储中。
  1. 使用内存中的向量存储和 OpenAI 嵌入:
  1. 使用 LangChain 预构建的 create_retriever_tool 创建一个检索器工具:
  1. 测试该工具:

3. 生成查询

现在我们将开始构建代理式 RAG 图的组件(节点)。 请注意,这些组件将在 MessagesState 上操作——该图状态包含一个带有聊天消息列表的 messages 键。
  1. 构建 generate_query_or_respond 节点。它将调用一个 LLM,根据当前图状态(消息列表)生成响应。根据输入消息,它将决定是使用检索器工具进行检索,还是直接回应用户。注意,我们通过 .bind_tools 让聊天模型访问我们之前创建的 retriever_tool
  1. 在随机输入上尝试:
输出:
  1. 问一个需要语义搜索的问题:
输出:

4. 评估文档

  1. 添加一个条件边grade_documents — 以确定检索到的文档是否与问题相关。我们将使用具有结构化输出模式 GradeDocuments 的模型进行文档评分。grade_documents 函数将根据评分决策返回要前往的节点名称(generate_answerrewrite_question):
  1. 在工具响应中包含不相关文档的情况下运行:
  1. 确认相关文档被正确分类:

5. 重写问题

  1. 构建 rewrite_question 节点。检索器工具可能返回潜在的不相关文档,这表明需要改进原始用户问题。为此,我们将调用 rewrite_question 节点:
  1. 尝试一下:
输出:

6. 生成答案

  1. 构建 generate_answer 节点:如果我们通过了评分检查,就可以根据原始问题和检索到的上下文生成最终答案:
  1. 试试看:
输出:

7. 组装图

  • generate_query_or_respond 开始,确定是否需要调用 retriever_tool
  • 使用 tools_condition 路由到下一步:
    • 如果 generate_query_or_respond 返回了 tool_calls,则调用 retriever_tool 来检索上下文
    • 否则,直接回应用户
  • 对检索到的文档内容进行相关性评分(grade_documents),并路由到下一步:
    • 如果不相关,使用 rewrite_question 重写问题,然后再次调用 generate_query_or_respond
    • 如果相关,则进入 generate_answer,并使用包含检索文档上下文的 ToolMessage 生成最终响应
可视化图:

8. 运行代理式 RAG

输出:
:::js 我们可以在 LangGraph 中实现 检索代理

设置

加载环境变量

./examples 文件夹的根目录下添加一个包含您的变量的 .env 文件。

安装依赖

检索器

代理状态

我们将定义一个图。 您可以向图传递一个自定义的 state 对象,或者使用一个简单的 messages 列表。 我们的状态将是一个 messages 列表。 图中的每个节点都会向其追加内容。

节点和边

每个节点将 - 1/ 要么是一个函数,要么是一个可运行对象。 2/ 修改 state 边选择接下来调用哪个节点。 我们可以这样布局一个代理式 RAG 图: 混合式 RAG