type
status
date
slug
summary
tags
category
icon
password

📚 上下文与内容丰富 (Context and Content Enrichment)

1. 上下文分块头部 (Contextual Chunk Headers)

  • 核心动机 (Motivation)
    • RAG 开发中许多问题的根源可以归结为一点:单个文本块往往不包含足够的上下文信息,导致检索系统或大语言模型 (LLM) 无法正确地使用它。这不仅会导致无法回答问题,更严重的是,它会引发模型产生幻觉。
    • 具体问题表现 (Examples):
      • 隐式引用与代词: 文本块常常通过代词(如“它”、“他们”)或隐式方式指代其主题。这会导致在需要检索它们时无法被召回,或者被 LLM 召回后无法正确理解其含义。
      • 脱离上下文的误导性: 单个文本块只有在整个章节或文档的语境下才有意义,孤立地阅读时可能会产生误导。
  • 实现方法详解 (Method Details)
    • 1. 上下文标题的构建 (Contextual Header Generation):
      • 核心思想是通过前置一个块标题,为文本块注入更高层级的上下文。这个标题可以很简单,也可以很丰富。
      • 标题内容的来源:
        • 文档标题 (Document Title): 这是最简单也最重要的上下文信息。如果文档本身没有描述性强的标题,可以通过一个简单的提示 (Prompt),将文档的截断文本传给 LLM 来生成一个。
        • 简明文档摘要 (Concise Document Summary): 提供整个文档的宏观视角。
        • 章节/子章节标题 (Section/Sub-section Title(s)): 这有助于检索系统处理针对文档中较大章节或主题的查询。
    • 2. 嵌入带标题的文本块 (Embedding Chunks with Headers):
      • 对每个文本块进行嵌入时,实际嵌入的文本是块标题和原始块文本的简单拼接
      • 重要提示: 如果您的检索流程中使用了重排序 (reranker) 模型,请务必确保在重排序阶段也使用这套拼接后的文本。
      • 格式: 待嵌入文本 = 块标题 + "\\n\\n" + 原始块文本
    • 3. 在最终生成时包含标题 (Including Headers in Final Generation):
      • 在将检索到的搜索结果呈现给最终的 LLM 时,同样包含这些块标题。这能给予 LLM 更丰富的上下文,使其更不容易误解单个文本块的真实含义。
  • 举例说明 (Illustrative Example)
    • 上下文信息 (Context Information):
      • 文档标题: "特斯拉公司2023年年度报告"
      • 章节标题: "第四部分:电池技术与创新"
    • 原始文本块 (Original Chunk):
      • 它采用了新的4680电池设计,显著提升了能量密度和制造成本效益。这一进步是实现下一代汽车目标的关键。
      • 问题: 这里的代词“它”指代不明,单独嵌入这个文本块,很难被关于“特斯拉电池技术”的查询命中。
    • 添加CCH后的待嵌入文本 (Text to be Embedded with CCH):
      • 文档标题: 特斯拉公司2023年年度报告 章节标题: 第四部分:电池技术与创新 它采用了新的4680电池设计,显著提升了能量密度和制造成本效益。这一进步是实现下一代汽车目标的关键。
      • 优势: 经过拼接后,这个文本块的嵌入向量现在清晰地包含了“特斯拉”、“2023年报告”和“电池技术”等关键上下文信息。因此,当用户查询“特斯拉在2023年在电池技术上有什么创新?”时,这个文本块被正确检索到的概率会大大增加。
  • 主要优势 (Key Benefits)
    • 显著提升检索质量: 使嵌入向量更能代表文本的真实含义,从而提高召回率和精确率。
    • 降低无关结果率: 上下文信息帮助系统更好地甄别不相关的文本块。
    • 减少LLM误解: 为下游的生成模型提供了更丰富的上下文,避免了因信息不全导致的错误解读。
    • 解决上下文缺失问题: 直接解决了单个文本块因缺乏上下文而难以被检索或理解的核心痛点。

