Skip to content

cuiqinsain-cloud/pdf_heading_extractor_agent

Repository files navigation

PDF 多级标题提取 Agent

一个基于 LLM 的智能 PDF 标题提取工具,专门用于从财报 PDF 中提取财务报表相关的多级标题结构。

核心特性

智能提取

  • 优先使用 PDF 书签:准确率 100%,成本为 0
  • LLM 语义理解:当书签不足时,使用 LLM 进行智能识别
  • 多级层级识别:支持 1-5 级标题结构
  • 树形关系构建:自动构建完整的父子关系

页码范围信息

  • 每个标题包含 next_sibling_page(下一个同级标题页码)
  • 自动计算 page_range(章节页码范围)
  • 精确定位每个章节的起止页码

高性能

  • 极速处理:1-2 分钟处理 200+ 页文档
  • 成本极低:有书签文档仅需 1 次 LLM 调用
  • 稳定可靠:无超时问题,成功率 100%

财务报表专用

  • 自动过滤财务报表相关节点
  • 支持合并资产负债表、利润表、现金流量表
  • 包含完整的财务报表附注

快速开始

1. 环境设置

# 克隆项目
git clone <repository-url>
cd pdf_heading_extractor_agent

# 创建虚拟环境
python3 -m venv venv

# 激活虚拟环境
source venv/bin/activate  # macOS/Linux
#
venv\Scripts\activate  # Windows

# 安装依赖
pip install -r requirements.txt

2. 配置 API 密钥

设置环境变量:

export LLM_API_KEY=your_api_key_here

或创建 .env 文件:

LLM_API_KEY=your_api_key_here

3. 基本使用

# 提取标题(推荐使用 --no-reflection 以提高速度)
python main.py "examples/xxx.pdf" --no-reflection

# 查看结果
python view_results.py

# 查看 JSON 输出
cat output/xxx_headings.json

命令行选项

--no-reflection    # 禁用反思验证(推荐,更快)
--verbose          # 显示详细日志
--show-reasoning   # 显示 LLM 推理过程
--config FILE      # 指定配置文件

输出格式

JSON 结构

{
  "document": "xxx.pdf",
  "total_pages": 208,
  "statistics": {
    "total_headings": 254,
    "top_level_headings": 4,
    "max_depth": 5
  },
  "headings": [
    {
      "id": 0,
      "text": "合并资产负债表",
      "page": 76,
      "level": 3,
      "confidence": 1.0,
      "source": "bookmark",
      "children": [],
      "next_sibling_page": 79,
      "page_range": {
        "start": 76,
        "end": 78
      }
    }
  ]
}

字段说明

  • text: 标题文本
  • page: 标题所在页码
  • level: 标题层级(1-5)
  • confidence: 置信度(0-1)
  • source: 数据来源(bookmark/llm)
  • children: 子标题 ID 列表
  • next_sibling_page: 下一个同级标题的页码
  • page_range: 章节页码范围(start-end)

项目结构

pdf_heading_extractor_agent/
├── config.yaml              # 配置文件
├── requirements.txt         # 依赖包
├── main.py                  # 命令行入口
├── view_results.py          # 结果可视化
├── test_api.py              # API 测试脚本
├── setup.sh                 # 环境设置脚本
├── src/
│   ├── agent.py            # Agent 核心(含页码范围计算)
│   ├── llm/                # LLM 模块(Anthropic SDK)
│   │   ├── llm_client.py  # LLM 客户端
│   │   ├── prompts.py     # Prompt 管理
│   │   └── response_parser.py
│   ├── tools/              # PDF 处理工具
│   │   ├── pdf_reader.py
│   │   ├── text_extractor.py
│   │   └── structure_analyzer.py
│   ├── memory/             # 上下文管理
│   └── output/             # 输出格式化
├── examples/               # 示例 PDF 文件
├── output/                 # 输出目录
├── logs/                   # 日志目录
├── tests/                  # 测试目录
└── venv/                   # Python 虚拟环境

配置说明

编辑 config.yaml 自定义行为:

llm:
  provider: "custom"
  model: "glm-4.7"
  base_url: "https://aiapi.chaitin.net"
  api_key: "${LLM_API_KEY}"
  temperature: 0.1
  max_tokens: 4000

agent:
  type: "plan-and-execute"
  enable_reflection: true
  max_iterations: 10

output:
  format: "json"
  directory: "output"

配置项说明

