Azure AI 搜索中的检索增强生成 (RAG)

检索增强生成 (RAG) 是一种体系结构,它通过添加一个提供基础数据的信息检索系统来增强大型语言模型 (LLM)(如 ChatGPT)的功能。 添加信息检索系统可让你控制 LLM 在规划响应时使用的基础数据。 对于企业解决方案,RAG 体系结构意味着,如果已有该内容的嵌入模型,则可以将生成式 AI 限制为源自矢量化文档和图像的企业内容

决定使用哪种信息检索系统至关重要,因为它将决定对 LLM 的输入。 信息检索系统应提供:

  • 按所需频率为所有内容进行大规模加载和刷新的索引策略。

  • 查询功能和相关性优化。 系统应以满足 LLM 输入的令牌长度要求所需的简短格式返回相关结果。

  • 数据和操作的安全性、全球影响力和可靠性。

  • 与用于索引编制的嵌入模型以及用于检索的聊天模型或语言理解模型集成。

Azure AI 搜索是 RAG 体系结构中一种可靠的信息检索解决方案。 它提供索引和查询功能,并且具有 Azure 云的基础设施和安全性。 通过代码和其他组件,你可以设计一项全面的 RAG 解决方案,其中包括基于专有内容的生成式 AI 的所有元素。

注意

不熟悉 Copilot 和 RAG 概念? 观看生成式 AI 应用的矢量搜索和先进检索

Azure 具有多个内置实施,用于在 RAG 解决方案中使用 Azure AI 搜索。

特选方法使入门变得简单,但要更好地控制体系结构,需要自定义解决方案。 这些模板在以下情况下创建端到端解决方案:

本文的其余部分将探讨如何将 Azure AI 搜索融入自定义 RAG 解决方案。

该模式的高级摘要如下所示:

  • 从用户问题或请求(提示)开始。
  • 将其发送到 Azure AI 搜索以查找相关信息。
  • 将排名靠前的搜索结果发送到 LLM。
  • 使用 LLM 的自然语言理解和推理功能生成对初始提示的响应。

Azure AI 搜索提供 LLM 提示符的输入,但不训练模型。 在 RAG 体系结构中,没有额外的训练。 LLM 是使用公共数据预先训练的,但它会生成由检索器中的信息扩充的响应。

包含 Azure AI 搜索的 RAG 模式具有下图所示的元素。

使用搜索和 ChatGPT 检索信息的体系结构图。

  • 提供用户体验的应用 UX(Web 应用)
  • 应用服务器或协调器(集成和协调层)
  • Azure AI 搜索(信息检索系统)
  • Azure OpenAI(适用于生成式 AI 和 LLM)

Web 应用提供用户体验,其中提供演示文稿、上下文和用户交互。 用户的问题或提示从此处开始。 输入通过集成层,首先转到信息检索以获取搜索结果,还会转到 LLM 以设置上下文和意向。

应用服务器或业务流程协调程序是协调信息检索和 LLM 之间交接的集成代码。 一个选项是使用 LangChain 协调工作流。 LangChain 与 Azure AI 搜索集成,使你能够更轻松地将 Azure AI 搜索作为检索器包含在工作流中。

信息检索系统提供可搜索索引、查询逻辑和有效负载(查询响应)。 搜索索引可以包含矢量或非矢量内容。 尽管大多数示例和演示都包含向量字段,但这不是必要的。 查询使用 Azure AI 搜索中的现有搜索引擎执行,该搜索引擎可以处理关键字(或术语)和矢量查询。 该索引根据你定义的架构预先创建,并使用从文件、数据库或存储中获取的内容加载。

LLM 收到原始提示以及 Azure AI 搜索的结果。 LLM 分析结果并制定响应。 如果 LLM 为 ChatGPT,则用户交互可能是你来我往的对话。 如果使用 Davinci,则提示可能是完全组合的答案。 Azure 解决方案最有可能使用 Azure OpenAI,但对此特定服务没有硬性依赖。

Azure AI 搜索未提供用于保存提示流或聊天的原生 LLM 集成,因此你需要编写用于处理编排和状态的代码。 可以查看演示源 (Azure-Samples/azure-search-openai-demo),了解完整解决方案的蓝图。 我们还建议使用 Azure AI Studio 或 Azure OpenAI Studio 来创建与 LLM 集成的基于 RAG 的 Azure AI 搜索解决方案。

在 Azure AI 搜索中,所有可搜索内容都存储在搜索服务所托管的搜索索引中。 搜索索引专为具有毫秒级响应时间的快速查询而设计,因此其内部数据结构旨在支持该目标。 为此,搜索索引将存储索引内容,而不是整个内容文件(如整个 PDF 或图像)。 在内部,数据结构包括标记化文本的倒排索引、嵌入的矢量索引,以及需要逐字匹配情况下的未更改文本(例如,在筛选器、模糊搜索、正则表达式查询中)。

