02.1 - 文档加载与解析
定位: RAG Pipeline 的第一站——将各种原始文档转化为可处理的文本 面试高频度: ⭐⭐⭐ 考查方式: 各类文档加载方式、不同格式的处理策略
一、这是什么?为什么需要它?
是什么
文档加载与解析是将 PDF、网页、数据库、代码等各种格式的原始数据转化为结构化的纯文本,供后续分块和向量化使用。
原始数据(多格式、异构) --> 加载器 --> 标准 Document 对象
(page_content + metadata)为什么需要专门的加载?
LLM 只能理解"纯文本",但世界上的数据格式五花八门。
PDF:天然的排版格式、表格、图片需要提取
网页:HTML 标签、脚本、广告需要过滤
数据库:SQL 查询结果需要结构化
代码:注释和代码需要区分
音视频:需要转录没有正确的加载策略,后面的检索和生成就建立在"错位"的数据基础上。
二、原理拆解
2.1 文档加载器架构
+------------------------------------------------------------------+
| 文档加载器 Pipeline |
| |
| 输入源 加载器类型 标准化输出 |
| |
| +-------+ +------------+ +-------------------+ |
| | PDF |--->| PyMuPDF | | Document( | |
| +-------+ | PDFPlumber | | page_content= | |
| +------------+ | "纯文本内容", | |
| +-------+ +------------+ | metadata={ | |
| | 网页 |--->| BS4 | | source: URL, | |
| +-------+ | Selenium | | title: "...", | |
| +------------+ | page: 1, | |
| +-------+ +------------+ | ... | |
| | 数据库 |--->| SQL | | } | |
| +-------+ | Connector | +-------------------+ |
| +------------+ |
| +-------+ +------------+ |
| | 代码 |--->| Git Loader | |
| +-------+ +------------+ |
| |
| +-------+ +------------+ |
| | 音视频 |--->| Whisper | |
| +-------+ | 转录 | |
| +------------+ |
+------------------------------------------------------------------+2.2 各格式加载深度对比
| 格式 | 推荐加载器 | 保留内容 | 丢失内容 | 注意事项 |
|---|---|---|---|---|
| PDF(文本) | PyMuPDF (fitz) | 文字、段落、部分格式 | 复杂表格、图片 | 速度最快,适合文字型PDF |
| PDF(扫描件) | OCR (Tesseract/OCRmyPDF) | 经过OCR识别的文字 | 准确率依赖扫描质量 | 需要额外安装OCR引擎 |
| PDF(表格密集) | PDFPlumber / Camelot | 表格结构(部分) | 非表格内容排版 | 表格提取精度有限 |
| HTML 网页 | BS4 / Trafilatura | 正文文本 | 脚本、样式、导航 | Trafilatura 对新闻类网页最好 |
| 动态网页 | Selenium / Playwright | JS渲染后的内容 | 性能较低 | 需要安装浏览器驱动 |
| Markdown | 原生读取 | 完整保留格式标记 | 无(如果不需要格式) | 最简单,结构化最好 |
| Word | python-docx | 段落、标题、部分格式 | 复杂排版、宏 | 支持.doc和.docx |
| CSV/Excel | Pandas | 完整表格数据 | 格式、公式 | 每一行可以作为一个Document |
| JSON | JSONLoader | 完整结构化数据 | 无 | 支持jq语法提取特定字段 |
| 数据库 | SQLAlchemy / 专用Connector | SQL查询结果 | 关系信息 | 每行作为Document |
| 代码仓库 | GitLoader / 文件系统遍历 | 文件内容和结构 | 依赖关系 | 按文件/函数切分 |
| 音视频 | Whisper / 语音API | 转录文本 | 语气、非语言信息 | 成本高、延迟大 |
2.3 Metadata:被低估的关键
每个 Document 都携带 metadata(元数据),这在后续的检索中至关重要:
python
document = Document(
page_content="根据公司规定,年假为每年15个工作日...",
metadata={
"source": "员工手册.pdf", # 来源文档
"page": 5, # 页码
"section": "第三章 福利待遇", # 章节
"last_updated": "2025-03-01", # 更新时间
"author": "HR部门", # 作者
"category": "制度文档", # 分类
}
)Metadata 的三大用途:
1. 过滤检索:只检索特定分类/时间的文档
retriever = vectorstore.as_retriever(filter={"category": "制度文档"})
2. 来源显示:回答时引用具体的文档名和页面
"根据【员工手册.pdf】第5页规定,年假为..."
3. 权限控制:基于 metadata 中的权限标签控制访问
只有有权限的用户才能检索到特定文档2.4 常见文档格式的处理难点
PDF 的噩梦:
"为什么 PDF 提取的文字乱七八糟?"
-> PDF 是"排版格式",不是"文本格式"!
-> PDF 中的"文字块"按位置排列,而非阅读顺序
-> 多列布局、页眉页脚、表格会严重干扰提取质量
解决方案:
1. 文本PDF -> PyMuPDF(速度快,质量好)
2. 扫描PDF -> OCR(需要额外处理)
3. 复杂排版 -> Marker / LlamaParse(AI辅助解析)三、图解全景
企业级文档加载架构
+------------------------------------------------------------------+
| 企业级文档加载系统 |
| |
| 文档源 加载集群 |
| +--------+ |
| | 文件服务器 |---+ |
| | SMB/NFS | | +------------+ +-------------------+ |
| +----------+ +-->| PDF Loader |--->| Document Queue | |
| +------------+ | (预处理/校验) | |
| +----------+ +------------+ +--------+----------+ |
| | 内部网站 |---+-->| Web Loader |---> | |
| | Confluence| | +------------+ | |
| +----------+ | | |
| | +------------+ | |
| +----------+ | | 数据库 | | |
| | 数据库 |---+-->| Loader |-----------+ |
| | PostgreSQL| | +------------+ | |
| +----------+ | | |
| | +------------+ | |
| +----------+ | | API Loader | | |
| | 外部API |---+-->| (REST) |-----------+ |
| | 第三方 | +------------+ | |
| +----------+ | |
| v |
| +--------------------+ +--------------------+ |
| | 文档预处理管道 | | 质量控制 | |
| | 去重 -> 清洗 -> 校验 | | 空文档检测 -> 重试 | |
| +--------------------+ +--------------------+ |
| | |
| v |
| +----------------+ |
| | Document Store | <-- 给分块模块使用 |
| | (统一格式) | |
| +----------------+ |
+------------------------------------------------------------------+四、实战验证
4.1 Python 多源加载实战
python
# 安装:pip install langchain-community pymupdf bs4 python-docx
from langchain_community.document_loaders import (
PyMuPDFLoader,
WebBaseLoader,
TextLoader,
CSVLoader,
PythonLoader,
UnstructuredWordDocumentLoader,
)
# === PDF 加载(推荐 PyMuPDF,速度最快) ===
pdf_loader = PyMuPDFLoader("documents/员工手册.pdf")
pdf_docs = pdf_loader.load() # 每页一个 Document
print(f"PDF 页数: {len(pdf_docs)}")
print(f"第一页 metadata: {pdf_docs[0].metadata}")
# === 网页加载(Trafilatura 模式,自动提取正文) ===
web_loader = WebBaseLoader(
web_paths=["https://example.com/policy"],
bs_kwargs=dict(
parse_only=bs4.SoupStrainer("article") # 只提取 article 标签
)
)
web_docs = web_loader.load()
# === Markdown 加载(最简单的格式) ===
md_loader = TextLoader("docs/README.md")
md_docs = md_loader.load()
# === CSV 加载(每行一个 Document) ===
csv_loader = CSVLoader("data/products.csv")
csv_docs = csv_loader.load()
# === 自定义 Metadata 注入 ===
from langchain_community.document_loaders import DirectoryLoader
# 批量加载目录中的所有 PDF
dir_loader = DirectoryLoader(
path="./documents",
glob="**/*.pdf",
loader_cls=PyMuPDFLoader,
show_progress=True,
loader_kwargs={}
)
all_docs = dir_loader.load()4.2 PDF 加载质量测试
bash
# PDF 加载质量基准测试
# 对比不同 PDF 加载器的速度和提取质量
# 安装测试工具
pip install pymupdf pdfplumber pdfminer.six
# 测试脚本思路:
# 1. 准备一个已知内容的 PDF 文件
# 2. 用不同加载器提取文本
# 3. 比较提取的文字完整度和准确度
# 典型基准结果(100页文本型PDF):
# PyMuPDF: 0.8s, 98% 文字保留率
# PDFPlumber: 2.5s, 97% 文字保留率(表格稍好)
# PDFMiner: 3.2s, 96% 文字保留率
# 对于扫描型PDF,需要 OCR:
# OCRmyPDF + Tesseract: 30-60s/页, 85-95% 准确率五、面试视角
| 问题 | 答案要点 |
|---|---|
| PDF 加载为什么这么难? | PDF 本质是"排版格式"不是"文本格式"——文字块按坐标排列而非阅读顺序。多列、表格、页眉页脚都会打乱提取顺序 |
| 文本 PDF vs 扫描 PDF 的处理区别? | 文本PDF可以直接提取文字(PyMuPDF);扫描PDF需要 OCR 识别(Tesseract/OCRmyPDF),速度慢、准确率依赖扫描质量 |
| Metadata 在 RAG 中的作用? | 1) 过滤检索(只搜某类文档);2) 来源追溯(显示具体出处);3) 权限控制(基于标签做访问控制) |
| 大文档如何分批加载? | 1) 按章节拆分(有结构文档);2) 按页拆分(PDF);3) 按行拆分(数据库/CSV);4) 递归分割(无结构长文本) |
| 网页加载需要注意什么? | 1) 识别并移除导航/广告/脚本;2) 动态渲染(Selenium/Playwright);3) 反爬虫策略(频率限制、User-Agent);4) 内容更新监测 |
📚 相关链接
- **文本分块策略** — 加载完毕后如何切分文档
- **Embedding模型与向量化** — 分块后如何向量化
- **向量数据库选型与对比** — 向量化后如何存储
- <- 返回 **检索系统索引**