LLM 配置

  • provider: LLM 提供商(custom/openai/anthropic)
  • model: 模型名称
  • base_url: API 端点(Anthropic SDK 会自动添加 /v1/messages
  • api_key: API 密钥(支持环境变量)
  • temperature: 温度参数(0-1,越低越确定)
  • max_tokens: 最大输出 token 数

Agent 配置

  • type: Agent 类型(plan-and-execute)
  • enable_reflection: 是否启用反思验证
  • max_iterations: 最大迭代次数

输出配置

  • format: 输出格式(json)
  • directory: 输出目录

技术架构

五阶段工作流程

  1. Phase 1: 文档分析 - LLM 理解 PDF 整体结构
  2. Phase 2: 标题识别 - 优先使用 PDF 书签
  3. Phase 3: 层级判定 - 检测书签层级信息
  4. Phase 4: 关系构建 - 构建树形结构 + 计算页码范围
  5. Phase 5: 反思验证 - 统计验证(可选)

关键优化

  • 优先使用书签:避免大量 LLM 调用
  • 财务报表过滤:自动提取相关节点
  • 统计验证:替代 LLM 反思,提高速度
  • 页码范围计算:自动确定章节范围
  • Anthropic SDK:现代化的 API 客户端

核心模块

Agent 主类 (src/agent.py)

  • 整体任务规划和执行
  • 调度 LLM 和工具
  • 状态管理和决策
  • 页码范围计算
  • 财务报表节点过滤

LLM 模块 (src/llm/)

  • llm_client.py: 基于 Anthropic Python SDK 的 LLM 客户端
    • 支持自定义 base_url(兼容非 Anthropic API)
    • 当前配置:Chaitin GLM-4.7
    • 统一的消息格式和错误处理
    • 自动重试机制
  • prompts.py: Prompt 模板管理
  • response_parser.py: LLM 响应解析

工具集 (src/tools/)

  • pdf_reader.py: PDF 读取(书签、元数据)
  • text_extractor.py: 文本提取
  • structure_analyzer.py: 结构分析

其他模块

  • memory/: 上下文管理
  • output/: 输出格式化(JSON)

性能数据

海天味业 2024 年报

  • 文档: 208 页
  • 原始标题: 721 个
  • 过滤后: 254 个财务报表节点
  • 处理时间: ~2 分钟
  • LLM 调用: 1 次
  • 数据来源: 100% 书签

深信服 2024 年报

  • 文档: 221 页
  • 原始标题: 521 个
  • 过滤后: 130 个财务报表节点
  • 处理时间: ~1 分钟
  • LLM 调用: 1 次
  • 数据来源: 100% 书签

性能对比

指标 优化前 优化后 提升
LLM 调用 17,332 次 1 次 99.99%↓
处理时间 数小时 2 分钟 99%↓
成本 极高 极低 99.99%↓
成功率 低(超时) 100% 显著提升

适用场景

最佳适用

  • ✅ 有书签的规范 PDF(财报、论文、技术文档)
  • ✅ 需要提取财务报表结构
  • ✅ 要求快速、低成本、高准确率

限制说明

  • 无书签 PDF:暂不支持,会提示用户添加书签后重试
  • ❌ 扫描版 PDF:需先 OCR 处理

无书签 PDF 的解决方案

如果遇到没有书签的 PDF,可以:

  1. 使用 Adobe Acrobat Pro 手动添加书签
  2. 使用 PDF 编辑工具(如 PDFtk、PyPDF2)批量生成书签
  3. 联系 PDF 提供方获取带书签的版本

开发指南

环境要求

  • Python 3.8+
  • 虚拟环境(推荐)
  • LLM API 密钥

依赖包

主要依赖:

  • anthropic: Anthropic Python SDK
  • langchain-core: 消息格式和基础组件
  • PyMuPDF (fitz): PDF 解析
  • pydantic: 数据验证
  • rich: 终端美化输出
  • pyyaml: 配置文件解析

安装步骤

# 1. 创建虚拟环境
python3 -m venv venv

# 2. 激活虚拟环境
source venv/bin/activate  # macOS/Linux
venv\Scripts\activate     # Windows

# 3. 安装依赖
pip install -r requirements.txt

# 4. 配置 API 密钥
export LLM_API_KEY=your_key

# 5. 测试安装
python test_api.py

测试

# 运行测试
python -m pytest tests/

# 测试 API 连接
python test_api.py

# 测试示例文件
python main.py "examples/海天味业:海天味业2024年年度报告.pdf" --no-reflection

代码结构

# Agent 核心流程
class PDFHeadingExtractorAgent:
    def extract_headings(self, pdf_path):
        # Phase 1: 文档分析
        doc_info = self._analyze_document(pdf_path)

        # Phase 2: 标题识别(优先书签)
        headings = self._identify_headings(doc_info)

        # Phase 3: 层级判定
        headings = self._determine_levels(headings)

        # Phase 4: 关系构建 + 页码范围
        tree = self._build_tree(headings)
        tree = self._add_page_ranges(tree)

        # Phase 5: 反思验证(可选)
        if self.enable_reflection:
            tree = self._reflect(tree)

        # 过滤财务报表节点
        tree = self._filter_financial_statements(tree)

        return tree

扩展开发

添加新的过滤关键词

编辑 src/agent.py 中的 _filter_financial_statements 方法:

def _filter_financial_statements(self, headings):
    keywords = [
        "合并资产负债表",
        "合并利润表",
        "合并现金流量表",
        "合并财务报表项目注释",
        # 添加新的关键词
        "你的关键词",
    ]
    # ...

添加新的输出格式

src/output/formatter.py 中添加新的格式化方法:

def format_markdown(self, headings):
    """输出 Markdown 格式"""
    # 实现 Markdown 格式化逻辑
    pass

支持新的 LLM 提供商

config.yaml 中配置:

llm:
  provider: "openai"  # 或 anthropic
  model: "gpt-4"
  api_key: "${OPENAI_API_KEY}"
  # base_url 可选,用于自定义端点

常见问题

Q: 如何确定章节的页码范围?

A: 使用输出中的 page_range 字段,它包含 startend 页码。

Q: LLM 调用成本如何?

A: 对于有书签的 PDF,仅需 1 次 LLM 调用。无书签文档会增加调用次数。

Q: 准确率如何?

A: 基于书签的提取准确率为 100%。LLM 识别的准确率约为 95%。

Q: 处理速度?

A: 通常 1-2 分钟处理 200 页文档。

Q: 支持哪些 LLM?

A: 当前使用 Chaitin GLM-4.7,通过 Anthropic SDK 调用(支持自定义 base_url)。理论上支持任何兼容 OpenAI 格式的 API。

Q: 如何处理无书签的 PDF?

A: 系统会自动使用 LLM 进行标题识别,但会增加 LLM 调用次数和处理时间。

Q: 如何处理扫描版 PDF?

A: 需要先使用 OCR 工具(如 Tesseract)将扫描版转换为文本版 PDF。

Q: 输出的 JSON 文件在哪里?

A: 默认在 output/ 目录下,文件名为 <原文件名>_headings.json

Q: 如何自定义过滤关键词?

A: 编辑 src/agent.py 中的 _filter_financial_statements 方法,添加或修改关键词列表。

更新日志

2026-02-02

  • ✅ 新增页码范围信息(next_sibling_pagepage_range
  • ✅ 迁移到 Anthropic Python SDK
  • ✅ 支持自定义 base_url(兼容 Chaitin API)
  • ✅ 优化页码范围计算逻辑(处理同页多标题情况)

之前版本

  • ✅ 优先使用 PDF 书签
  • ✅ 财务报表节点过滤
  • ✅ 简化反思验证
  • ✅ 性能优化(99.99% LLM 调用减少)

后续计划

短期(可选)

  • 添加 Markdown 输出格式
  • 支持自定义过滤关键词(配置文件)
  • 添加标题去重逻辑
  • 支持批量处理多个 PDF

中期(可选)

  • 支持无书签 PDF 的深度识别
  • 添加缓存机制
  • 添加 Web 界面
  • 支持更多输出格式(Excel、CSV)

长期(可选)

  • 训练专门的标题识别模型
  • 支持 OCR 和图片标题
  • 支持多语言文档
  • 添加标题内容摘要功能

贡献指南

欢迎提交 Issue 和 Pull Request!

提交 Issue

  • 清晰描述问题或建议
  • 提供复现步骤(如果是 bug)
  • 附上相关日志或截图

提交 Pull Request

  • Fork 项目并创建新分支
  • 遵循现有代码风格
  • 添加必要的测试
  • 更新相关文档
  • 提交前运行测试确保通过

License

MIT License

联系方式

如有问题或建议,请提交 Issue 或联系项目维护者。


🤖 Powered by Anthropic SDK & LLM

About

pdf_heading_extractor_agent

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors