Bläddra i källkod

feat(新增OvisOCR2接入分析文档): 添加OvisOCR2接入分析文档,详细介绍模型概况、接入方案及注意事项,提升文档的完整性与可用性。

zhch158_admin 2 veckor sedan
förälder
incheckning
1f9582f487
1 ändrade filer med 111 tillägg och 0 borttagningar
  1. 111 0
      docs/ocr_tools/universal_doc_parser/OvisOCR2接入分析.md

+ 111 - 0
docs/ocr_tools/universal_doc_parser/OvisOCR2接入分析.md

@@ -0,0 +1,111 @@
+# OvisOCR2 接入分析
+
+模型主页:https://huggingface.co/ATH-MaaS/OvisOCR2
+
+## 1. 模型概况
+
+- 基于 `Qwen3.5-0.8B` 后训练得到的**端到端页面级文档解析模型**(0.8B,体积小、推理快),与仓库里已接入的 dots.ocr / MinerU-VL / GLM-OCR 属于同一类"整页丢进去,直接吐出结构化 Markdown"的模型。
+- 输出格式固定为单一 Markdown:
+  - 正文:标准 Markdown
+  - 公式:LaTeX
+  - 表格:HTML `<table>...</table>`
+  - 图片/图表区域:`<img src="images/bbox_{left}_{top}_{right}_{bottom}.jpg" />`,坐标归一化到 `[0, 1000)`
+- 官方推理示例使用 **vLLM 离线 `LLM()` 接口**做批量推理;vLLM 同时支持 `vllm serve` 启动 OpenAI 兼容 HTTP 服务,与仓库现有 MinerU-VL / GLM-OCR 的部署方式一致,可直接复用。
+- 只有一个通用 prompt,**没有**类似 GLM-OCR 的 `task_prompt_mapping`(按 text/table/formula/seal 分别提问)。
+- 图像分辨率范围 `min_pixels=448*448` ~ `max_pixels=2880*2880`,整页直喂时对银行流水这类密集小字表格存在降采样丢字风险。
+
+## 2. 是否还需要 layout、方向、印章等专用模型?—— 仍然需要
+
+`universal_doc_parser` 现有流水线(见 [core/model_factory.py](../../../ocr_tools/universal_doc_parser/core/model_factory.py)、[config/bank_statement_glm_vl.yaml](../../../ocr_tools/universal_doc_parser/config/bank_statement_glm_vl.yaml))是:
+
+```
+方向校正 → 去水印 → layout 检测(含印章补充检测) → 表格有线/无线分类
+        → 有线表:UNet + RT-DETR 单元格融合 → 单元格二次 OCR
+        → 无线表/公式:VLM 识别 → 与并行 OCR 结果做单元格坐标匹配
+```
+
+| 环节 | OvisOCR2 能否替代 | 结论 |
+|---|---|---|
+| 方向识别(`paddle_orientation_classification`) | 模型卡未提及旋转鲁棒性训练 | **保留**,先扶正再喂给 OvisOCR2 |
+| Layout 检测(docling / PP-DocLayoutV3) | 内部隐式做了版面理解,但不输出显式类别框(除图片/图表外没有坐标) | **保留**,用于按区域路由到专用模型(有线表、印章) |
+| 印章检测(`seal_supplement`,PP-DocLayoutV3) | 无专门印章类别 | **保留** |
+| 印章识别(`SealOCRRecognizer`,MinerU seal 专用 OCR) | 无专门能力,见第 4 节 | **保留** |
+| 表格有线/无线分类 | 不区分,统一按通用 prompt 输出 HTML | **保留**,有线表继续走 UNet+RT-DETR 精细单元格管线,OvisOCR2 只承担无线表/正文/公式 |
+
+结论:OvisOCR2 适合**替换/补充现有 `vl_recognition` 环节**(对标 GLM-OCR/MinerU-VL 适配器),不适合替换整条 layout+方向+印章管线。
+
+## 3. 能否返回表格单元格坐标?—— 不能,需复用现有坐标匹配方案
+
+OvisOCR2 只对"图片/图表"类视觉区域给 `bbox_{left}_{top}_{right}_{bottom}`,**表格是纯 HTML `<table>` 结构,没有 per-cell 坐标**,这一点和 GLM-OCR、MinerU-VL 完全一样(见 [glmocr_vl_adapter.py](../../../ocr_tools/universal_doc_parser/models/adapters/glmocr_vl_adapter.py) 的 `recognize_table` 直接返回 `'cells': []`)。
+
+仓库已有解决方案:[core/table_coordinate_utils.py](../../../ocr_tools/universal_doc_parser/core/table_coordinate_utils.py) 的 `TableCellMatcher` —— 并行跑一遍普通 OCR(PaddleOCR/MinerU OCR)拿到文本框,再用**文本内容匹配**把 HTML 表格里每个 `<td>` 的文字对齐到 OCR 检测框上,反推单元格坐标。OvisOCR2 接入后直接复用这套匹配逻辑即可,无需额外开发。
+
+## 4. 能否识别印章?—— 不建议依赖它
+
+- 模型卡完全没提 "seal/印章/stamp" 能力,训练数据以 OmniDocBench/PureDocBench 通用文档为主。
+- 端到端 VLM 遇到印章大概率当成一个"图片视觉区域"整体裁出来(`<img src="images/bbox_...">`),不会转写印章内文字,这与 GLM-OCR 现状类似(虽然它有 `seal` 专用 prompt,效果也一般,所以仓库额外做了 `seal_supplement` + `SealOCRRecognizer`(MinerU 印章专用 OCR:`seal_PP-OCRv4_det` + 低阈值识别)兜底)。
+- **建议**:印章检测与识别继续用现有专用模块([seal_ocr_adapter.py](../../../ocr_tools/universal_doc_parser/models/adapters/seal_ocr_adapter.py)),不要指望 OvisOCR2。
+
+## 5. 接入方案建议
+
+**推荐:作为新增 `vl_recognition` 适配器接入,不做整页端到端替换**
+
+1. **部署**:用 vLLM 起 OpenAI 兼容服务(与 MinerU-VL/GLM-OCR 一致):
+   ```bash
+   vllm serve ATH-MaaS/OvisOCR2 --port <port> --gpu-memory-utilization 0.8
+   ```
+2. **新增适配器** `models/adapters/ovisocr2_vl_adapter.py`,继承 `BaseVLRecognizer`(见 [base.py](../../../ocr_tools/universal_doc_parser/models/adapters/base.py) 第 651 行):
+   - `recognize_table()`:传入裁剪出的表格区域图,用官方固定 prompt 调用,从返回文本中正则提取 `<table>...</table>` 片段作为 `html`,`cells: []` 交给 `TableCellMatcher` 补全。
+   - `recognize_formula()`:类似地从返回 Markdown 中抽取 LaTeX 片段。
+   - 由于没有任务级 prompt,需要在适配器里对返回内容做**后处理裁剪**(正则提取 `<table>`/LaTeX 部分),过滤掉多余的正文说明文字。
+3. **注册**到 [core/model_factory.py](../../../ocr_tools/universal_doc_parser/core/model_factory.py) 的 `create_vl_recognizer`:新增 `elif module_name == 'ovisocr2':` 分支。
+4. **新增配置** `config/bank_statement_ovisocr2_vl.yaml`,复制 `bank_statement_glm_vl.yaml` 结构,只替换 `vl_recognition` 段的 `module/api_url/model`,其余 layout/方向/印章/表格分类段保持不变。
+5. **分辨率注意**:`max_pixels=2880*2880` 对裁剪后的单表格/单区域小图影响不大,但整页直喂容易在密集小字表格上丢字,**不建议整页直喂**,优先沿用"裁剪表格区域后单独识别"的现有模式。
+
+**可选**:额外做一个独立端到端小工具(参考 [dots.ocr_vl_tool](../../../ocr_tools/dots.ocr_vl_tool)、[mineru_vl_tool](../../../ocr_tools/mineru_vl_tool) 的 `main.py`/`processor.py` 结构),用于快速整页 Markdown 预览、或不需要精确单元格坐标的非结构化文档(合同、报告等)。这类场景不需要 layout/朝向/印章管线,直接调用整页 parse 即可,发挥其"小、快、OmniDocBench SOTA"的优势。
+
+**风险提示**:
+- 0.8B 参数量偏小,在银行流水这类密集小字、复杂合并单元格场景上的精度需要用现有测试集(`data/流水典型表样数据` 等)实测验证后再决定是否替换 GLM-OCR/MinerU-VL。
+- 无分任务 prompt,效果依赖对整页通用 prompt 输出的后处理解析,建议先写小脚本跑几张真实银行流水表格测试提取稳定性。
+
+## 6. 能否用 llama.cpp 转 GGUF?—— 只能转文本骨干,视觉塔(mmproj)官方不支持
+
+结论:**只能转一半**。OvisOCR2 的文本骨干(Qwen3.5-0.8B)可以用 `convert_hf_to_gguf.py` 正常转成 GGUF,但真正让它"看图"的视觉塔/多模态投影层(`--mmproj`)目前**官方 llama.cpp 并不支持 Ovis 系列架构**的胶水层,不能简单一键转出可用的多模态 GGUF。
+
+### 证据
+
+1. **bartowski 的量化包**(`bartowski/ATH-MaaS_OvisOCR2-GGUF`,用 llama.cpp `b10068` release 转的)**只发布了纯文本权重**(`Architecture: qwen35`),完全没有 mmproj 文件。像 bartowski 这样成熟的量化维护者不带 mmproj,基本可以判断当前官方 llama.cpp 转不出(或转出来跑不了)Ovis 的视觉部分。
+2. llama.cpp 官方仓库两个直接相关的 issue:
+   - [#14552 Support for Ovis2 models](https://github.com/ggml-org/llama.cpp/issues/14552)
+   - [#12429 Feature Request: Support inference for OVIS2 models](https://github.com/ggml-org/llama.cpp/issues/12429)
+
+   都显示状态是"因 14 天无活动被 stale bot 自动关闭",**并非功能真正合并完成**。核心贡献者 `wsbagnsv1` 在 2025-08-23 明确说:"ViT 架构本身已经有了,但 ViT 输出对接到 Qwen 的'胶水层'还没搞定,我转出了 gguf 但还没法量化,因为这部分 arch 我自己还没实现"。也就是说截至目前,Ovis 系列(Ovis2 / Ovis2.5,OvisOCR2 同源架构只是换了 Qwen3.5 底座)的视觉编码器转换在官方主线里**没有完全合并**。
+3. 第三方仓库 `Abiray/OvisOCR2-GGUF` 虽然放出了 `mmproj-F16/F32/BF16`,但结合上面 issue 的进展看,大概率基于某个**非主线分支/自制 patch**产出,官方发行版 llama.cpp(`llama-mtmd-cli` 或旧的 `llama-llava-cli`/`llama-minicpmv-cli`)不一定能正确识别和推理,其模型卡引导语也比较含糊("depending on your build version"),需自行验证效果,不能默认当作官方支持的稳定路径。
+
+### 技术原因
+
+`convert_hf_to_gguf.py` 的 `--mmproj` 分支依赖模型架构在脚本里**显式注册**一个 MMPROJ 转换类(`get_model_class(arch, mmproj=True)`)。Ovis 系列用的是"Visual Tokenizer + Visual Embedding Table(VTE)"这种和主流 LLaVA 风格(CLIP + MLP projector)不同的连接方式,官方目前没有登记这个转换器,直接跑:
+
+```bash
+python convert_hf_to_gguf.py <OvisOCR2目录> --mmproj
+```
+
+大概率会报 `Model ... is not supported` 或直接失败。
+
+### 建议
+
+- **ocr_platform 生产接入**:仍然按第 5 节走 **vLLM(OpenAI 兼容 HTTP server)**部署,这是模型卡官方验证过的路径,也和仓库里 MinerU-VL/GLM-OCR 现有 HTTP adapter 模式一致,接入成本最低、结果可靠。
+- **如果确实需要 llama.cpp / 纯 CPU 或边缘部署**:
+  1. 先用 `convert_hf_to_gguf.py` 把 Qwen3.5 文本骨干单独转出来验证没问题;
+  2. 视觉部分建议直接试用 Abiray 现成的 `mmproj` 文件,但**先在一两页真实业务图上跑通 `llama-mtmd-cli` 验证输出质量**,不要直接上生产,因为它不是官方保证支持的路径;
+  3. 关注 [#14552](https://github.com/ggml-org/llama.cpp/issues/14552) 后续是否有人真正合并 Ovis 视觉支持的 PR。
+- 不建议自己从零写 Ovis 的 `--mmproj` 转换器,工作量接近重新实现一遍 vision-to-LLM 的对接层,性价比低。
+
+## 7. 结论汇总
+
+| 问题 | 结论 |
+|---|---|
+| 是否还需要 layout/朝向模型 | 需要,OvisOCR2 只替换 `vl_recognition` 环节 |
+| 能否返回单元格坐标 | 不能,需复用 `TableCellMatcher` 做文本匹配 |
+| 能否识别印章 | 不建议依赖,继续用 `SealOCRRecognizer` + `seal_supplement` |
+| 能否用 llama.cpp 转 GGUF | 文本骨干可以,视觉塔(mmproj)官方暂不支持,生产建议走 vLLM |