如何切分文档

在 RAG(Retrieval-Augmented Generation)系统中,多数检索效果不理想的问题,根源不在 Embedding 模型不够好,也不在向量数据库不够快,而在于文档切分(Chunking)这一步没有做好。切分质量直接决定检索效果——一块被错误截断的文本,无论用什么 Embedding 模型编码,都无法被正确检索到。

文档切分是将长文档拆分成更小单元(Chunk)的过程。这些 Chunk 是 Embedding 和检索的基本单位,也是 LLM 生成回答时的上下文来源。切得太大,一个 Chunk 里混杂了多个主题,检索精度下降;切得太小,上下文信息丢失,即使检索命中也无法提供足够的回答依据。

本文属于《从 0 到 1 AI 产品出海知识库》中的「RAG 知识库与 AI Agent 入门」章节,系统讲清楚文档切分的核心策略、参数选择、不同文档类型的处理方式,以及如何评估和优化切分效果。

为什么需要文档切分

在讨论切分策略之前,先理解为什么不能把整篇文档直接丢给 LLM。

Token 限制

每个 Embedding 模型和 LLM 都有输入 Token 上限。当前主流 Embedding 模型的输入限制通常在 512 到 8192 Token 之间。一篇 50 页的技术文档可能包含 5 万到 10 万 Token,远超模型的处理能力。即使模型支持更长的上下文窗口,将整篇文档作为单次检索单元也不现实——计算量和存储成本都会过高。

检索精度

检索的目标是找到与用户问题最相关的文本段落。如果 Chunk 太大,一个 Chunk 涵盖了多个主题,Embedding 向量实际上编码的是多个主题的「平均值」,与任何单一主题的相似度都不够高。如果 Chunk 太小(比如只有一句话),虽然与特定问题的匹配度可能很高,但缺少足够的上下文来支撑 LLM 生成完整回答。

合适的 Chunk 应该满足一个判断标准:它在脱离上下文的情况下,仍然能让读者理解其含义,并包含回答某一类问题所需的完整信息。

成本与延迟

更大的 Chunk 意味着更多的 Embedding 计算、更大的向量存储开销,以及更长的 LLM 推理时间。合理的切分能在检索质量和系统性能之间取得平衡。

常见切分策略

文档切分策略从简单到复杂,形成了一个递进的光谱。选择哪种策略取决于文档类型、业务需求和可用的计算资源。

固定大小切分(Fixed-size Chunking)

最直接的策略:按固定数量的字符或 Token 切分文本。例如每 500 个 Token 切一刀,遇到边界就断开。

这种策略的实现成本极低,几乎所有框架都支持。但它完全不考虑文本的语义结构,可能在句子中间、段落中间甚至单词中间断开,导致 Chunk 内容不连贯。

适用场景:对切分精度要求不高的通用文本、短文档、快速原型验证。

按句子/段落切分(Sentence / Paragraph Splitting)

利用标点符号或换行符作为切分边界,保证每个 Chunk 在语法上是完整的。句子级别的切分使用句号、问号、感叹号等作为分隔符;段落级别使用换行符或空行作为分隔符。

这种方式比固定大小切分更自然,但产出的 Chunk 大小不均匀——有的段落只有一句话(可能太短),有的段落长达数千字(可能太长)。通常需要配合合并和再拆分逻辑来控制 Chunk 的大小范围。

适用场景:博客文章、新闻报道、FAQ 文档等段落结构清晰的文本。

递归切分(Recursive Splitting)

递归切分是目前使用最广泛的策略之一。它的核心思路是:定义一组优先级递减的分隔符列表(如 \n\n\n. ),先尝试用最高优先级的分隔符切分,如果切分后的块仍然大于目标大小,再用下一级分隔符继续切分,直到每个 Chunk 满足大小要求。

LangChain 的 RecursiveCharacterTextSplitter 就是这种策略的典型实现。它在保持文本语义完整性方面比固定大小切分好得多,同时实现复杂度可控。

适用场景:通用的技术文档、产品手册、结构不固定的长文本。

语义切分(Semantic Chunking)

语义切分不依赖固定的分隔符,而是通过计算相邻句子或段落之间的语义相似度来确定切分边界。具体做法是:先计算每句话的 Embedding,然后计算相邻句子的相似度,在相似度出现显著下降的位置切分——那里通常意味着话题发生了转换。

