|
先embedding再chunking的时代来了。  ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">在RAG应用开发中,第一步就是对于文档进行chunking,chunk质量会直接决定整个RAG检索的质量。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">过去,行业通常会采用先chunking再embedding,最后检索、生成的思路进行。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">但这个思路中,在chunking环节,无论是固定长度分块,还是递归分块,其实都解决不了精度和上下文的平衡的问题。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">在此背景下,先embedding再chunking的思路逐渐被更多人接受。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">典型代表是Jina AI提出的Late Chunking策略,以及Max–Min semantic chunking。Late Chunking详见Late Chunking×Milvus:如何提高RAG准确率ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">本文将对Max–Min semantic chunking进行重点解读。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: center;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">01ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: center;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">常见chunk思路解读ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">一个典型的RAG流程是这样的:ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);text-align: left;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">第一步,数据清洗与处理:对元数据去除无关内容(如页眉页脚、乱码),统一格式,并将长文本分割成短片段(如 500 字 / 段),避免向量表示时丢失细节。第二步,向量生成与存储:用embedding模型(如 OpenAI 的 text-embedding-3-small、LangChain 的 BAAI embedding)将每个文本片段转换成向量(Embedding)然后将其存储到向量数据库(如 Milvus、Zilliz Cloud),数据库会通过不同索引方式优化语义检索效率。 第三步,查询:将用户的自然语言查询(如 “RAG 如何解决大模型幻觉问题”)通过相同的embedding模型转换成向量后,向量数据库根据查询向量,快速找到语义最相似的Top-K 个文本片段。 第四步,生成回答:将检索到的 Top-K 文本片段作为上下文,和用户的原始查询一起拼接成提示词(Prompt),传给大模型,大模型据此生成回答。 在这个过程中,高效的文档分块是整个流程中的第一步,它将文档拆成小块(一个段落、一节或一组句子),可以有效的提高后续召回内容的准确性与细节丰富度。 但做好一个高质量的chunking并不容易。 目前行业有两种常见的分块方法: 以这两种方式进行分块的时候,我们经常要考虑两个问题:精度和上下文的平衡。 越小的块,精度越高,但上下文可能不全;越大的块,语境更完整,但可能包含太多无关信息。 2025年Bhat等人的研究发现,分块大小这个问题没有标准答案,但整体上,事实类问题适合小块(64-128 token),而叙事类问题则适合大块(512-1024 token)。 有没有更聪明一点的办法?不要完全被长度限制的分块思路? 答案是有的——Max–Min semantic chunking。 论文链接:https://link.springer.com/article/10.1007/s10791-025-09638-7?utm_source=chatgpt.com 02Max–Min semantic chunking 解读Max–Min semantic chunking的核心是通过动态语义评估来实现分块优化。 相比传统RAG流程,先chunking再embedding,Max–Min semantic chunking会先对所有句子进行embedding,然后在此基础上进行分块。 Max–Min semantic chunking会将分块任务视为动态 / 时序聚类问题:基于句向量的相似度,将不同句子组合成新的分块。 但与传统聚类方法不同,该方法需尊重文档中句子的时序性——即同一聚类内的句子必须连续。算法会按顺序逐句处理文档,决定每个句子是加入当前分块,还是开启新分块。 具体步骤如下: 生成embedding并初步聚类:首先使用文本嵌入模型,将所有句子映射到高维空间。设文档包含 n 个句子,通过计算,已将前n-k个句子归入当前分块 C。此时需决策:n-k+1个句子,是加入分块 C,还是创建新分块。 计算分块内最小相似度:计算当前分块 C 内所有句子向量间的最小 pairwise 余弦相似度,识别分块内语义最不相似的句子对,衡量分块内句子的关联紧密程度,进而判断新句子是否与分块内句子足够相似。 计算新句子与分块的最大相似度:计算当前分块 C 内所有句子的最大余弦相似度,对比新句子与现有分块的最高语义相似度。 分块决策依据:核心决策逻辑为:若分块 C 内的最小相似度小于新句子与分块 C 的最大相似度,则新句子加入分块 C,否则开启新分块。 阈值调整(分块大小优化):对于如何调整块内语义相关度,我们可以动态调整分块大小、相似度阈值等等参数。 初始化处理(分块中仅有单个句子时):当当前分块仅包含 1 个句子时,需特殊处理初始化问题,直接对比第一句与第二句相似度与我们设置的阈值常数,高于常数就算入同一个分块,低于这个常数就开启新的分块。
03Max–Min semantic chunking的优劣势Max–Min semantic chunking的创新点一共有三: 动态分块逻辑:摒弃固定尺寸或结构依赖的静态规则,以 “句子语义相似度” 为核心决策依据。具体流程为:先计算当前分块内句子的最小语义相似度(衡量分块内语义关联的下限),再计算新句子与当前分块的最大语义相似度(衡量新句子与分块的适配度);若最大相似度高于最小相似度,则将新句子纳入当前分块,否则启动新分块。 轻量化参数设计:仅需调整 3 个核心超参数(最大分块大小、一二句之间的最低语义相似度需求、新句子与块内句子最大相似度的最低门槛),且超参数逻辑与分块大小自适应 —— 分块规模越大,新句子纳入的阈值越高。 计算资源复用:复用 RAG 系统原生所需的 “句子嵌入向量”(无需额外计算嵌入),仅在分块阶段增加轻量化的余弦相似度计算,整体计算开销低于传统语义分块方法。
但Max–Min semantic chunking方法也有其不足,因为是依据时序聚类,因此处理长文档时可能会丢失文档中长距离的上下文依赖关系。 如果关键信息散落在多个文本块中,脱离上下文的文本分块片段很可能失去其原有的意义,导致后续的召回效果比较差。 以Milvus 2.4.13 release note为例,假如分为如下两个文档块,如果我们要查询Milvus 2.4.13有哪些新功能?,直接相关内容在分块2里,而Milvus版本信息在分块1里,此时,Embedding 模型很难将这些指代正确链接到实体,从而产生质量不高的Embedding。 此外,由于功能描述与版本信息不在同一个分块里,且缺乏更大的上下文文档,LLM 难以解决这样的关联问题。 对于这种问题,我们可以采用滑动窗口重新采样、重叠的上下文窗口长度以及多次文档扫描等方式来解决。 |