
1. 先搞清楚 RAG 处理 Word 和 PDF 到底要解决什么问题如果你正在搭建本地知识库或者想让大模型能准确回答你私有文档里的问题RAG检索增强生成处理 Word 和 PDF 的能力就是第一个要跨过去的坎。很多人一上来就急着调模型参数、改检索策略结果发现效果不稳定——问题往往出在最前面文件根本没解析干净。RAG 处理文档不是简单把文件扔进去就行。Word 和 PDF 这类格式背后有复杂的结构标题层级、表格数据、图片注释、页眉页脚、特殊符号。如果解析阶段只抽出一堆乱序的文本块后面再好的检索模型也找不准答案。我一般会先看三件事这个工具或方案能不能保持原文的逻辑结构比如章节标题和下属段落是否还能关联上。对表格、公式、代码块这类特殊内容有没有单独处理直接当成普通文本抽出来数字和格式全乱套。切片chunking的时候是硬切还是按语义切硬切容易把一句话拆到两个片段里检索时根本搜不全。下面我会按实际落地顺序把文件解析、文本抽取、内容切片这三个环节的关键细节和踩坑点全拆清楚。如果你在搭知识库这套流程可以直接复用。2. 文件解析别让格式差异坑了你的数据质量2.1 Word 解析除了正文这些地方最容易被忽略Word 文档看起来是文字但背后有 XML 结构.docx或二进制格式.doc。直接用文本编辑器打开会看到大量标签和控制符。解析工具选不对轻则丢格式重则抽出一堆乱码。优先选支持结构识别的库比如用python-docx处理 .docxfrom docx import Document doc Document(your_file.docx) full_text [] for paragraph in doc.paragraphs: # 能拿到段落样式判断是否是标题 style paragraph.style.name text paragraph.text.strip() if style.startswith(Heading): full_text.append(f# {text}) # 标记标题层级 else: full_text.append(text)但要注意python-docx对老版 .doc 不支持如果环境里还有 .doc 文件需要先用 LibreOffice 或系统命令转成 .docx。更稳妥的做法是统一用pandoc做格式转换pandoc -s input.doc -o output.docx转换完再解析能避免很多编码问题。表格和图片不能直接跳过表格里的数据往往是关键信息比如产品参数、统计指标。解析时要判断表格位置把表格内容转成结构化标记比如[TABLE_START] | 产品 | 价格 | 库存 | |------|------|------| | A | 100 | 50 | [TABLE_END]这样后续切片时表格能作为一个整体处理不会拆散。图片虽然无法直接抽文本但至少要记录位置和标题否则检索到“如图1所示”时根本找不到对应内容。2.2 PDF 解析文本型 vs 扫描型策略完全不同PDF 分两种文本型能从里面直接复制文字和扫描型本质是图片。很多人卡在 PDF 解析就是因为没先判断类型。文本型 PDF优先用 pdfplumberpdfplumber能提取文字、表格、位置信息import pdfplumber with pdfplumber.open(doc.pdf) as pdf: for page in pdf.pages: text page.extract_text() tables page.extract_tables() # 记录文字在页面上的坐标后续切片可能用到 chars page.chars它的优势是能保持文字顺序对表格解析也比其他库准。但碰到复杂排版比如多栏、注释框时可能抽串行。这时候要结合pdfminer的布局分析手动调整抽取逻辑。扫描型 PDF先 OCR再按文本型处理如果pdfplumber抽不出文字说明是扫描件。用pytesseract做 OCRimport pytesseract from pdf2image import convert_from_path images convert_from_path(scanned.pdf) texts [] for img in images: text pytesseract.image_to_string(img, langchi_sim) # 中文需加语言包 texts.append(text)OCR 后的问题排版信息全丢章节标题和正文可能连成一段。识别准确率依赖图片质量数字、字母容易错。所以扫描 PDF 能避免就避免非要用的話OCR 后一定要人工抽查校正。2.3 解析阶段的质量检查清单文件解析完不要直接进下一步先跑一遍检查[ ] 文件编码是否统一特别是 Windows 和 macOS 换行符差异[ ] 特殊符号如 →、℃、①是否正常显示[ ] 表格数据是否完整数字和单位有没有拆散[ ] 标题层级是否保留比如 H1、H2 的标记[ ] 图片、图表是否有占位标记[ ] 页眉页脚、参考文献是否混入正文发现问题就回调解析逻辑不要指望后续环节能补救。3. 文本抽取干净的数据是检索准确的前提解析拿到了带结构的原始数据但里面有很多“噪音”多余的空格、换行符、页码标记、重复的页眉页脚。这些不断干净的文本直接切片会严重干扰检索效果。3.1 清洗步骤按顺序处理别跳步统一换行和空格多个连续换行符合并成一个全角空格转半角制表符转空格import re text re.sub(r\n, \n, text) # 合并多余换行 text re.sub(r[ \t], , text) # 合并空格移除页眉页脚和页码页眉页脚通常有固定模式比如“第 X 页”或文件名。用正则匹配移除# 移除类似 第1页 的页码 text re.sub(r第\s*\d\s*页, , text) # 移除连续的数字行可能是页码 text re.sub(r^\d$, , text, flagsre.MULTILINE)修复断行和断词PDF 解析经常在行末硬断词比如“人工智\n能”要拼回“人工智能”。针对中英文分别处理# 中文连接被断开的词语 text re.sub(r(\w)\n(\w), r\1\2, text) # 英文连接行末的连字符 text re.sub(r(\w)-\n(\w), r\1\2, text)标记保留区域代码块、公式、表格这些内容清洗时要跳过避免破坏结构。可以在解析时先包上特殊标记[CODE_START] def hello(): print(world) [CODE_END]清洗正则遇到这些标记就不处理。3.2 质量验证抽完的文本能不能直接读清洗后的人工检查方法随机选 3-5 段原文和抽取结果对比看是否有遗漏或错位。搜索文档中的特定术语比如产品型号、专业名词看是否完整保留。检查数字、日期、百分比等关键信息格式是否一致。如果发现大量乱码或丢内容退回解析阶段换工具重抽。清洗只能优化不能救根本性解析失败。4. 内容切片怎么切才能让检索更准这是 RAG 流程里最容易埋坑的一步。切片chunking的目标是让每个片段语义完整且长度适合模型处理。切不好会出现两种问题切太碎一个问题答案跨多个片段检索只返回一部分。切太大一个片段包含多个主题检索精度下降。4.1 切片策略按长度切 vs 按语义切按长度切固定大小最简单的方法设定一个 token 数比如 512超过就切from langchain.text_splitter import RecursiveCharacterTextSplitter splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50 # 重叠部分避免断句 ) chunks splitter.split_text(long_text)适合技术文档、手册这类结构规整的内容。但碰到对话记录、小说等段落长度差异大的材料可能切碎完整对话或场景。按语义切识别边界优先在章节标题、段落结尾、自然停顿处切分# 用句号、问号等作为切分点尽量保证句子完整 splitter RecursiveCharacterTextSplitter( separators[\n\n, 。, , , \n, , ], chunk_size500, chunk_overlap50 )更进阶的做法是用 NLP 模型判断语义边界比如 spaCy 的句子分割但对中文支持不一定稳定需要测试。4.2 重叠区设置不是越大越好重叠区overlap能防止切碎关键信息但设太大会导致存储翻倍相邻片段大量重复检索时相似片段扎堆影响排序一般设 chunk_size 的 10%-20% 足够。比如 500 的长度重叠 50-100。实际测试时拿几个典型问题在切片后的数据里搜看答案是否能完整覆盖。4.3 结构感知切片保持上下文关联对于手册、论文这类强结构文档切片时要保留层级信息。比如[CHUNK 1] # 第二章 安装步骤 ## 2.1 环境准备 需要 Python 3.8 和 pip。 [CHUNK 2] ## 2.1 环境准备续 建议使用虚拟环境运行python -m venv myenv。 ## 2.2 依赖安装 pip install -r requirements.txt这样即使“环境准备”被切成两段检索时也能通过标题关联找到全部内容。实现时可以在解析阶段给每个段落打上标题标记切片时优先在标记边界处切。4.4 切片质量检查清单切完片不要直接导入向量数据库先验证[ ] 随机抽 10 个片段读一遍是否通顺[ ] 找文档中的长表格是否被切散[ ] 搜索一个专业术语是否集中在某个片段[ ] 片段长度分布是否均匀突然出现极长或极短的要复查[ ] 重叠区是否避免了断句测试方法用切好的数据搭一个最简检索问几个你知道答案的问题看返回的片段是否包含完整信息。5. 整套流程的落地注意事项5.1 环境依赖别在版本兼容上踩坑Python 库版本冲突是常见问题。比如pdfplumber和pdfminer的兼容性或者pytesseract需要系统安装 Tesseract。建议用 conda 或虚拟环境隔离并固定版本pdfplumber0.10.3 python-docx1.1.0 pytesseract0.3.10 langchain0.1.0首次部署时先跑一个测试文件最好包含表格、图片、中英文确认全流程无误再处理批量数据。5.2 批量处理做好错误处理和日志处理成百上千个文件时难免有个别文件解析失败。不能因为一个文件卡住整个流程。需要单个文件解析加 try-catch失败时记录文件名和错误原因跳过继续。设置超时机制防止解析大文件时卡死。每处理完一个文件日志记录解析状态、切片数量、错误信息。import logging logging.basicConfig(filenameprocess.log, levellogging.INFO) for file in files: try: # 解析和切片流程 logging.info(fSuccess: {file}, chunks: {len(chunks)}) except Exception as e: logging.error(fFail: {file}, error: {str(e)})5.3 性能优化大文件怎么处理超过 100 页的 PDF 或 Word 文档解析和切片可能占大量内存。对策流式处理PDF 按页解析不要一次性加载全文。分批次切片切完一批就先保存或导入数据库清内存再处理下一批。限制并发批量处理时控制同时处理的文件数避免内存爆掉。5.4 后续衔接切片数据怎么喂给 RAG切片完成后每个片段要带上元数据供检索使用来源文件名原始页码或章节号片段在文档中的顺序 ID片段类型正文、表格、标题等这样检索到结果后不仅能返回文本还能定位到原文位置方便核对。6. 常见问题排查顺序实际落地时如果效果不理想按这个顺序查检索结果完全不对先检查解析阶段用原始文档对比解析出的文本看是否大量错位或丢内容。常见原因PDF 是多栏布局但解析器按单栏抽、Word 有复杂表格没识别。答案不完整重点查切片找一个问题手动在切片数据里搜看答案是否被切到多个片段。调整策略减小切片长度或增大重叠区。响应慢检查向量数据库的索引设置切片是否太大超过 1000 token 会影响速度。也可能是解析阶段耗时太长需要加缓存或预处理。特定类型内容公式、代码检索不到解析时是否做了特殊标记切片时是否保留了这些标记需要单独为代码、公式设计抽取和切片规则。最后提醒文档处理是 RAG 的基础设施一旦定下来改造成本很高。所以前期宁愿多花时间测试各种文档类型也不要急着上大规模数据。