Files
陈辅元 920c0b4a54 Update .gitignore and enhance README with new project plans
- Added `RAG_data/` to .gitignore to prevent tracking of specific data files.
- Expanded the README to include detailed plans for document type-specific chunk templates, improvements in document understanding, OCR accuracy, and layout detection design.
- Removed several outdated user manuals and documents to streamline the repository.
2026-07-21 11:02:58 +08:00

17 KiB
Raw Permalink Blame History

RAG-cut

自研 AI 助手知识库 Demo —— 以高质量文档切片为核心,召回为辅。

重建文档 ingestion / 切片流水线,针对现有 AFE 知识库的两类问题:

  1. 解析不足:Word / PDF / Excel 中的图片、表格无法有效提取
  2. 切分不佳:同一逻辑段落被硬切到不同 chunk,图片丢失或错位
项 说明
仓库 http://192.168.3.110:3000/AFE_RAG/RAG-CUT.git
需求文档 docx/自研搭建AI助手知识库.pdf
样例文档 自研RAG代表文档/

功能概览

能力 说明
多格式解析 pdf / doc / docx / ppt / pptx / ppsx / xlsx / csv / md / txt / html / json / xml / log / 常见图片
PDF 双引擎 MinerU(优先)+ PyMuPDF 回退;统一噪声过滤(页眉页脚、页码、目录 TOC)
四种切分模式 default · delimiter · parent_child · by_row(Demo 默认选结构感知)
语义切分 PDF / Word 在 default 下走 heading_layout_multimodal;超长章节按子标题/长度拆分(不产父片)
父子标识符 独立模式 parent_child:子片检索、父片上下文
表格切分 by_row:自动识别表头 / 说明行;Q&A 表可按行 1 片
Demo UI 原文预览 · 切片列表 · Markdown 预览 · 历史切片回看 · BM25 召回测试
CLI / API scripts/chunk_cli.py · /api/chunk · /api/results · /api/recall

未支持:.wps(可先转为 docx/pdf)。独立图片暂不做 OCR。


快速开始

1. 克隆与依赖

git clone http://192.168.3.110:3000/AFE_RAG/RAG-CUT.git
cd RAG-CUT

pip install -r requirements.txt

另需本机工具(按文档类型):

场景 依赖
.doc / .ppt 等 LibreOffice(soffice)或 Windows 上的 Microsoft Word/PowerPoint
PDF 高精度解析 MinerU(requirements.txt 已含 mineru[all])
MinerU 图内文字回填 本机 Tesseract(可选,见下方环境变量)

2. 启动 Demo

cd backend
python run.py

浏览器打开:http://127.0.0.1:8000(后端同时托管前端静态页)。

前后端分离开发时另开终端:

cd frontend
python run.py   # http://127.0.0.1:5173 ,API 默认指向 :8000

可选参数:--host 0.0.0.0 --port 8000 --no-reload(后端)· --port 5173(前端)

3. 运行测试

cd backend
python -m pytest tests/ -q

环境变量(PDF)

变量 默认 说明
RAG_CUT_PDF_ENGINE auto auto 优先 MinerU,失败回退 PyMuPDF;可强制 mineru / pymupdf
RAG_CUT_MINERU_CMD — MinerU 可执行路径(不在 PATH 时)
RAG_CUT_MINERU_API_URL — 复用已启动的 MinerU API,避免每次切分重复加载模型
RAG_CUT_MINERU_TIMEOUT 540 单次 MinerU 解析超时(秒)
RAG_CUT_MINERU_OCR 1 MinerU 图片无 OCR 时用 Tesseract 回填;0 关闭以加快切分

详见 docx/mineru-integration.md。

运行栈

类别 选型
Python 3.12+
Web FastAPI + Uvicorn
PDF MinerU / PyMuPDF + pdfplumber
Excel openpyxl
召回 内置 BM25(无向量库)

技术架构

上传文件
   │
   ▼
格式路由 (registry)
   │
   ▼
解析器 (parsers)  ──► 有序 Block 流(heading / paragraph / table / image …)
   │                  PDF:MinerU(优先)或 PyMuPDF → 噪声过滤 → 跨页表合并
   ▼
版面增强 (layout_meta) ──► 标题层级、图片/表格上下文、order_index
   │
   ▼
目录过滤 (filter_toc_blocks) ──► 全格式剔除「目录 / Contents」区
   │
   ▼
切分策略 (split_policy / pdf_strategy)
   │
   ▼
切分器 (splitters) ──► Block 分组(含父子切片关联)
   │
   ▼
渲染器 (renderer)  ──► Markdown Chunk + embedding_text / retrieval 标记

核心设计:先解析为不可拆分的 Block,再按结构切分。image / table 为原子块,不会被拆到不同 chunk。

目录结构

RAG-cut/
├── backend/
│   ├── rag_cut/
│   │   ├── models.py / pipeline.py / renderer.py / layout_meta.py
│   │   ├── split_policy.py / retrieval.py
│   │   ├── parsers/          # word / ppt / pdf / xlsx / text / image + MinerU
│   │   │   └── pdf/          # PyMuPDF 流水线、噪声过滤、跨页表合并
│   │   └── splitters/        # default / heading / pdf_semantic / by_row / delimiter / parent_child
│   ├── api/main.py           # FastAPI + 静态前端
│   ├── tests/
│   └── run.py
├── frontend/                 # Demo(index.html + css + js)
├── scripts/                  # chunk_cli · run_all_samples
├── storage/                  # uploads / assets / results(运行时,已 gitignore)
├── docx/                     # 需求 PDF、MinerU / 腾讯云切分说明
├── 自研RAG代表文档/           # 样例语料
└── requirements.txt

各格式处理

统一流水线:解析 → Block →(目录过滤)→ 切分 → Markdown Chunk。

扩展名 解析器 要点 推荐切分
.pdf PdfParser MinerU / PyMuPDF → 噪声过滤 → 跨页表合并 default(语义,max≈2600)
.doc .docx WordParser 转 PDF 后复用 PDF 流水线 同上
.ppt .pptx .ppsx PptParser 转 PDF;页码 ≈ 幻灯片序号 default
.xlsx .xls .csv SpreadsheetParser 检测 preamble / 表头 / 数据起始行 by_row(Demo 需手动选)
.md .html TextParser 按标题 / 段落拆块 default / delimiter / parent_child
.json TextParser 顶层 key / 数组元素 → code 块 default
.txt .xml .log TextParser 按空行分段 default
图片 ImageParser 整图 1 个 Block 整图 1 片

统一产出

项目 说明
Block 类型 heading / paragraph / table / image / list / code
Chunk Markdown + meta(heading / pages / embedding_text / retrieval / 可选 parent_chunk_id)
图片 storage/assets/{doc_id}/;JSON 内为 assets/{doc_id}/…
结果缓存 storage/results/{doc_id}.json(历史回看 / 召回)
中间产物 _conversion/(Office→PDF)、_mineru/(MinerU 输出)

Word / PPT 转 PDF

优先 LibreOffice(soffice --headless),Windows 可回退 Office COM。转换失败时 API 返回 500 并附带各后端错误信息。

Excel / CSV

detect_spreadsheet_layout 识别常见模板(说明行 + 表头 + 数据区);Q&A 评测表(列名含 query/answer 等)适合 rows_per_chunk=1。

.xls 依赖 openpyxl,老二进制格式可能失败,建议先转 xlsx。


PDF / Word 语义切分

.pdf / .doc / .docx 在 mode=default 时走 splitters/pdf_semantic.py(策略名:heading_layout_multimodal)。
Word 先转 PDF,再与 PDF 共用规则。自动策略下默认 max_chunk_size=2600、overlap=120;Demo 默认表单约为 2200 / 120。

流水线

PDF/Word
  │
  ├─ 解析:MinerU(优先)或 PyMuPDF → Block 流
  ├─ 噪声过滤:页眉/页脚/页码、文档目录、装饰小图
  ├─ 跨页表格合并
  ├─ 版面增强:标题层级、图片/表格上下文
  ├─ pdf_strategy:打标签(操作手册 vs 年报)
  └─ heading_layout_multimodal → Chunk

核心规则:heading_layout_multimodal

目标:同一逻辑小节(标题 + 正文 + 同节截图/表格)尽量落在同一 chunk。

步骤 行为
1. 再过滤噪声 跳过页码、running header、目录区、过小装饰图
2. 识别标题 解析器已标 heading,或正则/字号启发式补识别
3. 维护标题路径 标题栈记录章节层级
4. 按标题开新片 同级或更高级标题时 flush,开新 chunk
5. 图文同节 正文、image、table 跟在当前标题路径下
6. 超长二次切 超过 max_chunk_size 时按子标题/长度拆分;不单独保留父片

可识别标题形态示例:1. / 1.2.3 / A. / Chapter 2 / 一、 / (一);操作步骤 Step N … 作正文保留。封面 Logo 等无语义组标 retrieval=false。

文档类型标签:pdf_strategy

写入 split_config.pdf_chunk_strategy(Demo 策略面板可显示):

标签 典型特征 说明
pdf_feature_step_screenshot 步骤标题多、操作词多、截图密度高 操作手册型
pdf_outline_report 「年报/财务报表」等词,或文件名含 annual/report/年报 年报/报告型

当前两类切分算法相同,标签用于结果标注与后续策略分叉预留。


切分模式(全格式)

后端 4 种模式(SplitMode):default / delimiter / parent_child / by_row。

模式 设计意图 行为
default 非表格正文 PDF/Word 走语义切分;其他按标题/页/长度打包;image/table 不拆
delimiter 正文含可匹配标识符 按自定义标识符切开,再按长度二次切
parent_child 层级标识符 父标识符切父片,子标识符切子片;检索用子片
by_row 表格 每片 = 表头 + N 行 Markdown

Demo:始终显式传 mode(默认 default)。切 Excel/CSV 时请选手动「按行切分」。

自动策略(choose_split_config):仅当 API/Python 不传 mode/config 时生效——表格类选 by_row,PDF/PPT 等选 default 并覆盖 max_chunk_size。CLI 默认带 --mode default,不会走该自动选型。

父子标识符(mode=parent_child)

  1. 按 parent_delimiter 切父片;超长再按长度二次切
  2. 再按 child_delimiter(可选)切子片
  3. 父片:is_section_parent=true,retrieval=false
  4. 子片:is_sub_chunk=true,retrieval=true,parent_chunk_id 指向父片
参数 说明
parent_delimiter 必填;不写入切片正文
child_delimiter 可选;缺省则仅按子级最大长度拆
max_chunk_size 父级最大长度
child_max_size 子级最大长度(≤ 父级,硬上限 1500)
overlap 超长二次切分重叠

default 决策树(摘要)

.pdf / .doc / .docx  → heading_layout_multimodal
单 table 且含 rows   → 仅「不传 mode」时自动 by_row;显式 default 则走通用切分
有足够标题           → 标题大纲切;超长按子标题/长度拆(不产父片)
有 page、标题不足    → 按页;单页超限再按长度
否则                 → 按 max_chunk_size 打包

SplitConfig

参数 默认 说明
mode default 见上表
delimiter — delimiter 模式必填
parent_delimiter / child_delimiter — parent_child:父必填,子可选
max_chunk_size 1500 自动策略常覆盖为 1800–2600
child_max_size 512 parent_child 子级上限
overlap 150 超长二次切分重叠
header_row_start / header_row_end 1 表头行(1-based)
start_row 2 数据起始行
rows_per_chunk 1 每片数据行数

可解析扩展名(21 种):.pdf .doc .docx .ppt .pptx .ppsx .xlsx .xls .csv .md .txt .html .htm .json .xml .log .jpg .jpeg .png .bmp .gif。需求中的 .wps 尚未接入。


Demo 前端

三栏:原文 · 切片列表 · 切片预览;左侧配置切分模式与参数;下方可测召回。

区域 说明
上传 拖拽 / 选择文件
切分模式 默认(结构感知)/ 通用标识符 / 父子标识符 / 按行
策略面板 切分后回显 mode / max_size / overlap / PDF 策略
历史切片 列出 storage/results 中已切文档,可回看 / 删除
原文 PDF iframe / docx(mammoth)/ 文本 / 图片
切片列表 类型标签、父子标记、字符数
召回测试 query + top_k;retrieval=false 的片不进候选
API 面板 可折叠请求/响应 JSON

CLI / API

CLI

python scripts/chunk_cli.py "path/to/file.pdf" --preview 3
python scripts/chunk_cli.py "path/to/file.xlsx" --mode by_row --rows-per-chunk 5 -o storage/result.json
python scripts/chunk_cli.py "readme.md" --mode delimiter --delimiter "##"
python scripts/chunk_cli.py "readme.md" --mode parent_child \
  --parent-delimiter "##" --child-delimiter "###" \
  --max-chunk-size 2000 --child-max-size 512

批量样例(若有 data/):python scripts/run_all_samples.py

API

# 健康检查
curl http://127.0.0.1:8000/health

# 切分(不传 mode → 服务端自动策略)
curl -X POST http://127.0.0.1:8000/api/chunk -F "file=@./your.pdf"

# 切分(显式参数,与 Demo 一致)
curl -X POST http://127.0.0.1:8000/api/chunk \
  -F "file=@./your.xlsx" \
  -F "mode=by_row" \
  -F "rows_per_chunk=5"

# 历史结果
curl http://127.0.0.1:8000/api/results

# 召回(先切分拿到 doc_id)
curl -X POST http://127.0.0.1:8000/api/recall \
  -H "Content-Type: application/json" \
  -d '{"doc_id":"abcdef123456","query":"如何修改交易密码","top_k":5}'

主要端点:GET /health · POST /api/chunk · GET/DELETE /api/results… · POST /api/recall。

Python

from pathlib import Path
from rag_cut import chunk_document, SplitConfig, SplitMode
from rag_cut.retrieval import recall_chunks

# 不传 config → 自动策略
result = chunk_document(Path("doc.pdf"))

result = chunk_document(
    Path("doc.docx"),
    config=SplitConfig(mode=SplitMode.DEFAULT, max_chunk_size=2600, overlap=120),
)

hits, n = recall_chunks("login password", result.chunks, top_k=5)

将 backend/ 加入 PYTHONPATH,或通过 scripts/chunk_cli.py 调用。

输出字段(节选)

{
  "filename": "guide.docx",
  "doc_id": "61c2a152cd5e",
  "split_mode": "default",
  "split_config": {
    "mode": "default",
    "max_chunk_size": 2600,
    "pdf_chunk_strategy": "pdf_feature_step_screenshot",
    "chunk_strategy": "heading_layout_multimodal"
  },
  "block_count": 269,
  "chunk_count": 48,
  "chunks": [
    {
      "index": 0,
      "content": "# …\n\n![image3](assets/61c2a152cd5e/image3.png)",
      "char_count": 431,
      "block_types": ["heading", "paragraph", "image"],
      "meta": {
        "heading": "1 Getting Started",
        "pages": [3],
        "embedding_text": "…",
        "retrieval": true
      }
    }
  ],
  "assets_dir": "storage/assets/61c2a152cd5e"
}

期望效果对照

需求 状态
图片保留原文位置 ✅ PDF / Word / PPT(转 PDF)
表格提取为 Markdown ✅ PDF / Excel / CSV
Word 同标题内容同 chunk ✅ 语义切分
PDF 多栏阅读顺序 ✅ 双栏检测 + 行合并
页眉页脚 / 页码噪声过滤 ✅ MinerU 类型跳过 + 位置启发式
文档目录不进切片 ✅ 全格式 filter_toc_blocks
手册截图文字不混入正文 ✅ 大图区域过滤
父子切片(超长章节自动) ❌ 已从默认切分移除
父子标识符切分 ✅ parent_child
召回入参/出参可检视 ✅ /api/recall + Demo
历史切片回看 ✅ /api/results + Demo
wps ⏳ 未实现

后续计划

  • 按文档类型提供专用 Chunk 模板:在现有通用、按行和标识符切分的基础上,为论文、书籍、法律法规、演示文稿、问答和表格等文档提供结构感知的模板,并保留章节路径、页码、内容类型等元数据。
  • 参考 RAGFlow DeepDoc 完善文档理解层:在切分前统一完成 OCR、版面分析、表格结构识别、图片/图注关联和文档结构恢复,输出标准化 Block / Document Tree,供不同 Chunk 模板复用。
  • 完善 OCR 精准识别:增强扫描 PDF、文档内嵌图片和复杂背景图片的文字识别,补充方向校正、语言检测、置信度过滤与识别结果回填,并建立可量化的准确率评测集。
  • 引入 Layout Detection 设计:识别标题、正文、列表、表格、图片、图注、页眉和页脚等版面区域,结合坐标恢复多栏阅读顺序,并保证图片、表格与上下文在切片中的相对位置。
  • 向量召回(Embedding)
  • wps 格式支持

参考