你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

信息检索

在检索增强生成 (RAG) 解决方案的上一步中,你为区块生成了嵌入内容。 在此步骤中,将在向量数据库中生成索引并试验以确定最佳搜索。 本文介绍搜索索引的配置选项、搜索类型以及重新调整策略。

本文是系列文章的一部分。 阅读简介

配置搜索索引

备注

本部分介绍 Azure AI 搜索的特定建议。 如果使用其他存储区,请查看相应的文档以查找该服务的关键配置。

存储中的搜索索引为数据中的每个字段都设置了一个列。 搜索存储通常支持 非向量数据类型,例如字符串、布尔值、整数、单精度、双精度和日期时间。 它们还支持集合,例如单类型集合和 向量数据类型。 对于每一列,必须配置信息,例如数据类型以及字段是否可筛选、检索或搜索。

请考虑以下可以应用于矢量字段的矢量搜索配置

  • 矢量搜索算法:矢量搜索算法搜索相对匹配项。 AI 搜索有一个暴力算法选项,称为穷尽 k 最近邻 (EKNN),用于扫描整个矢量空间。 它还具有性能更好的算法选项,称为分层可导航小世界 (HNSW),能够执行近似最近邻 (ANN) 搜索。

  • 相似性指标: 算法使用 相似性指标 来计算接近度。 AI 搜索中的指标类型包括余弦、点积和欧几里得。 如果使用 Azure OpenAI 服务嵌入模型,请选择余弦值。

  • efConstruction参数:在构造 HNSW 索引期间使用此参数。 它确定在索引期间与向量连接的最近邻居的数量。 efConstruction 值越大,索引的质量就越好。 但更大的值需要更多的时间、存储和计算。 对于大量区块,请将 efConstruction 值设置为更高。 对于少量区块,请将值设置为较低的值。 若要确定最佳值,请试验数据和预期查询。

  • efSearch 参数: 在查询期间使用此参数来设置搜索过程中使用的最近邻居或类似区块的数量。

  • m 参数:此参数是双向链接计数。 范围为 4 到 10。 较小的数字在结果中返回的噪声较少。

在 AI 搜索中,矢量配置封装在 vectorSearch 配置中。 配置向量列时,请引用该向量列的相应配置并设置维度数。 矢量列的维度属性表示嵌入模型生成的维度数。 例如,存储优化 text-embedding-3-small 模型生成 1,536 个维度。

选择搜索方法

在通过提示协调器对搜索存储运行查询时,请考虑以下几个因素:

  • 要执行的搜索类型,例如矢量、关键字或混合

  • 是否要针对一个或多个列进行查询

  • 是否要手动运行多个查询,例如关键字查询和矢量搜索

  • 是否需要将查询分解为子查询

  • 是否应在查询中使用筛选

提示业务流程协调程序可能会采用静态方法,也可能采用动态方法,根据提示的上下文线索组合使用各种方法。 以下部分介绍这些选项,帮助你找到适合工作负荷的方法。

搜索类型

搜索平台通常支持全文搜索和矢量搜索。 某些平台(如 AI 搜索)支持混合搜索。

矢量搜索 比较矢量化查询(提示)和矢量字段之间的相似性。 有关详细信息,请参阅 为矢量搜索选择 Azure 服务

重要

在嵌入查询之前,应执行对区块执行的相同清理操作。 例如,如果在嵌入区块中小写每个单词,则应在嵌入之前将查询中的每个单词都小写。

注意

可以对同一查询中的多个向量字段执行矢量搜索。 在 AI 搜索中,这种做法被视为混合搜索。 有关详细信息,请参阅 混合搜索

以下示例代码针对 contentVector 字段执行矢量搜索。

embedding = embedding_model.generate_embedding(
    chunk=str(pre_process.preprocess(query))
)

vector = RawVectorQuery(
    k=retrieve_num_of_documents,
    fields="contentVector",
    vector=embedding,
)

results = client.search(
    search_text=None,
    vector_queries=[vector],
    top=retrieve_num_of_documents,
    select=["title", "content", "summary"],
)

嵌入查询的代码首先预处理查询。 这个预处理应该是用来在嵌入之前对数据块进行预处理的相同代码。 必须使用嵌入区块的同一嵌入模型。

全文搜索与索引中存储的纯文本匹配。 通常从查询中提取关键字,并在全文搜索中使用这些关键字对一个或多个索引列进行搜索。 您可以配置全文搜索,使其在任一字词或所有字词匹配时返回结果。

进行试验以确定要对其运行全文搜索的字段。 如 扩充阶段文章中所述,在内容具有类似语义含义但实体或关键字不同的情况下,应使用关键字和实体元数据字段进行全文搜索。 要考虑进行全文搜索的其他常见字段包括标题、摘要和区块文本。

以下示例代码针对标题、内容和摘要字段执行全文搜索。

formatted_search_results = []

results = client.search(
    search_text=query,
    top=retrieve_num_of_documents,
    select=["title", "content", "summary"],
)

formatted_search_results = format_results(results)

AI 搜索支持 混合查询,能够进行一个或多个文本搜索和一个或多个向量搜索。 平台执行每个查询,获取中间结果,使用倒数排名融合对结果进行重新排名,并返回前 N 个结果。

以下示例代码针对标题、内容和摘要字段执行全文搜索。 它还对 contentVector 和 questionVector 字段执行矢量搜索。 AI 搜索并行运行所有查询,重新检索结果,对结果进行重新排名,并返回排名靠前的 retrieve_num_of_documents

 embedding = embedding_model.generate_embedding(
    chunk=str(pre_process.preprocess(query))
)
vector1 = RawVectorQuery(
    k=retrieve_num_of_documents,
    fields="contentVector",
    vector=embedding,
)
vector2 = RawVectorQuery(
    k=retrieve_num_of_documents,
    fields="questionVector",
    vector=embedding,
)

results = client.search(
    search_text=query,
    vector_queries=[vector1, vector2],
    top=retrieve_num_of_documents,
    select=["title", "content", "summary"],
)

手动执行多个查询

可以手动运行多个查询,例如矢量搜索和关键字全文搜索。 可以聚合结果并手动对结果进行重新排名,然后返回排名靠前的结果。 对于手动多个查询,请考虑以下用例:

  • 使用的搜索平台不支持混合搜索。 您使用多个手动查询来执行您自己的混合搜索。

  • 你想要针对不同的查询运行全文搜索。 例如,可以从查询中提取关键字,并针对关键字元数据字段运行全文搜索。 然后,可以提取实体,并针对实体元数据字段运行查询。

  • 你想要控制重新排序过程。

  • 查询要求运行分解的子查询,以便从多个源检索基础数据。

查询翻译

查询翻译是 RAG 解决方案的信息检索阶段的可选步骤。 此步骤将查询转换为优化表单,以检索更好的结果。 查询翻译方法包括扩充、分解、重写和假设文档嵌入 (HyDE)。

查询扩充

查询扩充是一个转换步骤,使查询更简单、更可用并增强上下文。 如果查询较小或模糊,应考虑扩充。 例如,考虑查询“比较Microsoft的收入”。该查询不包括要比较的时间范围或时间单位,并且仅指定收益。 考虑一个改进版的查询,例如“比较微软公司在本年度与去年逐季度的利润和收入”。新查询清晰且具体。

扩充查询时,可以维护原始查询,但添加更多上下文。 请勿删除或更改原始查询,也不会更改查询的性质。

可以使用语言模型来扩充查询。 但您无法扩充所有查询。 如果有上下文,则可以将其传递给语言模型以增强查询。 如果没有上下文,则必须确定语言模型是否有可用于增强查询的信息。 例如,如果使用大型语言模型(如 GPT 模型),则可以确定有关查询的信息是否在 Internet 上随时可用。 如果是这样,可以使用模型来扩充查询。 否则,不应扩充查询。

在以下提示中,语言模型会扩展查询。 此提示包含有关查询何时具有上下文且没有的示例。 有关详细信息,请参阅 RAG 试验加速器 GitHub 存储库

Input Processing:

Analyze the input query to identify the core concept or topic.
Check whether the query provides context.
If context is provided, use it as the primary basis for augmentation and explanation.
If no context is provided, determine the likely domain or field, such as science, technology, history, or arts, based on the query.

Query Augmentation:

If context is provided:

Use the given context to frame the query more specifically.
Identify other aspects of the topic not covered in the provided context that enrich the explanation.

If no context is provided, expand the original query by adding the following elements, as applicable:

Include definitions about every word, such as adjective or noun, and the meaning of each keyword, concept, and phrase including synonyms and antonyms.
Include historical context or background information, if relevant.
Identify key components or subtopics within the main concept.
Request information about practical applications or real-world relevance.
Ask for comparisons with related concepts or alternatives, if applicable.
Inquire about current developments or future prospects in the field.

Other Guidelines:

Prioritize information from provided context when available.
Adapt your language to suit the complexity of the topic, but aim for clarity.
Define technical terms or jargon when they're first introduced.
Use examples to illustrate complex ideas when appropriate.
If the topic is evolving, mention that your information might not reflect the very latest developments.
For scientific or technical topics, briefly mention the level of scientific consensus if relevant.
Use Markdown formatting for better readability when appropriate.

Example Input-Output:

Example 1 (With provided context):

Input: "Explain the impact of the Gutenberg Press"
Context Provided: "The query is part of a discussion about revolutionary inventions in medieval Europe and their long-term effects on society and culture."
Augmented Query: "Explain the impact of the Gutenberg Press in the context of revolutionary inventions in medieval Europe. Cover its role in the spread of information, its effects on literacy and education, its influence on the Reformation, and its long-term impact on European society and culture. Compare it to other medieval inventions in terms of societal influence."

Example 2 (Without provided context):

Input: "Explain CRISPR technology"
Augmented Query: "Explain CRISPR technology in the context of genetic engineering and its potential applications in medicine and biotechnology. Cover its discovery, how it works at a molecular level, its current uses in research and therapy, ethical considerations surrounding its use, and potential future developments in the field."
Now, provide a comprehensive explanation based on the appropriate augmented query.

Context: {context}

Query: {query}

Augmented Query:

分解

复杂的查询需要多个数据集合来为模型奠定基础。 例如,查询“电动汽车是如何运作的,它们与内燃机(ICE)车辆相比如何?”可能需要借助多个来源的基础数据。 一位消息人士可能会描述电动汽车的工作原理,另一个消息人士将电动汽车与 ICE 车辆进行比较。

分解是将复杂查询分解为多个更小、更简单的子查询的过程。 独立运行每个分解的查询,并将所有已分解查询的顶级结果聚合为累积上下文。 然后运行原始查询,该查询将累积上下文传递给语言模型。

在运行任何搜索之前,应确定查询是否需要多个搜索。 如果需要多个子查询,则可以为所有查询运行手动多重查询。 使用语言模型确定是否建议多个子查询。

以下提示将查询分类为简单或复杂。 有关详细信息,请参阅 RAG 试验加速器 GitHub 存储库

Consider the given question to analyze and determine whether it falls into one of these categories:

1. Simple, factual question
  a. The question asks for a straightforward fact or piece of information.
  b. The answer can likely be found stated directly in a single passage of a relevant document.
  c. Breaking the question down further is unlikely to be beneficial.
  Examples: "What year did World War 2 end?", "What is the capital of France?", "What are the features of productX?"

2. Complex, multipart question
  a. The question has multiple distinct components or asks for information about several related topics.
  b. Different parts of the question likely need to be answered by separate passages or documents.
  c. Breaking the question down into subquestions for each component provides better results.
  d. The question is open-ended and likely to have a complex or nuanced answer.
  e. Answering the question might require synthesizing information from multiple sources.
  f. The question might not have a single definitive answer and could warrant analysis from multiple angles.
  Examples: "What were the key causes, major battles, and outcomes of the American Revolutionary War?", "How do electric cars work and how do they compare to gas-powered vehicles?"

