本地用 Ollama + 视觉模型识别 PDF 技术教程

本地用 Ollama + 视觉模型识别 PDF 技术教程

适用场景:在一台普通电脑(无独显、仅 CPU)上,本地运行 Ollama 与视觉大模型,识别/读取无水印的扫描型(图片型)PDF 内容。


一、方案概述

所谓"本地 PDF 识别",按 PDF 内部是否含有可提取文本层,分为两类,所需技术完全不同:

类型 特征 是否需视觉模型
有文本层 PDF Word 另存、LaTeX、浏览器打印、电子书等导出,文字可复制 否,直接提取即可
图片型/扫描型 PDF 扫描仪、拍照转 PDF,整页是图片 是,需 OCR/视觉模型

本教程聚焦第二类:当 PDF 没有文本层时,如何用本地视觉模型完成识别。

为什么选本地方案

  • 数据不出本机,隐私性好;
  • 一次部署,无 API 调用费用;
  • 普通办公电脑即可运行小模型(3B 级别)。

注:

博客:

https://blog.csdn.net/badao_liumang_qizhi

二、技术栈与核心概念

概念 说明
Ollama 本地大模型运行框架,提供模型管理命令与 /api/chat 等 REST 接口
视觉模型(VLM) 能理解图片的多模态模型,如 qwen2.5vlllava-phi3moondream
GGUF llama.cpp 的模型权重格式,Ollama 底层使用,可通过 Modelfile 直接导入
Modelfile Ollama 的模型定义文件(类似 Dockerfile),指定权重来源 FROM、对话模板 TEMPLATE、运行参数 PARAMETER
视觉投影层(mmproj) 将图片转换为视觉特征的部分。部分模型(如 llava)有独立投影文件;Qwen2.5-VL 系列则内置在权重中
PDF 栅格化 将 PDF 页面渲染为 PNG/JPG 图片,供视觉模型读取
base64 编码 把图片二进制转为文本,便于通过 JSON 传给模型接口

三、整体流程

复制代码
图片型 PDF
   │
   ├─ ① 判断是否已有文本层(PyMuPDF 检测)
   │     有 → 直接提取文本,流程结束
   │
   └─ 无 → 进入视觉识别流程:
         ② 用 PyMuPDF 将页面渲染为 PNG(建议 dpi 150--200)
         ③ 图片 base64 编码
         ④ 调用 Ollama /api/chat,附带图片与提示词
         ⑤ 解析返回文本,按页/块整理

四、环境准备

4.1 安装 Ollama

  • 前往 Ollama 官网下载对应系统安装包,安装后服务默认监听 http://localhost:11434
  • 验证:ollama --versionollama list

4.2 获取视觉模型

获取模型有两种途径:

途径一:官方仓库直接拉取(需能访问 Ollama 官方源)

bash 复制代码
ollama pull qwen2.5vl:3b

途径二:手动下载 GGUF + ollama create(适用于网络受限环境)

当官方源不可达时,可从国内模型平台(如 ModelScope)下载对应 GGUF 文件,再编写 Modelfile 导入:

bash 复制代码
# Modelfile 示例
FROM /path/to/Qwen2.5-VL-3B-Instruct-Q4_K_M.gguf

TEMPLATE """{{- if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}
{{- if .Images }}
{{- range .Images }}
{{ . }}
{{- end }}
{{- end }}
<|im_end|>
{{ end }}<|im_start|>assistant
"""

PARAMETER stop <|im_start|>
PARAMETER stop <|im_end|>
PARAMETER num_ctx 4096
PARAMETER num_gpu 0
bash 复制代码
ollama create myvlm -f Modelfile

关键注意 :视觉模型必须配置正确的多模态对话模板(TEMPLATE)。缺少模板时,图片 token 无法被正确投影,模型只会返回占位符(如 [img-0])或空内容。模板中应使用 {``{ range .Images }} 占位,而非手写 <|image_pad|> 等原生 chat template 语法------后者属于 llama.cpp 原生格式,Ollama 的 Go 模板引擎不兼容。

4.3 Python 依赖

bash 复制代码
pip install pymupdf requests

五、识别脚本示例

python 复制代码
import fitz, base64, json, urllib.request, os

PDF_PATH = "document.pdf"      # 待识别 PDF
MODEL = "myvlm"                # Ollama 中的视觉模型名
DPI = 180

doc = fitz.open(PDF_PATH)

for page_idx in range(len(doc)):
    page = doc[page_idx]
    # ① 先尝试提取文本层
    text = page.get_text().strip()
    if text:
        print(f"--- 第 {page_idx+1} 页(文本层)---\n{text}")
        continue

    # ② 无文本层 → 栅格化
    pix = page.get_pixmap(dpi=DPI)
    img_b64 = base64.b64encode(pix.tobytes("png")).decode()

    # ③ 调用视觉模型
    payload = {
        "model": MODEL,
        "messages": [
            {"role": "system",
             "content": "你是一个OCR助手。请对图片中的文字做OCR,按原文逐行输出所有可见文字。"},
            {"role": "user",
             "content": "请识别这张图片中的所有文字:",
             "images": [img_b64]}
        ],
        "stream": False,
        "options": {"temperature": 0.1}
    }
    req = urllib.request.Request(
        "http://localhost:11434/api/chat",
        data=json.dumps(payload).encode(),
        headers={"Content-Type": "application/json"}
    )
    resp = json.load(urllib.request.urlopen(req, timeout=900))
    out = resp["message"]["content"].strip()
    print(f"--- 第 {page_idx+1} 页(视觉识别,{len(out)} 字)---\n{out}")