2. 相关段落提取 (Relevant Segment Extraction)

  • 核心动机:动态分块的挑战
    • 在为 RAG 系统进行文本分块时,选择合适的分块大小总是一种权衡。大的文本块能为 LLM 提供更好的上下文,但难以精确检索到特定的信息点;小的文本块检索精准,但上下文信息不足。现实世界中的 RAG 应用需要同时处理需要简短答案的简单问题(适合小块)和需要宏观理解的复杂问题(需要大块)。
    • 我们真正需要的是一个动态系统,它既能在需要时检索短小精悍的文本块,也能在必要时提供大段的、连贯的上下文。如何实现?RSE 的解决方案源于一个简单的洞察:相关文本块在其原始文档中倾向于聚集在一起 (relevant chunks tend to be clustered)
  • 实现方法详解 (Method Details)
    • 1. 前置条件:无重叠分块 (Prerequisite: Non-Overlapping Chunks):
      • RSE 要求文档在切分时不设置重叠 (no overlap)。这是为了能够通过简单地拼接文本块,来完美地重构出文档中的原始连续片段。
    • 2. 前置条件:块文本键值存储 (Prerequisite: Chunk Text Key-Value Store):
      • RSE 需要一个能够根据 文档ID (doc_id)块索引 (chunk_index) 快速检索任意文本块的数据库。这是因为需要被“填补”到片段中的某些文本块,可能并未出现在最初的向量搜索结果中。因此,除了向量数据库,通常还需要一个键值存储系统。
    • 3. RSE 优化算法 (The RSE Optimization Algorithm):
      • 该算法在标准检索(理想情况下包含重排序步骤)完成后启动。
      • a. 计算块价值 (Calculating Chunk Value): 结合向量相似度分数和重排序后的排名,来计算一个更稳健的“块价值”分数。然后,从每个块的价值中减去一个恒定的阈值(例如 0.2),这样,不相关的块就变为负值(低至-0.2),而相关的块则为正值(高达0.8)。
      • b. 定义片段价值 (Defining Segment Value): 通过这种方式定义块价值后,一个“片段”的价值就可以简单地定义为其所包含的所有块的价值之和。
      • c. 寻找最佳片段 (Finding the Best Segment): 寻找最佳片段的问题,就转化为了一个受约束的**“最大和子数组问题”(maximum sum subarray problem)**。通过带有启发式规则的暴力搜索,通常可以在约 5-10 毫秒内高效地找到最优解。
  • 举例说明 (Illustrative Example)
    • 场景: 假设一篇文档被切分为10个无重叠的文本块 [chunk_0, chunk_1, ..., chunk_9]
    • 初始检索结果: 经过向量搜索和重排序,系统认为 chunk_2chunk_3chunk_7 是最相关的。
    • 传统 RAG 的问题:
      • 传统 RAG 会将这三个孤立的、可能乱序的文本块 [chunk_2, chunk_3, chunk_7] 直接提交给 LLM。LLM 缺失了 chunk_4, chunk_5, chunk_6 这些可能承上启下的关键连接信息,难以形成连贯的理解。
    • RSE 的处理流程:
      • 1. 计算价值: RSE 为所有10个块计算价值。chunk_2, chunk_3, chunk_7 获得较高的正分,而其他未被召回的块(如 chunk_4, chunk_5, chunk_6)则获得负分。
      • 2. 寻找最佳片段: 算法开始计算所有可能的连续片段的价值总和。它可能会发现,尽管 chunk_4, chunk_5, chunk_6 是负分,但由于 chunk_2chunk_3 的正分很高,将它们连接起来构成的片段 [chunk_2, chunk_3, chunk_4, chunk_5, chunk_6, chunk_7] 的总价值可能是所有可能片段中最高的。
      • 3. 重构片段: RSE 确定最佳片段是从 chunk_2chunk_7。它会使用键值存储,按顺序获取 chunk_2chunk_7 的所有文本内容,然后将它们拼接成一个单一、连贯的长文本。
    • 最终上下文:
      • LLM 不再接收到3个零散的文本块,而是收到了一个完整的、按原文顺序排列的、上下文连贯的长片段,从而能更好地理解和回答问题。
  • 主要优势 (Key Benefits)
    • 动态上下文长度: 根据查询的需要,既能返回小段精确信息,也能动态重构长篇连贯上下文。
    • 保证上下文连贯性: 确保提交给 LLM 的文本块是按原文顺序排列的,避免了信息错乱。
    • 智能填补信息空白: 能够将未被检索到但处于关键位置的“桥梁”文本块包含进来,形成完整的逻辑链。
    • 显著提升RAG性能: 通过提供质量更高、更连贯的上下文,直接提升了最终答案的质量和系统的整体性能。

