Skip to main content

概述

在本教程中,我们将使用 LangGraph 构建一个 检索 代理。 LangChain 提供了内置的 代理 实现,这些实现是使用 LangGraph 原语构建的。如果需要更深入的定制,可以直接在 LangGraph 中实现代理。本指南演示了检索代理的一个示例实现。检索 代理在您希望 LLM 决定是否从向量存储中检索上下文或直接响应用户时非常有用。 在本教程结束时,我们将完成以下操作:
  1. 获取并预处理将用于检索的文档。
  2. 索引这些文档以进行语义搜索并为代理创建检索器工具。
  3. 构建一个可以决定何时使用检索器工具的代理式 RAG 系统。
混合 RAG

概念

我们将涵盖以下概念:

设置

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

1. 预处理文档

  1. 获取将在我们的 RAG 系统中使用的文档。我们将使用 Lilian Weng 的优秀博客 上最新的三个页面。我们首先使用 WebBaseLoader 实用程序获取页面的内容:
  1. 将获取的文档拆分为较小的块以便索引到我们的向量存储中:

2. 创建检索器工具

现在我们已经有了拆分好的文档,我们可以将它们索引到一个向量存储中,我们将用它来进行语义搜索。
  1. 使用内存中的向量存储和 OpenAI 嵌入:
  1. 使用 @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 生成最终响应
可视化该图:
SQL 代理图

8. 运行代理式 RAG

现在让我们通过用问题运行它来测试完整的图:
输出: