提高 RAG 链质量

改善质量的 RAG 链的组件关系图。

本文介绍如何使用 RAG 链的组件提高 RAG 应用的质量。

RAG 链采用用户查询作为输入、检索该给定查询的相关信息,并根据检索到的数据生成适当的响应。 虽然 RAG 链中的确切步骤可能因用例和要求而异,但生成 RAG 链时需要考虑的关键组件如下:

  1. 查询理解:分析和转换用户查询以更好地表示意图并提取相关信息(如筛选器或关键字),从而改进检索过程。
  2. 检索:在给定检索查询的情况下查找相关性最高的信息区块。 在非结构化数据案例中,这通常涉及语义搜索和/或基于关键字的搜索。
  3. 提示增强:将用户查询与检索到的信息和说明相结合,引导 LLM 生成高质量的响应。
  4. LLM:为应用程序选择最合适的模型(和模型参数),以优化/平衡性能、延迟和成本。
  5. 后期处理和防护措施:应用额外的处理步骤和安全措施,以确保 LLM 生成的响应符合主题、与事实一致,并遵循特定的准则或约束。

以迭代方式实施和评估质量解决方法演示如何循环访问链的组件。

查询理解

将用户查询直接用作检索查询可能对某些查询有效。 但是,在检索步骤之前重新制定查询通常会很有用。 查询理解包含一个步骤或一系列步骤,位于链开头,用于分析和转换用户查询以更好地表示意图、提取相关信息,并最终为后续检索过程提供帮助。 转换用户查询以改善检索的方法包括:

  1. 查询重写:查询重写涉及将用户查询转换为一个或多个更好地表示原始意图的查询。 其目标是重新制定查询,以便增加检索步骤找到相关性最高的文档的可能性。 在处理可能与检索文档中使用的术语不直接匹配的复杂或有歧义查询时,这将特别有用。

    示例:

    • 在多轮次聊天中复述对话历史记录
    • 更正用户查询中的拼写错误
    • 将用户查询中的字词或短语替换为同义词,以捕获范围更广的相关文档

    重要

    必须结合检索组件的更改来完成查询重写

  2. 筛选器提取:在某些情况下,用户查询可能包含可用于缩小搜索结果范围的特定筛选器或条件。 筛选器提取涉及识别和提取查询中的这些筛选器,并将其作为额外参数传递到检索步骤。 这有助于重点专注可用数据的特定子集,从而提高检索到的文档的相关性。

    示例:

    • 提取查询中提到的特定时间段,例如“过去 6 个月的文章”或“2023 年的报告”。
    • 标识查询中特定产品、服务或类别的提及,例如“Databricks 专业服务”或“笔记本电脑”。
    • 从查询中提取地理实体,例如城市名称或国家/地区代码。

    注意

    必须同时结合元数据提取数据管道检索器链组件的更改来完成筛选器提取。 元数据提取步骤应确保相关的元数据字段可用于每个文档/区块,而且实施的检索步骤应接受并应用提取的筛选器。

除了查询重写和筛选器提取之外,查询理解中的另一个重要考虑因素是使用单个 LLM 调用还是多个调用。 尽管将单个调用与精心设计的提示结合使用比较高效,但在某些情况下,将查询理解过程分解为多个 LLM 调用可能会产生更好的结果。 顺便说一下,在尝试将许多复杂的逻辑步骤实现到单个提示中时,这是一个普遍适用的经验法则。

例如,可以使用一个 LLM 调用对查询意图进行分类,使用另一个调用来提取相关实体,使用第三个调用根据提取的信息来重写查询。 尽管此方法可能会给整个过程带来一些延迟,但它可以实现更精细的控制,并可能提高检索到的文档的质量。

支持机器人的多步骤查询理解

下面介绍了多步骤查询理解组件如何查找客户支持机器人:

  1. 意图分类:使用 LLM 将用户查询分为多个预定义类别,例如“产品信息”、“故障排除”或“帐户管理”。
  2. 实体提取:根据确定的意图,使用另一个 LLM 调用从查询中提取相关实体,例如产品名称、报告错误或帐号。
  3. 查询重写:使用提取的意图和实体将原始查询重写为更具体、更有针对性的格式,例如“我的 RAG 链无法在模型服务上部署,我看到了以下错误…”。

检索

