CrabNote螃蟹笔记

别让“无效分块”毁了你的RAG!优化效果提升80%的秘密

别让“无效分块”毁了你的RAG!优化效果提升80%的秘密

别让“无效分块”毁了你的RAG!优化效果提升80%的秘密 别让“无效分块”毁了你的RAG!优化效果提升80%的秘密 Modified November 26, 2025 大模型RAG长文本难题:分块是核心解法 Audio or video is not supported 2. 然后,它会检查分割出的块是否超过了预设的大小限制。 3. 如果某个块太大了,它就会递归地调用下一级别的分隔符(换行符)对这个 大块 进行再次分割。这个过程会一直持续下去,直到所有块的大小都符合要求。 如上图所示,我们首先将整篇文章按段落(紫色)分成了两个大块。随后,发现第一个段落仍然过长,于是再将其细分为更小的句子块。 优点: • 尊重文本结构 :它优先考虑了段落、句子等天然的语义边界,尽可能地保持了内容的连贯性。 • 大小可控 :同时它也保证了所有的块都不会超过尺寸限制。 缺点: • 实现稍复杂 :相比固定大小分块,它在实现和计算上会带来一些额外的开销。 4. 基于文档结构分块 (Document Structure based Chunking) 这又是一种非常直观的方法。对于那些本身就具有良好结构(如HTML、Markdown、LaTex)的文档,我们可以直接利用它们的 固有结构 (如标题、章节、列表、表格)来进行分块。 例如,我们可以将一个Markdown文档的每个一级标题( )和它下面的所有内容作为一个大块,或者将HTML中的每个 <section 标签作为一个块。 这种方法也可以和递归分块结合起来,我们可以把文档结构的不同层级符号设置为分隔符列表,比如Markdown文档的分隔符列表可以设置为[" "," "," "]。 这种分块方式的输入形式如下: 优点: • 逻辑清晰 :分块结果与文档的逻辑结构完全一致,保证了每个块在主题上的一致性。 缺点: • 适用性有限 :这种方法严重依赖于文档是否拥有清晰、规范的结构。对于纯文本(.txt)文件则完全无效。 • 块大小不一 :不同章节或部分的内容长度可能差异巨大,这可能导致某些块过大而超出模型上下文窗口,或某些块过小而信息量不足。(这个问题可以通过和递归分块结合来缓解。) 5. 基于大语言模型分块 (LLM based Chunking) LLM在几乎所有的自然语言处理任务上都取得了SOTA(State of the art,最佳的意思)表现,那么我们是不是也可以让LLM来做分块这件事。 我们可以通过prompt引导LLM将一篇长文分割成多个 语义上独立且内聚 的段落。 优点: • 语义准确性最高 :LLM本身就具备极强的语义理解能力。它能够理解超越简单分隔符和相似度计算的深层的语义关联,从而生成质量最高的文本块。 缺点: • 成本高昂 :这是五种方法中计算成本最高、速度最慢的技术。对每一篇文档都进行一次LLM调用,在处理大规模数据集时会是一笔巨大的开销。 • 上下文窗口限制 :LLM自身也有上下文窗口的限制,处理超长文档时需要设计更复杂的处理方案。 分块策略总结 那么,哪一种分块方式是最好的分块方式,我们应该如何进行选择呢? 事实上,分块也是一种权衡的艺术,并没有一种万能的在所有场景下都适用的分块方法。最佳策略的选择通常取决于 文档类型 、 计算预算 和对 检索精度 的要求。 在实际应用中,我们常常将多种策略结合起来。例如,从 递归分块 开始是一个非常稳健的选择;如果你的文档结构良好,可以尝试 基于结构的分块 并辅以递归分割来控制大小。如果追求极致的性能且不计成本, LLM分块 则是你的终极武器。 公众号 You don't have permission to access this synced block. Please log in and try again. Log In 大模型RAG长文本难题:分块是核心解法 Audio or video is not supported 大模型RAG长文本难题:分块是核心解法 Audio or video is not supported 2. 然后,它会检查分割出的块是否超过了预设的大小限制。 3. 如果某个块太大了,它就会递归地调用下一级别的分隔符(换行符)对这个 大块 进行再次分割。这个过程会一直持续下去,直到所有块的大小都符合要求。 如上图所示,我们首先将整篇文章按段落(紫色)分成了两个大块。随后,发现第一个段落仍然过长,于是再将其细分为更小的句子块。 优点: • 尊重文本结构 :它优先考虑了段落、句子等天然的语义边界,尽可能地保持了内容的连贯性。 • 大小可控 :同时它也保证了所有的块都不会超过尺寸限制。 缺点: • 实现稍复杂 :相比固定大小分块,它在实现和计算上会带来一些额外的开销。 4. 基于文档结构分块 (Document Structure based Chunking) 这又是一种非常直观的方法。对于那些本身就具有良好结构(如HTML、Markdown、LaTex)的文档,我们可以直接利用它们的 固有结构 (如标题、章节、列表、表格)来进行分块。 例如,我们可以将一个Markdown文档的每个一级标题( )和它下面的所有内容作为一个大块,或者将HTML中的每个 <section 标签作为一个块。 这种方法也可以和递归分块结合起来,我们可以把文档结构的不同层级符号设置为分隔符列表,比如Markdown文档的分隔符列表可以设置为[" "," "," "]。 这种分块方式的输入形式如下: 优点: • 逻辑清晰 :分块结果与文档的逻辑结构完全一致,保证了每个块在主题上的一致性。 缺点: • 适用性有限 :这种方法严重依赖于文档是否拥有清晰、规范的结构。对于纯文本(.txt)文件则完全无效。 • 块大小不一 :不同章节或部分的内容长度可能差异巨大,这可能导致某些块过大而超出模型上下文窗口,或某些块过小而信息量不足。(这个问题可以通过和递归分块结合来缓解。) 5. 基于大语言模型分块 (LLM based Chunking) LLM在几乎所有的自然语言处理任务上都取得了SOTA(State of the art,最佳的意思)表现,那么我们是不是也可以让LLM来做分块这件事。 我们可以通过prompt引导LLM将一篇长文分割成多个 语义上独立且内聚 的段落。 优点: • 语义准确性最高 :LLM本身就具备极强的语义理解能力。它能够理解超越简单分隔符和相似度计算的深层的语义关联,从而生成质量最高的文本块。 缺点: • 成本高昂 :这是五种方法中计算成本最高、速度最慢的技术。对每一篇文档都进行一次LLM调用,在处理大规模数据集时会是一笔巨大的开销。 • 上下文窗口限制 :LLM自身也有上下文窗口的限制,处理超长文档时需要设计更复杂的处理方案。 分块策略总结 那么,哪一种分块方式是最好的分块方式,我们应该如何进行选择呢? 事实上,分块也是一种权衡的艺术,并没有一种万能的在所有场景下都适用的分块方法。最佳策略的选择通常取决于 文档类型 、 计算预算 和对 检索精度 的要求。 在实际应用中,我们常常将多种策略结合起来。例如,从 递归分块 开始是一个非常稳健的选择;如果你的文档结构良好,可以尝试 基于结构的分块 并辅以递归分割来控制大小。如果追求极致的性能且不计成本, LLM分块 则是你的终极武器。 公众号 公众号 公众号 You don't have permission to access this synced block. Please log in and try again. Log In 🔗 原文链接: https://mp.weixin.qq.com/s/zMdaYVVI... https://mp.weixin.qq.com/s/zMdaYVVI... 原创 喜欢萨摩耶的Evan 星空拾荒2025年07月28日 23:19 广东 Indexing 指的是将各种格式的文档经过预处理之后索引为高维向量,并构建向量数据库的过程(下图红框的位置)。 分块则是Indexing中最基础也最重要的一个环节。 1. 什么是分块 我们知道,RAG的核心是让大模型在回答问题前,先阅读相关的参考资料。但是一本书,一份材料,一个文档往往有几十上百页,我们不可能一次性把所有的资料传入。这是因为: 1. 模型的上下文窗口大小是有限的 ,上下文窗口是指模型在一次处理中能够“看到”和“记住”的文本长度上限。超过长度的文本会被直接截断,这可能会导致重要信息的缺失。 2. 在最佳实践中,哪怕有时候输入的文本长度没有达到上下文窗口的限制,模型也会“忘记”一些他看到的内容,这称为 Lost in the middle 问题 。这经常出现在输入文本过长的时候。 所以,我们需要将外部的参考资料先进行分块,所谓 分块是指将大型的、非结构化的数据(如长文本、文档)切分成更小的、有意义的、独立单元的过程。 2. 如何选择块的大小 那么,我们应该如何选择块的大小呢? 一个最直接的限制是Embedding模型的上下文窗口大小。 Embedding模型的上下文窗口大小指的是Embedding模型一次性能够处理的文本长度,现在主流Embedding模型的Max Tokens一般是8092,也就是我们最多一次性能把8092 token长度的文本转为高维向量。 这意味着我们不可能把一篇几万字的报告直接转换成一个向量。 举个例子,《指环王》全系列约有57万个英文单词。如果我们想把它做成一个RAG知识库,并且使用一个上限为8K Token的Embedding模型,那么我们 至少 需要把它切分成93个块,才可能完成最基本的向量化。 越大的块能够包含越多的信息,但是,块的大小不是越大越好,因为我们分块的本质是追求 检索质量 。即便我们能把一个大块塞进模型,也通常不应该这么做。因为这会严重影响检索的精度。 要理解这一点,我们需要回到第一性原理:向量检索是如何工作的?简单说,系统在向量空间中,寻找与问题向量最近的文本块向量。因此,一个文本块的向量能否 精准地、无歧义地 代表其核心语义,就成了重中之重。 而过大的文本块,恰恰会破坏这种精准性。 Embedding模型的工作原理,本质上是一种 有损压缩 。它会把成百上千个词语蕴含的丰富语义,通过池化(Pooling)等技术,压缩成一个固定维度(例如768维)的向量。 如果我们分出来的块比较小,且主题聚焦。那么它的向量就能清晰指向其语义。举个例子,一个块只描述“草莓”。那么它的向量就能清晰地指向“红色”、“甜”、“水果”等语义方向。 但是如果我们分出来的 块较大 ,那么其中的主题必然更为混杂。比如现在一个大块里既有“草莓”,又有“蓝莓”,还有“猕猴桃”。为了用一个向量来代表所有内容,模型只能取一个“平均值”。最终得到的向量可能是一个模糊的、棕褐色的混合体,它既不能很好地代表草莓的红,也无法体现蓝莓的蓝。 这种“平均主义”是致命的。对于大块来说,其包含的语义信息越多,最终生成的向量就越“平庸”,越无法代表其中任何一个具体而鲜明的观点,从而导致检索时难以被精确匹配。 一个大块可能同时讨论了A、B、C三个不完全相关的主题。当用户提问一个只与A相关的问题时,这个大块的向量因为被B和C“稀释”了,导致它在A这个主题上的语义代表性并不强。结果就是,系统很可能会错过这个包含了正确答案的大块,反而检索出另一个虽然信息不全、但主题更纯粹、只讲了A的小块。 既然分块如此重要,那么到底分多大才合适呢? 这是一个需要权衡的艺术: 块太大可能导致每个块内部的主题稀释,进而导致检索精度下降。块太小则可能破坏了信息的完整性,比如:一句话被硬生生从中间切开,上下文丢失,导致无法被理解。这没有一个放之四海而皆准的答案,最佳大小取决于你的文档类型和具体应用场景。但一个普遍被接受的 实验起点是:大约500个Token 。 从这个基准开始,通过不断测试和评估我们的RAG系统在真实问题上的表现,逐步调整块的大小和overlap策略,逐步找到最优解。 分块是一个从根本上决定RAG系统检索上限的核心策略。 精心设计的分块策略,能够产生语义清晰、主题聚焦的向量,这是实现精准检索、进而生成高质量答案的基石。 3. 分块策略 接下来,我们将依次学习以下五种分块策略。 1. 固定大小分块 (Fixed size Chunking) 这是最直观、最简单粗暴的方法。顾名思义,就是把文本按照一个预先定义好的固定大小(如512个Token)进行切割。 为了缓解直接切分可能导致的语义断裂,我们通常会在两个连续的块之间设置一些 重叠内容 (称为Overlap),如上图中的蓝色部分所示。这样,即便一个完整的句子在块A的末尾被切断,它的后半部分也会出现在块B的开头,从而保留了信息的连续性。 优点: • 实现简单 :逻辑清晰,几行代码就能搞定。 • 便于处理 :所有块的大小统一,简化了后续的嵌入和批处理流程。 缺点: • 破坏语义 :这种机械式的切割会 粗暴地打断完整的句子或段落 ,导致一个完整的思想或关键信息被分散到两个甚至多个块中,影响检索效果。 2. 语义分块 (Semantic Chunking) 既然固定大小分块会破坏语义,那我们能不能直接根据语义来分块,保证每一个块里面的所有内容都是语义接近的呢?这就是语义分块的核心思想。 它的流程如下: 1. 首先,将文档按照句子或者段落拆分成一个个有意义的基础单元。 2. 接着,为每个单元计算嵌入向量。 3. 从第一个单元开始,计算它和下一个单元嵌入向量的 余弦相似度 。如果相似度很高,意味着它们在语义上是紧密相关的,就将它们合并成一个块。 4. 持续这个过程,直到某个单元与下一个单元的相似度 显著下降 。这通常意味着一个话题的结束和另一个新话题的开始。此时,我们便切断连接,开始一个新的分块。 最终我们形成的分块可能如下,红色,绿色,蓝色分别代表了一个块。 优点: • 保持语义完整性 :语义分块的切分方式天然地遵循了语义,能最大限度地保留完整的上下文信息。 • 提升检索精度 :由于每个块的语义都非常内聚,检索系统能更准确地找到与用户问题相关的上下文,从而帮助LLM生成更连贯、更优质的回答。 缺点: • 依赖阈值 : 显著下降阈值的设定是语义分块的核心难题 。这个阈值可能需要根据不同的数据集和文档类型进行实验和调整,没有统一标准。 3. 递归分块 (Recursive Chunking) 这是一种兼顾了 文档结构 与 块大小 的分块策略。 它的逻辑非常巧妙: 1. 首先,递归分块算法会尝试用一个预设的、有层次的 分隔符列表 (如: ["\n\n" (段落), "\n" (换行), "。" (句号)] )来分割文本。它会首先尝试用最高级别的分隔符(段落)进行分割。