A 1.3B OCR Model That Runs on Your Own Machine, and a 2B Model That Grades It

Short version: OpenBMB and ModelBest open-sourced two small models on October 31. MiniCPM-OCR 1.0 (1.3B) reads documents into text, tables, formulas, and charts. MiniCPM-OCR Jev (2B) does not read anything: it scores somebody else’s OCR output from 0 to 1, so you can auto-accept the good pages and send the rest to a human. The pair fits on a laptop, runs through llama.cpp, and the second model is the interesting one.

Two models, two jobs

Most OCR announcements are one model that reads better. This one is a pipeline with a quality gate built in, and the gate is the part worth stealing.

MiniCPM-OCR 1.0 is trained on top of MiniCPM-V 4.6, with a SigLIP vision encoder and a Qwen3.5 language model. It handles Chinese and English documents, including scans, phone photos, curved pages, and tilted inputs. It outputs plain text, tables as HTML, formulas as LaTeX, and key fields as JSON when you ask for specific fields.

MiniCPM-OCR Jev is a different animal. It is trained from Qwen3.5-2B with the language-model head replaced by a binary classification head. You give it a region crop from the document plus a candidate OCR result, and it returns a score: higher means the candidate is more likely correct. It works on output from any OCR engine, not just its sibling. On the authors’ JevOCRBench it scores 93.6 AUROC, ahead of a 35B judge model at 90.1 and close to a 397B model at 93.8. Those are the authors’ numbers, and the authors themselves say to validate separately on your own data before trusting it in production. Take both halves of that sentence seriously.

The pipeline the authors suggest, and the one I would actually build:

  1. Parse the document with MiniCPM-OCR 1.0 (or whatever parser you already run).
  2. Score every region with Jev.
  3. Auto-accept everything above your threshold, route the rest to a human or a correction step.

Pick the threshold from samples of your own documents, not from the paper. A higher threshold means fewer auto-accepted pages and more review work; that tradeoff is the whole product decision, and no benchmark makes it for you.

Running MiniCPM-OCR locally

The smallest honest setup is llama.cpp. The official GGUF repo has the files, and you need two of them: the language model and the vision projector. The projector is not optional.

hf download openbmb/MiniCPM-OCR-1.0-gguf MiniCPM-OCR-1_0-Q8_0.gguf --local-dir .
hf download openbmb/MiniCPM-OCR-1.0-gguf mmproj-model-f16-4x.gguf --local-dir .

Q8_0 is 0.81 GB and near-lossless; the F16 projector is 0.90 GB. The smallest recommended pair is Q4_K_M (0.53 GB) with the F16 projector, 1.43 GB total. Prefer Q8_0 for code or XML heavy pages: the Q4_K_M notes admit closing-tag slashes can drop in code-heavy documents, which is exactly the kind of quiet corruption OCR is supposed to eliminate.

Then point the multimodal CLI at a page:

llama-mtmd-cli \
  -m ./MiniCPM-OCR-1_0-Q8_0.gguf \
  --mmproj ./mmproj-model-f16-4x.gguf \
  --image page.png -p "Text Recognition:" \
  --jinja -ngl 99 -c 8192 --temp 0

You need llama.cpp b11826 or newer. The prompts are region-specific, and they matter:

  • Text block, paragraph, title, or whole page: Text Recognition:
  • Table: Table Recognition:
  • Display formula: Formula Recognition:
  • Chart: Chart to Table:
  • Seal: Seal Recognition:

For a whole PDF rather than one page, use the official SDK. It reads the PDF or image, detects layout with PP-DocLayoutV3, recognizes each region, and assembles Markdown in reading order. That is the difference between a demo and a pipeline: one page through a CLI proves the model works, the SDK gives you a document back.

The SDK also has an Agent Skill: point a coding agent at the skill doc in the repo and it sets up the environment, downloads the model, and parses a first document. I have opinions about letting an agent set up my environment unsupervised, but as a starting point for a Saturday afternoon it beats reading install docs.

Running MiniCPM-OCR Jev

Jev is a separate model, and its interface is narrower than the parser’s. It scores one region at a time: the original region image, the candidate text, and the region category (text, formula, or table). The service or SDK handles rendering the candidate text back into an image for comparison; if you call the SDK service without a renderer, you supply the rendered image yourself.

That narrowness is a feature. A judge that only answers “is this right, 0 to 1” is easy to slot into an existing pipeline, easy to threshold, and easy to log. You can also run several parsers over the same regions and let Jev pick the best candidate per region, which turns “which OCR engine should I use” from a religious question into a measured one.

Fine print

Everything about speed here is OpenBMB’s own claim: DSpark decoding acceleration improves end-to-end efficiency by 55 percent, throughput about 1.49x PaddleOCR-VL-1.6 and 3.62x MinerU2.5 Pro. I have not run inference on my own hardware for this post, so treat those as vendor numbers until someone measures them on a real machine. The commands, file sizes, and prompts above are verified against the official model cards, not copied from the press release.

Two gotchas from the model cards, both the kind that waste an evening:

  • If you convert the weights yourself instead of using the official GGUF files, start the server with thinking disabled, or llama-server returns the transcription in reasoning_content and an empty content. The official GGUF files already have thinking disabled in the embedded template.
  • A DSpark draft model must match its main checkpoint from the same release. Do not mix draft weights with a different main checkpoint.

Why this matters beyond OCR

OCR is a solved problem the way plumbing is a solved problem: it works until it silently does not, and then a bad table extraction flows into every downstream step. Every document agent that reads PDFs, invoices, and papers all day has this failure mode, and most of them have no quality gate at all.

Jev is a small, cheap, special-purpose answer to a general problem: put a verifier behind your generator, and make the verifier dumber and cheaper than the thing it checks. That pattern works far beyond OCR. A 2B model that says “this looks wrong, a human should look” is worth more in production than a 400B model that is right slightly more often and never admits doubt.

Both models are Apache-2.0, on Hugging Face and ModelScope, with day-one support for vLLM, SGLang, llama.cpp, and Ollama, plus OpenVINO builds for Intel hardware. The whole thing fits in under 2 GB at the small end. Try it on your hardest pages first: dense tables, formulas, phone photos. If it survives those, the easy pages take care of themselves.

Links

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top