PDF解析、表格提取与多模态文档理解

前言

在企业级 LLM 应用中,大部分知识存储在 PDF、Word 或扫描件中。如何准确地从这些非结构化文档中提取文本、表格和布局信息,是 RAG 系统成功的关键。本文将介绍现代文档智能处理的工具与策略。


文档处理的挑战

  1. 布局复杂性:多栏排版、页眉页脚、侧边栏干扰。
  2. 表格提取:跨行跨列、无框线表格、嵌套表格。
  3. 非文本元素:公式、流程图、印章、手写签名。
  4. 扫描件:需要高质量 OCR 和倾斜校正。

深度解析工具链:Marker vs Docling

在 2024 年,Marker 和 IBM 的 Docling 是开源界处理 PDF 的双雄。

1. 使用 Docling 进行工业级解析

Docling 采用了更轻量级的模型,解析速度比 Marker 快 10 倍,且对复杂表格的支持极佳。

from docling.datamodel.base_models import InputFormat
from docling.document_converter import DocumentConverter

def convert_with_docling(file_path: str):
    converter = DocumentConverter()
    result = converter.convert(file_path)
    
    # 导出为 Markdown
    markdown_content = result.document.export_to_markdown()
    
    # 导出为 JSON (包含完整的布局信息)
    json_content = result.document.export_to_dict()
    
    return markdown_content, json_content

# 示例
md, _ = convert_with_docling("complex_report.pdf")

2. 结构化切片 (Structural Chunking)

解析出 Markdown 后,我们需要根据文档的层级结构(H1, H2, H3)进行切片,而不是简单的字符数切片。

from langchain_text_splitters import MarkdownHeaderTextSplitter

def hierarchical_chunking(markdown_text: str):
    headers_to_split_on = [
        ("#", "Header 1"),
        ("##", "Header 2"),
        ("###", "Header 3"),
    ]
    
    splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
    chunks = splitter.split_text(markdown_text)
    
    # 每个 chunk 都会自动带上其所属的层级元数据
    # 例如: metadata={'Header 1': '第一章', 'Header 2': '1.1 节'}
    return chunks

核心进阶:多模态表格解析 (VLM-based)

对于扫描件中的复杂表格,传统的 OCR 往往会错行。使用 GPT-4o 或 Claude 3.5 Sonnet 直接解析图片是目前的 SOTA 方案。

import base64

def parse_table_with_vlm(image_path: str):
    with open(image_path, "rb") as f:
        base64_image = base64.b64encode(f.read()).decode('utf-8')

    prompt = """
    请分析图片中的表格,并将其转换为结构化的 JSON 格式。
    要求:
    1. 识别合并单元格。
    2. 保持数值的精确性。
    3. 输出格式为: {"tables": [{"headers": [], "rows": []}]}
    """
    # 调用 GPT-4o API...
    pass

---

#### 行业革命:ColPali (OCR-Free 检索)

传统的文档 RAG 流程是`PDF -> OCR -> 文本 -> 向量化 -> 检索`
**ColPali** 彻底颠覆了这一流程`PDF -> 图像块 -> 多模态向量化 -> 检索`

#### 为什么 ColPali 更好?
1.  **零丢失**不再受 OCR 识别错误的影响
2.  **视觉感知**模型能看到加粗的字体红色的警告复杂的流程图和表格排版
3.  **极速索引**直接对 PDF 页面截图进行编码省去了复杂的解析步骤

#### 架构
它基于 **PaliGemma** 多模态模型将图像块映射到与文本查询相同的向量空间检索时它能直接定位到 PDF 页面中包含答案的那个视觉区域”。

---

#### 布局分析 (Layout Analysis)

在处理长文档时识别出哪些是正文”,哪些是图表说明”,哪些是页码至关重要

- **工具**使用 **LayoutParser**  **Unstructured.io**
- **逻辑**
    - 移除页眉页脚防止检索到重复的干扰信息)。
    - 将图片和表格与其最近的标题关联起来
    - 识别出多栏排版的阅读顺序

---

#### 公式与学术文档处理 (Nougat)