为 RAG 解决方案设置数据时,可以使用在 Azure AI 搜索中创建和加载索引的功能。 索引包括复制或表示源内容的字段。 索引字段可能是简单的转移(源文档中的标题或描述成为搜索索引中的标题或描述),或者字段可能包含外部过程的输出,例如生成图像的表示形式或文本描述的矢量化处理或技术处理。

你可能知道你想要搜索哪种类型的内容,因此请考虑使用适合每种内容类型的索引功能:

内容类型 已编制索引为 功能
text 令牌,未更改的文本 索引器可以从其他 Azure 资源(如 Azure 存储和 Cosmos DB)中拉取纯文本。 你还可以向索引推送任何 JSON 内容。 若要修改使用中的文本,请使用分析器规范化器在编制索引期间添加词法处理。 如果源文档是可能在查询中使用的丢失的术语,则同义词映射会非常有用。
text 矢量 1 可以在索引器管道中对文本执行分块和矢量化处理,或者在外部处理,然后在你的索引中将其作为矢量字段编制索引
image 令牌,未更改的文本 2 OCR 和图像分析的技能可以处理图像以实现文本识别或图像特征。 图像信息转换为可搜索文本并添加到索引。 技能具有索引器要求。
图像 矢量 1 可以在索引器管道中对图像进行矢量化处理,或者在外部处理以获得图像内容的数学表示形式,然后在你的索引中将其作为矢量字段编制索引。 可以使用 Azure AI 视觉多模式OpenAI CLIP 等开源模型在同一嵌入空间中对文本和图像进行矢量化。

1 Azure AI 搜索提供集成的数据分块和矢量化,但必须依赖索引器和技能组。 如果无法使用索引器,Azure 的语义内核或其他社区产品/服务可以帮助你提供完整的堆栈解决方案。 有关显示这两种方法的代码示例,请参阅 azure-search-vectors 存储库

2 技能是对应用 AI 的内置支持。 为了进行 OCR 和图像分析,索引管道对 Azure AI 视觉 API 进行内部调用。 这些技能将提取的图像传递到 Azure AI 以进行处理,并接收输出作为由 Azure AI 搜索编制索引的文本。 技能还用于集成数据分块(文本拆分技能)和集成嵌入(调用 Azure AI 视觉多模式、Azure OpenAI 和 Azure AI Studio 模型目录中的模型的技能。)

矢量提供了对不同内容(多个文件格式和语言)的最佳适应性,因为内容以数学表示形式通用表达。 矢量还支持相似性搜索:在与矢量查询最相似的坐标上匹配。 与在标记化术语上匹配的关键字搜索(或术语搜索)相比,相似性搜索更加细致。 如果内容或查询中存在歧义或解释要求,这是更好的选择。

数据进入搜索索引后,就可以使用 Azure AI 搜索的查询功能来检索内容。

在非 RAG 模式中,查询从搜索客户端进行往返。 提交查询、在搜索引擎上执行查询,然后向客户端应用程序返回响应。 响应或搜索结果仅包含索引中找到的逐字匹配内容。

在 RAG 模式中,会在搜索引擎和 LLM 之间协调查询和响应。 用户的问题或查询会作为提示转发给搜索引擎和 LLM。 搜索结果从搜索引擎返回,然后重定向到 LLM。 返回给用户的响应是生成式 AI,即 LLM 的求和或答案。

查询功能 目的 使用原因
简单或完整的 Lucene 语法 对文本和非矢量数值内容的查询执行 全文搜索最适合精确匹配项,而不是相似匹配项。 全文搜索查询使用 BM25 算法排名,并支持通过计分概要文件进行相关性优化。 它还支持筛选器和 facet。
筛选器facet 仅适用于文本或数字(非矢量)字段。 根据包含或排除条件减少搜索外围应用。 提高查询的精准率。
矢量搜索 对矢量字段执行查询以实现相似性搜索,其中查询字符串是一个或多个矢量。 矢量可以用任何语言表示所有类型的内容。

构建查询响应

查询的响应向 LLM 提供输入,因此搜索结果的质量是决定成功与否的关键因素。 结果为表格行集。 结果的构成或结构取决于:

  • 用于确定响应中包含索引部分的字段。
  • 表示索引匹配项的行。