这种策略能确保每个 Chunk 围绕一个连贯的主题,避免将不同话题的内容混在一起。代价是需要额外的 Embedding 计算,处理速度明显慢于前几种策略。

适用场景:学术论文、长篇报告、法律文档等主题切换频繁且需要精确检索的文本。

按文档结构切分(Structure-based Chunking)

利用文档自身的结构信息来切分。Markdown 文档按标题层级(######)切分;HTML 文档按 DOM 结构切分;PDF 文档按页面和章节切分。

这种策略最大程度地保留了文档的逻辑结构。一个 ## 标题下的内容通常就是一个完整的话题,天然适合作为 Chunk 的边界。如果切分后的块仍然过大,可以在结构切分的基础上叠加递归切分做二次拆分。

适用场景:Markdown 文档、技术手册、API 文档、有清晰标题层级的长文档。

滑动窗口切分(Sliding Window Chunking)

在固定大小切分的基础上,引入相邻 Chunk 之间的重叠(Overlap)。例如 Chunk 大小为 500 Token,相邻两个 Chunk 共享 100 Token 的内容。这样每个位置的文字会出现在多个 Chunk 中,确保不会因为切分边界而丢失关键信息。

Overlap 的比例通常在 10% 到 20% 之间。过小的 Overlap 起不到保护边界的作用,过大的 Overlap 则导致存储冗余和检索重复。

适用场景:对话记录、会议转录、叙事性文本等上下文连续性强的内容。

层级切分(Hierarchical Chunking)

构建一个树状的 Chunk 结构:文档级别、章节级别、段落级别、句子级别。检索时先在大粒度上定位相关章节,再在小粒度上找到具体段落。每个小 Chunk 都携带父级 Chunk 的引用,检索命中时可以向上扩展上下文。

这种策略实现复杂度最高,但对于大型文档集或结构复杂的长文档,它提供了灵活的检索粒度选择。

适用场景:大型技术手册、百科全书、法规汇编等需要多层级检索的场景。

切分策略对比

策略实现复杂度语义保持计算成本Chunk 大小均匀性典型适用场景
固定大小均匀快速原型、通用短文本
句子/段落不均匀博客、新闻、FAQ
递归切分较好较均匀通用技术文档
语义切分优秀不均匀学术论文、法律文档
文档结构取决于文档Markdown、API 文档
滑动窗口均匀对话记录、会议转录
层级切分优秀多层级大型手册、百科全书

切分参数选择

切分策略确定后,还需要配置两个核心参数:Chunk 大小(Chunk Size)和重叠大小(Chunk Overlap)。这两个参数没有放之四海而皆准的最优值,但有一些经验性的指导范围。

Chunk Size 的选择

Chunk Size 通常以 Token 为单位衡量。主流的建议范围:

Chunk 大小(Token)特点适用场景
100–256信息密度高,检索精确,但上下文少事实型问答、实体检索、信息抽取
256–512平衡精度与上下文,最常见的默认值通用问答、技术文档、产品手册
512–1024上下文丰富,适合需要推理的场景长文摘要、分析报告、法律文书
1024+上下文极丰富,但检索精度下降,Embedding 可能超出有效范围需要大段上下文的特殊场景

选择时的核心权衡是:小 Chunk 检索精度高但上下文不足,大 Chunk 上下文丰富但检索精度下降。一个实用的测试方法是:把切分后的 Chunk 单独拿出来读,看它是否能在脱离原文的情况下传达完整的信息。如果不能,说明 Chunk 太小了。

Embedding 模型的有效输入长度也是重要的约束条件。多数 Embedding 模型在输入超过一定长度后,Embedding 质量会显著下降(即使模型标称支持更长的输入)。对于 OpenAI 的 text-embedding-3-small(最大 8191 Token),实践中 Chunk 大小控制在 512 Token 以内的检索效果通常优于 1024 Token 以上。

Chunk Overlap 的选择

Overlap 的作用是防止关键信息在切分边界处丢失。常见的 Overlap 设置:

Overlap 比例具体值(以 500 Token Chunk 为例)适用场景
5%–10%25–50 Token段落结构清晰的文档,切分策略已经尊重语义边界
10%–20%50–100 Token最常用的范围,适合大多数场景
20%–50%100–250 Token上下文连续性强的文本(对话记录、叙事文本)

需要注意,Overlap 直接增加了存储成本和检索时的重复度。如果 Chunk 大小是 500 Token、Overlap 是 250 Token,那么同一句话最多会出现在两个 Chunk 中,向量数据库的存储量接近翻倍。Overlap 不是越大越好,通常 10% 到 20% 就足够覆盖边界风险。

一个常见的误区是把 Overlap 当作解决检索质量问题的万能药。如果检索效果不好,优先检查切分策略是否合理、Chunk 大小是否合适,而不是一味增大 Overlap。

参数调优方法

参数调优不应该是凭感觉猜,而应该基于评估数据做系统性测试:

  1. 准备评估数据集:收集 20 到 50 个典型的用户问题,标注每个问题的正确答案以及答案出自哪个文档的哪个位置
  2. 网格搜索:对 Chunk Size(如 256、512、1024)和 Overlap(如 0、50、100)做组合测试
  3. 评估指标:测量每个参数组合下的命中率(Hit Rate)、精确率(Precision)和召回率(Recall)
  4. 选择最优:选择综合表现最好的参数组合,同时考虑存储和延迟成本

不同文档类型的切分策略

不同类型的文档有截然不同的结构和内容特征,用同一套切分参数处理所有文档类型是粗放的。

通用文本文档(TXT、Markdown)

Markdown 文档有天然的标题层级结构,优先按标题切分。一级标题(#)和二级标题(##)下的内容通常就是一个完整的话题。切分时保留标题作为 Chunk 的前缀,这样即使段落脱离了原始位置,Embedding 中仍然包含主题信息。

纯 TXT 文档没有结构信息,退回到递归切分作为默认策略。

PDF 文档

PDF 是最难处理的文档格式。文本型 PDF 的解析结果通常保留了段落分隔和页面信息,可以按段落切分后合并到目标 Chunk 大小。扫描型 PDF 需要先经过 OCR 处理,识别质量会直接影响后续的切分效果。

PDF 中的表格是一个特殊挑战。表格内容如果被按行切分到不同 Chunk 中,语义会完全破碎。建议在解析阶段识别表格区域,将表格作为独立的 Chunk 处理,或者将表格转换为结构化文本后单独切分。

代码文件

代码文件的切分需要特别注意语法边界。按函数或类的定义来切分是最自然的方式——每个函数通常就是一个自包含的逻辑单元。如果使用固定大小切分,可能会把函数从中间截断,导致代码片段无法理解。

实践中的做法:先按空行和缩进做初步分割,再按函数/类定义做合并或拆分。保留文件路径和语言类型作为 Chunk 的元数据,有助于检索时做过滤。

文档类型推荐切分策略建议 Chunk Size建议 Overlap注意事项
Markdown按标题层级 + 递归512–1024 Token50–100 Token保留标题作为 Chunk 前缀
PDF(文本型)按段落 + 递归256–512 Token50–100 Token表格单独处理
PDF(扫描型)OCR → 段落 + 递归256–512 Token50–100 TokenOCR 质量直接影响切分效果
Word(DOCX)按段落 + 递归256–512 Token50–100 Token表格和图片需特殊处理
代码文件按函数/类定义128–512 Token20–50 Token保留语法完整性
对话记录按发言轮次 + 滑动窗口512–1024 Token100–200 Token保留说话人信息
HTML / 网页按 DOM 结构 + 去噪256–512 Token50–100 Token先去除导航栏等无关内容
表格数据按行或按记录视数据而定通常不需要转为结构化文本再切分

对话记录与会议转录

对话记录的切分需要保留说话人信息和时间顺序。按发言轮次切分是最自然的方式,每一轮对话(一个说话人的连续发言)作为一个基础单元。如果单轮发言过长,可以在轮次内部做二次切分。

Overlap 在对话记录中尤其重要,因为前后发言之间经常有语义上的承接关系。20% 左右的 Overlap 可以有效避免对话上下文断裂。

表格与结构化数据

表格不适合用文本切分的方式处理。将每一行转为「列名:值」的键值对格式,然后按行或按逻辑记录切分。如果表格有明确的分类维度,可以按类别将多行合并为一个 Chunk。

切分效果评估

切分策略和参数确定后,需要量化评估效果。没有评估的切分就是在凭运气工作。

评估指标

指标含义关注点
命中率(Hit Rate)检索返回的 Chunk 中包含正确答案的比例切分是否让相关内容能被找到
精确率(Precision)检索返回的 Chunk 中,真正与问题相关的比例Chunk 是否太泛、包含太多无关内容
召回率(Recall)所有相关 Chunk 中,被检索到的比例是否有相关内容被遗漏
上下文相关性(Context Relevancy)检索到的 Chunk 与用户问题的语义匹配程度Chunk 的粒度是否合适
Chunk 利用率(Chunk Utilization)LLM 生成回答时实际使用了 Chunk 中多大比例的内容Chunk 是否太冗余
Chunk 归因(Chunk Attribution)系统是否能正确识别回答来源于哪个 Chunk检索结果是否指向了正确的位置

评估流程

  1. 构建测试集:从目标用户群体收集 20–50 个典型问题,标注每个问题的期望答案和答案所在的文档位置
  2. 基线测试:用默认参数(如 Chunk Size = 512, Overlap = 50)跑一遍测试集,记录各项指标
  3. 参数调优:调整 Chunk Size 和 Overlap,观察指标变化
  4. 策略对比:尝试不同的切分策略,在相同的测试集上比较效果
  5. 人工审核:自动化指标之外,安排人工审查部分检索结果,判断语义层面的匹配质量

评估不是一次性的工作。随着文档内容的更新、用户问题模式的变化、Embedding 模型的迭代,切分参数需要持续调整。

实际案例

案例一:跨境电商产品手册的知识库切分

某跨境电商平台需要将 500+ 份产品手册(PDF 格式,平均每份 20–40 页)接入知识库,供客服人员快速检索产品规格和售后政策。

初始方案使用固定大小切分(Chunk Size = 500 Token, Overlap = 50),测试后发现两个问题:一是产品规格表格被截断,检索时表格内容完全匹配不上;二是不同产品的信息混在同一个 Chunk 中,检索返回了错误产品的参数。

调整后的方案:

  • 使用 Docling 解析 PDF,识别并提取表格为独立的结构化文本
  • 按文档标题层级做初步切分,每个产品章节作为一个独立的 Chunk 候选
  • 对超长章节叠加递归切分,Chunk Size 设为 512 Token,Overlap 设为 100 Token
  • 表格内容转为「参数名:参数值」的键值对格式,单独作为 Chunk 存储
  • 每个 Chunk 附加产品名称、章节标题作为元数据,支持检索时做过滤

调整后的命中率从 62% 提升到 89%。产品规格类问题的改善尤为明显——表格单独切分后,检索可以精确匹配到具体产品的具体参数。

案例二:SaaS 产品 API 文档的切分优化

一家 B2B SaaS 公司将其 API 文档(Markdown 格式,约 200 个页面,托管在 Git 仓库)接入知识库,目标是让开发者能通过自然语言查询 API 用法。

初版使用按段落切分,Chunk 大小参差不齐(从 50 到 2000 Token 不等)。开发者反馈:对于「某个参数的取值范围是什么」这类精确问题,检索效果不错;但对于「如何实现某个功能」这类需要多步骤回答的问题,检索到的 Chunk 往往只覆盖了流程中的一步。

分析后发现问题在于按段落切分的 Chunk 太小,一个完整的操作流程被分散到了多个 Chunk 中。调整后:

  • 改用按二级标题(##)切分,保留标题作为 Chunk 前缀
  • 对于标题下内容超过 1024 Token 的章节,叠加递归切分
  • Chunk Size 设为 1024 Token,Overlap 设为 100 Token
  • 每个 Chunk 附加文件路径和标题层级作为元数据

调整后,「如何实现 XX」类问题的回答完整度明显提升——更大的 Chunk 包含了完整的操作步骤。同时通过标题前缀和元数据过滤,精确问题的检索精度也没有下降。

文档切分完整流程

流程图画布 · 115%
Mermaid 流程图加载中...

切分策略选择指南

决策因素选择建议
文档结构清晰(有标题层级)优先按文档结构切分,叠加递归切分处理超长章节
文档结构不清晰(纯文本)使用递归切分作为基线,尝试语义切分看是否提升
需要精确检索(事实型问答)较小的 Chunk Size(128–256 Token),较低的 Overlap
需要完整回答(流程说明、分析)较大的 Chunk Size(512–1024 Token),适当增加 Overlap
表格密集表格单独提取和切分,不混入正文切分逻辑
多主题长文档语义切分或层级切分,避免不同主题混在同一个 Chunk
上下文连续性强(对话、叙事)滑动窗口切分,Overlap 比例提高到 15%–20%
快速原型验证固定大小或递归切分,Chunk Size = 512, Overlap = 50
计算资源有限避免语义切分和层级切分,使用递归切分

构建文档切分方案的检查清单

  • 切分策略匹配文档类型:是否根据文档的实际结构和内容特征选择了合适的切分策略?
  • Chunk Size 在合理范围内:是否在 128–1024 Token 的常见范围内,针对业务场景做了测试?
  • Overlap 设置合理:是否在 10%–20% 的范围内,既能保护边界又不造成过多冗余?
  • 不破坏语义完整性:切分后的 Chunk 是否能脱离上下文独立理解,没有在句子或概念中间被截断?
  • 表格单独处理:文档中的表格是否被识别并作为独立单元处理,而不是按行截断?
  • 元数据完整:每个 Chunk 是否携带了来源文档、标题、页码等元数据,支持检索时过滤和归因?
  • 代码保持语法完整:代码文件的切分是否保留了函数和类的完整性?
  • 有评估数据集:是否准备了 20–50 个典型问题用于量化评估切分效果?
  • 有基线对比:是否在相同的测试集上对比了不同策略和参数的表现?
  • 命中率达标:检索命中率是否经过测量,并且达到了可接受的水平?
  • 人工审核:除了自动指标,是否安排了人工审查检索结果的质量?
  • 持续调优机制:是否建立了文档更新后重新评估切分参数的流程?
  • 存储成本可控:Overlap 带来的存储膨胀是否在可接受的范围内?
  • 多语言兼容:如果文档涉及多种语言,切分工具是否正确处理了不同语言的分词规则?

总结

文档切分是 RAG 系统中投入产出比最高的优化环节之一。它不需要更换模型、升级基础设施或调整算法架构,只需要根据文档类型和业务场景选择合适的切分策略和参数,就能显著提升检索效果。

几个核心原则值得记住:第一,切分策略应该匹配文档类型——Markdown 按标题切分,代码按函数切分,表格单独处理,不要用一种策略通吃所有格式。第二,Chunk Size 和 Overlap 的选择应该基于评估数据而不是直觉——准备好测试集,做网格搜索,用指标说话。第三,切分不是一次性的工作——文档在变、用户在变、模型在变,切分参数也需要跟着迭代。

对于出海产品,还需要额外注意多语言文档的分词差异(中文没有空格分隔词边界)、不同地区文档格式偏好的差异,以及数据存储和处理的合规要求。

参考资料

  1. Pinecone. "Chunking Strategies for LLM Applications." https://www.pinecone.io/learn/chunking-strategies/
  2. Weaviate. "Chunking Strategies to Improve LLM RAG Pipeline Performance." https://weaviate.io/blog/chunking-strategies-for-rag
  3. DataCamp. "Chunking Strategies for AI and RAG Applications." https://www.datacamp.com/blog/chunking-strategies
  4. Microsoft Azure. "Develop a RAG Solution – Chunking Phase." https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/rag/rag-chunking-phase
  5. Unstructured. "Chunking for RAG: Best Practices and Key Methods." https://unstructured.io/blog/chunking-for-rag-best-practices
  6. IBM. "RAG 中的分块:架构指南." https://www.ibm.com/cn-zh/think/architectures/rag-cookbook/chunking
  7. Databricks. "The Ultimate Guide to Chunking Strategies for RAG Applications." https://community.databricks.com/t5/technical-blog/the-ultimate-guide-to-chunking-strategies-for-rag-applications/ba-p/113089
  8. 腾讯云. "Chunking:基于大模型 RAG 系统中的文档分块." https://cloud.tencent.com/developer/article/2464168