PdfRouter
A smart PDF parsing pipeline featuring dynamic routing, broken table stitching, and Human-in-the-Loop for high-quality RAG data extraction.
Install / Use
/learn @horizon123104/PdfRouterREADME
PdfRouter
🤖 一个为使用者降本增效的 PDF 到 Markdown 智能转换系统,专为 RAG 向量库优化设计
📖 目录
✨ 核心特性
| 特性 | 描述 | |------|------| | 🔍 智能探针扫描 | 乱码检测、跨页表格雷达、多栏排版识别 | | 🎯 动态路由决策 | 根据页面特征自动选择最优解析工具 (PyMuPDF/TextIn/Doc2X/Docling) | | ⚡ 多工具并行解析 | 自动降级兜底,确保解析成功率 | | 🪡 LLM 智能缝合 | 跨页表格/段落断裂自动修复,语义连贯性保证 | | 🏥 Human-in-the-Loop | 问题页占位符标记 + 离线修正 + 重新注入 | | ⭐ 质量评分系统 | 5 级评分确保输出质量,支持 RAG 优化 | | 📦 多格式导出 | Markdown/JSON/CSV 一键输出,元数据完整 |
🚀 快速开始
1. 安装依赖
# 克隆项目
git clone https://github.com/your-repo/PdfRouter.git
cd PdfRouter
# 创建虚拟环境
python -m venv venv
# 激活虚拟环境
venv\Scripts\activate # Windows
source venv/bin/activate # Linux/Mac
# 安装依赖
pip install -r requirements.txt
2. 配置 API 密钥
# 复制配置模板
cp .env.example .env
# 编辑 .env 文件,填入你的 API 密钥
最低配置要求:只需配置 LLM_API_KEY(支持阿里云 DashScope、OpenAI 等)
# .env 文件示例
LLM_API_KEY=sk-your-api-key
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
LLM_MODEL_NAME=qwen-plus
3. 运行处理
# 方式 1: 第 1 轮处理(自动检测问题页)
python main.py process your_document.pdf
# 方式 2: 一键处理(交互式等待修正)
python main.py process_with_human your_document.pdf
# 方式 3: 第 2 轮重新注入(修正完成后)
python main.py reintegrate --task-id task_20260303_131048
📋 完整工作流程
┌─────────────────────────────────────────────────────────────────┐
│ PdfRouter 流水线 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 输入:document.pdf │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 1: 探针扫描与切片 │ │
│ │ - 乱码检测、BBox 雷达、多栏排版检测 │ │
│ │ - 输出:PDF 切片 + 路由清单 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 2: 多工具并行解析 │ │
│ │ - PyMuPDF/TextIn/Doc2X/Docling 自动路由 │ │
│ │ - 输出:Markdown 碎片列表 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 4: 问题页标记(第 1 轮) │ │
│ │ - 插入占位符、导出问题包 │ │
│ │ - 输出:带占位符的数据 + correction_tasks/ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 3: LLM 智能缝合 + 质量评分 │ │
│ │ - 跨页表格缝合、段落修复 │ │
│ │ - LLM 裁判评分 (0-100) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ═══════════════════════════════════════════════════════════ │
│ 【第 1 轮完成,等待用户修正问题页】 │
│ ═══════════════════════════════════════════════════════════ │
│ │ │
│ ▼ │
│ 用户修正阶段 │
│ - 打开 correction_tasks/task_xxx/ │
│ - 修正问题页 PDF │
│ - 保存为 corrected/page_X_corrected.md │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 4.5: 修正内容重新注入 │ │
│ │ - 读取修正后的.md 文件 │ │
│ │ - 替换占位符 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 3: 二次缝合(完整语义) │ │
│ │ - 使用修正后的内容重新缝合 │ │
│ │ - 验证无占位符残留 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Phase 5: 最终清洗与导出 │ │
│ │ - Markdown 格式化 │ │
│ │ - 语义切分 (Chunk) │ │
│ │ - 质量评分、元数据注入 │ │
│ │ - 输出:final.md / chunks.json / metadata.json │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 完成!🎉 │
│ │
└─────────────────────────────────────────────────────────────────┘
⚙️ 配置说明
环境变量 (.env)
| 变量名 | 说明 | 必填 | 默认值 |
|--------|------|------|--------|
| LLM_API_KEY | 大模型 API 密钥 | ✅ | - |
| LLM_BASE_URL | API 基础 URL | ❌ | DashScope |
| LLM_MODEL_NAME | 模型名称 | ❌ | qwen-plus |
| TEXTIN_APP_ID | TextIn API ID | ❌ | - |
| TEXTIN_SECRET_CODE | TextIn 密钥 | ❌ | - |
| DOC2X_API_KEY | Doc2X API 密钥 | ❌ | - |
评分阈值 (config.py)
class ScoreThreshold:
PHASE3_EXCELLENT = 90.0 # 优秀,直接导出
PHASE3_GOOD = 85.0 # 良好,可接受
PHASE3_MEDIUM = 70.0 # 中等,建议复核
PHASE3_POOR = 70.0 # 差,必须修正
📊 输出文件
output/final.md
完整清洗后的 Markdown 文档,适合直接阅读
output/chunks.json
RAG 向量库格式,包含完整元数据:
{
"id": "chunk_0001",
"content": "...",
"metadata": {
"source_pages": [1, 2],
"parse_tool": "TextIn_API",
"human_corrected": false,
"chunk_quality_score": 95.5,
"heading_hierarchy": ["第一章", "1.1 节"],
"char_count": 1500,
"table_alert": false
}
}
output/metadata.json
处理报告,包含质量评分和统计信息
output/chunks.csv
简化版 CSV,适合快速预览
⭐ 质量评分系统
Phase 1: 健康度初筛 (0-100)
- 基于乱码页比例
-
80% 乱码率触发熔断
Phase 2: 解析质量评分 (0-100)
| 解析工具 | 得分 | |----------|------| | TextIn/Doc2X 成功 | 100 | | PyMuPDF 解析 | 85 | | API 降级 | 60 |
Phase 3: LLM 裁判评分 (0-100)
| 维度 | 权重 | |------|------| | 语义连贯性 | 30 | | 表格完整性 | 30 | | 格式规范性 | 20 | | 无噪声 | 20 |
Phase 5: Chunk 质量评分 (0-100)
| 维度 | 权重 | |------|------| | 内容完整性 | 40 | | 元数据丰富度 | 30 | | 格式规范性 | 30 |
🛠️ 高级用法
批量处理
# 处理整个文件夹的 PDF
for pdf in documents/*.pdf; do
python main.py process "$pdf"
done
查看任务状态
# 查看所有未完成的任务
ls correction_tasks/
# 查看任务详情
cat correction_tasks/task_xxx/correction_tasks.json
手动修正问题页
- 打开
correction_tasks/task_xxx/correction_tasks.json - 查看待修正页面清单
- 使用工具修正
fragments/中的 PDF - 保存为
corrected/page_X_corrected.md - 运行
python main.py reintegrate --task-id task_xxx
自定义评分阈值
# config.py
class ScoreThreshold:
PHASE3_EXCELLENT = 95.0 # 提高优秀标准
CHUNK_HIGH_QUALITY = 95.0 # 高质量 Chunk 标准
📁 项目结构
PdfRouter/
├── main.py # 主入口,CLI 命令
├── config.py # 配置管理
├── phase1_profiler_v2.py # Phase 1: 探针扫描
├── phase2_parsers.py # Phase 2: 并行解析
├── phase3_stitcher.py # Phase 3: 缝合 + 评分
├── phase4_human_ui.py # Phase 4: 问题页标记
├── phase4_5_reinject.py # Phase 4.5: 重新注入
├── phase5_exporter.py # Phase 5: 清洗导出
├── .env.example # 环境变量模板
├── .env # 环境变量配置(需自行创建)
├── requirements.txt # 依赖包列表
├── README.md # 项目说明
├── phase_docs/ # Phase 文档目录
└── temp_fragments/ # PDF 切片目录 (运行时生成)
└── correction_tasks/ # 问题包目录 (运行时生成)
└── output/ # 输出目录 (运行时生成)
❓ FAQ
Q: 没有 LLM API Key 可以使用吗?
A: 可以,系统会自动降级为物理拼接和规则评分。
Q: 如何添加新的解析工具?
A: 在 phase2_parsers.py 中添加新的解析函数,并更新路由决策树。
Q: 修正后质量仍然不理想怎么办?
A: 检查 output/metadata.json 中的低质量 Chunk,针对性优化。
Q: 支持哪些大模型?
A: 支持所有 OpenAI 兼容格式的 API,包括阿里云 DashScope、DeepSeek、OpenAI 等。
Q: 如何处理超大 PDF(>500 页)?
A: 建议分批处理,或调整 ProcessConfig.MAX_WORKERS 增加并发数。
📄 License
MIT License
🙏 致谢
感谢以下开源项目:
