Skip to main content

docling-surya-ocr

Docling OCR plugin backed by Surya. It provides the Docling OCR engine key suryaocr and a stable Python import namespace docling_surya_ocr.

The repository currently contains three runtime paths:

  • surya2: target production path, using Surya 2 full-page OCR with llama.cpp on CPU by default and vLLM as a supported GPU backend.
  • surya1: validated v1-style Surya recognizer path, kept as an explicit rollback and benchmark reference.
  • unlimited: experimental comparison backend for internal evaluation only; it is explicit-only and not part of the Surya production path.

For UVO-style document processing, the intended production shape is Docling + Surya 2 + llama.cpp on a large CPU host, with page-level parallelism tuned by benchmark. GPU/vLLM stays available behind the same backend contract so the converter does not need to be rewritten later.

Install

From PyPI after release:

pip install docling-surya-ocr

From a built wheel:

pip install docling_surya_ocr-0.1.0-py3-none-any.whl

For local development:

pip install -e .[dev]

Runtime dependencies are declared for Python >=3.12,<3.13:

pip install "docling>=2.115,<3" surya-ocr

For GPU validation, install a CUDA-enabled Torch build that matches the target host/container.

Docling Usage

Use Docling's external OCR plugin seam and enable external plugins:

from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling_surya_ocr import SuryaOcrOptions

pipeline_options = PdfPipelineOptions(
    do_ocr=True,
    ocr_model="suryaocr",
    allow_external_plugins=True,
    ocr_options=SuryaOcrOptions(
        lang=["sk", "en"],
        backend="surya2",
        surya2_inference_backend="llamacpp",
        surya2_inference_parallel=4,
    ),
)

converter = DocumentConverter(
    format_options={
        InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options),
    }
)

result = converter.convert("document.pdf")
text = result.document.export_to_text()

The package also exposes a compatibility import alias for deployments that already use the upstream plugin import path:

from docling_surya import SuryaOcrOptions

The Docling OCR model key remains suryaocr.

Backend Selection

Select the plugin backend in code or through SURYA_OCR_BACKEND:

SuryaOcrOptions(backend="auto")    # prefers Surya 2 when available
SuryaOcrOptions(backend="surya2")  # target Surya 2 path; fails closed if unavailable
SuryaOcrOptions(backend="surya1")  # validated v1-style rollback path
export SURYA_OCR_BACKEND=surya2

auto prefers Surya 2 when the Surya 2 API is available. If Surya 2 is unavailable and no strong Surya 2 runtime setting is present, auto can fall back to surya1. Use explicit backend="surya2" for production validation when fallback must not hide failures.

The Surya 2 inference backend defaults to llamacpp:

export SURYA_OCR_BACKEND=surya2
export SURYA_INFERENCE_BACKEND=llamacpp
export SURYA_INFERENCE_PARALLEL=4

vLLM is supported as the GPU inference backend:

export SURYA_OCR_BACKEND=surya2
export SURYA_INFERENCE_BACKEND=vllm
export SURYA_INFERENCE_URL=http://localhost:8000/v1
export SURYA_INFERENCE_PARALLEL=8

CPU Production Path

For Surya 2 CPU production, use llama.cpp and tune page-level parallelism:

export SURYA_OCR_BACKEND=surya2
export SURYA_INFERENCE_BACKEND=llamacpp
export SURYA_INFERENCE_PARALLEL=4
export SURYA_DEVICE=cpu
export SURYA_CPU_THREADS=8

Benchmark SURYA_INFERENCE_PARALLEL=1/4/8/16/24/32 on the target EPYC host before selecting a default. The optimum may arrive before all CPU cores are saturated because Surya 2 OCR can become memory-bandwidth or decode limited.

GPU Validation Path

For Surya 2 GPU attach mode, run or attach to an OpenAI-compatible vLLM Surya inference server and configure:

export SURYA_OCR_BACKEND=surya2
export SURYA_INFERENCE_BACKEND=vllm
export SURYA_INFERENCE_URL=http://localhost:8000/v1
export SURYA_INFERENCE_PARALLEL=8
export SURYA_DEVICE=cuda
export SURYA_PRECISION=fp16

Verify CUDA from inside the runtime container:

python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))"

Options

SuryaOcrOptions can be configured directly or via environment variables.

Option Environment variable Example
Languages SURYA_OCR_LANGUAGES sk,en
Backend SURYA_OCR_BACKEND auto, surya1, surya2
Device SURYA_DEVICE cpu, cuda, auto
GPU devices SURYA_GPU_DEVICES 0
GPU memory fraction SURYA_GPU_MEMORY_FRACTION 0.8
Precision SURYA_PRECISION fp16, fp32, bf16, auto
CPU threads SURYA_CPU_THREADS 8
Recognition batch SURYA_RECOGNITION_BATCH 16
Detection batch SURYA_DETECTION_BATCH 16
Docling OCR batch DOCLING_OCR_BATCH 4
Preserve provenance SURYA_OCR_PRESERVE_PROVENANCE true
Surya 2 inference backend SURYA_INFERENCE_BACKEND llamacpp, vllm, auto
Surya 2 inference URL SURYA_INFERENCE_URL http://localhost:8000/v1
Surya 2 keep server SURYA_INFERENCE_KEEP_ALIVE true, false
Surya 2 parallelism SURYA_INFERENCE_PARALLEL 8

The codebase includes an explicit-only unlimited backend for internal experiments. It is not selected by auto and is intentionally omitted from the main Surya production configuration above.

Smoke Test

After installing the wheel, run a conversion without PYTHONPATH=src:

python scripts/smoke_convert.py sample.pdf --plugin suryaocr

Force the Surya 2 CPU path during smoke validation:

python scripts/smoke_convert.py sample.pdf \
  --plugin suryaocr \
  --backend surya2 \
  --inference-backend llamacpp \
  --inference-parallel 4

The smoke test fails closed if Docling external plugins are disabled, the plugin key is unavailable, Docling logs an OCR-stage failure, no text is produced, or Docling page/bbox provenance is missing.

Benchmark

Corpus benchmark example for the Surya 2 CPU path:

python scripts/benchmark_docling_corpus.py benchmarks/pdf-corpus \
  --plugin suryaocr \
  --backend surya2 \
  --inference-backend llamacpp \
  --inference-parallel 16 \
  --jsonl benchmarks/results/surya2-llamacpp.jsonl

The historical benchmark report for this repository is in:

benchmarks/results/docling-surya-ocr-benchmark-report.md

Those historical measurements are for the v1-style backend. They are retained as a rollback/reference baseline, not as Surya 2 llama.cpp production evidence.

Surya 2 Model License

Surya code is Apache 2.0, but Surya 2 model weights are distributed under a modified OpenRAIL-M license. Review the weight license before commercial/production rollout; this package does not vendor or redistribute model weights.

Compatibility Notes

The target verified runtime is Docling 2.115.0. In that version:

  • BaseOcrModel.post_process_cells uses the docling_2115 style and may mutate the page in place.
  • BoundingRectangle is available from docling_core.types.doc.page.
  • Docling provenance uses item.prov entries with page_no and bbox.
  • Surya v1 recognition is available through surya.recognition.RecognitionPredictor; Surya 2 additionally expects surya.inference.SuryaInferenceManager.

Development Checks

python -m pytest tests/unit tests/contract
python -m ruff check src tests scripts
python -m mypy src

Metadata

Release files for docling-surya-ocr 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for docling-surya-ocr 0.1.0
File Size Uploaded
docling_surya_ocr-0.1.0.tar.gz 103.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for docling-surya-ocr 0.1.0
File Interpreter ABI Platform
docling_surya_ocr-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 155.1 kB

Release files / docling_surya_ocr-0.1.0.tar.gz

Download URL docling_surya_ocr-0.1.0.tar.gz
Size 103.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5235ec41edb912b7d3cc1152a075be8094bf9fcf414e204f3d4e214122761918
BLAKE2b-256 checksum
How to use checksums
321cbdcb0f275b0816993852f8c16a310c1bf564fcc7a1e1d919fc1d740509db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

Release files / docling_surya_ocr-0.1.0-py3-none-any.whl

Download URL docling_surya_ocr-0.1.0-py3-none-any.whl
Size 51.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9db23dce499b74321d968a6e7cd9affad17ee46318522053026c595c48c30cad
BLAKE2b-256 checksum
How to use checksums
1939f1880ae4393a4af51b5638d2ed4e3f2ebe1dcbb0fe2b8a1ca20beaf64d30
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page