Based on this rubric, does the given question fall under category 1 (simple) or category 2 (complex)? The output should be in strict JSON format. Ensure that the generated JSON is 100% structurally correct, with proper nesting, comma placement, and quotation marks. There shouldn't be a comma after the last element in the JSON.

Example output:
{
  "category": "simple"
}

还可以使用语言模型来分解复杂的查询。 以下提示将分解复杂的查询。 有关详细信息,请参阅 RAG 试验加速器 GitHub 存储库

Analyze the following query:

For each query, follow these specific instructions:

- Expand the query to be clear, complete, fully qualified, and concise.
- Identify the main elements of the sentence, typically a subject, an action or relationship, and an object or complement. Determine which element is being asked about or emphasized (usually the unknown or focus of the question). Invert the sentence structure. Make the original object or complement the new subject. Transform the original subject into a descriptor or qualifier. Adjust the verb or relationship to fit the new structure.
- Break the query down into a set of subqueries that have clear, complete, fully qualified, concise, and self-contained propositions.
- Include another subquery by using one more rule: Identify the main subject and object. Swap their positions in the sentence. Adjust the wording to make the new sentence grammatically correct and meaningful. Ensure that the new sentence asks about the original subject.
- Express each idea or fact as a standalone statement that can be understood with the help of the given context.
- Break down the query into ordered subquestions, from least to most dependent.
- The most independent subquestion doesn't require or depend on the answer to any other subquestion or prior knowledge.
- Try having a complete subquestion that has all information only from the base query. There's no other context or information available.
- Separate complex ideas into multiple simpler propositions when appropriate.
- Decontextualize each proposition by adding necessary modifiers to nouns or entire sentences. Replace pronouns, such as it, he, she, they, this, and that, with the full name of the entities that they refer to.
- If you still need more questions, the subquestion isn't relevant and should be removed.

Provide your analysis in the following YAML format, and strictly adhere to the following structure. Don't output anything extra, including the language itself.

type: interdependent
queries:
- [First query or subquery]
- [Second query or subquery, if applicable]
- [Third query or subquery, if applicable]
- ...

Examples:

1. Query: "What is the capital of France?"
type: interdependent
queries:
    - What is the capital of France?

2. Query: "Who is the current CEO of the company that created the iPhone?"
type: interdependent
queries:
    - Which company created the iPhone?
    - Who is the current CEO of Apple? (identified in the previous question)

3. Query: "What is the population of New York City, and what is the tallest building in Tokyo?"
type: multiple_independent
queries:
    - What is the population of New York City?
    - What is the tallest building in Tokyo?

Now, analyze the following query:

{query}

重写

输入查询可能不是检索基础数据的最佳格式。 可以使用语言模型重写查询并取得更好的结果。 重写查询以解决以下难题:

  • 含糊
  • 缺少关键字
  • 不必要的单词
  • 语义不明确

以下提示使用语言模型重写查询。 有关详细信息,请参阅 RAG 试验加速器 GitHub 存储库

Rewrite the given query to optimize it for both keyword-based and semantic-similarity search methods. Follow these guidelines:

- Identify the core concepts and intent of the original query.
- Expand the query by including relevant synonyms, related terms, and alternate phrasings.
- Maintain the original meaning and intent of the query.
- Include specific keywords that are likely to appear in relevant documents.
- Incorporate natural language phrasing to capture semantic meaning.
- Include domain-specific terminology if applicable to the query's context.
- Ensure that the rewritten query covers both broad and specific aspects of the topic.
- Remove ambiguous or unnecessary words that might confuse the search.
- Combine all elements into a single, coherent paragraph that flows naturally.
- Aim for a balance between keyword richness and semantic clarity.

Provide the rewritten query as a single paragraph that incorporates various search aspects, such as keyword-focused, semantically focused, or domain-specific aspects.

query: {original_query}

HyDE 技术

