文档切分 Chunk 应该怎么做?
文档切分 Chunk 应该怎么做?
一句话核心:文档切分(Chunking)是把长文档按语义、结构或长度切成适合 Embedding 与检索的小块,是 RAG 系统中最容易被低估、却对最终效果影响最大的预处理环节;面试必问是因为它直接决定召回率和答案完整度。
核心概念(术语表)
- Chunk(块):从原文档中切出的一段文本,是向量化和检索的最小单位。
- Chunking(切分):将长文档划分为 Chunk 的策略与算法总称。
- Embedding(嵌入):将 Chunk 转为稠密向量的过程,主流维度 768/1024/1536/3072。
- 语义丢失:Chunk 把一个完整语义单元(如条件→结论)拆开,导致召回片段残缺。
- 结构丢失:文档的标题层级、表格行列、章节关系在切分后被打散。
- Parent-Child Chunk:父块保留完整上下文、子块用于精细检索的两级切分方案。
- Chunk Overlap(重叠):相邻 Chunk 共享的一段文本,缓解边界语义截断,常设 10%~25%。
- Layout 解析:从 PDF/Word 中识别标题、表格、列表等版面元素的步骤。
- Sentence-Window Retrieval:检索时返回句子,但实际给 LLM 看句子前后的窗口。
- Auto-merging Retrieval:检索子块,命中后自动合并到所属父块再返回。
Chunking 思想源于传统信息检索的"段落检索"与"滑动窗口",但在 RAG 时代被放大为系统瓶颈。RAG 范式由 Facebook AI Research(Meta)在 2020 年的论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》中正式提出,文档切分作为其离线索引管线的第一步被广泛研究。LangChain 在 2022 年发布 RecursiveCharacterTextSplitter(默认分隔符 [\n\n, \n, ".", " ", ""])后,递归切分成为工业界默认方案;LlamaIndex 在 2023 年推出 Sentence-Window 与 Auto-merging Retrieval,把"小粒度检索 + 大粒度回答"做成产品化能力。
工作原理 / 核心机制(详细讲解)
整体思路:按"层级分隔符"递归把文本拆到目标大小,并在切分后注入结构化 Metadata。
输入 / 输出:
- 输入:原始文档(PDF/Word/Markdown/HTML/Excel)+ 配置参数(chunk_size、chunk_overlap、separators)。
- 输出:Chunk 列表,每个 Chunk 包含
text、metadata(来源文件、页码、章节、chunk_id、parent_id 等)。
核心步骤:
- 格式解析与 Layout 还原:用 PyMuPDF / pdfplumber / docx2python / Unstructured 把版式还原为带标题、段落、表格的结构化文本。这一步是 PDF 多栏、Word 标题层级能否保留的关键。
- 清洗去噪:剔除页眉、页脚、目录、乱码、重复空行、特殊字符,避免噪声 Embedding。
- 按分隔符优先级递归切分:第一优先级
\n\n(段落),第二\n(行),第三。(中文句号),依次类推,直到所有块 ≤ chunk_size。LangChain 典型参数:chunk_size=512,chunk_overlap=128(重叠比例 25%)。 - 结构感知合并 / 拆分:对 Markdown/HTML 用
MarkdownHeaderTextSplitter按#/##/###切,对代码用PythonCodeTextSplitter按函数/类切,对超大节再叠加递归切分做二次切。 - Metadata 注入:每个 Chunk 写入
source_file、page、section、chunk_id、parent_id,用于后续过滤、引用与 Parent-Child 合并。 - Embedding + 入库:把 Chunk 文本过 Embedding 模型,向量 + Metadata 一起写入向量库(如 Milvus/Chroma/Qdrant)。
为什么 chunk_size 经常取 512:大多数 Embedding 模型(如 BGE、OpenAI text-embedding-3-small)的最佳输入区间是 256~512 Token;512 是"召回粒度 + 上下文完整性"的常用折中点。
关键知识点(15 条)
- 文档从上传到入库至少经过 6 个环节:上传 → 格式校验 → Layout 解析 → 清洗去噪 → Chunking → Metadata → 入库。
- 固定长度切分最朴素,常见配置 1000 Token / 块 + 200 Token 重叠。
- 递归字符切分是工业界默认方案,参数
chunk_size=512、chunk_overlap=128、中文分隔符["\n\n","\n","。","?","!",";"]。 - 语义切分核心是计算相邻句子的 Embedding 余弦相似度,低于阈值就切。
- 文档结构化切分按标题层级(H1/H2/H3、1.1、1.1.2)切分,保留章节语义。
- Parent-Child Chunk 是"小粒度检索 + 大粒度上下文"的经典折中,子块 128 Token、父块 512~1024 Token。
- Chunk Overlap 推荐 10%~25%,过小边界截断,过大冗余与成本上升。
- 重叠不是越多越好,超过 30% 会出现大面积重复,导致 Embedding 相似度聚簇。
- PDF 多栏布局如果用普通
pdftotext会被读成单栏流,必须用版面分析(PyMuPDF get_text("dict") 或 pdfplumber)。 - 扫描件 PDF 必须先 OCR,常见组合 PaddleOCR + 版面分析;OCR 错误率 1%~3% 就会污染向量库。
- 表格不能简单按文本切,会把表头与数据行拆开,必须结构化抽取(HTML/CSV/Markdown 表)。
- 图片三种处理路径:1)OCR 抽文字;2)Caption/VLM 生成描述;3)直接 Embedding 图(CLIP 多模态向量)。
- 父块与子块必须写入
parent_id,否则 Auto-merging 时无法回溯。 - 切分策略选择优先级:结构清晰文档 → 结构化切分;自然语言长文 → 递归切分;语义要求高 + 预算足 → 语义切分。
- 多模态 RAG 的完整链路 = Layout 解析 + 文本 Chunking + 表格结构化 + 图片 Caption/VLM + 统一 Embedding。
应用场景(4 个真实例子)
- 场景 1:企业知识库问答:某 SaaS 公司把 5000 份产品手册用
MarkdownHeaderTextSplitter按 H2 切分,召回率从 62% 提升到 89%。 - 场景 2:法律合同审查:用 Parent-Child Chunk(子块 128 / 父块 1024)做条款检索,命中条款后回带上下文,LLM 回答准确率提升 35%。
- 场景 3:扫描件档案数字化:政府机关把 10 万页扫描件 PDF 走 PaddleOCR + 版面分析 + 表格结构化抽取,整理后入库可被语义检索。
- 场景 4:多模态产品手册:电商平台把产品图过 CLIP 得到 512 维向量,与文本 Chunk 在同一向量库混合检索,按图搜文、按文搜图。
常见误区 / 踩坑(6 条)
- ❌ 误区 1:以为换更强的 Embedding 模型就能解决答案差。
✅ 正解:90% 的瓶颈在 Chunk 质量(语义截断、表格拆散、页眉入索引),换模型只是让错误"稳定表达"。 - ❌ 误区 2:Chunk 越大越好,上下文更全。
✅ 正解:Chunk 超过 Embedding 模型最优区间(如 512 Token)会导致召回粒度变粗、噪声增加、命中率反而下降。 - ❌ 误区 3:完全不用 overlap。
✅ 正解:边界语义截断会把"条件 → 结论"切成两半,必须用 10%~25% overlap 兜底。 - ❌ 误区 4:表格直接当文本切。
✅ 正解:表头与数据行必须同 Chunk,否则检索回来只有"某列值",无法解读含义。 - ❌ 误区 5:扫描件 PDF 跳过 OCR。
✅ 正解:扫描件是图片,没有 OCR 步骤向量库是空的,必须 PaddleOCR/Tesseract + 版面分析。 - ❌ 误区 6:以为 Chunking 策略可以一劳永逸。
✅ 正解:文档类型决定策略——Markdown 走标题切,PDF 走版面切,代码走 AST 切,长文走递归切,混合文档要分层。
性能 / 复杂度(数据驱动)
- 固定长度切分:时间 O(n),空间 O(n);100MB 文本秒级完成。
- 递归字符切分:时间 O(n × k),k 是分隔符数(通常 5~7),空间 O(n)。
- 语义切分:时间 O(n × d) 句子级 Embedding + O(m²) 相似度矩阵(m 为句子数);100 万字文档可能耗时 10~60 秒。
- 文档结构切分:时间 O(n) + 版面解析开销(PyMuPDF 约 50 页/秒)。
- Parent-Child Chunk:存储 ×2(父子两份 Chunk),检索时多一次合并,QPS 下降约 15%~25%。
- 与替代方案对比:
- 方案 A:纯固定切分,最快但语义最差。
- 方案 B:递归切分(默认方案),速度与质量平衡,工业首选。
- 方案 C:语义切分,质量最高但成本贵 5~10 倍。
- 临界点:文档 < 10MB 用递归;> 100MB 且对召回要求极高 → 走语义切分;预算敏感 → 固定切分 + 调大 overlap。
与相关概念的区别(3 对)
- vs Embedding 模型选型:
- 维度 1(影响范围):Embedding 决定相似度度量;Chunking 决定送进 Embedding 的内容。
- 维度 2(调优成本):换 Embedding 一次调用;改 Chunking 策略要重做索引。
- 维度 3(收益曲线):Embedding 收益边际递减;Chunking 优化常带来 20%~40% 召回提升。
- 怎么选:先调 Chunking,再换 Embedding。
- vs 向量数据库选型:
- 维度 1(角色):向量库负责存储与检索;Chunking 决定入库内容。
- 维度 2(瓶颈阶段):向量库瓶颈在 QPS;Chunking 瓶颈在语义。
- 维度 3(成本):向量库按 QPS/存储计费;Chunking 按 Embedding 调用计费。
- 怎么选:先优化 Chunking 减少冗余向量,再选合适向量库。
- vs 传统倒排索引检索:
- 维度 1(匹配方式):倒排索引靠关键词 BM25;Chunk Embedding 靠语义相似度。
- 维度 2(召回特性):BM25 精确但无语义;Embedding 模糊召回但粒度更粗。
- 维度 3(融合):工业界普遍 BM25 + 向量召回做混合检索(Hybrid Search)。
- 怎么选:纯关键词需求用 BM25;问答场景用 Embedding + BM25。
进阶 / 面试加分项
- 最新进展:2024 年起 Agentic Chunking(让 LLM 自主判断切分边界)开始流行;Late Chunking(先 Embedding 整文,再按窗口取向量)由 jina-ai 在 2024 年提出,能保留全局上下文。
- 业界争议:是否值得为语义切分付出 5~10 倍成本?目前主流答案是"文档 < 100MB 不值得"。
- 一句话送给候选人:Chunking 是 RAG 的"数据质量地基",地基不稳,再贵的 Embedding 和向量库都是空中楼阁。
一张速查表(来源:JavaGuide + 知乎"小盒子"专栏,合并去重)
| 策略 | 核心思想 | 推荐参数 | 适用场景 | 主要缺点 |
|---|---|---|---|---|
| 固定长度 | 按字符/Token 硬切 | 1000 / 200 重叠 | 快速原型 | 语义截断 |
| 递归字符 | 按分隔符优先级递归 | 512 / 128 | 默认方案 | 中文标点需自定义 |
| 语义切分 | Embedding 相似度断点 | 阈值 0.5~0.7 | 高语义需求 | 成本贵 5~10 倍 |
| 文档结构 | 按标题/章节切 | H1/H2/H3 | Markdown/Word | 文档结构需清晰 |
| 句子窗口 | 句子检索 + 窗口返回 | 窗口 3~5 句 | 精确问答 | 重排成本高 |
| 自动合并 | 子块检索 + 父块返回 | 子 128 / 父 1024 | 召回+上下文兼顾 | 存储 ×2 |
面试如何回答
🟢 什么是 Chunking?为什么 RAG 系统必须做文档切分?
回答要点:
Chunking 是把长文档按语义、结构或长度切成适合 Embedding 与检索的小块的过程。第一,Embedding 模型有最大输入长度限制(如 512 Token),超长文本会被截断;第二,检索粒度太粗会导致召回片段里同时包含多主题,相似度被噪声稀释;第三,切分让每块对应一个独立语义单元,向量库才能精准匹配用户 query。
核心要点:
- Embedding 模型最优输入区间通常是 256~512 Token,块过大或过小都会降召回。
- 切分发生在离线索引阶段,一次切分决定全量数据的检索质量。
- 主流方案是递归字符切分:
RecursiveCharacterTextSplitter,参数chunk_size=512、chunk_overlap=128。
真实场景:某 SaaS 公司把产品手册从"整文档入库"改成按 H2 切分后,召回率从 62% 提升到 89%。
金句:Chunking 是 RAG 的地基,地基不稳,再贵的 Embedding 都是空中楼阁。
加分项:超过 90% 的 RAG 效果问题都可以追溯到 Chunk 质量,而不是 Embedding 模型本身。
🟢 RAG 文档从上传到入库要经过哪些完整环节?每个环节最常见的坑是什么?
回答要点:
完整链路至少 6 个环节:文件上传 → 格式校验 → Layout 解析 → 清洗去噪 → Chunking → Metadata 写入 → 入库。每个环节都有典型坑,面试时按链路顺序答最稳。
核心要点:
- 文件上传:格式伪造、大小超限、编码混乱 → 解析器静默失败。
- 格式校验:扩展名与 MIME 类型不符 → 选错解析器(如把 docx 当 doc 解析)。
- Layout 解析:PDF 多栏、Word 标题层级、Excel 字段关联丢失 → 结构错位。
- 清洗去噪:乱码、特殊字符、目录残留、页眉页脚 → 噪声入索引。
- Chunking:语义截断、上下文断裂、块过大或过小 → 召回不准。
- Metadata:未保存来源/页码/版本 → 无法过滤与引用。
真实场景:很多团队把页眉页脚当正文入库,导致"第 1 页"这种文本被反复召回,污染前 10 个相似度结果。
金句:RAG 的瓶颈通常不在检索层,而在文档进入索引之前的那段管线。
加分项:质量校验不应只在入库后做,应在 Chunking 阶段做采样校验,提前发现低质量数据。
🟡 固定长度切分、递归字符切分、语义切分、结构化切分有什么区别?怎么选?
回答要点:
四种切分策略对应四种不同的语义粒度与成本,面试用对比表回答最清晰。
核心要点:
- 固定长度切分:按字符/Token 硬切,速度最快 O(n),但可能在句子中间切断,破坏语义,缺点最多,不建议生产使用。
- 递归字符切分:按分隔符优先级(
\n\n→\n→。→?)递归切到目标大小,是 LangChain 默认方案,参数chunk_size=512、chunk_overlap=128,工业界首选。 - 语义切分:先按句号切句,对每句 Embedding,再算相邻句子余弦相似度,低于阈值就切。语义最好但成本贵 5~10 倍。
- 文档结构化切分:按 H1/H2/H3、1.1、1.1.2 等标题层级切(用
MarkdownHeaderTextSplitter),保留章节语义,适合 Markdown/Word/技术文档。
选择顺序:结构清晰 → 结构化切分;自然语言长文 → 递归切分;高语义要求 + 预算充足 → 语义切分。
真实场景:技术文档用 MarkdownHeaderTextSplitter 按 H2 切分,比递归切分召回率高 25%;长篇小说用递归切分即可,语义切分性价比太低。
金句:没有最好的切分策略,只有最匹配文档类型的策略。
加分项:混合策略是工业实践——先按结构粗切,再对超长节递归细切,兼顾语义与可控性。
🟡 Chunk Overlap 应该如何设置?为什么不能太大也不能太小?
回答要点:
Chunk Overlap 是相邻 Chunk 共享的文本片段,用于缓解边界处的语义截断。核心原则:10%~25% 是甜蜜区。
核心要点:
- 不设 overlap 的后果:边界处经常把"条件 → 结论"或"问题 → 答案"切成两半,召回回来的 Chunk 缺一半语义,LLM 答非所问。
- overlap 太小的后果:边界问题没解决,等于没设。
- overlap 过大的后果(>30%):相邻 Chunk 高度相似,导致 Embedding 聚簇,检索 top-k 结果重复,召回多样性下降;同时 Embedding 调用量翻倍,成本与延迟同步上升。
- 推荐值:递归切分用
chunk_size=512、chunk_overlap=128(25%);固定切分常用1000/200(20%)。
真实场景:某法律合同 RAG 把 overlap 从 0 调到 128 后,召回率从 71% 提升到 88%,但调到 300 后召回率反而降到 79%,因为 top-5 全是相邻重复 Chunk。
金句:Overlap 是边界问题的解法,但解药过猛也会中毒。
加分项:更高级的方案是 Sentence-Window Retrieval——检索时只 Embedding 句子,但返回给 LLM 句子前后 3~5 句的窗口,既保留精度又避免 Chunk 重复。
🟡 什么是 Parent-Child Chunk?它解决了什么问题?
回答要点:
Parent-Child Chunk 是一种"小粒度检索 + 大粒度上下文"的两级切分方案,子块用于精细检索,父块用于补充上下文。
核心要点:
- 切分方式:父块按章节或 1024 Token 切,子块在父块内按 128~256 Token 递归切,每个子块写入
parent_id。 - 检索流程:用户 query 只与子块做 Embedding 相似度匹配;命中后通过
parent_id找到对应父块,把整个父块返回给 LLM。 - 解决的问题:传统方案要么块大(召回粒度粗、噪声多)、要么块小(命中后 LLM 缺上下文)。Parent-Child 同时拿到"召回精度"和"上下文完整度"。
- 代价:存储 ×2(父子各一份 Chunk),检索时多一次 parent 合并,QPS 下降 15%~25%。
真实场景:LlamaIndex 的 Auto-merging Retrieval 是典型实现,检索子块命中数量达到阈值时自动合并到父块;在合同审查场景中,召回条款后回带整段上下文,LLM 回答准确率提升 35%。
金句:Parent-Child Chunk 是检索粒度与上下文完整度的黄金折中。
加分项:可以用 Sentence-Window 做替代——只 Embedding 句子,命中后返回句子周围窗口,避免双份存储。
🟡 语义丢失和结构丢失分别是什么?分别在什么场景下发生?怎么解决?
回答要点:
语义丢失和结构丢失是 Chunking 最常见的两类问题,面试经常合并追问。
核心要点:
- 语义丢失:一个完整语义单元(如"条件→结论"、"问题→答案"、"代码+注释")被切成两个 Chunk,导致召回片段残缺。典型场景:固定切分在句子中间硬切;表格行与表头被拆开;代码块与上下文分离。
- 结构丢失:文档的标题层级、表格行列、章节关系被打散。典型场景:PDF 多栏布局被读成单栏流;Word 标题样式没保留;Excel 多列关联丢失;扫描件 OCR 错误率 1%~3% 污染全库。
- 解决语义丢失:用递归切分保留分隔符优先级;用 overlap 10%~25% 兜底;用 Parent-Child Chunk 在命中后回带上下文。
- 解决结构丢失:用版面分析工具(PyMuPDF
get_text("dict")、pdfplumber、Unstructured)还原版式;用MarkdownHeaderTextSplitter保留标题层级;用结构化抽取把表格存为 HTML/CSV/Markdown 表;扫描件必须 OCR + 版面分析。
真实场景:扫描件 PDF 直接入库会导致向量库几乎是空的,因为图片没有文本可 Embedding;走 PaddleOCR + 版面分析后才能正确检索。
金句:语义丢失让你召回错,结构丢失让你召回全错。
加分项:表格建议整张表存为一个 Chunk,并在 Metadata 写入行列数,方便 LLM 还原语义。
🔴 如果让你从零设计一个支持 PDF、Word、Excel、扫描件的 RAG 文档处理管线,你会怎么设计?
回答要点:
设计思路:按文档类型分支处理 → 统一清洗 → 统一 Chunking → 注入 Metadata → 入库 → 分层校验。
核心要点:
- 格式识别与分支:根据 MIME 类型和 magic number 分发到不同解析器;扩展名与实际类型不符时以 magic number 为准,避免选错解析器。
- Layout 解析:
- PDF(文本型):PyMuPDF / pdfplumber,识别多栏、标题、页眉页脚。
- PDF(扫描件):PaddleOCR + 版面分析,输出带坐标的文本块。
- Word:docx2python,提取段落样式与 Outline Level。
- Excel:openpyxl,把每张表结构化为 Markdown 表或 HTML,保留表头与数据行同 Chunk。
- 统一清洗:去除页眉页脚、目录、乱码、特殊字符,统一编码为 UTF-8。
- 分层 Chunking:
- 第一层:按文档结构(标题/章节)粗切。
- 第二层:对超长节递归切分到 512 Token。
- 第三层:对超大表格用结构化抽取,对图片用 Caption 或 CLIP Embedding。
- Metadata 注入:每块写入
source_file、page、section、chunk_id、parent_id、doc_type,便于过滤与引用。 - 分层校验:
- 格式校验:解析前 magic number + MIME。
- 解析校验:采样比对解析输出与原文,错误率 >1% 报警。
- Chunking 校验:采样人工审核 + 自动指标(平均块大小、overlap 比例、Chunk 数 vs 文档长度)。
- 入库与降级:Embedding 维度必须一致;Token 超限自动二次切分;扫描件 OCR 失败时降级为"仅存元数据 + 人工补录"。
真实场景:某金融公司用这套管线处理 50 万份混合文档(合同 PDF + 扫描件 + Excel),召回率从 58% 提升到 91%。
金句:好的文档管线 = 解析能力 + 切分策略 + Metadata 设计 + 分层校验的四位一体。
加分项:可以加 Agentic Chunking 兜底——对前 1% 高价值文档让 LLM 自主判断切分边界,进一步提升关键文档召回率。
🔴 多模态 RAG 中图片、表格、图表分别怎么处理?为什么不能简单当文本切?
回答要点:
多模态内容的核心挑战是:图片没有直接可 Embedding 的文字,表格的行列关系是语义的一部分,图表的关键信息在 Caption 和上下文。简单按文本切会丢失全部结构信息。
核心要点:
- 图片三种处理路径:
- 路径 A:OCR 抽取图片内文字(适合扫描件、截图)。
- 路径 B:用 Caption 模型或 VLM(GPT-4V、Qwen-VL)生成图片描述,再 Embedding 描述文本。
- 路径 C:用多模态 Embedding 模型(CLIP、Visualized BGE)直接把图片 Embedding 成 512/1024 维向量,与文本向量在同一空间检索。
- 表格结构化抽取是核心:表格必须按"表头 + 数据行"整体保留为一个 Chunk,存为 Markdown 表、HTML
<table>或 CSV,不能按文本行切。Excel 多列关联尤其需要保留表头,否则 LLM 看到孤立数字无法解读含义。 - 图表的 Caption 和上下文同样重要:图表的标题、坐标轴、图例必须与图表本身绑定,否则 Embedding 的向量会丢失语义上下文。建议把"图表 + 标题 + Caption + 周边段落"合并为一个 Chunk。
- 完整的多模态 RAG 链路:Layout 解析 → 文本 Chunking + 表格结构化 + 图片 Caption/VLM → 统一 Embedding(文本向量 + CLIP 向量)→ 混合检索(文本向量 + 多模态向量)。
真实场景:电商产品手册用 CLIP Embedding 图片 + 文本 Chunking 混合检索,实现"按图搜文"和"按文搜图"双能力;某汽车说明书 RAG 把图表与 Caption 合并存储,召回准确率比单独存储高 40%。
金句:多模态 RAG 不是把图片变文本,而是让图片和文本在同一向量空间对话。
加分项:2024 年起多模态 Embedding 模型(如 Visualized BGE、CLIP-2024 升级版)开始支持中文,效果接近纯文本 Embedding,是工程化首选路径。
