虽然标题写的是几个 VL 模型的测试,但本文会先从一个真实业务场景的优化过程讲起。
数月前,我刚来到这家公司时,接手了医院检验单格式化数据的提取工作。
具体来说,是将医院检验单中每一项的项目名称、项目编号、检验结果值、检验结果区间、异常符号、检验值单位等信息,提取为数据库里的结构化结果。
这个功能在我来之前就已经有了,但也仅限于“能跑起来”,处理流程、代码逻辑、大模型提示词都一言难尽。最初我的任务是优化性能,但很快发现其代码逻辑和最终精度都有不小问题,于是干脆推翻重写,用“大模型 + 大量工程化代码”的方式重新实现;后续上线之后又暴露出一批 bad case,于是再引入 VL 模型继续优化。
断断续续经过多轮优化之后,现在在不同检验单上可以做到平均约 95% 的准确率(拍摄质量较高的场景基本能到 100%),其中大量依赖了图像矫正、VL 模型和 LLM 模型。
这个准确率应该已经高于市面上绝大部分现有产品,甚至高出不少。(Ps:当然不能和动辄上百亿参数的超大模型方案去硬比~)
我们用的大模型是 32B 的,参数量并不算高。对一些超大的模型,其实用很简单的提示词就能达到不错的效果,但我们的业务场景强调的是本地部署、小模型和高性能。
样例图片:
检验单提取的难点
难点1:格式多样。如果只针对单一格式的检验单,不使用 LLM 其实也能解决,比如根据固定版式用 Python 识别横纵线区域 -> 表格提取 -> OCR -> 数据清理 -> …
真正的难点在于,我们需要覆盖全国上百家医院的检验单提取,几乎每家医院都有自己一套完全不同的检验单格式。
难点2:拍摄质量差。大部分检验单都是业务人员用手机拍摄上传的,图片会出现扭曲、凹凸不平、角度不正等问题。
解决方案
难点1
大模型的出现,帮我们补上了很多传统工程化做不了的部分,尤其是边界条件不清晰、需要自然语言判断、规则难以穷举的场景。
在检验单这个场景下,可以直接把 OCR 的结果喂给大模型,让它返回标准的结构化数据,比如 Markdown 表格、JSON、YAML 等,再由代码做解析和校验。
因此,相比其他问题,这一块其实是比较容易解决的。
难点2
除了整体流程的搭建,我的大部分时间其实都花在了这个难点上。在业务批量测试时,反馈最多的问题主要集中在三类:行串行、数值/符号识别不正确、漏项。
行串行的问题。主要是由于图片倾斜、纸张凹凸不平等原因造成的。之前我在
OCR推理前,尝试用霍夫变换做角度矫正,但精度并不高,大概在 80% 左右。后来对角度矫正方案做了升级,简单说就是借助OCR识别后每个 box 的倾斜角度,做数据统计、智能角度聚类、异常值过滤等一系列操作,最终实现了较高精度的角度识别。
凹凸不平这个问题就更难了,引入VL之后能解决一部分,但离完全解决还差不少。理论上可以借助一些“文档展平”模型,不过“文档展平”会对原本就比较正常的图片产生副作用,而且开源方案整体效果一般。不过,扫描全能王自家的“文档展平”效果确实非常好。数值/符号识别不正确。之前我在华为
910B上部署了一版OCR模型,虽然经过了一轮性能优化,但精度还是稍显不足。后面GPU到位之后,换了一版模型,精度有了一波提升;再叠加VL模型之后,整体精度又往上走了一截。漏项。漏项问题大部分其实出在大模型上。后来通过“VL 模型 + 提示词优化”的组合,这块问题得到了非常明显的缓解。
在做这些优化的过程中,还发现了一些挺有意思的现象。第一版时,我非常“精心”地写了提示词,并且根据 bad case 不断往里加规则、加约束、加特殊说明。最后提示词变得庞大臃肿,但我又不太敢再去动它。
而在最近和 VL 模型结合做优化时,我反过来只写了一个非常简单的提示词,其中只有少量描述和几条基础规则。结果效果反而给了我惊喜:整体精度更高了。随后我又在这个基础上不断加规则、做批量测试,发现随着约束条件的增加,精度反而呈现下降趋势。
我发现,有时候不要把大模型的边界限制得太死,给它留一点“发挥空间”和容错余地,相比于条条框框的提示词,反而更有可能获得更高的精度。
正题:VL 模型。
在 OCR 这一块的优化上,我们基本已经做到当前方案的瓶颈,只能考虑其他路径。于是我测试了多款版面识别 VL 模型的能力,大致摸清了它们各自的能力边界,最终选择将 OCR 结果和 VL 结果进行融合,再一起送入大模型做后处理。
对于 VL 模型,最近开源又比较火的是这四个:MinerU、Dots.ocr、PaddleVL、DeepSeekOCR。
MinerU:使用的是他们新出的多模态模型 MinerU 2.5VL。MinerU 是最火的开源版面识别项目之一,最初是以一个 Pipeline 的形式,用多个传统模型串联进行推理:比如先做版面识别,然后根据版面类型分别做表格识别、公式识别、文本 OCR 识别,最后再用一个排序模型进行整合。我对 Pipeline 版本的 MinerU 比较熟悉,在上一份工作中,曾多次和 MinerU 的主力开发对接,帮他们实现了在昇腾 910B、910A 上的高性能推理,后面他们也开源了相关的推理代码。
说回正题,MinerU 在几个月前开始走单模型路线,我之前试过它的两个版本,效果都不算理想,但这次的 2.5 确实不错,表格还原能力比上一代强多了。
Dots.ocr:小红书 7 月底开源的一款模型,当时属于 SOTA 级别(现在也是)。
PaddleVL:PaddleOCR 家喻户晓,Paddle 现在也下场做了 OCR 相关的 VL 模型,大家的期待值都挺高。但实测效果一般,而且速度极慢:硬件是 H20-140G,用的是官方推理脚本,整体推理耗时远超预期,让我一度怀疑是不是环境配置哪里出了问题,但后面测试精度也不及预期就懒得看了。
DeepSeekOCR:明星产品。实测速度还不错,但在我们这个检验单场景下,精度表现比较一般。
下面是 113 张图片、13 路并发下的批量测试结果。这里的召回率和精确率,都是针对检验单中“异常符号”识别情况统计的。

在我们的检验单场景下,
精度排行:MinerU ≈ 小红书 dots.ocr > PaddleVL > DeepSeekOCR
性能上,在 13 路并发下,MinerU 略快于小红书;在低并发下,MinerU 比 dots.ocr 快很多。
但 MinerU 有一个比较致命的问题:表格有时候会完全检测不到,直接被当成纯文本;dots.ocr 在这方面就非常稳定,即便是质量比较差的图片,也大多能成功检出表格。整体来看,MinerU 的抗干扰能力比 dots.ocr 略强一些。

我还写了一个简单的测试对比网页,专门拿一些 bad case 做了对比实验。除了 MinerU 的表格识别问题之外,两者在精度上可以说是各有胜负;但在性能上,MinerU 还是要强出不少。