RAG 链的检索组件负责在给定检索查询的情况下查找相关性最高的信息区块。 在非结构化数据环境中,检索通常涉及语义搜索和/或基于关键字的搜索以及元数据筛选。 检索策略的选择取决于应用程序的特定要求、数据的性质以及要处理的查询类型。 让我们来比较以下选项:

  1. 语义搜索:语义搜索使用嵌入模型将每个文本区块转换为捕获其语义含义的矢量表示形式。 通过将检索查询的矢量表示形式与区块的矢量表示形式进行比较,语义搜索可以检索概念上相似的文档,即使它们不包含查询中的确切关键字也是如此。
  2. 基于关键字的搜索:基于关键字的搜索通过分析检索查询与索引文档之间共享字词的频率和分布来确定文档的相关性。 查询与某一文档中出现相同字词的频率越高,分配给该文档的相关性分数就越高。
  3. 混合搜索:混合搜索采用两步检索过程,将语义搜索和基于关键字的搜索的优势结合在了一起。 混合搜索的具体过程如下:首先执行语义搜索以检索一组概念上相关的文档, 然后对此精简组应用基于关键字的搜索,以便根据确切关键字匹配进一步优化结果。 最后将这两个步骤中的分数结合在一起,对文档进行排名。

比较检索策略

下表对每个检索策略进行了相互对比:

语义搜索 关键字搜索 混合搜索
简单说明 如果查询和潜在文档中出现相同的概念,则它们相关 如果查询和潜在文档中出现相同的字词,则它们相关。 查询中的字词在文档中出现的越多,文档相关性就越高 同时运行语义搜索和关键字搜索,然后将结果结合在一起。
示例用例 用户查询不同于产品手册中的字词情况下的客户支持。 示例:“我如何打开手机?” 对应的手册章节名为“切换电源”。 查询包含特定的非描述性技术术语情况下的客户支持。 示例:“HD7-8D 型号的作用是什么?” 查询结合使用了语义术语和技术术语情况下的客户支持。 示例:“我如何打开 HD7-8D?”
技术方法 使用嵌入来表示连续矢量空间中的文本,从而启用语义搜索。 依赖于基于标记的离散方法(例如 bag-of-wordsTF-IDFBM25)进行关键字匹配。 使用重新排名方法将结果结合在一起,例如倒数排名融合或重新排名模型。
优势 检索与查询的上下文相似的信息,即使未使用确切字词也是如此。 需要精确关键字匹配的情形,非常适合以特定术语为重点的查询,例如产品名称。 结合两种方法的优势。

增强检索过程的方法

除了这些核心检索策略之外,还可以应用多种方法来进一步增强检索过程:

  • 查询扩展:查询扩展使用检索查询的多个变体来帮助捕获范围更广的相关文档。 这可以通过对每个扩展查询执行单个搜索,或者在单个检索查询中串联使用所有扩展的搜索查询来实现。

注意

必须结合查询理解组件(RAG 链)的更改来完成查询扩展。 检索查询的多个变体通常在此步骤中生成。

  • 重新排名:检索初始区块集后,应用其他排名条件(例如,按时间排序)或重排器模型来重新排序结果。 重新排名有助于设置在给定特定检索查询的情况下相关性最高的区块的优先级。 使用跨编码器模型(如 mxbai-rerankColBERTv2)进行重新排名可能会提高检索性能。
  • 元数据筛选:使用从查询理解步骤中提取的元数据筛选器,根据特定条件缩小搜索空间的范围。 元数据筛选器可以包括文档类型、创建日期、作者或特定于域的标记等属性。 通过将元数据筛选器与语义搜索或基于关键字的搜索相结合,可以创建更有针对性且更加高效的检索。

注意

必须结合查询理解(RAG 链)和元数据提取(数据管道)组件的更改来完成元数据筛选。

提示增强

提示增强这一步骤是将用户查询与检索到的信息和说明结合在提示模板中,从而引导语言模型生成高质量的响应。 需要在此模板上进行迭代以优化提供给 LLM(又名提示工程)的提示,以确保引导模型生成准确、可靠且连贯的响应

有完整的提示工程指南,但在提示模板上进行迭代时,请记住以下注意事项:

  1. 提供示例
    • 在提示模板本身中包含格式标准的查询及其相应的理想响应的示例(少样本学习)。 这有助于模型了解响应的所需格式、样式和内容。
    • 想出好例子的一个有用方法是识别链难以处理的查询类型。 为这些查询创建黄金标准响应,并将其作为示例包含在提示中。
    • 确保提供的示例代表你在推理时预测的用户查询。 目标是涵盖各种预期查询,以帮助模型更好地通用化。
  2. 将提示模板参数化
    • 通过将提示模板参数化使其设计灵活多变,以纳入检索到的数据和用户查询之外的其他信息。 这可能是当前日期、用户上下文或其他相关元数据等变量。
    • 在推理时将这些变量注入提示可以使响应更加个性化,或者感知上下文的能力更强。
  3. 考虑思维链提示
    • 对于直接答案不太明显的复杂查询,请考虑思考链 (CoT) 提示。 这种提示工程策略将复杂的问题分解为更简单的有序步骤,引导 LLM 完成逻辑推理过程。
    • 通过提示模型“逐步思考问题”,你建议其提供更详细且更合理的响应,这对于处理多步骤查询或开放式查询尤其有效。
  4. 提示可能无法跨模型传输
    • 识别提示通常不会跨不同的语言模型无缝传输。 每个模型都有其自己的独特特征,其中,对一个模型有效的提示可能对另一个模型无效。
    • 使用不同的提示格式和长度进行试验,请参阅在线指南(如 OpenAI 指南Anthropic 指南),并做好在模型之间切换时调整和优化提示的准备。