3. 上下文窗口增强 (Context Window Enhancement)

  • 核心动机 (Motivation)
    • 传统的向量搜索经常返回孤立的文本片段,这些片段由于缺乏必要的上下文,可能导致理解不完整或产生歧义。本方法旨在通过包含邻近的文本块,为检索到的信息提供一个更全面、更连贯的视角,从而解决“信息孤岛”问题。
  • 与 RSE 的核心区别
    • 此技术与前述的“相关片段提取 (RSE)”相似,但实现方式更简单直接:
    • 上下文丰富化窗口 (本方法): 采用固定窗口策略。对于每一个被检索到的块,机械地、固定地添加其前后 k 个邻近块。实现非常简单,主要依赖索引操作。
    • 相关片段提取 (RSE): 采用动态片段策略。它通过一个更复杂的优化算法,基于“价值总和”来智能地寻找一个可能很长的、最优的连续片段。实现更复杂,但效果也更智能、更动态。
  • 实现方法详解 (Method Details)
    • 1. 文档预处理:
      • 读取 PDF 文档并转换为字符串。
      • 将文本分割成带有重叠 (overlap) 的文本块。至关重要的是,每个文本块都需要被标记其在文档中的顺序索引 (index),以便后续能够定位其邻居。
    • 2. 向量存储创建:
      • 使用 OpenAI Embeddings 为每个文本块创建向量表示。
      • 将这些嵌入向量存入 FAISS 向量存储中。
    • 3. 上下文丰富化检索流程:
      • 该核心逻辑被封装在一个自定义函数中(例如 retrieve_with_context_overlap),其步骤如下:
        • a. 初始检索 (Initial Retrieval): 首先,根据用户查询执行一次标准的向量搜索,获取一批相关的文本块。
        • b. 邻近块获取 (Fetch Neighbors): 对于每一个被检索到的相关块,利用其预存的索引,获取其前后指定数量(即“窗口大小”)的邻近文本块。
        • c. 拼接与去重 (Concatenate & De-overlap): 将原始检索到的块及其邻近块,按照它们在原文中的正确顺序进行拼接。在拼接过程中,需要妥善处理因“重叠分块”而产生的重复文本部分。
        • d. 返回结果: 为每个初始检索到的相关块,返回一个经过上下文扩展后的、更长的文本片段。
  • 举例说明 (Illustrative Example)
    • 设置:
      • 一篇文档被切分为10个带重叠的文本块 [chunk_0, ..., chunk_9]
      • 我们将“上下文窗口”的大小设置为 1(即向前看1个块,向后看1个块)。
    • 初始检索结果:
      • 向量搜索返回 chunk_5 作为与用户查询最相关的结果。
    • 传统 RAG 的问题:
      • 系统仅将 chunk_5 的内容提供给 LLM。如果 chunk_5 的开头或结尾依赖于 chunk_4chunk_6 的内容,LLM 将无法获得完整的理解。
    • 上下文丰富化窗口的处理:
        1. 系统识别出 chunk_5 是检索结果。
        1. 它利用索引 5,获取其邻居:chunk_4 (索引 5-1) 和 chunk_6 (索引 5+1)。
      1. 系统将这三个块按 [chunk_4, chunk_5, chunk_6] 的顺序拼接起来(同时处理重叠部分),形成一个连贯的文本片段。
    • 最终上下文:
      • LLM 最终接收到的是一个由三个块组成的、上下文更完整的窗口,而不是单一的 chunk_5,从而能够做出更准确的判断和生成。
  • 主要优势 (Key Benefits)
    • 结果更连贯: 返回的不再是零散的片段,而是上下文更丰富、逻辑更连贯的文本。
    • 缓解信息孤岛问题: 有效地弥补了向量搜索只返回孤立文本片段的固有缺陷。
    • 窗口大小灵活可调: 可以根据应用需求,轻松调整上下文窗口的大小(即向前或向后看几个块)。

4. 语义分块 (Semantic Chunking)

  • 核心动机 (Motivation)
    • 传统的文本切分方法常常在任意点切分文档,这可能会破坏信息的自然流动和上下文的连贯性。语义分块通过在文本的“自然断点”处进行切分,致力于解决这一问题,从而在每个文本块内部最大程度地保留其语义的完整性。
  • 实现方法详解 (Method Details)
    • 1. 语义分块的核心逻辑:
      • 其基本思想是识别句子之间的语义“鸿沟”:
        • a. 首先,将文档中的每个句子进行向量化(即计算其嵌入向量)。
        • b. 然后,计算每两个相邻句子之间的余弦相似度。
        • c. 当相邻句子之间的相似度出现一个急剧的下降时,系统就认为这里存在一个语义上的断点或主题的转换,并在此处进行切分。
    • 2. 实现工具与断点类型:
      • 该技术通常利用 LangChainSemanticChunker 组件和 OpenAI 的嵌入模型来实现。SemanticChunker 提供了多种用于定义“急剧下降”的断点策略:
        • 'percentile' (百分位法): 当句子间相似性差异的剧烈程度,超过了所有差异值分布的某个百分位阈值时(例如,前10%的剧烈变化点),进行切分。这是本方法中最常用的策略
        • 'standard_deviation' (标准差法): 当差异大于所有差异平均值的 X 个标准差时进行切分。
        • 'interquartile' (四分位距法): 使用统计学中的四分位距来识别异常的语义差异点并进行切分。
    • 3. 向量存储与检索:
      • 经过语义分块后,将这些具有高度内部一致性的文本块进行向量化,并存入 FAISS 等向量存储中。
      • 后续的检索器在进行搜索时,就能从这些语义更完整的块中寻找答案。
  • 举例说明 (Illustrative Example)
    • 原始文本 (Original Text):
      • "电动汽车(EV)通过使用电动机而非内燃机来驱动。它们将电能储存在可充电电池中,行驶时零排放,有助于减少空气污染。另一方面,氢燃料电池汽车(FCEV)也属于电动汽车的一种,但它们通过氢气和氧气的化学反应来发电,唯一的排放物是水。它们的加氢时间比充电快得多。"
    • 传统分块的可能结果 (Potential Traditional Chunking Result):
      • 如果按固定长度切分,可能会在句子中间断开,破坏语义:
      • [ "电动汽车(EV)通过使用电动机而非内燃机来驱动。它们将电能储存在可充电电池中,行驶时零排放,有助于减少空气污染。另一方面,氢燃料电池汽", "车(FCEV)也属于电动汽车的一种,但它们通过氢气和氧气的化学反应来发电,唯一的排放物是水。它们的加氢时间比充电快得多。" ]
    • 语义分块的结果 (Semantic Chunking Result):
      • 语义分块会检测到从“传统EV”到“FCEV”的语义转变(即“另一方面”前后句子相似度大幅下降),从而在两个主题之间进行切分:
      • [ "电动汽车(EV)通过使用电动机而非内燃机来驱动。它们将电能储存在可充电电池中,行驶时零排放,有助于减少空气污染。", "另一方面,氢燃料电池汽车(FCEV)也属于电动汽车的一种,但它们通过氢气和氧气的化学反应来发电,唯一的排放物是水。它们的加氢时间比充电快得多。" ]
      • 优势: 这样就得到了两个逻辑上独立、语义上连贯的文本块,极大地提升了后续检索和问答的质量。
  • 主要特性与优势 (Key Features & Benefits)
    • 上下文感知的切分: 致力于在文本块内部保持语义的连贯性和完整性。
    • 提升检索相关性: 通过保留完整的上下文,能够提升检索结果的准确性。
    • 灵活的配置: 允许根据文档的性质和检索需求,灵活选择不同的断点检测策略和阈值。
    • 可能增进LLM的理解: 对于下游的 LLM 或其他任务来说,处理语义更连贯的文本片段,其表现可能会更好。

