博客
教程

面向扫描文档的服务端视觉模型 OCR

Simmetric Chat 如何用服务端视觉模型 OCR 管线读取扫描 PDF--页面渲染、Ollama 视觉模型,以及人工审批步骤。

Simmetric Team6 分钟阅读28/03/2026

为什么扫描文档会破坏文本提取

让文本提取器去读一份扫描 PDF,你几乎什么也得不到。文字处理软件生成的 PDF 自带文本层--字符以文本形式存储,提取轻而易举。扫描仪生成的 PDF 则是一包页面图像:没有文本层,只有像素。collector 的解析器只能提取真实存在的内容,因此纯图像页面返回空白或近空白,一份在查看器里看起来完全可读的文档,对知识库毫无贡献。

Simmetric Chat 在服务端、在文档到达切分与 embedding 阶段之前就处理了这个问题。当摄取检测到文本稀薄的 PDF 时,平台把它送入一条专用 OCR 管线,其引擎不是经典的模式识别 OCR 库,而是通过 Ollama 本地提供的具备视觉能力的语言模型。结果是提取出的 Markdown,对标题、列表和表格结构的保留远好于字符级 OCR--而且一切完全运行在你的基础设施内。没有任何文档需要离开网络才能被读取。

本文说明管线如何工作、它暴露哪些控制,以及防止一个读错页面的模型静默污染知识库的人工审批步骤。

从像素到 Markdown:管线

Simmetric Chat 中的 OCR 是一条服务端、基于 job 的管线。提取文本未通过预检的上传--默认情况下,少于约 200 个可提取字符即标记为扫描文档--会成为一个 OCR job,轮询调度器每 10 秒领取 job,并带全局并发上限,因此一批上传不会压垮机器。单个文档随后走过五个阶段:

  1. 加载。 pdfjs-dist 在服务端打开 PDF 并枚举页面,每个 job 上限 50 页,作为防止失控处理的安全边界。
  2. 渲染。 每一页以放大比例渲染为 PNG 图像--默认 2x--因此即使是传真质量扫描件上的小号字体,到达模型时也有可读的分辨率。
  3. 识别。 每张页面图像以 base64 图像形式发送给配置的 Ollama 视觉模型,模型把该页转录为 Markdown 文本。
  4. 防护。 原始转录首先经过防幻觉守卫和 grounding 清理步骤。视觉模型有时会在输出上标注 grounding 标记,或在页面确实不可读时编造看似合理的内容--两种情况都在这里被拦截,而不是被保存。
  5. 评分与组装。 每一页获得质量评分,页面被拼接成单一文档,job 以一个诚实的摘要收尾:失败的页面被计数并报告为失败页,绝不会被静默吸收进一个干净的「已完成」结果。

这份列表中的每一步都发生在服务器上。浏览器从不执行 OCR,也不会调用任何第三方 OCR API--唯一的网络跳转是从你的服务器到你的 Ollama 实例。

模型选择

视觉模型可配置,管线包含一个小型模型注册表,知道如何与每个受支持的模型家族对话:

  • glm-ocr--默认值(OCR_MODEL=glm-ocr:latest),一个专攻 OCR 的视觉模型。注册表通过 Ollama 的 chat 端点路由它,对这类模型家族而言,转录结束的检测更可靠。
  • deepseek-ocr--第二个针对 OCR 优化的模型家族,使用 grounding token;注册表向它发送单页图像,并在清理时移除 grounding 标记。
  • 任何通用视觉模型--注册表不认识的模型回退到通过 Ollama generate 端点的通用 prompt,因此你已在本地运行的多模态模型也能用。

与模型相关的参数是环境变量,与配置面的其余部分一起记录:

env
# 服务端视觉 OCR
OCR_MODEL=glm-ocr:latest   # 视觉模型(支持 model:version)
OCR_TIMEOUT=600000         # 10 分钟 - 视觉模型很慢
OCR_NUM_PREDICT=8192       # 每页最大输出 token

prewarm 端点允许管理员在第一个 job 之前把模型加载进内存,因此当天第一份扫描上传不必支付模型的冷启动成本。

人在环中:批准或拒绝

转录质量随扫描质量变化,而知识库是发现模型读错页面的最糟场所。因此管线把 OCR 输出当作草稿,而不是事实。每个 job 产出一个可复核的工件:预览把提取文本绑定到与图像面板相同的页面区域,复核者可以把任何页面与它来源的扫描件对照查看。

从 OCR 设置面板,管理员可以看到模型目录、带每页质量与可信度评分的 job 列表,以及工作流本身:

  • 批准--提取的页面被接受并继续:已批准的 archive job 会把页面物化进知识库,从批准的结果还可以发起一次 synthesis 运行。
  • 拒绝--输出被丢弃,决定记录在 job 上。

自动化可用而不必放弃闸门。一个事件驱动的自动批准 hook 可以终结质量信号干净的 job,并在人类决定就是契约的所有地方有意保留手动批准流程--明确路由进知识库的导入永远不会被静默自动批准。无论如何,job 摘要对页面健康状况保持诚实:一个以三个失败页结束的 job 会在结果和日志中说明这一点。

这套仪式的意义只有一个不变式:文本只有在经过干净的质量检查或人工查看之后,才进入你的 RAG 索引。

提取的文本去向何处

已批准的 OCR 输出回到正常的摄取流程。对于上传的文档,提取的 Markdown 取代扫描件缺失的文本层,文档随后就像原生 PDF 一样进行切分、embedding 和混合检索索引。对于 archive,已批准的页面成为 workspace 精选知识库的一部分,wikilink、backlink 和 synthesis 管线可以像处理任何其他页面一样处理它们。

由于管线在服务端,它与平台其余部分的保障协同:DLP 过滤器继续在内容离开网络之前扫描,RBAC 继续决定谁可以发起 job、批准结果,OCR 路径上没有任何一点需要到云端 OCR 服务的出站连接。

实用设置

大多数部署只需要三个决定:

  • 启用它。 OCR_ENABLED 和 OCR_PRECHECK_CHARS--把 PDF 路由进管线的字符阈值--在管理设置中管理。
  • 选择模型。 glm-ocr:latest 是合理的默认值;模型目录列出注册表认识什么,按 job 的模型选择可在设置面板完成,自定义指令可以为你的文档领域微调转录行为。
  • 预算时间。 视觉 OCR 用速度换保真度。默认 10 分钟超时和 50 页上限存在,是为了让病态扫描退化为可见失败,而不是被阻塞的 worker。

如果你的语料主要是原生 PDF,你很少会注意到这条管线:健康的文本层完全绕过 OCR。当扫描文档到来时,它走过渲染、视觉模型和你的批准--最终变得可搜索,而不是不可见。

在文档中阅读完整指南 →

相关文章