LLM

RAG 链的生成组件采用上一步中的增强提示模板,并将其传递给 LLM。 为 RAG 链的生成组件选择和优化 LLM 时,请考虑以下因素,这些因素同样适用于涉及 LLM 调用的任何其他步骤:

  1. 利用不同的现有模型进行试验。
    • 每个模型都有其自己的独特属性、优势和弱点。 某些模型可能更加了解某些域,或者执行特定任务的效果更好。
    • 如前所述,请记住,模型的选择可能还会影响提示工程过程,因为不同的模型可能会对相同提示做出不同的响应。
    • 如果在链中除了生成步骤外还有多个步骤需要 LLM(例如,查询理解的调用),请考虑针对不同的步骤使用不同的模型。 对于像确定用户查询意图这样的任务来说,更昂贵的通用模型可能有些滥用。
  2. 请从小型模型开始,然后根据需要纵向扩展。
    • 虽然立即接触最强大、功能最齐全的模型(例如 GPT-4、Claude)可能很诱人,但从更小、更轻量级的模型开始往往更有效。
    • 在许多情况下,更小的开源替代项(如 Llama 3 或 DBRX)可以提供令人满意的结果,而且成本更低、推理时间更短。 对于不需要高度复杂推理或大量知识储备的任务,这些模型特别有效。
    • 开发和优化 RAG 链时,请持续评估所选模型的性能和限制。 如果发现模型难以处理某些类型的查询,或者无法提供足够详细或准确的响应,请考虑纵向扩展到功能更齐全的模型。
    • 监视不断变化的模型对关键指标(如响应质量、延迟和成本)的影响,以确保特定用例的各个要求得到正确的平衡。
  3. 优化模型参数
    • 使用不同的参数设置进行试验,以在响应质量、多样性和连贯性之间找到最佳平衡。 例如,调整温度可以控制生成文本的随机性,而 max_tokens 可以限制响应长度。
    • 请注意,最佳参数设置可能因特定任务、提示和所需输出样式而异。 根据所生成响应的评估,以迭代方式测试和优化这些设置。
  4. 特定于任务的微调
    • 优化性能时,请考虑微调 RAG 链(例如查询理解)中特定子任务的较小模型。
    • 使用 RAG 链训练专用于各个任务的模型与对所有任务使用单个大型模型相比,整体性能可能会提高,延迟可能会减少,而且推理成本可能会降低。
  5. 继续预先训练
    • 如果 RAG 应用程序处理专用域或者需要预先训练的 LLM 中未能充分展示的知识,请考虑对特定于域的数据执行继续预先训练 (CPT)。
    • 继续预先训练可以加深模型对域独有的特定术语或概念的理解。 这进而可以减少对大量提示工程或少样本示例的需求。

后期处理和防护措施

LLM 生成响应后,通常需要应用后期处理技术或防护措施来确保输出满足所需的格式、样式和内容要求。 链中的这个最后一步(或多个步骤)有助于保持生成的各响应之间的一致性,并保证其质量。 如果要实施后期处理和防护措施,请考虑以下一些事项:

  1. 强制输出格式
    • 根据用例,生成的响应可能需要遵循特定格式,例如结构化模板或特定文件类型(如 JSON、HTML、Markdown 等)。
    • 如果需要结构化输出,可以从 Instructor轮廓等库开始实施此类验证步骤。
    • 开发时,请花些时间确保后期处理步骤足够灵活,以处理所生成响应中的变体,同时保持所需的格式。
  2. 保持样式一致性
    • 如果 RAG 应用程序有特定的样式准则或语气要求(例如正式与随意、简洁与详细),则后期处理步骤可以在生成的响应中检查并强制实施这些样式属性。
  3. 内容筛选器和安全防护措施
  4. 处理误报
    • 抵御误报也可以作为后期处理步骤来实施。 这可能涉及使用检索到的文档交叉引用生成的输出,或使用其他 LLM 来验证响应的事实准确性。
    • 开发回退机制来处理生成的响应无法满足事实准确性要求的情况,例如生成替代响应或向用户提供免责声明。
  5. 错误处理。
    • 使用任何后期处理步骤时,都要实施一些机制来妥善处理步骤遇到问题或未能生成令人满意的响应等情况。 这可能涉及生成默认响应,或将问题上报给人工操作员进行手动评审。