ARTICLE · 1278715
RAG 文档解析与 Chunking 详解:Chunk Size、Overlap 和切分策略应该怎么选?
发布时间:2026-10-30 12:22:53 最近访问:2026-10-30 12:22:54
RAG 文档解析与 Chunking 详解:Chunk Size、Overlap 和切分策略应该怎么选?
在 RAG(Retrieval-Augmented Generation,检索增强生成)系统中,大语言模型通常不会每次都读取整个知识库。系统一般会先将原始文档处理成适合搜索的内容,再根据用户的问题检索相关片段,最后把这些片段交给大语言模型生成回答。因此,RAG 的回答质量不仅取决于模型能力和检索算法,还取决于一个更早发生的环节:知识是如何被解析、切分和保存的。原始文档中明明存在明确答案,RAG 系统却可能返回错误金额,或者表示没有找到相关依据。原因不一定是检索模型不够准确,也可能是文档在进入知识库时,已经丢失了关键结构,或者在切分过程中破坏了完整的语义关系。本文将从完整处理流程出发,解释这些技术的工作原理、适用场景及工程实践中的常见问题。一、文档为什么需要切分?
1. 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。切分的目标不是产生更多片段,而是构造既适合检索、又能保留完整信息的知识单位。二、Document Parsing:为什么切分之前必须先正确解析?
Document Parsing,即文档解析,是将 PDF、Word、网页等原始文件转换成计算机可以进一步处理的内容。如果解析已经破坏了原文关系,后续切分通常无法可靠地恢复这些关系。1. 复杂表格为什么容易出问题?
员工级别 普通员工 部门经理 总监 标准 300元 500元 800元 |
但原始表格中最重要的行列对应关系并没有被明确保留。如果后续系统把这些文字切成不同片段,错误可能进一步扩大。因此,表格解析不能只关注有没有提取出文字,还应该检查行、列、表头和数值之间的关系。差旅报销制度 ## 住宿报销标准 | 员工级别 | 标准 ||---|---|| 普通员工 | 300元/天 || 部门经理 | 500元/天 || 总监 | 800元/天 | |
在合适的场景下,也可以将表格中的每一行整理成独立事实:普通员工的住宿报销标准为300元/天。 部门经理的住宿报销标准为500元/天。 总监的住宿报销标准为800元/天。 |
Markdown 表格能够保留行列结构,适合需要理解整张表格的场景。但逐行展开可能丢失合并单元格、脚注、跨行条件等复杂关系。因此,工程实践中可以同时保存原始表格结构和用于检索的文本表达,而不是简单地把所有表格都转换成普通段落。2. 文档解析还需要注意什么?
OCR(Optical Character Recognition)指从图片中识别文字的技术。但 OCR 能识别字符,不代表它一定能准确恢复复杂的版面关系。这也是为什么企业知识库中的 PDF 解析,往往不只是调用一个简单的文本提取函数。三、Chunk Size:文档应该切多大?
Chunk Size 指每个 Chunk 的目标大小或最大大小。具体计量单位取决于实现方式,常见的有字符数和 Token 数。Token 是模型处理文本时使用的基本单位,它不等于一个汉字,也不一定等于一个英文单词。到底代表 500 个字符还是 500 个 Token,需要看所使用的切分工具和长度计算方式。1. Chunk 太小的问题
普通员工的住宿报销标准为300元/天。 超出标准的费用,需要提前提交审批。 |
Chunk A: 普通员工的住宿报销标准为 Chunk B: 300元/天。超出标准的费用, Chunk C: 需要提前提交审批。 |
三个 Chunk 都包含原文的一部分,但独立理解时存在明显问题。Chunk C 包含审批动作,却缺少触发审批的条件。这类问题可以称为语义割裂:原本属于同一事实的条件、对象和结论被切开。2. Chunk 太大的问题
反过来,如果一个 Chunk 同时包含报销、考勤、请假、薪酬等多个主题,也会产生问题。Chunk A: 第一章 入职制度 第二章 考勤制度 第三章 差旅报销 第四章 薪酬管理 第五章 离职制度 |
当用户只询问住宿报销时,整个 Chunk 中的大部分内容可能无关。对于跨多个段落才能解释完整的问题,更大的 Chunk 可能恰好有助于保留上下文。3. Chunk Size 应如何选择?
制度条款、产品说明、技术手册和会议记录的内容组织方式不同。如果用户通常询问某个金额、型号或操作步骤,小而完整的事实块可能更合适。如果用户经常要求综合分析多个章节,则需要考虑更大的上下文范围,或者在检索后组合相关片段。Embedding 模型有输入长度限制,生成模型也有上下文预算,而每个 Chunk 的长度还会影响向量化、检索及最终输入成本。所以,Chunk Size 是需要评测和调整的参数,不存在适用于所有 RAG 系统的统一最优值。四、Chunk Overlap:为什么相邻片段需要重复内容?
Chunk Overlap 指相邻两个 Chunk 之间重复保留的内容长度。Chunk Size = 500 Tokens Overlap = 100 Tokens |
Chunk 1:Token 0~499 Chunk 2:Token 400~899 Chunk 3:Token 800~1299 |
1. Overlap 与步长的关系
Step Size = Chunk Size - OverlapStep Size = 500 - 100 = 400 Tokens |
每生成一个新 Chunk,切分窗口就向后移动 400 Token。对于长度为 L 的文档,当 L 大于 Chunk Size、且切分器允许最后一个不足完整长度的 Chunk 时,可以使用以下公式计算块数:Chunk 数量 = ceil((L - Chunk Size) / Step Size) + 1 |
如果文档本身不超过一个 Chunk,则只需要一个块。2. Overlap 太大会发生什么?
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 个 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 的附加文本或结构化信息保留下来。4. Semantic Chunking:语义切分
语义切分尝试根据内容之间的语义关联确定边界,而不是只依赖字符数和标题。第一部分:数据库连接故障 第二部分:数据库连接恢复 第三部分:服务器磁盘扩容 |
前两部分虽然标题不同,但可能属于同一组故障处理流程。语义切分可以尝试识别主题边界,在合适的位置形成 Chunk。其实现方式并不唯一。有些方法比较相邻句子或段落的 Embedding 相似度,有些方法利用模型或专门的文档理解组件识别语义段落。它可能产生额外的模型计算成本,也可能因为判断不准确而错误地合并或拆分内容。尤其对于合同条款、制度表格和技术配置,明确的文档结构有时比推测的语义边界更可靠。5. 四种策略如何选择?
优先按文档结构分组,对超长章节使用递归切分,再结合适量 Overlap 保留边界上下文。这不是所有场景的最优答案,但可以作为结构清晰的文档的一种合理初始方案。六、工程实现:如何用代码验证切分效果?
对于普通文本,可以使用 LangChain 提供的文本切分组件进行实验。pip install -U langchain-text-splitters |
from langchain_text_splitters import ( RecursiveCharacterTextSplitter ) text = """ 差旅报销制度 ## 住宿标准 普通员工的住宿报销标准为300元/天。部门经理的住宿报销标准为500元/天。 ## 审批规则 超出住宿标准的费用需要事先审批。未经批准的超额费用不予报销。""" splitter = RecursiveCharacterTextSplitter( chunk_size=100, chunk_overlap=20, separators=[ "\n\n", "\n", "。", "!", "?", ";", ",", "" ], keep_separator="end", length_function=len) chunks = splitter.split_text(text) for i, chunk in enumerate(chunks, 1): print(f"Chunk {i}:") print(chunk) print("---") |
但在递归切分器中,实际重叠长度可能受到分隔符和文本结构影响,不一定严格等于 20。这里使用 Python 的字符长度计算方式,而不是 Token 计数。因此,上述代码里的 chunk_size=100 不能直接理解为 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元/天。" } |
元数据能够帮助系统定位内容来源,或者在检索时保留必要的语境。不过,只有保存元数据,并不代表系统已经具备版本一致性和访问权限控制。这些还需要在检索及权限管理环节单独实现。第五阶段:生成索引并验证
完成切分后,为每个 Chunk 建立适当的检索索引。之后不能只检查索引是否创建成功,还应该检查 Chunk 是否保留了真实问答所需的完整依据。八、如何评估不同 Chunking 策略的效果?
Chunking 的效果不能只靠观察几个片段是否看起来完整。更合理的方法是建立固定测试集,对不同策略进行对照实验。1. 建立测试数据
其中部分问题可能需要多个 Chunk 联合回答,这一点应当在标注测试数据时明确。2. 设计不同实验组
| |
|---|
| |
| 固定长度,500 Token,重叠 100 Token |
| |
| |
上述数值只是实验配置示例,不代表已测得的最优参数。为了比较结果,应该尽量保持 Embedding 模型、检索方式、Top-K、生成模型和 Prompt 等其他条件不变。3. 评估哪些指标?
观察应该找到的相关 Chunk 是否进入检索结果,例如 Recall@K。检索到的内容是否同时包含完整的对象、条件、数值和必要的操作步骤。例如,仅检索到“300 元/天”,但没有对应员工级别,不应直接认为这份证据足以回答问题。比较不同方案产生的 Chunk 数量、累计文本量、重复内容比例、索引体积及处理耗时。在保持生成条件一致的情况下,检查答案是否正确,是否有充分的资料支持。需要注意,答案生成属于检索之后的环节。如果最终答案有错误,要进一步判断是证据不足,还是模型没有正确使用已有证据。4. 为什么不能只看 Recall@K?
这只能说明预先标记的相关内容有更多进入了前五个检索结果。但如果这五个结果都是高度重复的片段,或者关键事实仍然被拆开,最终回答质量未必随之提高。因此,对于 Chunking,检索召回率与证据完整性最好结合起来评价。九、常见问题:什么时候应该调整解析,什么时候应该调整切分?
这张表只能帮助定位排查方向,并不能单凭现象确定故障原因。例如,检索不到某个金额,也可能是文档没有成功建立索引,而不一定是 Chunking 出错。工程上需要结合原文、解析输出、切分结果和检索记录逐层验证。十、总结:Chunking 不是简单的字符串切割
RAG 中的文档切分,实际上是在决定知识以什么粒度参与检索。Document Parsing 负责把原始资料转换为可处理的内容,并尽量保留原有结构。Chunking 决定如何组织检索单位,使相关信息尽可能完整地保留在一起。Chunk Size 控制片段大小,但过大和过小都可能带来问题。Overlap 能够缓解切分边界带来的上下文丢失,但也可能增加重复内容与处理成本。固定长度、递归、结构化和语义切分各有适用场景,不存在统一最优方法。对于结构清晰的企业文档,可以优先考虑保留章节和表格结构,再对过长内容进行递归切分,并通过测试调整 Chunk Size 和 Overlap。最终,需要通过固定测试集验证检索召回、证据完整性、答案质量与运行成本,而不是仅凭几个样例判断方案是否有效。RAG 的检索质量,不只取决于如何搜索,还取决于搜索之前,知识被组织成了什么样子。如果关键事实在解析和切分阶段就已经丢失或割裂,后续再复杂的检索策略,也无法保证正确还原原始知识。Microsoft Learn,Chunk large documents for RAG and vector search。介绍常见切分方法、Chunk Size、Overlap、Token 限制与参数选择。Microsoft Learn,Chunk and Vectorize with Content Understanding。介绍基于文档理解的结构化内容提取和语义切分流程,部分功能属于预览能力。LangChain,RecursiveCharacterTextSplitter。介绍递归文本切分器的接口和工作方式。LangChain,Markdown Text Splitters。介绍针对 Markdown 结构的不同切分组件。Unstructured,Chunking strategies。介绍基于文档元素的 Basic、By Title 切分和表格处理方式。