Skip to main content
Open on GitHub

检索

安全

此处回顾的某些概念会利用模型生成查询(例如,用于 SQL 或图数据库)。 这样做存在固有风险。 确保您的数据库连接权限仅限于满足您应用程序需求的最窄范围。 这将减轻(但不能完全消除)构建能够查询数据库的驱动模型系统的风险。 有关一般安全最佳实践的更多信息,请参阅我们的安全指南

概述

检索系统是许多 AI 应用的基础,能够高效地从大型数据集中识别相关信息。 这些系统支持各种数据格式:

  • 非结构化文本(例如,文档)通常存储在向量存储或词汇搜索索引中。
  • 结构化数据通常存储在具有已定义模式的关系数据库或图数据库中。

尽管数据格式日益多样化,但现代 AI 应用越来越倾向于通过自然语言界面访问所有类型的数据。 模型在此过程中发挥着至关重要的作用,它们将自然语言查询转换为与底层搜索索引或数据库兼容的格式。 这种转换能够实现与复杂数据结构更直观、更灵活的交互。

关键概念

Retrieval

(1) 查询分析:模型转换或构建搜索查询以优化检索的过程。

(2) 信息检索:搜索查询用于从各种检索系统中获取信息。

查询分析

虽然用户通常更喜欢使用自然语言与检索系统进行交互,但这些系统可能需要特定的查询语法或受益于某些关键字。 查询分析充当原始用户输入和优化搜索查询之间的桥梁。查询分析的一些常见应用包括:

  1. 查询重写:可以重写或扩展查询以改进语义或词汇搜索。
  2. 查询构建:搜索索引可能需要结构化查询(例如,SQL 数据库)。

查询分析利用模型从原始用户输入转换或构建优化的搜索查询。

查询重写

检索系统理想情况下应能处理各种用户输入,从简单、措辞不佳的查询到复杂、多方面的问题。 为了实现这种通用性,一种流行的方法是使用模型将原始用户查询转换为更有效的搜索查询。 这种转换可以从简单的关键词提取到复杂的查询扩展和改写。 以下是使用模型进行非结构化数据检索查询分析的一些关键优势:

  1. 查询澄清:模型可以重述模糊或措辞不佳的查询以获得清晰度。
  2. 语义理解:它们可以捕捉查询背后的意图,超越字面关键词匹配。
  3. 查询扩展:模型可以生成相关术语或概念来拓宽搜索范围。
  4. 复杂查询处理:它们可以将多部分问题分解为更简单的子查询。

已经开发了各种技术来利用模型进行查询重写,包括:

名称何时使用描述
Multi-query当您希望通过提供问题的多种措辞来确保检索中的高召回率时。使用多种措辞重写用户问题,为每个重写的问题检索文档,并为所有查询返回独特的文档。
Decomposition当一个问题可以分解为较小的子问题时。将问题分解为一组子问题/子问题,这些子问题可以按顺序(使用第一个检索的答案回答第二个)或并行解决(将每个答案合并成最终答案)。
Step-back当需要更高级的概念理解时。首先提示 LLM 询问有关更高级概念或原理的通用“回退”问题,并检索有关它们的相关事实。利用此基础来帮助回答用户问题。论文
HyDE如果您在使用原始用户输入检索相关文档时遇到困难。使用 LLM 将问题转换为回答该问题的假设文档。使用嵌入的假设文档检索真实文档,前提是文档-文档相似性搜索可以产生更相关的匹配项。论文

例如,查询分解可以通过仅使用提示和强制执行子问题列表的结构化输出来完成。 然后可以在下游检索系统上按顺序或并行运行这些。

from typing import List

from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage

# 定义一个 Pydantic 模型来强制输出结构
class Questions(BaseModel):
questions: List[str] = Field(
description="A list of sub-questions related to the input query."
)

# 创建模型的实例并强制输出结构
model = ChatOpenAI(model="gpt-4o", temperature=0)
structured_model = model.with_structured_output(Questions)

# 定义系统提示
system = """You are a helpful assistant that generates multiple sub-questions related to an input question. \n
The goal is to break down the input into a set of sub-problems / sub-questions that can be answered independently. \n"""

# 将问题传递给模型
question = """What are the main components of an LLM-powered autonomous agent system?"""
questions = structured_model.invoke([SystemMessage(content=system)]+[HumanMessage(content=question)])
tip