HyDE 是 RAG 解决方案的替代信息检索技术。 HyDE 使用语言模型从查询生成答案,而不是将查询转换为嵌入内容,并使用这些嵌入项查找矢量数据库中最接近的匹配项。 这些答案被转换为嵌入式表示,用于查找最接近的匹配项。 此过程使 HyDE 能够执行答案对答案的嵌入相似度搜索。

将查询翻译合并到管道中

您可以使用多种查询翻译。 甚至可以结合使用这四种翻译。 下图显示了一个示例,说明如何将这些翻译整合到一个管道中。

显示具有查询转换器的 RAG 管道的图表。

管道具有以下步骤:

  1. 可选的查询增强器步骤接收原始查询。 此步骤输出原始查询和扩充查询。

  2. 扩充查询由可选查询分解器步骤接收。 此步骤输出原始查询、扩充查询和分解的查询。

  3. 每个分解的查询执行三个子步骤。 所有分解的查询经过子步骤后,输出包括原始查询、扩充查询、分解查询和累积上下文。 累计上下文包括从所有经过子步骤的已分解查询中聚合的排名靠前的 N 个结果。 子步骤包括以下任务:

    1. 可选查询重写器重写分解的查询。

    2. 搜索索引处理重写的查询或原始查询。 它使用搜索类型(如矢量、全文、混合或手动多个)运行查询。 搜索索引还可以使用高级查询功能,例如 HyDE。

    3. 结果已重新排序。 排名靠前的 N 个重新排序结果将添加到累积上下文中。

  4. 原始查询以及累积的上下文会经历与每个分解查询相同的三个子步骤。 但只有一个查询会完成这些步骤,调用方会收到排名靠前 N 个结果。

在查询中传递图像

某些多模式模型(如 GPT-4V 和 GPT-4o)可以解释图像。 如果使用这些模型,可以避免对图像进行分块,并将图像作为提示的一部分传递给多模式模型。 你应该进行实验来确定此方法与在传递和不传递额外上下文的情况下对图像进行分块相比的表现如何。 还应比较成本差异并执行成本效益分析。

筛选查询

若要筛选查询,可以使用配置为可筛选的搜索存储中的字段。 考虑对使用这些字段的查询进行关键字和实体的筛选,以帮助缩小结果范围。 使用筛选来消除不相关的数据。 仅从索引中检索满足特定条件的数据。 这种做法可提高查询的整体性能,并提供更相关的结果。 若要确定筛选是否有利于你的方案,请执行试验和测试。 考虑像没有关键字或者有不准确关键字、缩写或首字母缩略词的查询等因素。

权重字段

在 AI 搜索中,可以加权字段以基于条件影响结果排名。

注意

本部分介绍 AI 搜索加权功能。 如果使用其他数据平台,请研究该平台的加权功能。

AI 搜索支持计分概要文件,这些文件包含 指定加权字段的参数和处理数值数据的函数 。 计分概要文件仅适用于非矢量字段。 对矢量和混合搜索的支持处于预览状态。 可以在索引上创建多个计分概要文件,并且可以选择在每个查询中使用一个。

权重的字段取决于查询类型和用例。 例如,如果查询是以关键字为中心的,比如“Microsoft 总部在哪里?”,你需要一个给实体或关键字字段更高权重的计分概要文件。 可以将不同的配置文件用于不同的用户,允许用户选择其关注的重点,或根据应用程序选择配置文件。

在生产系统中,应仅维护在生产环境中实际使用的配置文件。

使用重新排序

使用重新计算来运行一个或多个查询、聚合结果并对这些结果进行排名。 考虑以下受益于重新排序搜索结果的情境:

  • 执行了手动多重搜索,并希望对搜索结果进行聚合和排名。

  • 矢量和关键字搜索并不总是准确的。 你想要增加从搜索中返回的文档数量,其中包括可能被忽略的有效结果,并使用重新排序来评估结果。

