拓冰建站拓冰建站
首页 / 资讯中心 / 正文

深入解析RAG文档预处理:重叠区与按页分割的最佳实践

这次我们认真聊一个 RAG 落地时绕不开的问题文档预处理阶段的切片与重叠区设计。很多人做 RAG 知识库时文档一进来就直接按固定长度切成 chunk再塞给 embedding 模型结果检索效果不稳定追问起来才发现是预处理阶段埋了雷。尤其是 PDF 和 PPT 这类强结构文档到底按页切还是按段落切重叠区overlap到底该设多少网上说法很多实际一测差距又很大。这篇文章不谈玄学把 PDF、PPT 按页分割的适用场景和重叠区设计思路拆开讲清楚。先说结论重叠区不是越大越好按页分割也不是万能方案。它适合“一页一个主题单元”的文档不适合“连续叙述型长文”。重叠区的本质是补偿切分时丢失的上下文它的最优值取决于文档结构、embedding 模型能力、检索策略这三个变量必须用测试集去验证不能拍脑袋定一个数。本文会从文档加载规则、按页分割适用场景、重叠区设计、功能验证、批量处理与接口调用几个方面展开适合正在做 RAG 知识库、遇到底层文档切片效果不稳定的开发者阅读。1. 核心能力速览能力项说明解决的问题RAG 文档加载、预处理、切片粒度、重叠区设计主要文档类型PDF、PPT、TXT、Word 等常见办公文档关键处理环节格式解析、内容提取、结构化切分、重叠区设置、向量化核心难点跨页内容断裂、扫描件 OCR、表格/图示跨页、重叠区噪音适用框架LangChain、LlamaIndex 均可也可纯手写解析管线硬件要求解析本身 CPU 足够向量化取决于 embedding 模型部署方式是否支持批量支持建议按目录扫描 任务队列 失败重试是否支持 API可封装为 HTTP 服务供上游系统调用适合场景企业内部知识库、课程课件解析、产品文档问答、合同/报告检索表格里这些能力项本质上都是围绕一个问题让切片后的文本块既保持语义完整又能被检索系统稳定命中。所以接下来先从文档加载和预处理规则说起。2. 文档加载与预处理不是所有文件都该用同一种切法RAG 的文档预处理不是“读文本 - 切分 - 向量化”这么简单。不同格式的文档内容组织方式完全不同预处理规则必须跟着文档结构走。2.1 TXT / Markdown 类纯文本这类文件没有版面信息只能依靠段落、标题、空行来判断语义边界。常见做法是按空行分段落。按 Markdown 标题层级识别章节。对无结构的纯文本才退化为固定 token 切分 重叠区。纯文本的切分自由度最高也是重叠区设计讨论最多的场景。2.2 Word 文档Word 除了段落和标题还有表格、智能目录、批注、页眉页脚等附加信息。预处理时应先提取正文结构优先读取内嵌标题样式而不是纯文本换行。表格建议单独提取作为独立的切片单元。页眉页脚默认丢弃避免检索噪音。2.3 PDF 文档PDF 是 RAG 预处理中情况最复杂的格式。同样是 PDF可能是「数字生成型」或「扫描图片型」PDF 类型特征预处理方式数字生成型 PDF文本可选中、可复制直接用 pypdf、pdfplumber 提取文本扫描图片型 PDF本质是图片文本不可选中先 OCR 再走文本切分流程图文混排 PDF有图表、多栏排版需要版面分析或按页抽取幻灯片导出 PDF每页内容相对独立适合按页分割 页面元数据PDF 按页分割在这里是一个「候选策略」不是默认策略。后面单独展开讲。2.4 PPT 文档PPT 的特殊性在于它的最小语义单元天然是「页面」。每一页 PPT 通常包含标题、正文、图片、表格、备注一页往往表达一个完整主题。处理时建议优先提取「标题 正文 备注」三部分。页眉页脚、装饰性占位符要去除。如果一页中同时包含多个并列要点可以考虑按“标题级别”二次拆分。PPT 按页分割的收益通常比 PDF 更明显因为 PPT 的版式本身就是信息块。3. 重叠区设计先理解它补偿的是什么重叠区被称为“玄学”是因为很多人把它当成一个固定参数。但想让重叠区发挥价值必须理解它到底在补偿什么。3.1 为什么需要重叠区假设一份文档被切分成chunk1: A B C D chunk2: E F G H如果检索问题涉及「C D E」这个语义片段而切分点刚好落在 D 和 E 之间那么 chunk1 和 chunk2 各自都不完整。加上重叠区后chunk1: A B C D E chunk2: D E F G HD 和 E 同时出现在两个 chunk 中即使检索命中了其中一个也能拿到相对完整的上下文。这是重叠区最核心的作用。3.2 重叠区大小由什么决定从实践角度看重叠区大小主要受三个变量约束文档结构强度如果文档本身有明确的章节、标题、列表切分边界更容易落在语义边界上重叠区可以小如果文档是连续叙述型长文重叠区需要适当增大。Embedding 模型窗口Embedding 模型对文本长度有上限重叠区过大会挤占主体内容的 token 预算导致有效信息被稀释。检索策略如果后面接 rerank 模型重叠区可以压缩如果只用向量相似度直接取 top-k重叠区要更谨慎避免多个高度相似的 chunk 同时命中导致内容重复。3.3 重叠区不是越大越好大重叠区容易造成两个问题向量存储冗余相同内容出现多次增加存储成本和检索噪音。检索结果集中度下降Top5 结果可能全是同一段话的不同切法真正需要的信息反而排不到前面。所以重叠区设计应当遵循一个原则刚好覆盖切分边界丢失的上下文不给检索制造重复噪音。4. PDF 按页分割的适用场景与设计思路PDF 按页分割是一个很容易被过度使用的方法。不是所有 PDF 都应按页切但特定场景下按页切效果很好。4.1 适合按页分割的 PDF 类型文档类型为什么适合按页切企业年报、财报、投研报告每页通常是一个独立的分析模块产品宣传 PPT 导出的 PDF页面本身就是设计好的语义单元合同、发票、简历一页一个文档或一页一个关键部分课程课件 PDF每页标题 要点内容密度适中4.2 不适合按页分割的 PDF 类型文档类型问题技术手册、操作说明一个操作步骤可能跨两页按页切会切断流程学术论文段落和公式可能跨页按页切严重破坏语义多栏排版 PDF一页里有两个或三个内容栏按页切会导致一页多个并列主题混合4.3 按页分割时的增强设计按页分割不是简单地把每页文本变成一个 chunk还需要做三件事保留页面元数据记录page_number、source_path检索结果返回时能定位到具体页面。跨页粘连处理如果上一页末尾是不完整句子尝试与下一页开头合并或通过重叠区覆盖。窄文本合并有些页面只有一行标题或一个图单独成 chunk 没有检索价值可以和相邻页合并。一个兼顾「按页分割」和「语义完整性」的通用思路是先按页切再对每页内容做二次判断——如果页面内容太少合并如果页面内容超长再细分。5. PPT 按页分割的适用场景与设计思路PPT 按页分割比 PDF 更自然因为 PPT 的页面本身就承载了「一个页面一个主题」的设计逻辑。5.1 适合按页分割的 PPT 类型文档类型为什么适合按页切培训课件每页讲一个知识点产品方案每页介绍一个模块或功能项目汇报每页一个议题技术分享每页一个技术点这类 PPT 的标题、正文、备注往往构成完整的信息单元按页切后可以直接作为 RAG 的检索单元。5.2 按页分割时的内容组装PPT 页面的文本分布在不同的文本框中直接按阅读顺序拼接可能让语义乱掉。推荐组装顺序页面标题 正文要点按排版顺序 备注内容备注往往包含讲解者补充的信息是 RAG 检索中的高价值内容。但如果备注是演讲稿风格的流水账需要适当截断避免 chunk 过长。5.3 PPT 按页分割注意事项显式识别「标题占位符」和「正文占位符」优先用 pptx 文件中的 XML 结构而不是 OCR。图片中的文字如果参与检索需要 OCR 后合并到文本中否则信息丢失。每页的“第 X 页 / 共 Y 页”这类装饰文本要去除。6. RAG 重叠区与按页分割的工程实现到这里设计思路已经清楚了接下来看具体实现。以下示例使用通用 Python 库实际项目需要根据你的文件路径和环境调整。6.1 环境准备建议最小验证环境Python 3.9 及以上。安装以下依赖pip install pypdf python-pptx pdfplumber langchain-text-splitters如果要做 OCR再安装 OCR 相关依赖具体以你的源文档类型为准。6.2 PDF 按页分割 重叠区示例from pypdf import PdfReader def split_pdf_by_page_with_overlap(pdf_path, overlap_chars80): reader PdfReader(pdf_path) pages [] for page_num, page in enumerate(reader.pages, start1): text page.extract_text() if text: pages.append({ page_number: page_num, text: text.strip() }) chunks [] for i, page in enumerate(pages): text page[text] if i 0: prev_tail pages[i - 1][text][-overlap_chars:] text prev_tail \n text chunks.append({ page_number: page[page_number], source: pdf_path, text: text }) return chunks这段代码做的事情是按页提取文本再引入前一页末尾的 overlap_chars 字符保证跨页上下文不断裂。实际项目中overlap_chars需要根据测试结果调整。6.3 PPT 按页分割示例from pptx import Presentation def split_ppt_by_slide(pptx_path): prs Presentation(pptx_path) slides [] for idx, slide in enumerate(prs.slides, start1): parts [] for shape in slide.shapes: if shape.has_text_frame: for para in shape.text_frame.paragraphs: line .join(run.text for run in para.runs).strip() if line: parts.append(line) notes_text if slide.has_notes_slide: notes_text slide.notes_slide.notes_text_frame.text.strip() content \n.join(parts) if notes_text: content f\n备注{notes_text} slides.append({ slide_number: idx, source: pptx_path, text: content }) return slidesPPT 按页分割后每一页的标题、正文、备注作为一个整体 chunk特别适合课件的 RAG 检索。6.4 通用文本切分 重叠区示例对于已经提取出来的纯文本推荐使用langchain-text-splitters的RecursiveCharacterTextSplitterfrom langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter RecursiveCharacterTextSplitter( chunk_size512, chunk_overlap80, separators[\n\n, \n, 。, , , . , ! , ? ] ) chunks text_splitter.split_text(long_text)这里的chunk_size和chunk_overlap是通用建议值不是固定标准。实际项目中应该先跑一组候选参数再通过检索测试选择最优组合。7. 功能测试与效果验证预处理管线搭好之后不能只看「能跑通」要看检索效果。下面给出一套通用验证流程。7.1 准备测试集建议手工构造 10 到 30 个测试问题覆盖明确出现在某个页面/段落的问题。跨页才能回答的问题。需要结合 PPT 备注才能回答的问题。容易混淆的相似主题问题。每个问题标注对应的标准答案片段最好精确到页码或 slide 编号。7.2 对比测试维度参数测试候选值chunk_size256 / 512 / 768chunk_overlap0 / 64 / 128 / 256分割策略按页 / 按段落 / 固定长度运行同一组测试问题记录每个配置下的检索命中率和答案完整性。7.3 判断标准命中率正确答案片段是否出现在检索结果 Top5 中。上下文完整性命中的 chunk 是否包含足够上下文支撑回答。冗余度Top5 结果中有多少重复内容。定位准确性是否能够定位到源文档的准确页面或 slide。这种验证方法不需要复杂框架几行脚本就能跑出来但价值远高于凭感觉调参数。8. 接口 API 与批量任务设计文档预处理做完了下一步是工程化接入。推荐把预处理 切分 向量化封装成服务方便上游系统调用。8.1 FastAPI 接口示例from fastapi import FastAPI, UploadFile, File import tempfile app FastAPI() app.post(/documents/process) async def process_document(file: UploadFile File(...)): suffix file.filename.rsplit(., 1)[-1].lower() with tempfile.NamedTemporaryFile(suffixf.{suffix}, deleteFalse) as tmp: tmp.write(await file.read()) tmp_path tmp.name if suffix pdf: chunks split_pdf_by_page_with_overlap(tmp_path) elif suffix in (pptx, ppt): chunks split_ppt_by_slide(tmp_path) else: return {error: unsupported file type} return { filename: file.filename, chunk_count: len(chunks), chunks: chunks }这个接口接收 PDF 或 PPT 文件返回按页分割后的 chunk 列表方便上层系统直接对接向量库。8.2 批量任务设计批量处理文档时建议按以下思路组织目录扫描输入一个总目录递归找出所有 PDF、PPTX 文件。任务队列每个文件作为一个任务写入队列记录处理状态。失败重试对解析失败的文件单独记录日志不阻塞整个队列。结果输出每个文件生成独立的 JSON 输出包含 chunk 内容和元数据。{ input_dir: ./docs, output_dir: ./outputs, file_types: [pdf, pptx], overlap_chars: 80, retry_count: 3 }批量任务最重要的是可观测。每个文件处理完成后输出“文件名、页数、chunk 数、耗时、状态”有问题时能快速定位到具体文件。9. 资源占用与性能观察文档预处理阶段的资源占用容易被忽略实际跑批量任务时往往在这里卡住。9.1 解析阶段的资源占用PDF 文本提取和 PPT 文本框提取都是 CPU 密集操作单个文件通常不会占用太多内存但几百个文件并发处理时CPU 会成为瓶颈。如果 PDF 是扫描件需要 OCR资源占用会明显上升OCR 对 CPU、内存的需求都更高。大批量文档处理建议用队列控制并发数不要一次性全部载入内存。9.2 向量化阶段的资源占用如果 embedding 模型是本地部署显存占用取决于模型尺寸和 batch size。如果 embedding 服务通过 API 调用批量任务要注意速率限制和超时重试。向量库写入时批量插入的 batch size 不宜设置过大避免内存峰值。9.3 性能观察方法用time记录每个文件处理耗时。观察CPU / 内存 / 显存三个维度。批量任务增加「每 100 个文件输出一次统计」的日志。这种观察方式不依赖特定平台在实际项目中能帮你快速识别预处理管线的瓶颈。10. 常见问题与排查方法问题现象可能原因排查方式解决方案PDF 提取出的文本乱序PDF 是多栏排版或图层复杂打印每页文本顺序检查改用 pdfplumber 按坐标提取或人工指定栏顺序PDF 提取不到任何文本扫描版或图片型 PDF查看 PDF 是否可选择文本接入 OCR 流程后再切片PPT 按页切后检索效果差只提取了正文忽略了标题/备注检查 chunk 内容是否完整按“标题 正文 备注”组装页面内容设置了重叠区但检索噪音变大重叠区过大或文档结构强无需重叠对比不同 overlap 值的命中率减小 overlap 或对强结构页面关闭重叠跨页表格被切断按页分割时表格跨了两页定位到具体页数查看内容对表格区域做完整块提取再覆盖到相邻页中文文档切分后语义碎片化切分边界落在中文句子中间检查 separator 是否包含中文字符在分隔符中加入“。”“”和换行符批量任务处理中途卡住单个文件解析异常导致线程阻塞查看日志定位到具体文件增加超时控制和失败跳过机制单文件异常不阻塞队列向量库中重复内容过多重叠区跨多个 chunk 造成高度相似检索 Top 结果相似度对比加重叠区对检索结果做去重或改用 rerank接口调用超时大文件解析耗时过长查看服务日志和文件大小接口层增加异步任务文件解析完成后回调通知排查时建议先看“单文件是否能解析”再看“解析结果是否合理”最后看“检索效果是否达标”。大多数问题在第二阶段就能暴露出来。11. 最佳实践与使用建议把前面所有内容收敛成几条可操作的实践准则。先小批量验证再全量处理。不要一上来就处理上千个文件先拿 10 个代表性文件跑通全流程确认解析结果和切分效果。按文档类型分组配置。PDF 按页分割、PPT 按页分割、TXT 按段落切分不要用同一套参数处理所有格式。把重叠区当成可调参数而不是固定值。每一批新文档都要重新验证 chunk_size 和 overlap 的组合。保留元数据。每个 chunk 都记录来源文件、页码、slide 编号否则检索到内容后无法溯源。建立检索评测集。哪怕只是 10 个问题也比没有评测集靠感觉调参强。接口和批量任务要加日志和失败重试。文档解析不可控因素多尤其是 PDF一个坏文件就能卡住整条流水线。关注版权与授权边界。企业内部文档、课程 PPT、合同、报告在投入 RAG 前要确认文档来源和复制范围是否符合授权要求涉及个人隐私或商业机密的内容要做脱敏和访问控制。发布前做效果复核。RAG 问答系统对事实性要求高检索召回不准会导致回答误导关键业务场景必须人工复核后再上线。12. 总结与下一步回到开头的问题重叠区是玄学吗不是。它是对切分边界信息丢失的补偿是一个可以量化、可以用测试集评估的设计参数。PDF 按页分割和 PPT 按页分割也一样核心判断标准是“这一页是否构成一个独立的语义单元”。是就按页切不是就按段落或定长切再用重叠区补偿边界。最容易踩的坑有三个一是所有文档统一用一套切分参数二是只要设了重叠区就以为能解决所有跨页问题三是只看“能跑通”不看真实检索效果。先找 10 个代表性文档建立小测试集跑一遍不同配置下的命中率对比几分钟就能得到比凭感觉调参可靠得多的结论。下一步你可以做三件事把本文的 PDF、PPT 按页分割脚本接到你的文档目录上跑一版构造一个 10 到 30 条问题的评测集对比「固定长度切分 重叠区」与「按页切分 重叠区」的召回差异。做完这三步你对 RAG 文档预处理的把控能力会比大多数现成框架默认配置更扎实。建议收藏备用等实际跑完再回来对照参数。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门