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
Document analysis backend SURYA_DOCUMENT_ANALYSIS_BACKEND surya2_ocr_only, surya2_full, docling_default
Layout backend SURYA_LAYOUT_BACKEND docling, surya2
Table backend SURYA_TABLE_BACKEND docling, surya2, disabled
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.

Document Analysis Modes

Full Surya 2 document analysis is optional and off by default. The default document-analysis mode is surya2_ocr_only, which keeps the existing behavior: Surya handles OCR only, while Docling continues to own layout and table processing.

Select document-analysis behavior with SuryaOcrOptions or environment variables:

SuryaOcrOptions(
    backend="surya2",
    document_analysis_backend="surya2_ocr_only",  # default: full integration off
    layout_backend="docling",
    table_backend="docling",
)
export SURYA_DOCUMENT_ANALYSIS_BACKEND=surya2_ocr_only
export SURYA_LAYOUT_BACKEND=docling
export SURYA_TABLE_BACKEND=docling

Valid document-analysis values are:

Mode Valid layout/table settings Behavior
surya2_ocr_only SURYA_LAYOUT_BACKEND=docling, SURYA_TABLE_BACKEND=docling by default Default and recommended first-slice mode. Surya OCR is used through the OCR plugin seam; Docling layout/table remain in place.
docling_default docling layout/table Comparison/control mode. It must not be interpreted as Surya 2 full integration.
surya2_full Requires SURYA_OCR_BACKEND=surya2, SURYA_LAYOUT_BACKEND=surya2, and SURYA_TABLE_BACKEND=surya2 or disabled Explicit, experimental, fail-closed mode. In this first slice it probes Surya 2 document-analysis capabilities and then fails with surya2_full_not_implemented; it does not yet replace Docling layout/table.

Rollback/disable options:

  • Leave SURYA_DOCUMENT_ANALYSIS_BACKEND unset, or set SURYA_DOCUMENT_ANALYSIS_BACKEND=surya2_ocr_only, to keep full integration disabled.
  • Use SURYA_OCR_BACKEND=surya1 to return to the validated v1-style OCR rollback path.
  • Do not remove Docling layout/table components for this first slice; no Egret/tableformer removal is claimed here.

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.2.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.2.0
File Size Uploaded
docling_surya_ocr-0.2.0.tar.gz 122.1 kB Details

Built distribution (wheel)

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

Total release size: 181.2 kB

Release files / docling_surya_ocr-0.2.0.tar.gz

Download URL docling_surya_ocr-0.2.0.tar.gz
Size 122.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5af10a1cd97bfe559c99e736cef44e817d121cba5cda56e1c528a1bcbcb2fa05
BLAKE2b-256 checksum
How to use checksums
de21036fddb61f7988644f6c5eabd853df6f34f8a5954b59b76b28c1ae3de6a2
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 10, 2026.

Transparency log

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

Download URL docling_surya_ocr-0.2.0-py3-none-any.whl
Size 59.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6577e40e14545a0cf6b4e8a0f2a663e319d51d5fda140586ef67a4e77686f13
BLAKE2b-256 checksum
How to use checksums
8e33d469ad9639e316c955fe6f696f678ca2a037c20bf95090a560f5a4ac1ae0
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 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

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