doc.close()

六、提升识别质量的实践建议

  1. 先判文本层再识别:有文本层的 PDF 直接提取,速度快、零错误,避免无谓调用模型。
  2. 合理设置 dpi:过低(<120)小字模糊;过高(>250)图片过大、推理慢。150--200 是平衡点。
  3. 分块识别:整页密集中文容易让小模型漏字或幻觉。可先裁剪出单段文字区域,逐块送模型。
  4. 明确提示词:用 system 角色固定"OCR 助手"身份,要求"逐行输出原文",比开放式提问更准。
  5. 模型规模取舍:3B 模型单页 CPU 推理约 5--20 秒,适合简单清晰内容;密集教材/扫描件建议 7B 以上模型。
  6. 控制台乱码 :Windows 终端默认 GBK,建议脚本中用 print(repr(text)) 查看原始输出,或切到 UTF-8 编码。

七、常见问题排查

模型只回 [img-0] 或空内容

  • 原因 :Modelfile 缺少多模态 TEMPLATE,视觉投影未生效。
  • 解决 :补充 Qwen2-VL 风格模板后重新 ollama create

ollama pull 连接官方源超时

  • 原因 :网络无法访问 registry.ollama.ai 或其底层存储(Cloudflare R2)。
  • 解决 :改用国内模型平台的 GGUF 文件直链下载 + 手动 ollama create;国内镜像通常只代理目录元数据,不代理实际权重存储,pull 仍可能失败。

设置镜像环境变量后 pull 仍走官方源

  • 原因 :部分 Ollama 旧版本不识别 OLLAMA_REGISTRY_MIRROR 类变量名,pull 仍硬编码官方地址。
  • 解决:不要依赖该变量,直接走手动下载 GGUF 的路径。

用 hosts 把官方域名指向镜像 IP 失败

  • 原因 :TLS 证书校验不通过------镜像证书签的是自己域名,而非 registry.ollama.ai,握手报 tls: internal error
  • 解决:此路不通,改用 GGUF 直链方案。

识别结果乱码

  • 原因:终端编码非 UTF-8。
  • 解决 :脚本内用 repr() 打印,或 chcp 65001

小模型识别不准、出现幻觉

  • 原因:3B 级别模型对密集中文 OCR 能力有限。
  • 缓解:提高 dpi、分块识别、升级更大模型。

八、方案对比与选型

方案 优点 局限 适用
本地视觉模型(本教程) 隐私好、零调用费、可离线 小模型准确率低、CPU 慢 普通电脑、轻量识别
本地传统 OCR(PaddleOCR/Tesseract) 快、准(清晰扫描件)、轻量 需 Python 环境、复杂版面弱 批量、结构化程度高
云端视觉 API 准确率高、无需本地算力 数据出网、有费用 高质量、偶发需求

九、小结

本地用 Ollama + 视觉模型识别 PDF 的完整链路是:判断文本层 → 栅格化页面 → base64 → 调用 /api/chat → 解析文本。该方案在普通 CPU 电脑上即可运行,3B 级别模型单页推理约 5--20 秒。成功的关键在于:① 正确获取并配置视觉模型(尤其是多模态模板);② 根据内容复杂度合理选择模型规模与分块策略。瓶颈通常不在电脑配置,而在模型获取渠道与模型能力本身。

相关推荐
经典19923 小时前
解析pdf表格内容
windows·pdf
星花月5 小时前
【无标题】
ai·语言模型·pdf·deep learning
E_ICEBLUE5 小时前
Python 办公自动化:将 PowerPoint (PPT/PPTX) 转换为 PDF 【全面指南】
python·pdf·powerpoint
XLYcmy1 天前
pdf论文处理:CSV输出模式
数据库·python·pycharm·pdf·论文·csv·dify
SamChan902 天前
用Python+Requests批量翻译PDF:从脚本到调度
后端·python·microsoft·ai·pdf·机器翻译
SamChan903 天前
PDF翻译API的JWT签名鉴权与速率限制设计:安全实战指南
网络·安全·pdf
Web打印3 天前
gridreport导出后的pdf只支持①到⑨,然而⑩之后的不支持_gwj_20260811_122323.docx
pdf
AmyLin_20013 天前
PDF 脱敏技术【1】:PDF 脱敏不是盖黑框:为什么敏感信息仍能被复制,正确的保护方式是什么?
安全·pdf·sdk·脱敏·文档安全·pdf 脱敏·智能脱敏
denggun123453 天前
PDF解析 Mineru
pdf