977bfb832b
- README 更新项目定位为实验室共用清洗库,明确 data/ 职责与 profile 复用原则; - 新增 ClinDB-ReviewBench(论文清洗)5 份 Markdown 问题审计(scratch), 并确定第一版清洗范围:9 类确定性规则(reference/CLINDB_REVIEWBENCH_CLEANING_SCOPE.md); - 45 份政务文档审计重命名为 GOVDOC_SAAS_CLEANING_SCOPE.md,截去第 6 节起的 实施建议,只保留问题报告(396 行); - 收录 2026-08-20 生态调研草稿(scratch)。
493 lines
24 KiB
Markdown
493 lines
24 KiB
Markdown
# Markdown 清洗生态调研与通用架构建议
|
||
|
||
> 状态:调研草稿,尚未批准为项目设计。
|
||
>
|
||
> 调研日期:2026-08-20。
|
||
>
|
||
> 更新方式:候选工具、许可证、实测结果或项目范围变化时更新;形成实施决定后转写为下一编号 design。
|
||
|
||
## 1. 结论先行
|
||
|
||
这个项目不应该重新实现一个“正则表达式合集”,也不应该把 Prettier、mdformat、Unstructured 或某个
|
||
PDF→Markdown 模型直接包装成最终产品。
|
||
|
||
现有工具各自只解决问题的一层:
|
||
|
||
- Markdown parser/formatter 能统一语法,但无法知道一句话是不是模型幻觉;
|
||
- HTML 容错解析器能补齐标签,但无法保证补出的表格在业务上正确;
|
||
- PDF/DOCX 提取器能回源重建,但仍可能 OCR 错误或生成幻觉;
|
||
- PII 工具能提供候选实体,但无法自动决定跨文档伪名是否应该一致;
|
||
- 文本质量过滤器能发现重复和低熵,却常以“整篇丢弃”为目标,不适合忠实修复文档。
|
||
|
||
因此建议把 `govdoc-md-cleaner` 定位为:
|
||
|
||
> **面向多项目的、可审计的文档规范化与派生框架。Markdown 是主要输入输出格式,但核心对象是带来源、
|
||
> 结构、置信度和问题记录的文档,而不是一串待正则替换的文本。**
|
||
|
||
推荐的技术组合是:
|
||
|
||
| 层 | 首选候选 | 在本项目中的角色 |
|
||
|---|---|---|
|
||
| 核心语言 | Python | 与文档解析、OCR、隐私工具及现有下游生态衔接 |
|
||
| Markdown 解析 | `markdown-it-py` + GFM 插件 | CommonMark/GFM 结构识别、块级行号映射;不负责语义修复 |
|
||
| Markdown 输出 | 自有受控 renderer;`mdformat` 只作可选格式化后端 | 保证 profile 输出稳定,避免 formatter 越权改原文 |
|
||
| 损坏 HTML | `html5lib`,必要时配合 `lxml` tree builder | 按浏览器规则恢复 DOM;恢复动作必须进入审计 |
|
||
| 回源提取 | Docling 作为默认候选 adapter | PDF/DOCX/图片转结构化文档,保留页码、bbox 和 provenance |
|
||
| 编码异常 | `ftfy` 作为候选建议器 | 识别/建议 mojibake 修复;默认不静默应用到法律文本 |
|
||
| 隐私 | Presidio 可选 adapter + 中文自定义 recognizer | 检测、确定性伪名和图片脱敏;不是默认核心依赖 |
|
||
| 重复/退化 | 自有 detector,参考 DataTrove 指标 | 长行、低熵、重复字符/n-gram、语言突变和固定幻觉模板 |
|
||
| 多格式转换 | Pandoc 可选 adapter/对照 oracle | DOCX/HTML/Markdown 转换与 AST filter;不作为忠实度权威 |
|
||
|
||
`remark/unified` 是 Markdown 原生变换能力最完整的候选,但它会引入 Node.js/TypeScript 运行时;本项目的
|
||
回源、OCR、中文隐私和下游环境更偏 Python,所以建议把 remark 作为设计参照和交叉验证器,而不是第一版核心。
|
||
|
||
这不是最终技术选型。下一步应以本报告为输入编写 design,并用小型 spike 验证关键假设后再批准依赖。
|
||
|
||
## 2. 审计告诉我们的真实问题
|
||
|
||
本报告以 [45 份 Markdown 清洗审计](../reference/MARKDOWN_CLEANING_AUDIT.md) 为本地事实来源。
|
||
审计发现的不是单一格式问题,而是至少五个不同层次的问题:
|
||
|
||
1. **字节与字符层**:替换字符、私用区字符、NBSP、零宽字符、多余转义;
|
||
2. **Markdown/HTML 语法层**:标题扁平、悬空链接、损坏 HTML/GFM 表格、极端长行;
|
||
3. **文档结构层**:段落断裂、阅读顺序错误、页眉页脚混入、图片与表格丢失;
|
||
4. **内容可信度层**:模型幻觉、退化重复、OCR 语义错误、无法凭 Markdown 恢复的缺失内容;
|
||
5. **用途与合规层**:对比、RAG、受控忠实版、公开脱敏版对内容保留规则不同。
|
||
|
||
其中两个结论直接改变技术路线。
|
||
|
||
第一,Markdown parser 解析成功不能作为质量通过条件。CommonMark 明确规定任意字符序列都是合法文档,
|
||
因此绝大多数“脏 Markdown”仍然可以无报错解析;我们必须建立额外的结构、内容和来源验证器
|
||
([CommonMark 0.31.2](https://spec.commonmark.org/0.31.2/))。
|
||
|
||
第二,GFM parser 接受的表格也未必满足我们的忠实度要求。GFM 对正文行缺列会补空单元格,多出的单元格
|
||
会被忽略;这对法律和金额表格可能造成静默丢失,所以项目必须在 parser 之上做严格矩形网格验证
|
||
([GFM 表格规范](https://github.github.io/gfm/#tables-extension-))。
|
||
|
||
## 3. 为什么成熟 formatter 不能直接解决
|
||
|
||
### 3.1 Prettier、mdformat
|
||
|
||
[Prettier](https://prettier.io/docs/) 和 [mdformat](https://mdformat.readthedocs.io/) 都是成熟的确定性格式化器。
|
||
它们通过“解析后重新打印”统一标题、列表、换行等书写风格。mdformat 使用 `markdown-it-py`,并提供语法扩展
|
||
和代码围栏 formatter 插件([mdformat 插件文档](https://mdformat.readthedocs.io/en/stable/users/plugins.html))。
|
||
|
||
适合:
|
||
|
||
- 已经确认语义正确的 Markdown;
|
||
- 统一输出风格;
|
||
- 检查幂等性;
|
||
- Wiki、README 和开发者手写文档。
|
||
|
||
不适合直接处理本审计数据:
|
||
|
||
- formatter 不知道 `The quick brown fox...` 是幻觉;
|
||
- 重新打印会扩大 diff,使逐项审计更困难;
|
||
- 对 raw HTML、损坏表格和未知扩展可能规范化或转义;
|
||
- 它无法从缺失图片引用恢复资产,也无法回到 PDF bbox。
|
||
|
||
建议:只在结构和内容已经通过验证的节点上使用,或作为最终输出的可选 profile;永不直接覆盖原输入。
|
||
|
||
### 3.2 markdownlint、remark-lint
|
||
|
||
[remark-lint](https://github.com/remarkjs/remark-lint) 有约 70 条可组合规则,能检查标题跳级、硬换行、
|
||
链接语法和行长等;markdownlint 也有成熟的规则集。这些工具适合开发文档质量门禁,但其规则主要面向
|
||
作者书写风格,不认识 PDF 页、OCR 置信度、表格合并单元格或业务实体。
|
||
|
||
建议:用作本仓 Wiki/README 的 CI,或复用部分规则思想;不作为业务文档清洗引擎。
|
||
|
||
## 4. Markdown AST 候选
|
||
|
||
### 4.1 `remark` / `unified`
|
||
|
||
[remark](https://github.com/remarkjs/remark) 提供 Markdown→mdast→Markdown 的完整插件流水线;
|
||
[mdast](https://github.com/syntax-tree/mdast) 对 CommonMark、GFM 表格、图片、raw HTML 等节点有稳定模型,
|
||
unist 生态还提供位置、source extraction、遍历、lint 和 vfile 消息。它是本次调研中最完整的
|
||
Markdown-native 变换生态。
|
||
|
||
优点:
|
||
|
||
- parser、AST、visitor、transformer、lint、stringifier 是同一生态;
|
||
- 节点通常带行、列、offset,适合生成诊断;
|
||
- GFM、frontmatter、数学、directives 等扩展成熟;
|
||
- TypeScript 类型和插件边界清晰。
|
||
|
||
代价:
|
||
|
||
- 核心运行时是 Node.js/ESM;
|
||
- PDF/DOCX/OCR、中文文本处理和当前下游大多仍在 Python;
|
||
- 双运行时会增加部署、版本锁定和跨语言 IR 的维护成本。
|
||
|
||
判断:如果项目只清洗开发者 Markdown,remark 是首选;对当前“文档回源 + 多项目 profile”目标,第一版
|
||
不建议为它引入第二套运行时。可把它用于 conformance 对照或以后提供 TypeScript 前端。
|
||
|
||
### 4.2 `markdown-it-py` + `mdformat`
|
||
|
||
[markdown-it-py](https://markdown-it-py.readthedocs.io/en/latest/) 遵循 CommonMark,支持插件、自定义规则和
|
||
GFM 相关扩展;Token 的 `map` 字段提供块级起止行号
|
||
([Token 文档](https://markdown-it-py.readthedocs.io/en/v4.2.0/_modules/markdown_it/token.html))。它活跃、
|
||
MIT、Python 原生,适合本项目第一版。
|
||
|
||
局限也需要明确:
|
||
|
||
- 它主要是 parser/HTML renderer,不是完整的 Markdown transformation framework;
|
||
- 行号映射主要在块级,细粒度字符 offset 和跨回源 bbox 仍需我们维护;
|
||
- raw HTML 会成为特殊 token,表格恢复仍要交给 HTML parser;
|
||
- CommonMark 合法不等于文档内容可信。
|
||
|
||
建议:把它用于“识别现有 Markdown 的结构和边界”,再投影到项目自己的 Document IR;不要直接在 token
|
||
列表上堆满业务规则。`mdformat` 可为确认安全的 AST 提供稳定输出,但 renderer 行为必须通过回归样本冻结。
|
||
|
||
### 4.3 Pandoc
|
||
|
||
[Pandoc](https://pandoc.org/MANUAL.html) 使用 reader→AST→writer 架构,Lua/JSON filter 可以按顺序变换 AST
|
||
([Pandoc filter 文档](https://pandoc.org/filters.html))。它的多格式覆盖和长期稳定性很强。
|
||
|
||
适合:
|
||
|
||
- DOCX、HTML、Markdown 等格式导入导出;
|
||
- 做第二实现的转换对照;
|
||
- 用户明确接受 Pandoc 方言规范化的 profile。
|
||
|
||
不适合担任忠实版核心:
|
||
|
||
- reader/writer round-trip 会改变原始 Markdown 表达;
|
||
- Pandoc AST 不是为逐字符审计和 PDF bbox 设计的;
|
||
- 外部二进制与 [GPL-2.0 许可证](https://github.com/jgm/pandoc/blob/main/COPYING.md)需要独立部署评估;
|
||
- 不能修复不存在于输入中的图片和内容。
|
||
|
||
判断:可选 adapter,不作为唯一内部表示。
|
||
|
||
### 4.4 Marko、Mistune 等 Python parser
|
||
|
||
[Marko](https://marko-py.readthedocs.io/en/latest/) 提供纯 Python CommonMark AST 和扩展机制,Mistune 偏向
|
||
高速渲染。它们都能用于特定场景,但相较 `markdown-it-py`,当前项目更看重现成插件、维护活跃度、
|
||
生态采用以及块级 source map。第一轮 spike 不必同时维护三个 Python parser。
|
||
|
||
## 5. 损坏 HTML 与表格恢复
|
||
|
||
[html5lib](https://html5lib.readthedocs.io/en/stable/) 按 WHATWG 浏览器解析算法处理可能损坏的 HTML,
|
||
可以输出 ElementTree 或使用 lxml tree builder;[lxml 的 HTML5 接口](https://lxml.de/4.5/apidoc/lxml.html.html5parser.html)
|
||
也支持 fragment 解析。
|
||
|
||
推荐流程:
|
||
|
||
1. 从 Markdown AST 中只取 raw HTML fragment,不把整篇 Markdown 当 HTML;
|
||
2. 保存原 fragment、source span 和哈希;
|
||
3. 使用 html5lib 容错解析并收集 parser errors;
|
||
4. 构建显式二维 table grid,展开 `rowspan`/`colspan`;
|
||
5. 校验每个输出 cell 都能映射到原节点或 source 区域;
|
||
6. 仅无合并单元格的简单矩形表格输出 GFM;
|
||
7. 复杂表格输出规范 HTML,并并行保留 JSON grid;
|
||
8. parser 自动补齐的标签只说明“语法可恢复”,不能自动标为“语义已验证”。
|
||
|
||
不能采用旧实现那样用正则匹配 `<table>...</table>`:审计已经证明大量闭合标签缺失,正则既无法正确嵌套,
|
||
也会把后续正文吞入表格。
|
||
|
||
## 6. PDF、DOCX 和图片回源候选
|
||
|
||
### 6.1 Docling:默认候选 adapter
|
||
|
||
[Docling](https://docling.org/) 支持 PDF、Office、HTML、Markdown、图片等格式,能输出 Markdown 和结构化
|
||
`DoclingDocument`;后者包含表格、层级、bbox 和 provenance
|
||
([DoclingDocument 说明](https://github.com/docling-project/docling/blob/main/docs/concepts/docling_document.md))。
|
||
项目是 Python/MIT,OCR 后端可插拔。
|
||
|
||
它与审计需求最匹配的不是“Markdown 看起来更漂亮”,而是能先保存结构化、带位置的中间结果,再由我们
|
||
生成 fidelity/profile 输出。因此建议把 Docling 作为第一批回源 adapter 的基准候选。
|
||
|
||
但它仍不能成为无条件真值:OCR、阅读顺序和表格模型都会出错,VLM 路径也可能生成内容。必须在 001、003
|
||
有原始 PDF 的受控样本上验证字符、数字、表格和图片,不以官方 demo 或总准确率代替本项目测试。
|
||
|
||
### 6.2 Unstructured
|
||
|
||
[Unstructured partition](https://docs.unstructured.io/open-source/core-functionality/partitioning) 能把多种格式切成
|
||
`Title`、`NarrativeText`、`ListItem`、`Table` 等元素,一些格式保留页码、坐标和 table HTML,适合作为
|
||
另一种 source adapter 或元素分类对照。
|
||
|
||
其 `cleaners` 不能整体照搬。例如官方实现中的 `clean_dashes` 会替换连字符,`clean_bullets` 会删除项目符号,
|
||
`clean_non_ascii_chars` 会丢弃非 ASCII 字符;这对中文法律文本、项目编号和列表结构明显过于激进
|
||
([cleaners 源码](https://github.com/Unstructured-IO/unstructured/blob/main/unstructured/cleaners/core.py))。
|
||
|
||
判断:可评估 partition/metadata;不采用通用 `clean(...)` 作为默认清洗策略。
|
||
|
||
### 6.3 MinerU、Marker、MarkItDown
|
||
|
||
- [MinerU](https://github.com/opendatalab/MinerU) 支持 PDF/Office/图片到 Markdown、JSON 和图片资产,能力覆盖广,
|
||
但本地审计已经展示某些现有解析产物中的幻觉与退化;此外它当前是 Apache-2.0 加附加商业与署名条款,
|
||
不是无条件的标准 Apache-2.0([MinerU 许可证](https://github.com/opendatalab/MinerU/blob/master/LICENSE.md))。
|
||
- [Marker](https://github.com/datalab-to/marker) 能输出 Markdown、JSON、HTML 和 chunks,也暴露页/块结构;代码为
|
||
Apache-2.0,但模型权重采用带商业门槛和用途限制的修改版 OpenRAIL-M,必须把代码与模型许可分开审查
|
||
([Marker 模型许可证](https://github.com/datalab-to/marker/blob/master/MODEL_LICENSE))。
|
||
- [Microsoft MarkItDown](https://github.com/microsoft/markitdown) 是轻量多格式→Markdown 工具,适合低成本文本提取,
|
||
但它的目标不是页级 provenance、复杂表格忠实恢复或审计账本。
|
||
|
||
判断:三者都可成为 benchmark adapter,不应把任何一个输出直接标为 fidelity 真值。第一轮优先比较
|
||
Docling、MinerU 和 Marker 的结构化 JSON,而不是只比较最终 Markdown 的视觉效果。
|
||
|
||
## 7. 编码、内容退化和隐私工具
|
||
|
||
### 7.1 `ftfy`
|
||
|
||
[ftfy](https://ftfy.readthedocs.io/en/latest/) 用保守启发式修复 Unicode mojibake,目标之一是避免把正常文本
|
||
误改。它适合发现和建议典型 UTF-8/Windows-1252 误解码。
|
||
|
||
边界:
|
||
|
||
- 已经变成 `�` 的原字符信息不在字符串中,ftfy 无法凭空恢复;
|
||
- 私用区字符需要字体或源文件映射;
|
||
- 中文旧编码误解码和法律文本中的兼容字符仍需专门验证;
|
||
- 即使候选看起来合理,也要保留 before/after、置信度和规则版本。
|
||
|
||
建议:作为 detector/candidate fixer;默认 profile 只自动应用有严格前置条件、通过实体保护检查的修复。
|
||
|
||
### 7.2 重复、低熵和幻觉模板
|
||
|
||
[DataTrove](https://github.com/huggingface/datatrove) 是大规模文本过滤/去重框架,已有行重复率、长行比例、
|
||
标点比例、语言分数和 contamination 等统计。它的默认任务是筛掉低质量训练语料,而本项目需要定位并修复
|
||
文档中的局部区域。
|
||
|
||
建议借鉴指标,不把 DataTrove 作为核心依赖:
|
||
|
||
- 最大行长与结构白名单;
|
||
- 字符/短片段 run-length;
|
||
- 唯一字符、token 和 n-gram 比例;
|
||
- 压缩率与局部信息熵;
|
||
- 相邻和非相邻重复块;
|
||
- 文档主要语言与局部语言突变;
|
||
- 已知转换器/模型幻觉签名。
|
||
|
||
detector 只产生 issue 和范围。没有可信来源时,默认隔离或人工确认,不自动编写替代内容。
|
||
|
||
### 7.3 Presidio
|
||
|
||
[Presidio](https://microsoft.github.io/presidio/) 支持文本、图片和结构化数据中的 PII 检测与匿名化,并允许使用
|
||
正则、校验和、上下文、NER 和自定义 recognizer。官方也明确说明自动检测不能保证找到全部敏感信息。
|
||
|
||
适合:
|
||
|
||
- 作为可选 privacy adapter;
|
||
- 为中国身份证、统一社会信用代码、手机号、银行账号等实现校验和与上下文 recognizer;
|
||
- 用 custom operator 实现稳定、按实体区分的伪名;
|
||
- 把文本、表格单元格和图片脱敏放进同一 profile。
|
||
|
||
不适合:
|
||
|
||
- 默认把所有候选直接覆盖;
|
||
- 把不同值统一变成同一 `[PHONE]`/`[ID]`;
|
||
- 认为通用 NER 已覆盖中文政务/合同实体;
|
||
- 把 privacy profile 与 fidelity 修复写死在一起。
|
||
|
||
## 8. 推荐的领域无关架构
|
||
|
||
下面是候选架构,不是已批准契约:
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Markdown / HTML / PDF / DOCX / Image] --> B[Immutable source artifact]
|
||
B --> C[Preflight detectors]
|
||
B --> D[Parser / source adapters]
|
||
C --> E[Issue ledger]
|
||
D --> F[Document IR]
|
||
F --> G[Validation and routing]
|
||
E --> G
|
||
G --> H[Safe deterministic repair]
|
||
G --> I[Source-verified repair]
|
||
G --> J[Quarantine / human review]
|
||
H --> K[Canonical fidelity document]
|
||
I --> K
|
||
J --> K
|
||
K --> L[Fidelity profile]
|
||
K --> M[Retrieval profile]
|
||
K --> N[Compare profile]
|
||
K --> O[Public/privacy profile]
|
||
L --> P[Markdown + assets + audit]
|
||
M --> P
|
||
N --> P
|
||
O --> P
|
||
```
|
||
|
||
### 8.1 Immutable source artifact
|
||
|
||
任何输入先冻结:原始 bytes、SHA-256、媒体类型、来源 ID 和接收时间。后续全部是新产物,不原地覆盖。
|
||
只有路径而没有内容哈希不足以复现。
|
||
|
||
### 8.2 Document IR
|
||
|
||
IR 至少需要表达:
|
||
|
||
- block/node 类型、层级和子节点;
|
||
- 原始 byte/line/column span;
|
||
- 有源文档时的 page、bbox、source artifact hash;
|
||
- 文本、表格网格、图片 asset ref 和文档边界;
|
||
- parser/extractor、版本和置信度;
|
||
- issue、annotation、repair 和 unresolved 关联。
|
||
|
||
不要让 Markdown AST 直接承担全部职责:mdast 或 markdown-it token 不包含完整的 PDF provenance、表格网格、
|
||
修复证据和多 profile 状态。也不要直接把 DoclingDocument 定为公共契约,否则核心会被某个提取器绑定。
|
||
|
||
### 8.3 Detector 与 transformer 分离
|
||
|
||
每条规则先检测,再决定是否变换。建议规则声明:
|
||
|
||
- `rule_id` 与版本;
|
||
- 支持的 node/input 类型;
|
||
- source span 与证据;
|
||
- safety level;
|
||
- 是否确定性、幂等、可逆;
|
||
- 影响文本、数字、实体、结构、资产或下游权重;
|
||
- 验收 predicate。
|
||
|
||
安全级别建议:
|
||
|
||
| 级别 | 含义 | 默认行为 |
|
||
|---|---|---|
|
||
| `detect_only` | 只能确认异常,不能确认正确内容 | 记录 issue,不修改 |
|
||
| `deterministic` | 不改变语义、前置条件严格 | 可自动执行并记录 |
|
||
| `source_verified` | 新内容可回链到可信源区域 | 自动或抽检执行 |
|
||
| `heuristic` | 有合理推断但可能误伤 | profile 显式开启或人工确认 |
|
||
| `forbidden_without_source` | 金额、编号、缺失正文等无法猜测 | 隔离/未解决 |
|
||
|
||
### 8.4 Canonical fidelity 与 profiles
|
||
|
||
核心不应硬编码只有 `clean_fidelity.md` 和 `clean_compare.md`。更通用的方式是先生成 canonical fidelity
|
||
document,再由 profile 派生:
|
||
|
||
| Profile | 目标 | 典型变化 |
|
||
|---|---|---|
|
||
| `fidelity` | 法律/业务忠实与可回源 | 只含确定性和源验证修复 |
|
||
| `retrieval` | 搜索、RAG 和可读分块 | 规范段落、结构化 chunk、保留来源 |
|
||
| `compare` | 相似度与模板分析 | 页眉页脚降噪、稳定图片 token、模板标注/降权 |
|
||
| `public` | 可共享样例或外部处理 | 确定性伪名、图片/二维码脱敏、严格日志脱敏 |
|
||
|
||
未来项目可以增加自己的 profile;GovDoc 的章节模式、投标模板、compare 权重和中国政务字段放在插件/配置包,
|
||
不能污染领域无关 core。
|
||
|
||
## 9. 建议的第一版产品边界
|
||
|
||
第一版不要一开始就做“全自动修复所有 Markdown”。建议逐层交付。
|
||
|
||
### M0:只读 audit
|
||
|
||
- 接受 Markdown;
|
||
- 冻结哈希并解析 CommonMark/GFM/raw HTML 边界;
|
||
- 输出 issue、source span、统计和阻断等级;
|
||
- 覆盖编码、超长行、重复退化、链接/图片、标题、HTML/GFM 表格和 PII 候选;
|
||
- 不改输入,不需要 PDF 模型。
|
||
|
||
这一阶段可以最早验证规则召回、误报、性能和审计 schema,不把修复风险混进来。
|
||
|
||
### M1:安全规范化
|
||
|
||
- 只执行严格确定性的 LF、NFC、尾空白、空标题等修复;
|
||
- 每项变更有 source span 和 before/after hash;
|
||
- 输出 fidelity Markdown、audit 和 unresolved;
|
||
- 强制幂等、确定性和原输入不覆盖。
|
||
|
||
### M2:结构与回源
|
||
|
||
- raw HTML fragment 恢复和 table grid;
|
||
- Docling source adapter;
|
||
- 图片 asset store 与 manifest;
|
||
- 页/区域级 re-extract;
|
||
- 标题、列表、段落只在来源或高置信结构证据下恢复。
|
||
|
||
### M3:多用途 profile
|
||
|
||
- `retrieval`、`compare`、`public`;
|
||
- privacy adapter;
|
||
- 模板标注/权重和稳定实体/图片 token;
|
||
- 各 profile 的差异可回链到 fidelity。
|
||
|
||
### M4:插件与规模化
|
||
|
||
- 稳定 rule/adapter/profile API;
|
||
- 项目专属配置包;
|
||
- 并行批处理、缓存、可恢复任务和机器可读报告;
|
||
- 再评估 CLI、Python SDK、服务接口和跨语言消费。
|
||
|
||
## 10. 选型 spike 与验收建议
|
||
|
||
进入实现前建议建立下一份 design,并批准两个小型 spike。
|
||
|
||
### Spike A:Markdown/HTML 核心
|
||
|
||
使用脱敏合成 fixture 和审计列出的结构模式,比较:
|
||
|
||
- `markdown-it-py` + 自有 IR/renderer;
|
||
- remark/mdast 作为对照;
|
||
- html5lib 与 lxml recover 对损坏 table fragment 的差异。
|
||
|
||
至少覆盖:未闭合 table、GFM 多/少列、raw HTML 与 Markdown 交错、代码围栏内伪标签、超长行、中文硬换行、
|
||
图片 URL、Word `_Toc`、标题断裂和多余转义。
|
||
|
||
验收关注:source span 完整率、round-trip 语义一致、没有静默 cell 丢失、幂等性、峰值内存和每 MiB 耗时。
|
||
|
||
### Spike B:回源提取
|
||
|
||
只在受控环境抽取 001、003 的风险分层页面,对 Docling、MinerU、Marker 做 A/B:
|
||
|
||
- 原文字符和关键实体准确率;
|
||
- 表格网格、合并单元格和阅读顺序;
|
||
- 图片数量、bbox 和 asset 引用;
|
||
- 已知幻觉与重复退化命中;
|
||
- CPU/GPU、耗时、峰值内存、模型版本和许可证约束。
|
||
|
||
不能只比较“生成的 Markdown 肉眼是否整齐”,也不能把某个引擎自己的置信度当作金标。
|
||
|
||
### 回归体系
|
||
|
||
- 公开/合成 fixture 进入 Git,复现结构问题但不包含客户原文;
|
||
- 真实样本只在外部受控目录运行,以 case/file/page ID 和聚合指标报告;
|
||
- P0 页面 100% 人工核对,其他页面风险分层抽样;
|
||
- 金额、日期、项目编号、公司名、身份证候选做前后对账;
|
||
- 每个 transformer 测幂等、确定性、边界和反例;
|
||
- fidelity、retrieval、compare、public 分别验收,不能用单一“清洗率”。
|
||
|
||
## 11. 明确不建议的路线
|
||
|
||
- 不恢复旧版逐行正则清洗器作为默认基线;
|
||
- 不对原文件直接运行 Prettier/mdformat 并覆盖;
|
||
- 不用正则解析或补齐 HTML 表格;
|
||
- 不把 parser 无报错当成 Markdown 正确;
|
||
- 不对全文执行 `clean_extra_whitespace`、`clean_dashes`、全局 NFKC 或非 ASCII 删除;
|
||
- 不因重复就删除合同条款,不因语言突变就自动删除段落;
|
||
- 不用生成模型补写缺失文字、表格单元格或图片说明;
|
||
- 不让不同实体、图片和缺失区域坍缩成同一个通用 token;
|
||
- 不把某个 PDF 提取器的 Markdown 直接当权威真值;
|
||
- 不把 GovDoc 的投标/采购规则写进通用 core。
|
||
|
||
## 12. 下一份 design 需要决定的事项
|
||
|
||
1. 是否批准“Python core + adapter/profile”方向;
|
||
2. 第一阶段是否只做 Markdown audit,暂不引入 PDF/OCR 重依赖;
|
||
3. 内部 IR 的最小字段和版本策略;
|
||
4. audit/unresolved 的事件粒度与敏感信息保存边界;
|
||
5. `fidelity`、`retrieval`、`compare`、`public` 哪些进入第一版;
|
||
6. Markdown dialect 是 CommonMark + GFM,还是还要支持 frontmatter、math、directives;
|
||
7. Docling/MinerU/Marker 的 benchmark 范围和许可证审查责任;
|
||
8. 真实数据输出目录、保留周期、人工审核和脱敏规则;
|
||
9. Python SDK、CLI、配置文件和插件 API 哪些属于首个可交付范围。
|
||
|
||
在这些事项获得批准前,本报告只代表调研判断,不代表依赖、schema 或产品行为已经确定。
|
||
|
||
## 13. 主要资料来源
|
||
|
||
本次优先使用官方文档、规范和上游仓库,GitHub 活跃度与许可证检查日期为 2026-08-20:
|
||
|
||
- [CommonMark 规范](https://spec.commonmark.org/0.31.2/)
|
||
- [GitHub Flavored Markdown 规范](https://github.github.io/gfm/)
|
||
- [markdown-it-py 文档](https://markdown-it-py.readthedocs.io/en/latest/)
|
||
- [mdformat 文档](https://mdformat.readthedocs.io/en/stable/)
|
||
- [remark](https://github.com/remarkjs/remark) 与 [mdast](https://github.com/syntax-tree/mdast)
|
||
- [Pandoc filters](https://pandoc.org/filters.html)
|
||
- [Docling](https://docling.org/) 与 [DoclingDocument](https://github.com/docling-project/docling/blob/main/docs/concepts/docling_document.md)
|
||
- [Unstructured partition/cleaning](https://docs.unstructured.io/open-source/core-functionality/partitioning)
|
||
- [html5lib](https://html5lib.readthedocs.io/en/stable/)
|
||
- [ftfy](https://ftfy.readthedocs.io/en/latest/)
|
||
- [Presidio](https://microsoft.github.io/presidio/)
|
||
- [DataTrove](https://github.com/huggingface/datatrove)
|
||
- [MinerU](https://github.com/opendatalab/MinerU)
|
||
- [Marker](https://github.com/datalab-to/marker)
|
||
- [MarkItDown](https://github.com/microsoft/markitdown)
|