Skip to content

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 / PlaywrightJS渲染后的内容性能较低需要安装浏览器驱动
Markdown原生读取完整保留格式标记无(如果不需要格式)最简单,结构化最好
Wordpython-docx段落、标题、部分格式复杂排版、宏支持.doc和.docx
CSV/ExcelPandas完整表格数据格式、公式每一行可以作为一个Document
JSONJSONLoader完整结构化数据支持jq语法提取特定字段
数据库SQLAlchemy / 专用ConnectorSQL查询结果关系信息每行作为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模型与向量化** — 分块后如何向量化
  • **向量数据库选型与对比** — 向量化后如何存储
  • <- 返回 **检索系统索引**

Knowledge4J — Java 知识库