Skip to content

文档解析与 OCR

本页说明上传文档如何变成可检索的文本层(content_text):四类文件各走什么抽取路径、扫描件与图片如何 OCR、第三方解析库的选型结论,以及存量数据的回填机制。文本层产出后的分块与索引见分块与索引机制

四类抽取路径

抽取入口统一在 app/services/document_service.pyextract_text,按扩展名/MIME 分派:

文件类型抽取路径关键机制代码位置
PDF(文字层)pypdf 文字层基线 + pymupdf find_tables 结构化线框表格输出 Markdown 管道表;表外文本与无表页逐字保持 pypdf 现链;顺带治好 pypdf 解不动 CMap 缺失 CJK 字体的乱码document_ocr.extract_pdf_text_structured
扫描件 PDF + 图片RapidOCR(rapidocr-onnxruntime)文字层优先:先用 pypdf 判定缺文字页(单页 < 10 字),仅缺文字页进 OCR;全局信号量限 1 并发;依赖缺失优雅降级为只抽文字层document_ocr.ocr_pdf_pages / ocr_image_file
XLSXopenpyxl 普通模式每工作表输出 ## 工作表:{名} 章节头 + Markdown 管道表(首个 ≥2 非空单元格的行作表头,无够格表头不硬造);单元格批注内联为「值(批注:…)」document_service._extract_text_from_xlsx
DOCXpython-docx按 body 子元素顺序遍历 w:p/w:tbl:段落与表格混排保持原文顺序;表格转 Markdown 管道表(旧口径只取段落、表格整个丢弃,已根修)document_service._extract_text_from_docx

统一产出形态

四条路径的产出都是带 Markdown 管道表的纯文本,落 Document.content_text。管道表形态与下游 row:: 表格行结构化索引(见分块与索引机制)对齐:章节头让行条目带工作表/章节前缀,列名进「列名: 值」拼接。extraction_status 三态:pending(待抽取/待 OCR)→ success / error

扫描件与图片 OCR 的工程纪律

  • 文字层优先:有文字层的页绝不进 OCR,只补缺文字页;OCR 文本按页序与文字层合并回 content_text
  • 内存峰值 = 一页:逐页渲染(200 DPI)、逐页识别、逐页释放,绝不整本进内存。
  • 全局信号量限 1 并发_ocr_semaphore):onnxruntime CPU 推理本身吃满核,后来的后台线程排队,并发只会把内存拱爆。
  • 优雅降级:pymupdf / rapidocr 全部 lazy import + 失败标记;缺依赖 = 只抽文字层 + warning 日志,绝不炸上传链路。

XLSX 批注的坑

openpyxl 的 read_only 模式拿不到 cell.comment(批注整个丢失),必须用普通模式加载并配合 closing 保证 workbook 句柄关闭(document_service.py:124 血泪实证)。

Docling 评估结论:不进

曾评估 Docling 作为统一解析后端(spike 代码保留,DOC_PARSER_BACKEND=docling 启用,默认关):依赖体积磁盘约 1.8GB、实测转换峰值工作集约 1.9GB,对桌面安装包与云端小机都不可接受。结论是不进;正解是 pymupdf find_tables 的表格结构化路线(顺带治好 CJK 乱码),即上面的现行方案。

存量回填:extract_md_tables_v1

XLSX/DOCX 抽取口径升级为管道表后,存量 success 文档的 content_text 还是旧格式(XLSX 空格拼接无表结构、DOCX 表格整个丢弃),需要一次性回填(document_service.backfill_md_table_documents):

  • 启动后约 120s 后台线程跑一次,完成标记 extract_md_tables_v1system_configs_MD_TABLES_MARKER_KEY),有 marker 即跳过,幂等
  • 逐文档重抽取,有差异才更新:文本不变不动库;更新后重走 FTS 重同步 + 向量重嵌;
  • 全部处理成功才落 marker,中途失败下次启动续跑。

桌面 sidecar 的 OCR 全家桶

桌面端把 OCR 依赖整体打进 PyInstaller sidecar(约 693MB):pymupdf、rapidocr-onnxruntime、onnxruntime、cv2 收进 spec。0.2.115 起 sidecar 含 Markdown 管道表抽取码,存量 xlsx/docx 首启自动回填(同上 marker 机制)。桌面与云端跑同一份抽取代码。

下一步

基于 AGPL-3.0 协议发布。