当属性“可检索”时,字段将显示在搜索结果中。 索引架构中的字段定义具有属性,这些属性确定字段是否在响应中使用。 仅在全文或矢量查询结果中返回“可检索”字段。 默认情况下,将返回所有“可检索”字段,但可以使用“选择”指定子集。 除了“可检索”之外,该字段没有限制。 字段可以是任意长度或类型。 对于长度,Azure AI 搜索中没有最大字段长度限制,但 API 请求的大小有限制。

行与查询匹配,按相关性、相似性或两者设置排名。 默认情况下,全文搜索的结果限制为前 50 个匹配项,矢量搜索限制为前 50 个 k 最近邻匹配项。 可以更改默认值,以增加或减少最多 1,000 个文档的限制。 还可以使用top 和skip 分页参数将结果检索为一系列分页结果。

最大化相关性和召回率

处理复杂流程、大量数据和预期的毫秒级响应时,每个步骤都必须增加价值并提高最终结果的质量,这一点至关重要。 在信息检索方面,相关性优化活动可以提高发送给 LLM 的结果的质量。 结果中应尽包含最相关或最相似的匹配文档。

下面是最大化相关性和召回率的一些提示:

  • 结合关键字(非矢量)搜索和矢量搜索的混合查询可以在输入相同时提供最大的召回率。 在混合查询中,如果对相同的输入加倍,则文本字符串及其向量等效项将生成关键字和相似性搜索的并行查询,并在统一的结果集中返回每种查询类型最相关的匹配项。

  • 此外,还可以扩展混合查询。 可以在同一请求中对详细分块内容进行相似性搜索,对名称进行关键字搜索。

  • 通过以下方式支持相关性调整:

    • 计分概要文件,如果在特定搜索字段或其他条件中找到匹配项,可提高搜索分数。

在比较和基准测试中,包含文本和矢量字段的混合查询(与语义排名相补充)会产生最相关的结果。

RAG 工作流的示例代码

以下 Python 代码演示了 Azure AI 搜索中 RAG 工作流的基本组件。 需要设置客户端、定义系统提示并提供查询。 提示告知 LLM 仅使用查询的结果,以及如何返回结果。 有关此示例的更多步骤,请参阅此 RAG 快速入门

# Set up the query for generating responses
from azure.identity import DefaultAzureCredential
from azure.identity import get_bearer_token_provider
from azure.search.documents import SearchClient
from openai import AzureOpenAI

credential = DefaultAzureCredential()
token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default")
openai_client = AzureOpenAI(
    api_version="2024-06-01",
    azure_endpoint=AZURE_OPENAI_ACCOUNT,
    azure_ad_token_provider=token_provider
)

search_client = SearchClient(
    endpoint=AZURE_SEARCH_SERVICE,
    index_name="hotels-sample-index",
    credential=credential
)

# This prompt provides instructions to the model. 
# The prompt includes the query and the source, which are specified further down in the code.
GROUNDED_PROMPT="""
You are a friendly assistant that recommends hotels based on activities and amenities.
Answer the query using only the sources provided below in a friendly and concise bulleted manner.
Answer ONLY with the facts listed in the list of sources below.
If there isn't enough information below, say you don't know.
Do not generate answers that don't use the sources below.
Query: {query}
Sources:\n{sources}
"""

# The query is sent to the search engine, but it's also passed in the prompt
query="Can you recommend a few hotels near the ocean with beach access and good views"

# Retrieve the selected fields from the search index related to the question
search_results = search_client.search(
    search_text=query,
    top=5,
    select="Description,HotelName,Tags"
)
sources_formatted = "\n".join([f'{document["HotelName"]}:{document["Description"]}:{document["Tags"]}' for document in search_results])

response = openai_client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": GROUNDED_PROMPT.format(query=query, sources=sources_formatted)
        }
    ],
    model="gpt-35"
)

print(response.choices[0].message.content)

集成代码和 LLM

包含 Azure AI 搜索的 RAG 解决方案可以利用内置的数据分块和矢量化功能,或者你也可以使用语义内核、LangChain 或 LlamaIndex 等平台构建自己的解决方案。

演示库中的笔记本是一个很好的起点,因为它们展示了 LLM 集成的模式。 RAG 解决方案中的大多数代码都由对 LLM 的调用组成,因此你需要了解这些 API 的工作原理,但本文并未涵盖这些内容。

如何开始使用

  • 查看索引概念和策略以确定引入和刷新数据的方式。 决定是使用矢量搜索、关键字搜索,还是混合搜索。 需要搜索的内容类型以及要运行的查询类型将决定索引设计。

  • 查看创建查询,以了解更多搜索请求语法和要求。

注意

某些 Azure AI 搜索功能适用于人机交互,在 RAG 模式中不起作用。 具体而言,可以跳过自动完成和建议。 其他功能(如 facet 和 orderby)可能很有用,但在 RAG 方案中并不常见。

另请参阅