Skip to main content

概述

本教程将帮助你熟悉 LangChain 的文档加载器嵌入模型向量存储抽象。这些抽象旨在支持从(向量)数据库和其他来源检索数据,以便集成到 LLM 工作流中。对于需要获取数据以在模型推理过程中进行推理的应用程序(例如检索增强生成或 RAG)来说,它们非常重要。 在这里,我们将构建一个基于 PDF 文档的搜索引擎。这将允许我们检索 PDF 中与输入查询相似的段落。本指南还包括在搜索引擎基础上实现的一个最小 RAG 示例。

概念

本指南侧重于文本数据的检索。我们将涵盖以下概念:

设置

安装

本教程需要 langchain-communitypypdf 包:
更多详情,请参阅我们的安装指南

LangSmith

使用 LangChain 构建的许多应用程序将包含多个步骤和多次 LLM 调用。随着这些应用程序变得越来越复杂,能够检查链或代理内部究竟发生了什么变得至关重要。最好的方法是使用 LangSmith 在通过上方链接注册后,请确保设置环境变量以开始记录追踪:
或者,如果在 notebook 中,可以这样设置:

1. 文档和文档加载器

LangChain 实现了 Document 抽象,旨在表示一个文本单元及其关联的元数据。它有三个属性:
  • page_content:表示内容的字符串;
  • metadata:包含任意元数据的字典;
  • id:(可选)文档的字符串标识符。
metadata 属性可以捕获有关文档来源、其与其他文档的关系以及其他信息。请注意,单个 Document 对象通常代表较大文档的一个块。 我们可以在需要时生成示例文档:
然而,LangChain 生态系统实现了与数百个常见源集成的文档加载器。这使得可以轻松地将这些来源的数据整合到你的 AI 应用程序中。

加载文档

让我们将一个 PDF 加载到一系列 Document 对象中。这里是一个示例 PDF —— 耐克 2023 年的 10-k 文件。我们可以查阅 LangChain 文档以了解可用的 PDF 文档加载器
PyPDFLoader 为每个 PDF 页面加载一个 Document 对象。对于每个对象,我们可以轻松访问:
  • 页面的字符串内容;
  • 包含文件名和页码的元数据。

分割

对于信息检索和下游问答目的,页面可能是一个过于粗糙的表示。我们的最终目标是检索能够回答输入查询的 Document 对象,进一步分割我们的 PDF 将有助于确保文档相关部分的意义不会被周围的文本“冲淡”。 我们可以为此使用文本分割器。这里我们将使用一个基于字符进行分区的简单文本分割器。我们将把文档分割成 1000 个字符的块,块之间有 200 个字符的重叠。重叠有助于减轻将语句与其重要上下文分离的可能性。我们使用 RecursiveCharacterTextSplitter,它将使用常见分隔符(如换行符)递归地分割文档,直到每个块达到适当的大小。这是通用文本用例的推荐文本分割器。 我们设置 add_start_index=True,以便将每个分割后的 Document 在初始 Document 中开始的字符索引作为元数据属性“start_index”保留。

2. 嵌入模型

向量搜索是存储和搜索非结构化数据(如非结构化文本)的常见方法。其思想是存储与文本关联的数字向量。给定一个查询,我们可以将其嵌入为相同维度的向量,并使用向量相似性度量(如余弦相似度)来识别相关文本。 LangChain 支持来自数十个提供商的嵌入模型。这些模型指定了如何将文本转换为数字向量。让我们选择一个模型:
有了生成文本嵌入的模型,接下来我们可以将它们存储在支持高效相似性搜索的特殊数据结构中。

3. 向量存储

LangChain VectorStore 对象包含将文本和 Document 对象添加到存储中的方法,以及使用各种相似性度量进行查询的方法。它们通常使用嵌入模型进行初始化,嵌入模型决定了文本数据如何转换为数字向量。 LangChain 包含一系列与不同向量存储技术的集成。一些向量存储由提供商托管(例如,各种云提供商),需要使用特定的凭据;一些(如 Postgres)运行在可以本地运行或通过第三方运行的独立基础设施中;其他可以内存运行以处理轻量级工作负载。让我们选择一个向量存储:
实例化向量存储后,我们现在可以对文档建立索引。
请注意,大多数向量存储实现都允许你连接到现有的向量存储——例如,通过提供客户端、索引名称或其他信息。有关更多详细信息,请参阅特定集成的文档。 一旦我们实例化了包含文档的 VectorStore,我们就可以查询它。VectorStore 包含用于查询的方法:
  • 同步和异步;
  • 通过字符串查询和向量;
  • 返回和不返回相似性分数;
  • 通过相似性和 最大边际相关性(以平衡查询相似性与检索结果的多样性)。
这些方法通常在其输出中包含一个 Document 对象列表。 用法 嵌入通常将文本表示为“密集”向量,使得具有相似含义的文本在几何上接近。这使我们能够仅通过传入问题来检索相关信息,而无需了解文档中使用的任何特定关键术语。 根据与字符串查询的相似性返回文档:
异步查询:
返回分数:
根据与嵌入查询的相似性返回文档:
了解更多:

4. 检索器

LangChain VectorStore 对象不继承 Runnable。LangChain Retrievers 是 Runnables,因此它们实现了一组标准方法(例如,同步和异步的 invokebatch 操作)。虽然我们可以从向量存储构建检索器,但检索器也可以与非向量存储数据源(如外部 API)交互。 我们可以自己创建一个简单版本,而不需要继承 Retriever。如果我们选择希望使用哪种方法来检索文档,我们可以轻松创建一个 runnable。下面我们将围绕 similarity_search 方法构建一个:
Vectorstores 实现了一个 as_retriever 方法,该方法将生成一个 Retriever,具体来说是 VectorStoreRetriever。这些检索器包含特定的 search_typesearch_kwargs 属性,用于标识要调用的底层向量存储的方法以及如何参数化它们。例如,我们可以使用以下方式复制上述内容:
VectorStoreRetriever 支持 "similarity"(默认)、"mmr"(最大边际相关性,如上所述)和 "similarity_score_threshold" 搜索类型。我们可以使用后者来根据相似性分数对检索器输出的文档进行阈值过滤。 检索器可以轻松地集成到更复杂的应用程序中,例如检索增强生成 (RAG) 应用程序,这些应用程序将给定问题与检索到的上下文结合到 LLM 的提示中。要了解有关构建此类应用程序的更多信息,请查看 RAG 教程 教程。

后续步骤

你现在已经了解了如何基于 PDF 文档构建语义搜索引擎。 有关文档加载器的更多信息: 有关嵌入模型的更多信息: 有关向量存储的更多信息: 有关 RAG 的更多信息,请参阅: