借鉴 pdf-inspector 补齐原生 PDF 布局、语义与表格质量 - #6
Merged
Conversation
PDF 原生路径此前逐词输出且仅按 (top,left) 排序,字体元数据采集后即丢失, 导致双栏交错、段落碎片化、标题/列表/代码不可表达,页眉页脚与断词也原样泄漏。 - extract.py: 词级候选 + 行重建 + 双栏/跨栏阅读顺序,行分割与列聚类有界 - semantics.py: 文档级正文基准字号、标题/列表/代码块/段落语义、保守断词、 重复页眉页脚与页码过滤;代码围栏动态加长防逃逸 - analyze.py: 移除不可控 pdfplumber text/text 回退,改为 ≤500 词的有界本地 无边框表格启发式(3 行 ×2 列、数字占比 ≥40%) - extract.py: 拒绝一维伪表格;文本不同的嵌套表不再被去重吞掉; Unicode 非字符/代理项纳入编码质量检测 - merge.py: 表格/视觉区域按词中心点所有权,hybrid 元素按所属栏插入, 保持列阅读顺序;所有权裁决后再重建行 - models.py: NativeTextCandidate 携带 font_size/font_name 并贯通 wire - parser.py: _has_semantic_blocks 识别标题/列表/代码块,避免误报无内容 Tested: 全量 pytest 634 passed/9 skipped;ruff check/format、ty check、 git diff --check 全部通过;新增真实合成 PDF 反例(对齐段落不误判表格、 无边框数字表格可恢复)及双栏/跨栏/断词/页码/Unicode 边界测试 Scope-risk: 原生路由 PDF 的输出从逐词 TextBlock 变为语义块,依赖视觉的 hybrid/full-vision 页面输出不变;跨栏表格与视觉插入顺序为新启发式 Not-tested: 私有验收语料与真实多页复杂版式未在本次验证;pdf-inspector 预分类层与 OCR 回退路由暂未引入
路由耗时此前被两个因素主导:worker 冷启动时顶层 import pdfplumber (约 100 ms+),以及无文本扫描件仍走 pdfplumber 全量解析;同时 3 MiB 的 wire 估算上限使约 2000 词以上的真实文档(如 22 页商业 计划书)直接解析失败,尽管实际帧仅约为估算的四分之一。 - analyze.py: 快速分类层——用 pdfminer 的 xref/页树层轻量扫描内容流 操作符,全文无文本操作符时直接构造扫描件/空白页 facts,跳过 pdfplumber;pdfplumber 改为函数内惰性导入,冷启动不再加载 - analyze.py: wire 估算上限 3 MiB -> 8 MiB,与 native 协议内联上限对齐, 22 页真实语料从直接报错变为可完整解析 - analyze.py: 空白页(无文本无图像)保持原有 BLANK 路由,不被误判扫描件 - tests: 快速路径跳过 pdfplumber、旋转几何保留、页数上限、文本 PDF 回退、 空白页 BLANK、22 页中型文档 wire 放宽,共 5 个新测试 Tested: 全量 pytest 639 passed/9 skipped;ruff/format/ty 通过; 扫描件路由 129 ms -> 110 ms(新进程),热调用 4.7 ms(文本型的 1/37) Scope-risk: 快速分类仅命中全文无文本操作符的文档;任何含文本或无法 解码的流均回退原路径,行为与之前一致 Not-tested: worker 常驻复用(跨文档热调用 4.7 ms 的收益需架构级支持)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
对照 pdf-inspector(Firecrawl 的纯本地 PDF 分类/提取/转 Markdown 库)分析后,OpenDocs 原生 PDF 路径存在四类可落地差距:逐词输出导致段落碎片化与双栏交错、字体元数据采集后丢失导致无法表达标题/列表/代码、页眉页脚与断词原样泄漏、无边框表格与编码质量问题无本地兜底。
改动范围(均在私有
src/opendocs/parsers/pdf/内,无公共 API/依赖变更)extract.pysemantics.py(新增)analyze.pytext/text回退,改为 ≤500 词的有界本地无边框表格启发式(3 行 × 2 列、数字占比 ≥40%)merge.pymodels.pyNativeTextCandidate携带font_size/font_name并贯通 native worker wireparser.py_has_semantic_blocks识别标题/列表/代码块,避免误报 NoUsableContent验证
新增测试覆盖:真实合成 PDF 反例(对齐段落不误判表格、无边框数字表格可恢复)、双栏/跨栏/右栏视觉顺序、断词正反例、1–2 页页码过滤、Unicode 各平面边界、完整
PageFactswire 往返、列表 identity/ordinal、代码围栏与语义-only 文档判定。残余风险 / 未覆盖
TextBlock变为语义块;hybrid/full-vision 页面输出不变