5. 上下文压缩 (Contextual Compression)

  • 核心动机 (Motivation)
    • 传统的文档检索系统通常会返回完整的文档块 (chunks) 或整个文档,这些返回内容中可能包含大量与用户查询无关的“噪音”信息。上下文压缩技术旨在解决这一问题,通过智能地仅提取和压缩与查询最相关的部分,实现更专注、更高效的信息检索。
  • 实现方法详解 (Method Details)
    • 该技术的实现是一个清晰的流水线过程:
    • 1. 基础搭建:向量存储与基础检索器 (Foundation: Vector Store & Base Retriever):
      • 首先,通过标准流程(如使用 encode_pdf 函数)将 PDF 等文档处理并加载到一个向量存储中。
      • 基于此向量存储,创建一个标准的、作为基础的检索器 (Base Retriever)。
    • 2. 核心组件:上下文压缩器 (Core Component: The Contextual Compressor):
      • 接着,初始化一个基于大语言模型 (LLM) 的上下文压缩器。一个常见的实现是 LLMChainExtractor,它内部使用 GPT-4 等强大的模型。
      • 这个压缩器的任务是:接收一个文档块和用户的原始查询,然后判断该文档块中的哪些句子或片段与查询直接相关,并将其提取出来。
    • 3. 整合:上下文压缩检索器 (Integration: The ContextualCompressionRetriever):
      • 这是将检索与压缩结合在一起的关键步骤。ContextualCompressionRetriever 是一个“包装器 (wrapper)”,它内部包含了基础检索器上下文压缩器
      • 其工作流程分为两步
        • a. 第一步 (检索): 当收到用户查询时,内部的基础检索器首先从向量库中获取一批相关的、但内容未经处理的完整文档块。
        • b. 第二步 (压缩): 上下文压缩器接着处理这些返回的文档块,并根据原始用户查询,从中仅提取出最相关的句子或片段。
    • 4. 应用:问答链 (Application: Question-Answering Chain):
      • 最后,使用这个配置好的 ContextualCompressionRetriever 来构建一个问答链 (如 RetrievalQA)。
      • 现在,最终用于生成答案的 LLM 所接收到的上下文,不再是冗长的完整文档块,而是经过压缩后留下的、高度相关的核心信息片段。
  • 举例说明 (Illustrative Example)
    • 用户查询 (User Query):
      • "特斯拉的4680电池有什么优势?"
    • 基础检索器返回的完整文本块 (Full Chunk Returned by Base Retriever):
      • "在2020年的电池日上,特斯拉发布了其创新的4680电池。这种新设计的优势在于通过无极耳技术显著提升了能量密度并降低了生产成本。该电池的量产计划最初遇到了一些挑战,但公司正努力在德州和柏林的超级工厂中扩大生产。未来,它将被用于Cybertruck等新车型。"
    • 上下文压缩器的输出 (Output from Contextual Compressor):
      • 压缩器在理解了用户查询后,会从上述完整文本块中,精准地提取出直接回答问题的那句话:
      • "这种新设计的优势在于通过无极耳技术显著提升了能量密度并降低了生产成本。"
    • 优势:
      • 最终的问答 LLM 只需处理这句干净、简洁、高度相关的信息,而不是整个段落。这不仅减少了无关信息的干扰和产生幻觉的风险,还降低了计算负荷,使得最终的答案更直接、更准确。
  • 主要优势 (Key Benefits)
    • 提升相关性: 系统只返回与查询最相关的信息,极大地减少了噪音。
    • 提升效率: 通过压缩和提取,显著减少了下游 LLM 需要处理的文本量,加快了响应速度并降低了成本。
    • 增强上下文理解: 基于 LLM 的压缩器能够深刻理解查询的上下文,并据此进行精准提取。
    • 灵活性: 该系统可以轻松适应不同类型的文档和查询需求。