可以使用语言模型或交叉编码器执行重新排序。 某些平台(例如 AI 搜索)具有重新排序结果的专有方法。 你可以评估这些数据选项,以确定最适合你的方案的选项。 以下部分提供有关这些方法的详细信息。

语言模型重新排序

以下示例语言模型提示重新排序结果。 有关详细信息,请参阅 RAG 试验加速器

Each document in the following list has a number next to it along with a summary of the document. A question is also provided.
Respond with the numbers of the documents that you should consult to answer the question, in order of relevance, and the relevance score as a JSON string based on JSON format as shown in the schema section. The relevance score is a number from 1 to 10 based on how relevant you think the document is to the question. The relevance score can be repetitive. Don't output any other text, explanation, or metadata apart from the JSON string. Just output the JSON string, and strip every other text. Strictly remove the last comma from the nested JSON elements if it's present.
Don't include any documents that aren't relevant to the question. There should be exactly one document element.

Example format:
Document 1:
content of document 1
Document 2:
content of document 2
Document 3:
content of document 3
Document 4:
content of document 4
Document 5:
content of document 5
Document 6:
content of document 6
Question: user-defined question

schema:
{
    "documents": {
        "document_1": "Relevance",
        "document_2": "Relevance"
    }
}

交叉编码器重新排名

以下示例使用 Hugging Face 提供的 交叉编码器来加载 Roberta 模型。 它循环访问每个区块,并使用模型计算相似性,从而提供一个值。 它会对结果进行排序,并返回排名靠前的 N 个结果。 有关详细信息,请参阅 RAG 试验加速器 GitHub 存储库

from sentence_transformers import CrossEncoder
...

model_name = 'cross-encoder/stsb-roberta-base'
model = CrossEncoder(model_name)

cross_scores_ques = model.predict(
    [[user_prompt, item] for item in documents],
    apply_softmax=True,
    convert_to_numpy=True,
)

top_indices_ques = cross_scores_ques.argsort()[-k:][::-1]
sub_context = []
for idx in list(top_indices_ques):
    sub_context.append(documents[idx])

语义排名

AI 搜索具有称为 语义排名的专有功能。 此功能使用从Microsoft必应改编的深度学习模型,以提升最语义上相关的结果。 有关详细信息,请参阅 语义排名器的工作原理

考虑其他搜索指南

实现搜索解决方案时,请考虑以下常规指南:

  • 从搜索中返回标题、摘要、来源和原始未处理内容字段。

  • 提前确定是否需要将查询分解为子查询。

  • 对多个字段运行矢量和文本查询。 收到查询时,不知道矢量搜索还是文本搜索更好。 你不知道矢量搜索或关键字搜索应搜索的理想字段。 可以搜索多个字段(可能有多个查询),重新检索结果,并返回得分最高的结果。

  • 筛选关键字和实体字段以缩小结果范围。

  • 将关键字与矢量搜索一起使用。 关键字将结果筛选为较小的子集。 矢量存储可针对该子集查找最佳匹配项。

评估搜索结果

在准备阶段,收集了测试查询和测试文档信息。 可以使用在该阶段收集的以下信息来评估搜索结果:

  • 查询:示例查询
  • 上下文:用于处理示例查询的测试文档中所有文本的集合

若要评估搜索解决方案,可以使用以下成熟的检索评估方法:

  • 在 K 处的精确度: 在所有搜索结果中正确识别的相关项的百分比。 此指标侧重于搜索结果的准确性。

  • K 召回: 在可能的相对项目总数中,排名靠前的 K 个项目中相关项目的百分比。 此指标侧重于搜索结果覆盖率。

  • 平均倒数排名 (MRR):MRR 衡量搜索结果中排名第一的相关答案的倒数排名平均值。 此指标侧重于搜索结果中出现第一个相关结果的位置。

应测试阳性和负面示例。 对于正示例,你希望指标尽可能接近 1。 对于负示例,在数据无法回应查询的情况下,应当使指标尽可能接近 0。 应测试所有测试查询。 平均正查询结果和负查询结果,以了解搜索结果在聚合中的表现。

下一步