现在开源 OCR 模型有个怪趋势:参数越卷越大,好像不上几十 B 都不好意思叫文档模型。DeepSeek-OCR 偏偏反着来:视觉侧的 DeepEncoder 把一整页文档压成几十到几百个 vision token,解码侧挂一个 3B 的 MoE,实际激活参数只有 570M 左右——单张卡就能吞文档,官方论文口径是单张 A100-40G 一天能产出 20 万页以上的 LLM/VLM 训练数据。对要批量灌训练数据、做知识库数字化的团队来说,这组数字的含义很直白:干这件事的门槛,从一张数据中心卡,降到了一张 24GB 消费卡。更划算的是 token 账:分辨率模式从每页 64 个 vision token 到 400+ 档位任选,10 倍压缩比以内精度还有 97%。
这篇是动手向 SOP:从环境安装、Transformers 推理、vLLM 批量、API 服务化到排障清单,命令全部取自官方 README 原文。先说边界:本文只管「怎么装」;至于 DeepSeek-OCR 两代和 GOT-OCR2.0、MinerU2.0 等模型横向怎么选、每页 token 谁更省,看同批横评《六款开源 OCR 模型横评》(opensource-ocr-models-comparison-review)——怎么选看横评,怎么装看本文。
一、两代模型,两条路线:先定主轴
动手前必须先搞清楚一个坑:DeepSeek-OCR 有两个官方仓库,路线并不一样。分不清这一点,很容易在 2 代 README 里翻不到 vLLM 上游安装法,或者拿 1 代的推理参数去套 2 代代码,然后卡在报错上。很多教程把两代混着写,读者照抄发现参数对不上,多半就是踩了这里——所以本文每条命令、每个参数都标注代际。
2 代仓库 DeepSeek-OCR-2(github.com/deepseek-ai/DeepSeek-OCR-2)2026 年 1 月 27 日发布,许可证 Apache-2.0,自带 transformers 和 vLLM 两套脚本。但注意:它的 README 里没有上游 vLLM 支持的段落,vLLM nightly 安装法、防乱码的 logits 处理器、OpenAI 兼容 API 这些成熟生态,全部在 1 代仓库 DeepSeek-OCR(github.com/deepseek-ai/DeepSeek-OCR)的文档里——1 代从 2025 年 10 月 20 日起获得 vLLM 上游支持。
所以本文主轴定为:环境安装和 Transformers 推理主线用 2 代,vLLM 上游和 API 服务化走 1 代兼容路线并注明差异。这样安排的理由:2 代是当前主推版本,新项目从它起步以后不用迁移;1 代则是 vLLM 生态的成熟入口,服务化生产环境绕不开。两代代码参数不能混抄,后文逐一标明。
许可证先交代清楚:1 代 LICENSE 文件是 MIT(Copyright (c) 2025 DeepSeek,仓库原文实抓);2 代 LICENSE.txt 是 Apache-2.0,文末署 Copyright (c) 2023 DeepSeek,年份疑似模板复用笔误。两代都可商用,但别笼统写成 MIT。这个差异也不是文案问题:MIT 只要求保留版权声明,Apache-2.0 额外带专利授权和变更声明条款,企业采购前合规审一遍更稳妥。
二、硬件账:6.68GB 权重,激活 570M
权重体积是从 ModelScope 文件清单 API 实抓的:单分片 model-00001-of-000001.safetensors 共 6,672,547,120 字节,约 6.68GB(bf16),外加约 9.5MB 的 tokenizer.json,以及 trust_remote_code 必需的 modeling_deepseekocr.py 等文件。tokenizer.json 看着不起眼,少了它加载照样失败,下载完对着文件清单核一遍再开跑。
架构账(论文 arXiv 2510.18234 口径):DeepEncoder 约 250M 参数,SAM-base 窗口注意力、16 倍卷积压缩、CLIP-large 全局注意力和 MLA 一路串下来;解码器 DeepSeek3B-MoE-A570M,总参 3B,激活约 570M。激活小,就是显存省、速度快的原因。对部署者来说这笔账有两层:总参 3B 决定权重要占约 6.68GB 存储,放显存里也是它;激活 570M 决定推理时真正参与计算的部分很小,这才是它能在消费卡上跑出可用速度的底层原因。
吞吐账同样用论文口径:生产环境单张 A100-40G 日产 20 万+ 页;README 另载 vLLM PDF 路径并发约 2500 tokens/s(同卡)。压缩比:低于 10 倍时 OCR 精度 97%,20 倍时约 60%。这笔账对应到下游:一页纸从图片变成几百个 token,再喂给任何 LLM 做摘要、抽取、翻译,成本都按 token 计——压得越狠,下游越便宜,这也是「上下文光学压缩」这个定位的实际价值。
显存账要泼盆冷水:官方从未公布显存门槛,至今没有数字。社区实测口径(多出自 CSDN 推广文,需自行验证)是 bfloat16 峰值约 19.1 至 22.8GB(低/高分辨率),结论 24GB 卡安全;A10 24GB 每页 3.2 至 12.5 秒,4090 快 2.4 至 2.6 倍;另有 3060 12GB 用 sdpa 注意力加分块预处理的低配路线。要提醒的是,这批数字部分出自含第三方镜像推广的 CSDN 星图系列文章,只能当社区口径参考,不构成官方承诺。稳妥的结论是:24GB 卡按可跑准备,12GB 卡按低配实验路线准备,8GB 及以下不要硬上。
三、环境安装:conda 加 torch 2.6.0 加 flash-attn
官方 README 原话:Our environment is cuda11.8+torch2.6.0,两代环境一致。逐字安装命令如下(以 2 代为例):
git clone https://github.com/deepseek-ai/DeepSeek-OCR-2.git # 1代: DeepSeek-OCR.git
conda create -n deepseek-ocr2 python=3.12.9 -y
conda activate deepseek-ocr2
# 需先手动下载 vllm-0.8.5 whl: https://github.com/vllm-project/vllm/releases/tag/v0.8.5
pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu118
pip install vllm-0.8.5+cu118-cp38-abi3-manylinux1_x86_64.whl
pip install -r requirements.txt
pip install flash-attn==2.7.3 --no-build-isolation几个要点:python 固定 3.12.9,社区反馈 3.11 装 flash-attn 会失败;flash-attn 2.7.3 必须加 --no-build-isolation,且 torch 先装再装它;conda 单独开环境是刚需,flash-attn 和 vLLM 的版本锁得很死,别往 base 环境里塞。至于为什么 vllm-0.8.5 的 whl 要手动下载:官方环境锁定 cu118,PyPI 上的通用包对不上 CUDA 版本,README 的做法是从 vLLM 的 GitHub release 页把对应 whl 下到本地再装。如果想让 vLLM 和 transformers 共存于同一环境,README 原注说明 vllm 0.8.5+cu118 requires transformers>=4.51.1 这类报错可以忽略。版本组合总结:python 3.12.9、torch 2.6.0 加 cu118、transformers 按 requirements.txt(不低于 4.51.1)、flash-attn 2.7.3;vLLM 走仓库脚本路线装 0.8.5+cu118,走上游路线装 nightly。这套 cuda11.8 组合放到 2026 年已经偏旧,官方文档未更新,属生态滞后点,能跑就行。磁盘预留至少 20GB:权重 6.68GB 加缓存、conda 环境和 torch cu118 全家桶,紧张的话把 HF 缓存目录指到大容量盘。
四、Transformers 推理:2 代代码逐字
装完先走最短的 transformers 路线,以下为 2 代 README 原文逐字:
from transformers import AutoModel, AutoTokenizer
import torch, os
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
model_name = 'deepseek-ai/DeepSeek-OCR-2'
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModel.from_pretrained(model_name, _attn_implementation='flash_attention_2', trust_remote_code=True, use_safetensors=True)
model = model.eval().cuda().to(torch.bfloat16)
# prompt = "<image>\nFree OCR. "
prompt = "<image>\n<|grounding|>Convert the document to markdown. "
image_file = 'your_image.jpg'
output_path = 'your/output/dir'
res = model.infer(tokenizer, prompt=prompt, image_file=image_file, output_path = output_path, base_size = 1024, image_size = 768, crop_mode=True, save_results = True)1 代有三处差异:model_name 换成 deepseek-ai/DeepSeek-OCR,image_size=640,并且多一个 test_compress = True 参数——两代代码千万别混抄。
拆一下 infer 的参数:base_size=1024 是全局图尺寸,image_size=768 是切块尺寸,crop_mode=True 打开动态切块,save_results=True 会把识别结果写到 output_path 指定的目录;2 代默认就是这套动态组合。首次运行会自动从 HF 下载权重到缓存目录,国内网络不稳的话,建议先手动下载再改本地路径加载。
prompt 写法上,2 代只保留两条主 prompt:文档转 markdown 用带 <|grounding|> 的 Convert the document to markdown.,自由 OCR 用 Free OCR.。带 <|grounding|> 的写法会让模型输出带版面坐标的 markdown,做版面还原和后期定位时用得上,不要坐标就换 Free OCR。1 代更丰富:图表解析用 Parse the figure.,通用描述、无版式输出之外,还有带 <|ref|> 的定位模式,中文也能当 ref 用,README 示例就是「先天下之忧而忧」。
下载模型走 HF 官方源,国内可用 ModelScope 或镜像站,社区命令如 modelscope download --model deepseek-ai/DeepSeek-OCR。切记把 safetensors 和 modeling 文件一起下全,只下权重不下 py 文件,trust_remote_code 加载时会报错。顺带一提,2 代的模型 ID 是 deepseek-ai/DeepSeek-OCR-2,从 ModelScope 或镜像站下载时别写成 1 代的仓库名。
五、五种分辨率模式与 token 账
这是 DeepSeek-OCR 最值得算的一笔账。1 代 README 给了五种模式(原文数据):
| 模式 | base_size/image_size | crop_mode | vision tokens/页 | 适用场景 |
|---|---|---|---|---|
| Tiny | 512/512 | False | 64 | 批量粗筛、速度优先 |
| Small | 640/640 | False | 100 | 普通文档;论文称 100 tokens 已胜 GOT-OCR2.0 的 256 tokens |
| Base | 1024/1024 | False | 256 | 均衡默认 |
| Large | 1280/1280 | False | 400 | 密排小字文档 |
| Gundam | 1024/640 | True | 动态,约 n×100+256 | 版面复杂、报纸、含图文档,速度换质量 |
crop_mode 为 False 是原生固定分辨率,True 是动态切块。2 代没有五模式选型表,只给单一动态模式:(0-6) 块 768×768 加 1 块 1024×1024,对应 (0-6)×144+256 个 vision token,默认 crop_mode=True,可以理解为把 Gundam 的动态思路做成了唯一默认。
怎么选:普通文档从 Small 640 起步最划算,一页 100 个 token,相当于把一页纸压进一百个词元,后续处理成本直接降一档;密排小字上 Large;版面乱、图文混排用 Gundam;批量粗筛 Tiny 64 tokens 起跑。Gundam 的动态切块数随页面内容变化,版面越复杂切块越多,token 也随之上涨,做预算时留余量。算一笔具体的账:一本 300 页的文档,Tiny 模式视觉侧只要约 1.9 万 token,Base 要 7.7 万,Large 要 12 万,差距接近 6 倍;对日均几千页的流水线,模式选择直接决定要几张卡。跑起来显存吃紧,先降 base_size 到 512/640 或关掉 crop_mode,这两招社区实测有效。
六、vLLM 路径:nightly 加 NGramPerReqLogitsProcessor
vLLM 上游支持是 1 代的事(2025 年 10 月 23 日起官方支持),1 代 README 原文安装法:
uv venv
source .venv/bin/activate
# Until v0.11.1 release, you need to install vLLM from nightly build
uv pip install -U vllm --pre --extra-index-url https://wheels.vllm.ai/nightly离线批量推理,1 代 README 原文逐字:
from vllm import LLM, SamplingParams
from vllm.model_executor.models.deepseek_ocr import NGramPerReqLogitsProcessor
from PIL import Image
llm = LLM(
model="deepseek-ai/DeepSeek-OCR",
enable_prefix_caching=False,
mm_processor_cache_gb=0,
logits_processors=[NGramPerReqLogitsProcessor]
)
image_1 = Image.open("path/to/your/image_1.png").convert("RGB")
image_2 = Image.open("path/to/your/image_2.png").convert("RGB")
prompt = "<image>\nFree OCR."
model_input = [
{"prompt": prompt, "multi_modal_data": {"image": image_1}},
{"prompt": prompt, "multi_modal_data": {"image": image_2}}
]
sampling_param = SamplingParams(
temperature=0.0,
max_tokens=8192,
# ngram logit processor args
extra_args=dict(
ngram_size=30,
window_size=90,
whitelist_token_ids={128821, 128822}, # whitelist: <td>, </td>
),
skip_special_tokens=False,
)
model_outputs = llm.generate(model_input, sampling_param)
for output in model_outputs:
print(output.outputs[0].text)三个要点:一是 NGramPerReqLogitsProcessor 必须传,不挂它输出会重复乱码;二是 whitelist_token_ids 里的 128821 和 128822 对应表格起止标记,要表格输出就带上;三是按 vLLM 官方 recipe 提示,关闭 prefix caching、用 plain prompt、按显存调 max_num_batched_tokens。再补一句:temperature=0.0 是 OCR 任务的标配,识别要确定性输出,不要开采样;max_tokens=8192 是给密排长文档留的余量,按自己的页面密度调整。上游支持意味着不用碰仓库自带脚本,直接 pip 装 vLLM 就能跑 1 代模型,这也是后文 vllm serve 做 API 服务化的前提。
2 代仓库也自带 vLLM 脚本:进 DeepSeek-OCR2-vllm 目录,改 config.py 里的 INPUT_PATH 和 OUTPUT_PATH,跑 run_dpsk_ocr2_image.py(流式输出)、run_dpsk_ocr2_pdf.py(README 称速度与 1 代持平)或 run_dpsk_ocr2_eval_batch.py(OmniDocBench v1.5 批测)。1 代对应文件是 run_dpsk_ocr_image/pdf/eval_batch.py。
七、API 服务化与 PDF 批处理
OpenAI 兼容 API 用 vLLM 官方 recipe 的命令(1 代口径,社区转载 recipe 原文):
vllm serve deepseek-ai/DeepSeek-OCR --logits_processors vllm.model_executor.models.deepseek_ocr:NGramPerReqLogitsProcessor --no-enable-prefix-caching --mm-processor-cache-gb 0服务起来后,客户端用 openai 库连 http://localhost:8000/v1,图片走 image_url 传 base64,请求里要带防乱码参数:skip_special_tokens 设为 False,vllm_xargs 传 ngram_size 30、window_size 90、whitelist_token_ids [128821, 128822],与离线推理同一套配置。2 代能否直接 vllm serve 未经验证(其 README 无此段落),服务化示范用 1 代最稳。
PDF 批处理两条路:官方路线是仓库里的 run_dpsk_ocr_pdf.py,改 config.py 即可,1 代 A100-40G 口径约 2500 tokens/s;社区路线用 PyMuPDF 逐页 get_pixmap(dpi=150) 转 PIL Image,拼成 batched input 一次 generate,页间用分隔符拼接 markdown。dpi=150 这个参数别乱改,社区实测它是清晰度和速度的平衡点,拉到 300 显存和耗时都会明显上涨。Docker 路线是社区方案:拉 vllm/vllm-openai:v0.11.2 镜像起容器挂模型目录,起容器记得带 --gpus all 和 --shm-size,共享内存给小了多进程加载会卡死,注意官方仓库本身没有提供 Dockerfile,这点要认清楚。显存富余想多卡,社区口径是 vllm 侧加 tensor_parallel_size=N。
八、排障清单
高频问题十条,处理口径均已标注:
| 问题 | 处理 |
|---|---|
| flash-attn 编译失败 | 官方命令即 pip install flash-attn==2.7.3 --no-build-isolation;社区:python 3.11 会失败、务必 3.12;torch 先装 |
| 不想编译 flash-attn | 加载时改 _attn_implementation='sdpa'(社区实测 3060 可用,略慢) |
| transformers 版本冲突警告 | 官方 README:vllm 0.8.5 requires transformers>=4.51.1 报错可忽略 |
| trust_remote_code 报错 | 必须 trust_remote_code=True 且 use_safetensors=True;勿只下 safetensors 不下 modeling py 文件 |
| 显存 OOM | 社区:降分辨率(base_size=512/640)、crop_mode=False、减 batch;连续推理 OOM 加 torch.inference_mode() 并每轮 empty_cache;vLLM 侧减 max-model-len 和 gpu-memory-utilization |
| 输出乱码或重复 | vLLM 必须挂 NGramPerReqLogitsProcessor |
| 表格输出异常 | whitelist_token_ids 加表格 token(128821/128822) |
| 中文路径加载失败 | 模型、图片、输出目录全用英文路径(社区实测) |
| 长图小字识别差 | 先切块再缩放,勿整页强缩;改用 Gundam 动态模式(社区实测) |
| Mac 能不能跑 | 社区称模型未适配 Metal,M 系列不可用(非官方口径,需自行核实) |
FAQ
Q1:DeepSeek-OCR 到底需要多少显存? 官方没有给过任何显存数字。社区口径是 bf16 峰值约 19 至 23GB、24GB 卡安全,另有 3060 12GB 用 sdpa 的低配路线;这些数据多出自带推广性质的 CSDN 文章,只能参考,上量前建议按自己的分辨率模式实测。如果手上只有 12GB 卡,先走 sdpa 加降分辨率的组合,把模式固定在 Small 再往上试。
Q2:1 代和 2 代怎么选? 想用新架构、走 Transformers 推理,选 2 代(Apache-2.0);要上游 vLLM 支持、API 服务化和成熟生态,选 1 代(MIT)。判断方法很朴素:先问自己要不要 vllm serve 和上游 vLLM 的批量推理,要就 1 代;只做单机脚本推理,2 代代码更简洁。两代的精度差异官方没有给对照数据,别只凭版本号新旧下结论。更细的横向对比看同批横评篇。
Q3:flash-attn 装不上怎么办? 先核对 python 是 3.12.9、torch 2.6.0 已装好,再执行带 --no-build-isolation 的 flash-attn 2.7.3 安装命令。编译很吃内存和编译器环境,机器配置低的话别硬耗,把模型加载参数改成 _attn_implementation='sdpa',牺牲一点速度换能跑。
Q4:能部署成 OpenAI 兼容 API 吗? 能,走 1 代:vllm serve 加 --logits_processors 和 --no-enable-prefix-caching 参数,客户端带防乱码的 extra_body 配置,见第七节,命令是 vLLM 官方 recipe 原文。2 代能否 vllm serve 未验证。服务化前先用两条图片请求验证输出正常,再接生产流量。
Q5:中文表格效果怎么样? 官方没有中文专项说明;prompt 的 <|ref|> 定位支持中文,社区称中英混排可用但需实机验证。表格输出务必带上 128821 和 128822 两个白名单 token,否则表格容易被截断或乱码。建议先用 Small 或 Base 模式小批量试跑中文文档,确认格式再放量。另外中文文档的竖排、印章、手写批注这些场景,官方都没有基准数据,横评篇里有同尺对比可参考。