6. 通过问题生成进行文档增强 (Document Augmentation)

  • 核心动机 (Motivation)
    • 通过用相关的、多样化的问题来丰富原始的文本片段,我们旨在显著提升系统识别文档中“能够回答用户查询”的最相关部分的准确性。本质上,这是将“问题-文档”的匹配,转化为更精准、更高效的“问题-问题”匹配。
  • 与 HyPE 的核心关联
    • 此技术在核心理念上与前文提到的“假设性提示嵌入 (HyPE)”几乎完全相同。两者都遵循以下原则:
      • 离线处理: 在文档索引阶段进行处理,没有运行时开销。
      • 问题生成: 为知识库中的每个文档块 (chunk) 生成多个潜在的问题
      • 提升匹配: 将检索过程转化为“问题-问题”匹配,以解决查询与文档风格不匹配的问题。
    • 您可以将此方法视为 HyPE 理念的一种具体实现或变体。
  • 实现方法详解 (Method Details)
    • 1. 文档预处理 (双层分块 - Two-Level Chunking):
      • 这是一个值得注意的细节。该实现采用了一种双层分块策略:
        • a. 第一层 (上下文文档 text_document): 首先,使用 PyPDFLoader 加载文档后,将其切分为较大的、带重叠的文本块。这些较大的块主要用于在检索到目标信息后,构建最终提供给 LLM 的、更完整的上下文。
        • b. 第二层 (检索片段 text_fragment): 接着,将每个较大的 text_document 进一步切分为更小的、带重叠的文本片段。这些小片段是执行问题生成和语义搜索的基本单元。
    • 2. 文档增强:生成问题 (Document Augmentation: Question Generation):
      • 针对每一个小粒度的 text_fragment,系统会调用 OpenAI 的语言模型为其生成多个(数量可通过 QUESTIONS_PER_DOCUMENT 等常量配置)相关的假设性问题。
    • 3. 向量存储创建 (Vector Store Creation):
      • a. 嵌入内容: 对每个生成的假设性问题使用 OpenAIEmbeddings 进行向量化。
      • b. 建立关联: 在 FAISS 向量存储中,建立起每个“问题向量”与其对应的原始文本片段 (text_fragment) 之间的关联映射。
    • 4. 检索与生成 (Retrieval & Generation):
      • a. 检索: 当用户发起一个真实查询(一个问题)时,系统在 FAISS 向量库中搜索与之最相似的假设性问题向量
      • b. 上下文构建: 系统根据命中的问题向量,找到其关联的 text_fragment。随后,可以进一步获取该 text_fragment 所属的、更大的 text_document,从而构建出一个既精准又信息丰富的上下文。
      • c. 生成答案: 最后,LLM 基于这个高质量的上下文来生成最终答案。
  • 举例说明 (Illustrative Example)
    • 原始文本片段 (text_fragment):
      • "4680电池通过无极耳设计显著提升了能量密度并降低了生产成本。"
    • 为其生成的假设性问题 (Generated Questions for the Fragment):
      • "4.680 电池的设计有何创新之处?"
      • "无极耳技术给电池带来了哪些好处?"
      • "特斯拉如何降低电池成本并提升能量密度的?"
    • 检索过程 (Retrieval Process):
      • 当一个用户发起一个相似的查询,例如“4680电池的主要优点是什么?”时,这个查询的向量会与上述预先生成的多个问题向量产生很高的相似度。系统因此能够精准地命中这些问题,并返回它们所关联的原始文本片段作为核心事实依据。
  • 主要优势 (Key Benefits)
    • 增强的检索流程: 极大地增加了为用户查询找到最相关文档片段的概率。
    • 灵活的上下文调整: 双层分块的设计,使得在构建最终上下文时可以灵活地调整窗口大小。
    • 高质量的语言理解: 利用 OpenAI 强大的语言模型来生成高质量、多样化的问题和最终的答案。
百度云4机A800测试Agent 框架汇总
Loading...