夜雨聆风学习资料网

ARTICLE · 1278715

RAG 文档解析与 Chunking 详解:Chunk Size、Overlap 和切分策略应该怎么选?

RAG 文档解析与 Chunking 详解:Chunk Size、Overlap 和切分策略应该怎么选?
在 RAG(Retrieval-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
导航栏、广告、重复内容干扰正文
正文提取与结构清理
复杂表格
表头、单位、行列关系丢失
结构化解析及关联关系校验
OCR(Optical 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 1:Token 0~499

Chunk 2:Token 400~899

Chunk 3:Token 800~1299

相邻 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 提供的文本切分组件进行实验。
安装:

pip install -U langchain-text-splitters

下面使用 Python 演示递归切分。

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("---")

这段代码中有三个需要注意的参数。
`chunk_size=100`
表示每个 Chunk 的目标长度限制。
`chunk_overlap=20`
表示尽可能在相邻块之间保留一部分重叠内容。
但在递归切分器中,实际重叠长度可能受到分隔符和文本结构影响,不一定严格等于 20。
`length_function=len`
这里使用 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元/天。"

}

这些字段通常称为 Metadata,即元数据。
元数据能够帮助系统定位内容来源,或者在检索时保留必要的语境。
不过,只有保存元数据,并不代表系统已经具备版本一致性和访问权限控制。这些还需要在检索及权限管理环节单独实现。

第五阶段:生成索引并验证

完成切分后,为每个 Chunk 建立适当的检索索引。
之后不能只检查索引是否创建成功,还应该检查 Chunk 是否保留了真实问答所需的完整依据。

八、如何评估不同 Chunking 策略的效果?

Chunking 的效果不能只靠观察几个片段是否看起来完整。
更合理的方法是建立固定测试集,对不同策略进行对照实验。

1. 建立测试数据

假设知识库包含企业制度、技术手册和故障处理文档。
设计一组测试问题:
测试问题
检查重点
普通员工住宿报销上限是多少?
对象与金额是否完整
哪些情况需要超额审批?
条件和动作是否完整
数据库备份失败后应执行哪些步骤?
多步骤信息是否保留
某设备型号对应什么配置要求?
表格字段关联是否保留
故障恢复需要满足哪些条件?
跨段落上下文是否完整
其中部分问题可能需要多个 Chunk 联合回答,这一点应当在标注测试数据时明确。

2. 设计不同实验组

例如:
实验组
切分策略
A
固定长度,500 Token,不重叠
B
固定长度,500 Token,重叠 100 Token
C
按章节和段落切分,超长部分再拆分
D
结构化切分,并对普通文本补充适量重叠
上述数值只是实验配置示例,不代表已测得的最优参数。
为了比较结果,应该尽量保持 Embedding 模型、检索方式、Top-K、生成模型和 Prompt 等其他条件不变。

3. 评估哪些指标?

可以从四个方面进行评价。
第一,检索召回质量。
观察应该找到的相关 Chunk 是否进入检索结果,例如 Recall@K。
第二,证据完整性。
检索到的内容是否同时包含完整的对象、条件、数值和必要的操作步骤。
例如,仅检索到“300 元/天”,但没有对应员工级别,不应直接认为这份证据足以回答问题。
第三,重复与成本。
比较不同方案产生的 Chunk 数量、累计文本量、重复内容比例、索引体积及处理耗时。
重叠比例较大时,这些指标尤其值得关注。
第四,最终答案质量。
在保持生成条件一致的情况下,检查答案是否正确,是否有充分的资料支持。
需要注意,答案生成属于检索之后的环节。如果最终答案有错误,要进一步判断是证据不足,还是模型没有正确使用已有证据。

4. 为什么不能只看 Recall@K?

假设一个切分方案让 Recall@5 提升了。
这只能说明预先标记的相关内容有更多进入了前五个检索结果。
但如果这五个结果都是高度重复的片段,或者关键事实仍然被拆开,最终回答质量未必随之提高。
因此,对于 Chunking,检索召回率与证据完整性最好结合起来评价。
这是区别于单纯优化检索算法的重要一点。

九、常见问题:什么时候应该调整解析,什么时候应该调整切分?

在实际排查中,可以先通过错误表现定位问题。
现象
优先检查
PDF 表格的行列关系混乱
文档解析
正确数字存在,但适用对象缺失
解析结果及 Chunk 边界
标题与正文分离
结构化切分与标题保留
检索返回大量重复内容
Overlap、Chunk 数量及结果去重
一个 Chunk 混合多个不相关主题
Chunk Size 与切分策略
跨多个段落的完整流程没有被找到
Chunk 组织方式及多片段联合检索
改变切分参数后答案偶尔改善
固定测试集与对照评测
这张表只能帮助定位排查方向,并不能单凭现象确定故障原因。
例如,检索不到某个金额,也可能是文档没有成功建立索引,而不一定是 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 切分和表格处理方式。

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料