跳到主要内容

检索

安全

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

概述

检索系统是许多 AI 应用程序的基础,可以有效地从大型数据集中识别相关信息。这些系统适用于各种数据格式

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

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

关键概念

Retrieval

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

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

查询分析

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

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

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

查询重写

理想情况下,检索系统应处理各种用户输入,从简单且措辞不当的查询到复杂的多方面问题。为了实现这种多功能性,一种流行的方法是使用模型将原始用户查询转换为更有效的搜索查询。这种转换的范围可以从简单的关键字提取到复杂的查询扩展和重构。以下是在非结构化数据检索中使用模型进行查询分析的一些主要好处

  1. 查询澄清:模型可以改写含糊不清或措辞不当的查询,以使其清晰。
  2. 语义理解:它们可以捕获查询背后的意图,而不仅仅是字面关键字匹配。
  3. 查询扩展:模型可以生成相关术语或概念以扩大搜索范围。
  4. 复杂查询处理:它们可以将多部分问题分解为更简单的子查询。

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

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

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

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

# Define a pydantic model to enforce the output structure
class Questions(BaseModel):
questions: List[str] = Field(
description="A list of sub-questions related to the input query."
)

# Create an instance of the model and enforce the output structure
model = ChatOpenAI(model="gpt-4o", temperature=0)
structured_model = model.with_structured_output(Questions)

# Define the system prompt
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 answers in isolation. \n"""

# Pass the question to the model
question = """What are the main components of an LLM-powered autonomous agent system?"""
questions = structured_model.invoke([SystemMessage(content=system)]+[HumanMessage(content=question)])
提示

请观看我们的 RAG 从头开始视频,了解几种不同的具体方法

查询构建

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

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

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

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

名称何时使用描述
自我查询如果用户提出的问题最好通过基于元数据而不是文本相似性获取文档来回答。这使用 LLM 将用户输入转换为两件事:(1)语义查找的字符串,(2)与其一起使用的元数据过滤器。这很有用,因为通常问题是关于文档的元数据(而不是内容本身)。
文本到 SQL如果用户提出的问题需要关系数据库中存储的信息,可以通过 SQL 访问。这使用 LLM 将用户输入转换为 SQL 查询。
文本到 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)
进一步阅读

此页面对您有帮助吗?