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 withllama.cppon CPU by default andvLLMas 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_BACKENDunset, or setSURYA_DOCUMENT_ANALYSIS_BACKEND=surya2_ocr_only, to keep full integration disabled. - Use
SURYA_OCR_BACKEND=surya1to 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_cellsuses thedocling_2115style and may mutate the page in place.BoundingRectangleis available fromdocling_core.types.doc.page.- Docling provenance uses
item.proventries withpage_noandbbox. - Surya v1 recognition is available through
surya.recognition.RecognitionPredictor; Surya 2 additionally expectssurya.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)
| File | Size | Uploaded | |
|---|---|---|---|
| docling_surya_ocr-0.2.0.tar.gz | 122.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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