RAG系统:文档解析与文本分块的常见方案
做RAG系统的同行都知道: RAG效果好不好,80% 取决于文档解析与分块的质量 。
我们日常导入的文件,从来不是单纯的纯文本,而是PDF、Word、Excel、扫描件,甚至还有双栏排版、嵌套表格、带水印的复杂文档,每一种格式都藏着解析的坑。要是想把导入效果做到极致,确实要啃不少细致的硬骨头。
那目前主流的开源RAG系统,到底是怎么解决多格式、复杂结构文档的解析难题的?
一、先搞定统一加载:屏蔽所有格式差异,一行读全
面对五花八门的文件格式,开源RAG的核心思路第一步,就是做一层统一的加载接口,不管是PDF、Word还是Excel,不用单独写适配代码,直接自动识别、批量读取。
目前主流框架都内置了完善的加载工具,核心能力如下:
LangChain:100+ 加载器覆盖全场景
LangChain内置了超过100种文件加载器,覆盖几乎所有常用格式。
– 单文件读取:针对PDF用PyPDFLoader,Word用Docx2txtLoader,Excel用CSVLoader;
– 批量读取:通过DirectoryLoader+文件后缀自动映射,指定文件夹就能一次性读取所有格式文件。
LlamaIndex:极简自动识别神器
LlamaIndex的SimpleDirectoryReader是很多人的首选,核心优势是零配置自动识别。
– 支持20+种格式:PDF、DOCX、MD、CSV、Excel、PPT等都能直接读取;
– 底层自动调用适配工具:不用手动配置,底层会自动调用PyPDF2、python-docx、pandas等对应库。
RAGFlow/OpenRAG:专业级解析加持
这两款专注RAG场景的开源系统,内置了DeepDoc、Docling等专用解析器,读取后直接输出结构化的JSON格式,比普通框架更贴合RAG后续的分块和检索需求。
不管选哪种框架,统一加载后都会得到标准的Document对象,包含两个核心部分:
– page_content/text:提取的纯文本内容;
– metadata:文件名、页码、路径、修改时间、文件格式类型,这些元数据是后续精准检索的关键。
二、核心突破:分层解析架构,搞定复杂格式
统一加载只是第一步,真正的难点是从不同格式的文件中,精准提取有效内容、恢复文档结构。开源RAG系统统一采用了“规则优先+视觉补全+OCR兜底”的三层解析架构,层层覆盖所有场景。
第一层:规则解析,应对原生数字文档
针对可复制的PDF、Word等原生数字文档,优先用规则引擎解析,速度快且精准。
– 文本抽取:直接调用pdfminer.six、PyPDF2、python-docx等工具读取文本流,避免提取到乱码;
– 结构恢复:这是重点!通过内置的版面分析模型(LayoutLM、LayoutTransformer等),自动识别文档中的区块——标题、正文、表格、图片、页眉页脚,然后按阅读顺序拼接;
– 冗余清理:自动剔除页眉页脚、水印、页码等无关内容,只保留核心信息。
第二层:表格专项解析,解决RAG重灾区
Excel、PDF中的表格是RAG解析的重灾区,合并单元格、无框线、嵌套表格,稍有不慎就会提取混乱。
– Excel文件:直接用pandas读取每个sheet,自动转换为Markdown或HTML表格格式,保留行列对应关系;
– PDF内嵌表格:简单表格用规则识别横线竖线即可;复杂表格(合并单元格、无框线)则调用TableFormer、Docling等专用表格模型,重建表格结构,最终输出清晰的表格文本。
第三层:OCR兜底,攻克扫描件/图片PDF
很多业务场景中,会遇到扫描件、图片PDF,甚至是拍照上传的文件,这类文件没有可复制的文本,只能靠OCR解析。
– 主流OCR工具:Tesseract、Surya、PaddleOCR,其中Surya和PaddleOCR的中文识别精度更高;
– 解析流程:先做版面分析,识别出文档中的文字块、标题块、表格块,再对每个区块单独做OCR,最后按阅读顺序拼接,还原文档结构。
目前有几个开源解析库,专门优化了复杂格式的处理,值得重点关注:
1. Unstructured-IO:支持25+种格式,是目前兼容性最强的开源解析库。提供两种模式,Fast模式用规则解析,速度快;Hi-Res模式用视觉模型+OCR,适合复杂扫描件,输出的JSON包含文本、表格、结构、元数据,适配所有RAG框架;
2. Docling:OpenRAG内置的解析库,主打多模态解析,不仅能处理文本、表格,还能把图表(折线图、柱状图)转化为文字描述,避免RAG丢失图表信息;
3. RAGFlow DeepDoc:针对中文文档优化的解析引擎,强在复杂表格、合同、论文等专业文档的解析,结构还原精度极高。
三、智能分块:不是乱切,要保语义完整
解析完成后,不能直接把整个文档塞给RAG系统,必须做智能分块(Chunk)——如果切得太碎,会割裂语义;切得太大,会包含无关内容,都会严重影响检索和生成效果。
开源RAG系统主流用三种分块策略,按需组合:
1. 递归分块:基础通用款
这是LangChain默认的分块方式,核心是按层级切分,不割裂关键词。
– 分块顺序:先按段落切,段落太长再按句子切,句子再按字符切;
– 核心参数:chunk_size(单块大小,一般设置1024字符)、chunk_overlap(块之间的重叠部分,避免语义断裂,通常设为chunk_size的10%)。
2. 语义分块:精准匹配话题
适合没有固定结构的文档,核心是按语义边界切分。
– 实现逻辑:先对文本做嵌入计算,得到每个句子的向量相似度;
– 分块规则:当相邻句子的相似度突然下降时,判定为话题边界,在此处切分,保证每一块都是完整的语义单元。
3. 结构分块:复杂文档首选
针对有明确标题层级的文档(比如PDF论文、Word报告),优先按结构分块,这是保证RAG检索精准度的关键。
– 分块规则:按标题层级切块,H1对应一个章节,H2对应小节,表格、图片单独切块;
– 核心优势:保留“章节-标题-内容”的层级关系,检索时能精准定位到具体章节,生成的内容也更贴合原文结构。
表格特殊处理:单独切块是关键
表格绝对不能和正文混在一起切分,要么整个表格作为一个块,要么按行分块,同时必须附加表头信息,避免RAG检索时搞不清表格内容的对应关系。
四、实操演示:多格式文档解析最小代码
首先安装依赖库:
pip install langchain unstructured pdf2image pytesseract python-docx pandas openpyxl
示例:
from langchain.document_loaders import UnstructuredFileLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitter# 读取多格式文件,支持pdf、docx、xlsx、jpg等loader = UnstructuredFileLoader("你的文件路径/复杂文档.pdf", # 替换为实际文件路径,支持docx/xlsx/jpg/pngmode="elements", # 保留文档结构,是解析复杂文件的关键strategy="hi_res" # 扫描件用hi_res,原生文档用fast# 加载文件documents = loader.load()# 智能分块text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024,chunk_overlap=100,separators=["\n\n", "\n", ".", "。", "!", "?", " ", ""]# 生成分块结果chunks = text_splitter.split_documents(documents)# 打印分块结果,查看结构和内容for i, chunk in enumerate(chunks):print(f"第{i+1}块")print(f"文件来源:{chunk.metadata['source']}")print(f"页码/位置:{chunk.metadata.get('page_number', '无')}")print(f"内容:{chunk.page_content}")print("-" * 50)
五、总结开源方案的核心逻辑
看完上面的解析流程,其实能发现,开源RAG系统解决多格式复杂文档的核心,就四句话:
1. 统一加载:自动识别格式,批量读取,屏蔽底层差异;
2. 分层解析:规则+视觉模型+OCR,覆盖所有文件类型,精准提取内容;
3. 结构保留:还原标题、段落、表格、层级,不丢核心信息;
4. 智能分块:按结构、语义切分,保证语义完整,适配RAG检索。
夜雨聆风