RAG 文档解析与 Chunking 详解:Chunk Size、Overlap 和切分策略应该怎么选?
在 RAGRetrieval-Augmented Generation检索增强生成系统中大语言模型通常不会每次都读取整个知识库。系统一般会先将原始文档处理成适合搜索的内容再根据用户的问题检索相关片段最后把这些片段交给大语言模型生成回答。因此RAG 的回答质量不仅取决于模型能力和检索算法还取决于一个更早发生的环节知识是如何被解析、切分和保存的。假设企业差旅制度中有这样一张表格员工级别住宿报销标准普通员工300 元/天部门经理500 元/天总监800 元/天用户询问“普通员工出差住宿费每天最多能报销多少钱”原始文档中明明存在明确答案RAG 系统却可能返回错误金额或者表示没有找到相关依据。原因不一定是检索模型不够准确也可能是文档在进入知识库时已经丢失了关键结构或者在切分过程中破坏了完整的语义关系。要理解这个问题需要掌握六个核心概念Document Parsing文档解析Chunking文本切分Chunk Size切分块大小Chunk Overlap相邻块的重叠内容结构化切分与语义切分切分质量评估本文将从完整处理流程出发解释这些技术的工作原理、适用场景及工程实践中的常见问题。一、文档为什么需要切分1. RAG 的文档处理流程一个典型的 RAG 知识入库流程可以概括为原始文档 ↓ Document Parsing文档解析 ↓ 文本与结构清洗 ↓ Chunking文档切分 ↓ 生成 Embedding向量表示 ↓ 建立检索索引 ↓ 等待用户查询这里的 Embedding是指将文本转换成能够表示其语义特征的数字向量以便系统计算文本之间的相似程度。需要注意RAG 并不必须使用向量检索有些系统使用关键词检索也有些系统同时使用多种检索方式。但无论采用哪种方式文档在建立索引之前如何被组织都会影响后续检索效果。2. 为什么不直接把整份文档建立为一个检索对象假设一份员工手册包含 100 页内容涵盖入职、考勤、薪酬、报销、离职等多个主题。如果直接把整份手册当作一个检索单位会遇到几个问题。首先整份文档可能超出 Embedding 模型允许的单次输入长度。其次如果整份手册只对应一个向量那么这个向量需要同时表示多个主题。用户只问“住宿报销标准”整份手册的整体语义未必能准确代表这一小段内容。最后即使检索到了整份文档后续还需要从中定位与问题直接相关的部分。所以很多 RAG 系统会将长文档拆成多个较小的 Chunk。例如员工手册 ├── Chunk 01入职流程 ├── Chunk 02考勤制度 ├── Chunk 03请假制度 ├── Chunk 04住宿报销标准 ├── Chunk 05交通报销标准 └── Chunk 06离职手续当用户询问住宿报销问题时系统就有机会直接检索到 Chunk 04。但是Chunk 并不是越小越好。切分的目标不是产生更多片段而是构造既适合检索、又能保留完整信息的知识单位。二、Document Parsing为什么切分之前必须先正确解析Document Parsing即文档解析是将 PDF、Word、网页等原始文件转换成计算机可以进一步处理的内容。文档解析与 Chunking 是两个不同阶段。解析负责识别文档中有什么以及这些内容如何组织。切分负责决定哪些内容应该组合成一个检索片段。如果解析已经破坏了原文关系后续切分通常无法可靠地恢复这些关系。1. 复杂表格为什么容易出问题继续使用差旅报销表格。原始内容员工级别标准普通员工300 元部门经理500 元总监800 元某些简单文本提取方式可能得到员工级别 普通员工 部门经理 总监 标准 300元 500元 800元从文字提取的角度看所有内容似乎都存在。但原始表格中最重要的行列对应关系并没有被明确保留。如果后续系统把这些文字切成不同片段错误可能进一步扩大。因此表格解析不能只关注有没有提取出文字还应该检查行、列、表头和数值之间的关系。一种更适合保留结构的文本表达方式是# 差旅报销制度 ## 住宿报销标准 | 员工级别 | 标准 | |---|---| | 普通员工 | 300元/天 | | 部门经理 | 500元/天 | | 总监 | 800元/天 |在合适的场景下也可以将表格中的每一行整理成独立事实普通员工的住宿报销标准为300元/天。 部门经理的住宿报销标准为500元/天。 总监的住宿报销标准为800元/天。两种表达方式各有优势。Markdown 表格能够保留行列结构适合需要理解整张表格的场景。逐行文本则适合围绕单个对象进行精确问答。但逐行展开可能丢失合并单元格、脚注、跨行条件等复杂关系。因此工程实践中可以同时保存原始表格结构和用于检索的文本表达而不是简单地把所有表格都转换成普通段落。2. 文档解析还需要注意什么不同类型的文件具有不同的解析风险。文档类型常见问题处理重点普通 PDF多栏文字顺序混乱、页眉页脚混入正文阅读顺序、版面识别扫描 PDF文件实际上是图片没有可直接提取的文字OCR 文字识别与质量校验Word标题层级、表格、列表结构丢失保留结构信息Markdown标题和正文分离、代码块被截断保留标题层级及完整内容块网页 HTML导航栏、广告、重复内容干扰正文正文提取与结构清理复杂表格表头、单位、行列关系丢失结构化解析及关联关系校验OCROptical Character Recognition指从图片中识别文字的技术。但 OCR 能识别字符不代表它一定能准确恢复复杂的版面关系。这也是为什么企业知识库中的 PDF 解析往往不只是调用一个简单的文本提取函数。三、Chunk Size文档应该切多大Chunk Size 指每个 Chunk 的目标大小或最大大小。具体计量单位取决于实现方式常见的有字符数和 Token 数。Token 是模型处理文本时使用的基本单位它不等于一个汉字也不一定等于一个英文单词。因此chunk_size 500到底代表 500 个字符还是 500 个 Token需要看所使用的切分工具和长度计算方式。1. Chunk 太小的问题假设原文为普通员工的住宿报销标准为300元/天。 超出标准的费用需要提前提交审批。如果切分过小可能得到Chunk A 普通员工的住宿报销标准为 Chunk B 300元/天。超出标准的费用 Chunk C 需要提前提交审批。三个 Chunk 都包含原文的一部分但独立理解时存在明显问题。Chunk A 缺少金额。Chunk B 包含金额却缺少适用对象。Chunk C 包含审批动作却缺少触发审批的条件。这类问题可以称为语义割裂原本属于同一事实的条件、对象和结论被切开。2. Chunk 太大的问题反过来如果一个 Chunk 同时包含报销、考勤、请假、薪酬等多个主题也会产生问题。例如Chunk A 第一章 入职制度 第二章 考勤制度 第三章 差旅报销 第四章 薪酬管理 第五章 离职制度当用户只询问住宿报销时整个 Chunk 中的大部分内容可能无关。Chunk 过大可能导致检索单位不够聚焦。单个向量混合表达多个主题。后续模型需要处理更多无关文字。在有限上下文预算下能够放入的独立证据减少。但也不能简单认为大 Chunk 一定不准确。对于跨多个段落才能解释完整的问题更大的 Chunk 可能恰好有助于保留上下文。3. Chunk Size 应如何选择需要结合三个因素第一文档结构。制度条款、产品说明、技术手册和会议记录的内容组织方式不同。第二用户问题。如果用户通常询问某个金额、型号或操作步骤小而完整的事实块可能更合适。如果用户经常要求综合分析多个章节则需要考虑更大的上下文范围或者在检索后组合相关片段。第三模型与系统约束。Embedding 模型有输入长度限制生成模型也有上下文预算而每个 Chunk 的长度还会影响向量化、检索及最终输入成本。所以Chunk Size 是需要评测和调整的参数不存在适用于所有 RAG 系统的统一最优值。四、Chunk Overlap为什么相邻片段需要重复内容Chunk Overlap 指相邻两个 Chunk 之间重复保留的内容长度。假设Chunk Size 500 Tokens Overlap 100 Tokens在最简单的固定长度滑动窗口切分中Chunk 1Token 0499 Chunk 2Token 400899 Chunk 3Token 8001299相邻 Chunk 重复 100 个 Token。这样可以降低信息恰好被切在边界上的风险。1. Overlap 与步长的关系对于固定长度的滑动窗口算法Step Size Chunk Size - Overlap即Step Size 500 - 100 400 Tokens每生成一个新 Chunk切分窗口就向后移动 400 Token。对于长度为 L 的文档当 L 大于 Chunk Size、且切分器允许最后一个不足完整长度的 Chunk 时可以使用以下公式计算块数Chunk 数量 ceil((L - Chunk Size) / Step Size) 1其中ceil表示向上取整。如果文档本身不超过一个 Chunk则只需要一个块。2. Overlap 太大会发生什么假设一份文档有 3,000 Token设置Chunk Size 500 Overlap 400那么Step Size 500 - 400 100 Chunk 数量 ceil((3000 - 500) / 100) 1 26原本不重叠时3,000 Token 可以形成 6 个完整的 500 Token Chunk。现在却产生了 26 个。在这个特定例子中26 个 Chunk 都是完整长度索引中的文本 Token 总量 26 × 500 13,000也就是说同一份 3,000 Token 的文档经过高度重叠切分累计需要处理约 13,000 个 Chunk Token。这不是原始文档变长了而是大量内容被重复保存。它可能增加 Embedding 计算量、索引规模和维护成本。此外高度相似的 Chunk 可能同时进入检索结果挤占其他独立证据的位置。需要说明上述计算针对允许这种重叠比例的固定滑动窗口算法。实际工具可能具有不同的切分边界和参数约束并不一定允许 Overlap 达到 Chunk Size 的 80%。3. Overlap 的合理定位Overlap 主要用于缓解相邻块之间的上下文割裂。但它不能解决所有问题。如果 PDF 解析时就丢失了表格的行列关系增加 Overlap 不能保证恢复原本不存在于文本中的关系。如果原始文档具有明确的章节和段落结构优先按结构切分通常比大量增加 Overlap 更有针对性。Overlap 是切分策略的补充不应该替代正确的文档解析与结构识别。微软 Azure AI Search 的文档提供了从 512 Token、25% 重叠开始测试的建议但同时明确指出最终参数需要根据文档和应用情况调整。这是测试起点而不是通用最优配置。五、四种常见的 Chunking 策略除了设置 Chunk Size 和 Overlap还需要决定切分边界如何确定。常见方案包括固定长度切分、递归切分、结构化切分和语义切分。1. Fixed-size Chunking固定长度切分固定长度切分按照字符数或 Token 数建立片段。例如每 500 Token 一个 Chunk相邻片段重叠 100 Token。优势是实现简单、参数明确适合作为初始实验基线。局限是如果不考虑标点、段落和文档结构容易切断完整句子或事实。因此纯固定滑动窗口更适合作为一种基线方案而不一定是所有生产场景的首选。2. Recursive Chunking递归切分递归切分不是简单地从某个位置切断文本而是按一组预设的分隔符逐层尝试。例如第一优先级按空行划分段落 第二优先级按换行划分 第三优先级按句号、问号等标点划分 第四优先级进一步切分过长内容如果一个段落没有超过长度限制就尽量保留完整。如果段落过长再使用下一层切分规则。这种方式可以减少不必要的语义割裂。LangChain 的RecursiveCharacterTextSplitter就是一个典型实现。对于中文内容还需要考虑中文标点和文本长度计算规则而不能完全照搬英文文本的默认分隔符。3. Structure-aware Chunking结构化切分结构化切分利用文档本身的组织方式决定边界。例如# 系统运维手册 ## 数据库备份 ### 全量备份 ### 增量备份 ## 故障恢复 ### 故障确认 ### 恢复步骤 ### 恢复验证一种结构化切分方案可以先按照二级标题拆分。如果“故障恢复”章节仍然太长再按照三级标题拆分。如果某个三级章节依然超过长度限制则进一步按段落或句子划分。这种方式比较适合结构清晰的 Markdown、HTML、Word 技术文档和企业制度。需要注意不能只保存正文而把标题丢掉。例如一个 Chunk 只包含恢复完成后检查服务状态和数据一致性。如果丢掉了“故障恢复 / 恢复验证”这一标题路径单独检索时就可能缺少语境。可以将标题路径作为 Chunk 的附加文本或结构化信息保留下来。4. Semantic Chunking语义切分语义切分尝试根据内容之间的语义关联确定边界而不是只依赖字符数和标题。例如某段内容依次讨论第一部分数据库连接故障 第二部分数据库连接恢复 第三部分服务器磁盘扩容前两部分虽然标题不同但可能属于同一组故障处理流程。而第三部分已经切换到磁盘容量管理。语义切分可以尝试识别主题边界在合适的位置形成 Chunk。其实现方式并不唯一。有些方法比较相邻句子或段落的 Embedding 相似度有些方法利用模型或专门的文档理解组件识别语义段落。但语义切分不一定优于结构化切分。它可能产生额外的模型计算成本也可能因为判断不准确而错误地合并或拆分内容。尤其对于合同条款、制度表格和技术配置明确的文档结构有时比推测的语义边界更可靠。5. 四种策略如何选择切分策略优势主要风险适用场景固定长度简单、参数可控容易破坏完整语义基线实验、结构较弱的文本递归切分尽量保留段落和句子不一定理解文档业务结构一般文章、知识文档结构化切分能利用标题、章节和元素类型依赖解析出的结构质量技术手册、制度、Markdown语义切分关注内容主题变化成本和复杂度可能较高主题变化不规则的长文本实际工程中通常可以组合多种方法。例如优先按文档结构分组对超长章节使用递归切分再结合适量 Overlap 保留边界上下文。这不是所有场景的最优答案但可以作为结构清晰的文档的一种合理初始方案。六、工程实现如何用代码验证切分效果对于普通文本可以使用 LangChain 提供的文本切分组件进行实验。安装pipinstall-Ulangchain-text-splitters下面使用 Python 演示递归切分。fromlangchain_text_splittersimport(RecursiveCharacterTextSplitter)text # 差旅报销制度 ## 住宿标准 普通员工的住宿报销标准为300元/天。 部门经理的住宿报销标准为500元/天。 ## 审批规则 超出住宿标准的费用需要事先审批。 未经批准的超额费用不予报销。 splitterRecursiveCharacterTextSplitter(chunk_size100,chunk_overlap20,separators[\n\n,\n,。,,,,,],keep_separatorend,length_functionlen)chunkssplitter.split_text(text)fori,chunkinenumerate(chunks,1):print(fChunk{i}:)print(chunk)print(---)这段代码中有三个需要注意的参数。chunk_size100表示每个 Chunk 的目标长度限制。chunk_overlap20表示尽可能在相邻块之间保留一部分重叠内容。但在递归切分器中实际重叠长度可能受到分隔符和文本结构影响不一定严格等于 20。length_functionlen这里使用 Python 的字符长度计算方式而不是 Token 计数。因此上述代码里的chunk_size100不能直接理解为 100 Token。如果需要严格按照 Token 数限制长度就应该采用与目标模型兼容的 Tokenizer分词和编码工具或相应的长度计算方法。还需要说明上面的代码演示的是普通文本的递归切分并没有真正完成 PDF 表格解析。如果处理的是复杂 PDF应当先使用能够识别文档布局和表格结构的解析方案再把解析后的结构化内容交给切分器。七、如何设计更完整的企业文档切分流程对于包含标题、段落、表格和操作步骤的企业文档我更倾向于将处理过程划分为以下阶段。第一阶段解析与内容清洗读取原始文件提取文本、标题、表格和必要的版面信息。清理页眉页脚、重复导航等无关内容同时校验表格结构和正文阅读顺序。对于无法正确识别的表格不应直接假设它已经被转换为可靠知识。第二阶段建立文档结构识别章节层级、段落和不同类型的内容块。例如文档企业差旅制度 └── 第三章报销标准 ├── 3.1 住宿报销 ├── 3.2 交通报销 └── 3.3 超额审批第三阶段按内容类型执行切分普通文本优先保留段落和句子。结构明确的内容优先按章节切分。表格优先保留表头、数据与约束关系。特别长的内容再进行二次切分。这样可以减少所有内容统一按固定长度处理所带来的风险。第四阶段为 Chunk 保留来源信息一个 Chunk 除了正文还可以保留对应的文件、章节和位置信息。例如{chunk_id:travel-001,document_id:travel-policy,title:企业差旅制度,section:第三章/住宿报销,page:8,content:普通员工住宿报销标准为300元/天。}这些字段通常称为 Metadata即元数据。元数据能够帮助系统定位内容来源或者在检索时保留必要的语境。不过只有保存元数据并不代表系统已经具备版本一致性和访问权限控制。这些还需要在检索及权限管理环节单独实现。第五阶段生成索引并验证完成切分后为每个 Chunk 建立适当的检索索引。之后不能只检查索引是否创建成功还应该检查 Chunk 是否保留了真实问答所需的完整依据。八、如何评估不同 Chunking 策略的效果Chunking 的效果不能只靠观察几个片段是否看起来完整。更合理的方法是建立固定测试集对不同策略进行对照实验。1. 建立测试数据假设知识库包含企业制度、技术手册和故障处理文档。设计一组测试问题测试问题检查重点普通员工住宿报销上限是多少对象与金额是否完整哪些情况需要超额审批条件和动作是否完整数据库备份失败后应执行哪些步骤多步骤信息是否保留某设备型号对应什么配置要求表格字段关联是否保留故障恢复需要满足哪些条件跨段落上下文是否完整其中部分问题可能需要多个 Chunk 联合回答这一点应当在标注测试数据时明确。2. 设计不同实验组例如实验组切分策略A固定长度500 Token不重叠B固定长度500 Token重叠 100 TokenC按章节和段落切分超长部分再拆分D结构化切分并对普通文本补充适量重叠上述数值只是实验配置示例不代表已测得的最优参数。为了比较结果应该尽量保持 Embedding 模型、检索方式、Top-K、生成模型和 Prompt 等其他条件不变。3. 评估哪些指标可以从四个方面进行评价。第一检索召回质量。观察应该找到的相关 Chunk 是否进入检索结果例如 RecallK。第二证据完整性。检索到的内容是否同时包含完整的对象、条件、数值和必要的操作步骤。例如仅检索到“300 元/天”但没有对应员工级别不应直接认为这份证据足以回答问题。第三重复与成本。比较不同方案产生的 Chunk 数量、累计文本量、重复内容比例、索引体积及处理耗时。重叠比例较大时这些指标尤其值得关注。第四最终答案质量。在保持生成条件一致的情况下检查答案是否正确是否有充分的资料支持。需要注意答案生成属于检索之后的环节。如果最终答案有错误要进一步判断是证据不足还是模型没有正确使用已有证据。4. 为什么不能只看 RecallK假设一个切分方案让 Recall5 提升了。这只能说明预先标记的相关内容有更多进入了前五个检索结果。但如果这五个结果都是高度重复的片段或者关键事实仍然被拆开最终回答质量未必随之提高。因此对于 Chunking检索召回率与证据完整性最好结合起来评价。这是区别于单纯优化检索算法的重要一点。九、常见问题什么时候应该调整解析什么时候应该调整切分在实际排查中可以先通过错误表现定位问题。现象优先检查PDF 表格的行列关系混乱文档解析正确数字存在但适用对象缺失解析结果及 Chunk 边界标题与正文分离结构化切分与标题保留检索返回大量重复内容Overlap、Chunk 数量及结果去重一个 Chunk 混合多个不相关主题Chunk Size 与切分策略跨多个段落的完整流程没有被找到Chunk 组织方式及多片段联合检索改变切分参数后答案偶尔改善固定测试集与对照评测这张表只能帮助定位排查方向并不能单凭现象确定故障原因。例如检索不到某个金额也可能是文档没有成功建立索引而不一定是 Chunking 出错。工程上需要结合原文、解析输出、切分结果和检索记录逐层验证。十、总结Chunking 不是简单的字符串切割RAG 中的文档切分实际上是在决定知识以什么粒度参与检索。Document Parsing 负责把原始资料转换为可处理的内容并尽量保留原有结构。Chunking 决定如何组织检索单位使相关信息尽可能完整地保留在一起。Chunk Size 控制片段大小但过大和过小都可能带来问题。Overlap 能够缓解切分边界带来的上下文丢失但也可能增加重复内容与处理成本。固定长度、递归、结构化和语义切分各有适用场景不存在统一最优方法。对于结构清晰的企业文档可以优先考虑保留章节和表格结构再对过长内容进行递归切分并通过测试调整 Chunk Size 和 Overlap。最终需要通过固定测试集验证检索召回、证据完整性、答案质量与运行成本而不是仅凭几个样例判断方案是否有效。RAG 的检索质量不只取决于如何搜索还取决于搜索之前知识被组织成了什么样子。如果关键事实在解析和切分阶段就已经丢失或割裂后续再复杂的检索策略也无法保证正确还原原始知识。参考资料Microsoft LearnChunk large documents for RAG and vector search。介绍常见切分方法、Chunk Size、Overlap、Token 限制与参数选择。Microsoft LearnChunk and Vectorize with Content Understanding。介绍基于文档理解的结构化内容提取和语义切分流程部分功能属于预览能力。LangChainRecursiveCharacterTextSplitter。介绍递归文本切分器的接口和工作方式。LangChainMarkdown Text Splitters。介绍针对 Markdown 结构的不同切分组件。UnstructuredChunking strategies。介绍基于文档元素的 Basic、By Title 切分和表格处理方式。