请参阅我们的“从头开始构建 RAG”视频,了解几种不同的具体方法:

查询构建

查询分析还可以侧重于将自然语言查询转换为专门的查询语言或过滤器。 这种转换对于有效地与存储结构化或半结构化数据的各种类型数据库进行交互至关重要。

  1. 结构化数据示例:对于关系数据库和图数据库,使用领域特定语言 (DSL) 来查询数据。

  2. 半结构化数据示例:对于向量存储,查询可以将语义搜索与元数据过滤相结合。

这些方法利用模型来弥合用户意图与不同数据存储系统特定查询要求之间的差距。以下是一些流行技术:

名称何时使用描述
Self Query如果用户提出的问题最好通过元数据过滤来检索文档,而不是与文本进行相似性匹配。这利用 LLM 将用户输入转换为两件事:(1)一个用于语义查找的字符串,(2)一个与之匹配的元数据过滤器。这很有用,因为问题通常是关于文档的元数据(而不是内容本身)。
Text to SQL如果用户提出的问题需要访问关系数据库中存储的信息,而该信息可以通过 SQL 访问。这利用 LLM 将用户输入转换为 SQL 查询。
Text-to-Cypher如果用户提出的问题需要访问图数据库中存储的信息,而该信息可以通过 Cypher 访问。这利用 LLM 将用户输入转换为 Cypher 查询。

例如,这是如何使用 SelfQueryRetriever 将自然语言查询转换为元数据过滤器。

metadata_field_info = schema_for_metadata 
document_content_description = "Brief summary of a movie"
llm = ChatOpenAI(temperature=0)
retriever = SelfQueryRetriever.from_llm(
llm,
vectorstore,
document_content_description,
metadata_field_info,
)
进一步阅读

信息检索

通用检索系统

词汇搜索索引

许多搜索引擎都基于将查询中的单词与每个文档中的单词进行匹配。 这种方法称为词汇检索,使用通常基于词频的搜索算法。 直观来说很简单:一个单词在用户的查询和特定文档中都频繁出现,那么该文档可能是一个很好的匹配项。

用于实现这一点的特定数据结构通常是 倒排索引。 此类型的索引包含单词列表以及每个单词在不同文档中出现位置的映射。 使用此数据结构,可以有效地将搜索查询中的单词与它们出现的文档进行匹配。 BM25TF-IDF两种流行的词汇搜索算法

进一步阅读

向量索引

向量索引是索引和存储非结构化数据的另一种方法。 有关详细概述,请参阅我们关于向量存储 的概念指南。 简而言之,向量存储不使用词频,而是使用嵌入模型 将文档压缩为高维向量表示。 这允许使用简单的数学运算(如余弦相似度)对嵌入向量进行高效的相似性搜索。

进一步阅读

关系数据库

关系数据库是许多应用程序中使用的基本类型的结构化数据存储。 它们将数据组织到具有预定义模式的表中,其中每个表代表一个实体或关系。 数据以行(记录)和列(属性)的形式存储,允许用户通过 SQL(结构化查询语言)进行高效的查询和操作。 关系数据库在维护数据完整性、支持复杂查询和处理不同数据实体之间的关系方面表现出色。

进一步阅读

图数据库

图数据库是一种专门类型的数据库,旨在存储和管理高度关联的数据。 与传统的的关系数据库不同,图数据库使用由节点(实体)、边(关系)和属性组成的灵活结构。 这种结构允许高效地表示和查询复杂、关联的数据。 图数据库以节点、边和属性的图结构存储数据。 它们在存储和查询复杂数据点之间的关系方面特别有用,例如社交网络、供应链管理、欺诈检测和推荐服务。

进一步阅读

检索器

LangChain 通过检索器 概念提供了一个统一的接口来与各种检索系统进行交互。该接口很简单:

  1. 输入:查询(字符串)
  2. 输出:文档列表(标准化的 LangChain Document 对象)

您可以使用前面提到的任何检索系统来创建检索器。我们讨论的查询分析技术在这里尤其有用,因为它们为通常需要结构化查询语言的数据库提供了自然语言接口。 例如,您可以使用文本到 SQL 转换器为 SQL 数据库构建检索器。这允许后台将自然语言查询(字符串)转换为 SQL 查询。 无论底层检索系统如何,LangChain 中的所有检索器都共享一个通用接口。您可以使用简单的 invoke 方法来使用它们:

docs = retriever.invoke(query)
进一步阅读