对于包含大量数学公式的论文或技术手册普通的解析器会把公式变成乱码
- **方案**使用 Meta 开源的 **Nougat** 模型
- **特点**它是一个图像到序列的模型能直接将 PDF 页面图像翻译成高质量的 LaTeX 源码

---

#### 总结:文档处理的“金字塔”策略

1.  **底层纯文本 PDF** -> 使用 `PyMuPDF`  `pypdf` 快速提取
2.  **中层复杂排版/表格** -> 使用 **Docling**  **Marker** 转换为 Markdown
3.  **高层扫描件/学术文档** -> 使用 **Nougat**  **GPT-4o (VLM)**
4.  **顶层极致体验** -> 引入 **ColPali** 实现视觉增强检索

文档处理不再是简单的读字”,而是一场结合了计算机视觉CV和自然语言处理NLP的综合战役
    """
    
    # 调用多模态 LLM
    # response = llm.invoke([HumanMessage(content=[{"type": "text", "text": prompt}, {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}}])])
    # return response.content

表格提取策略

表格是文档中最难处理的部分。

1. 视觉解析法 (Vision-based)

将表格区域截图,发送给多模态模型(如 GPT-4o)。

def extract_table_with_vision(image_path: str):
    """使用多模态模型提取表格"""
    prompt = "请将图片中的表格转换为 Markdown 格式。确保保留所有行和列,不要遗漏数据。"
    # 调用 GPT-4o-mini 或 Claude 3.5 Sonnet
    response = vision_model.invoke(prompt, image_path)
    return response.content

2. 结构化解析法

使用 Table TransformerDeepSearch 识别表格边界和单元格。


多模态文档理解

对于极其复杂的文档,直接使用多模态 LLM 往往比先解析再处理效果更好。

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

def analyze_complex_document(image_paths: list[str]):
    """多模态文档分析"""
    llm = ChatOpenAI(model="gpt-4o")
    
    content = [
        {"type": "text", "text": "请分析这些文档页面,总结核心财务指标,并以表格形式输出。"}
    ]
    
    for img in image_paths:
        content.append({
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{img}"}
        })
    
    message = HumanMessage(content=content)
    return llm.invoke([message]).content

布局分析 (Layout Analysis)

在切片(Chunking)之前,识别文档的逻辑结构(标题、段落、列表)。

from unstructured.partition.pdf import partition_pdf

def smart_partitioning(pdf_path: str):
    """使用 Unstructured 进行布局感知分区"""
    elements = partition_pdf(
        filename=pdf_path,
        strategy="hi_res", # 使用模型进行高精度解析
        infer_table_structure=True,
        chunking_strategy="by_title", # 按标题切片
        max_characters=1000,
        combine_text_under_n_chars=200
    )
    
    return elements

# 遍历元素
for el in elements:
    if el.category == "Title":
        print(f"Heading: {el.text}")
    elif el.category == "Table":
        print(f"Table Data: {el.metadata.text_as_html}")

文档处理流水线 (Pipeline)

一个完整的企业级文档处理流程:

[上传 PDF] 
    │
    ▼
[预处理] (去噪、纠偏、转图片)
    │
    ▼
[布局分析] (识别标题、正文、表格区域)
    │       │
    │       └─→ [表格处理] (OCR + 结构化提取)
    │
    ▼
[文本提取] (Markdown 转换)
    │
    ▼
[语义切片] (基于布局信息的智能切片)
    │
    ▼
[向量化与存储] (写入向量数据库)

最佳实践

场景 推荐方案
标准论文/报告 Marker (Markdown 转换)
复杂报表/发票 多模态 LLM (GPT-4o/Claude)
海量历史文档 Unstructured + PaddleOCR
法律合同 布局分析 + 层次化切片

总结

文档智能处理是 RAG 系统的“脏活累活”,但也是决定系统上限的关键。通过组合使用传统的规则解析、现代的深度学习模型(如 Marker)以及强大的多模态 LLM,我们可以攻克绝大多数文档解析难题。


参考资源

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 LLM应用开发——文档智能处理实战 》

本文链接:http://localhost:3015/ai/%E6%96%87%E6%A1%A3%E6%99%BA%E8%83%BD%E5%A4%84%E7%90%86.html

本文最后一次更新为 天前,文章中的某些内容可能已过时!