
《案件材料进入大模型之前》第三篇
这套本地 OCR 第一次处理真实材料时,程序给出的结果是:PASS。
九页扫描材料全部跑完,识别文件完整生成,原件没有被改动。从程序的角度看,任务成功了。
然后我打开识别结果,发现第 2、3 页根本不能用。
这两页原本是横向表格。程序确实认出了一部分项目名称、单位和数字,却没有先把页面转正,也没有保住表格的行列关系。项目名称在一处,工程量、单价和合价散在另一处。
字认出来了,事实关系却丢了。
如果把这样的全文直接交给大模型,它仍然可以生成一份语气完整、结构清楚的分析。危险之处正在这里:模型未必知道数字已经找错了对象。
那次实测让我确认了一件事:
律师需要的 OCR,不是“成功导出文字”,而是关键内容能不能重新钉回原页,错误能不能在进入案件分析前被发现。
自动检查通过,不等于律师可以使用
先说清楚,第一次的 PASS 并不是程序撒谎。
它检查的是另一组问题:九页是否都已处理,规定的文件是否完整,页图和识别结果能否打开,原件是否保持不变。
这些检查很重要,但它们回答的是“程序有没有按设计运行”,不是“这份材料能不能安全用于办案”。
一张表格里,十个数字全部认对,却分别落到错误的项目下面,程序可以完整运行,律师却不能使用。一个姓名只错一个同音字,全文仍然流畅,后面的当事人匹配和检索却可能全部偏掉。
所以,我后来把验收分成了两层:
- 技术验收:产物是否齐全、格式是否有效、原件是否被改动;
- 业务验收:主体、金额、日期、期限、案号、账户、签章和表格对应关系,能否回到来源页核对。
前一层可以自动完成很多。后一层不能交给一句 PASS。
律师其实需要两份不同的结果
继续修改这套工具时,我发现“识别得准”和“排得好读”并不是同一件事。
律师一方面需要准确位置:某句话来自哪一页、页面什么位置、机器有多大把握。另一方面又需要阅读结构:标题在哪里,段落顺序怎样,一张十列表格怎样恢复成可以阅读的行列。
一个输出很难同时把两件事都做好。
所以,我现在把 OCR 分成两个彼此独立的模式。
证据模式使用本地 PP-OCRv6 识别逐行文字,再由 PP-LCNet 判断页面是 0°、90°、180°还是 270°。它保存页码、文字坐标、置信度、方向判断、表格候选和质量报告。
它解决的是:这段文字识别成了什么,来自哪里,哪些地方需要复核。
这里的“证据模式”只是我给功能起的名字,不表示 OCR 文字已经成为法律上的证据,更不表示可以脱离原件引用。
结构模式使用在本机运行的 HunyuanOCR-1.5,帮助恢复段落、阅读顺序和 Markdown 表格。它生成的阅读副本更整齐,更适合快速浏览复杂版面。
但当前结构结果没有逐行坐标和置信度。它解决的是“怎样读”,不能单独证明“原页究竟写了什么”。
因此,两种结果分开保存。遇到姓名、数字、日期和表格单元格冲突时,不自动选一个,也不悄悄拼成一份更漂亮的全文,而是保留冲突,回到原页。

第一次返工解决横向表格,又暴露了手写问题
针对那两页横置表格,我先加了页面方向判断。
原始页图始终保留;需要转正时,另存一张处理页,再在转正后的页面上识别文字。这样既不覆盖原件,也能让后续复核知道机器实际看的是哪一张图。
接着,我按表格线和文字坐标恢复行列。重新跑那份九页材料后,第 2、3 页被自动转正,表头和数据行恢复成十列。原来散开的项目与数字,重新回到了相应单元格。
这个问题改善以后,我又加入结构模式,希望复杂页面能够更好读。
印刷表格确实改善了。
但同一页底部有一处潦草手写,结构模型没有停下来承认看不清,而是替它补出了一句看似合理、实际上并不可靠的话。
这比输出“无法辨认”更危险。
无法辨认会提醒律师回看原件。一句流畅的错话却可能直接混进事实摘要,之后再被引用、比较和推理。
从那以后,我不再允许结构模型承担精确抄字。它可以帮助恢复阅读顺序,却不能因为表达更完整,就覆盖带位置的识别结果。
置信度很高,也不能放过关键事实
OCR 会给每一行一个置信度。最简单的做法,是设一条统一分数线:低于某个数就复核,高于就放行。
对律师材料,这样不够。
普通叙述错一个标点,影响可能很小;金额少一个零、日期错一天、主体名称错一个字,后果完全不同。错误风险取决于内容,不只取决于模型分数。
我现在的规则是:
- 普通叙述行低于 0.85,进入复核;
- 姓名、主体、金额、日期、期限、案号、证件号、账号、文号、联系方式、地址和签章语境,无论分数多少都进入复核;
- 0.95 只用于安排高风险内容的复核先后,不代表可以免检;
- 手写、签名、印章和指印始终需要人工终审。
这套规则不假装已经算出一个适用于所有材料的“最佳阈值”。它只是承认:同样一次识别错误,落在普通叙述和落在付款金额上,不是同一种风险。
当前版本的一页真实测试中,共识别出 64 行,系统挑出 2 行复核:一行因为置信度低于 0.85,另一行虽然分数不低,却因内容属于关键字段被强制留下。
后者正是这套规则存在的意义。
模型视觉只能提意见,不能改原文
发现需要复核的行以后,另一个问题出现了:难道还要把整页扫描件再交给视觉模型看一遍?
我的做法是先生成一个复核包,只裁出需要检查的最小区域。视觉模型只看这些小裁块,对现有识别结果给出三种意见:一致、可能的其他读法,或者无法辨认。
它不能直接修改正式 OCR 记录。
即使视觉模型认为某个字应该换成另一个字,这也只是一条候选意见。原来的识别文字保持不变,最终是否更正,仍然由人对照原页决定。
这条限制是故意的。
如果模型可以在后台自动把 OCR 文字改得更顺,最后得到的也许是一份很好读的文本,却没人知道哪些字来自原识别,哪些字是后来猜出来的。
还要说明:最小裁块不等于已经脱敏。裁块里仍可能有姓名、金额或账号。是否可以交给外部视觉模型,仍要根据材料性质和使用条件另行判断;不适合提交的,就只作人工复核。
减少范围,不等于取消资料边界。
我最后留下的,不是一份 TXT
一套适合律师工作的 OCR,最后不应只剩一份连续全文。
我现在要求保留的东西包括:
- 原始文件;
- 逐页渲染图,以及必要时的转正处理图;
- 带页码、坐标、置信度和复核规则的正式识别记录;
- 便于阅读的结构副本;
- 表格候选和质量报告;
- 需要复核的最小裁块;
- 模型候选意见和人工终审状态。
原件不覆盖,校正生成新的衍生文件。证据模式与结构模式不混写。模型候选不能回填正式文字。
这些文件看起来比一个 TXT 麻烦,却回答了律师真正会追问的问题:这句话从哪里来,机器哪里没有把握,谁核过,改动依据是什么。
程序通过,只证明程序按规则跑完
现在这套 glex-ocr 已经迭代到 0.4.0。当前自动化测试是 24 项全部通过,本地识别、结构处理和复核包都可以正常运行。
但我不会据此宣传一个统一准确率,也不会说律师可以放心把材料交给它自动处理。
自动化测试证明的是:工具会按规定保存原件、生成产物、标记复核项,并阻止视觉模型悄悄修改正式结果。
它不能证明下一份模糊复印件、手写收条或复杂流水一定认得对。
我给律师工作做这套本地 OCR,最后追求的并不是“机器永远不出错”。这不现实。
我更在意三件事:
错误能不能被发现,疑点能不能回到原页,最终由谁确认。
认出文字只是第一步。
让文字保留出处,让不确定性留在结果里,让机器不能越过律师替案件事实定稿,才是这套工具真正要解决的问题。
资料说明
本文分享的是一套仍在迭代的个人工作方法,不构成对任何 OCR 模型或部署方案的购买建议,也不承诺公开发布代码或 Skill。文中的真实测试已经去除客户名称、案情、金额、文件路径和其他可识别信息。
技术资料核验截至 2026 年 7 月 20 日:
文中版本、测试数量和返工经过,依据本机 glex-ocr 0.4.0 的现行实现,以及 v0.1 至 v0.4 的匿名化测试记录整理。自动测试通过只表示工具按既定规则运行,不代表任何新材料已经识别正确。