# Docling Administrator & Developer Guide

Docling is an open-source Python framework developed by IBM Research for converting documents from 17 input formats into 8 output formats. It combines AI-powered OCR, layout analysis, table structure recognition, and vision-language models to produce structured document representations. This guide covers the architecture, configuration, deployment, and internals that administrators, operators, and contributing developers need.

---

## 1. Architecture Overview

### 1.1 High-Level Component Diagram

```
                         ┌─────────────────────────────────────────────────┐
                         │              DocumentConverter                  │
                         │   (docling/document_converter.py)               │
                         │                                                 │
                         │  ┌──────────────┐   ┌───────────────────────┐   │
  Sources ──────────────►│  │  FormatOption │   │     InputDocument     │   │
  (file/URL/stream)      │  │  (per-format) │   │  (source + metadata)  │   │
                         │  └──────┬───────┘   └───────────┬───────────┘   │
                         │         │                       │               │
                         │         ▼                       ▼               │
                         │  ┌──────────────┐   ┌───────────────────────┐   │
                         │  │   Backend    │   │      Pipeline         │   │
                         │  │  (parsing)   │──►│    (processing)       │   │
                         │  └──────────────┘   └───────────┬───────────┘   │
                         │                                 │               │
                         │                                 ▼               │
                         │                     ┌───────────────────────┐   │
                         │                     │   ConversionResult    │   │
                         │                     │   (DoclingDocument)   │   │
                         │                     └───────────┬───────────┘   │
                         └─────────────────────────────────┼───────────────┘
                                                           │
                                                           ▼
                                              ┌───────────────────────┐
                                              │   Export / Save As    │
                                              │  MD / JSON / YAML /   │
                                              │  HTML / DocTags / etc │
                                              └───────────────────────┘

Pipeline Detail (StandardPdfPipeline):

  ┌──────────┐   ┌────────┐   ┌─────┐   ┌───────────┐   ┌─────────┐   ┌──────────┐
  │Preprocess│──►│ Layout │──►│ OCR │──►│Table Struct│──►│Read Ord.│──►│Page Assem│
  └──────────┘   └────────┘   └─────┘   └───────────┘   └─────────┘   └──────────┘
                                                                            │
                                                                            ▼
                                                              ┌─────────────────────┐
                                                              │ Optional Enrichments │
                                                              │ Code │ Formula │ Pic │
                                                              │ Chart│ PicClass│ Desc│
                                                              └─────────────────────┘
```

> [!NOTE]
> Docling itself is a **library and CLI tool**, not a web server. The HTTP/REST serving layer lives in the separate `docling-serve` project. This guide covers the core conversion framework only.

### 1.2 Component Inventory

| Component | Location | Responsibility |
|---|---|---|
| **DocumentConverter** | `docling/document_converter.py` | Orchestrates end-to-end conversion; selects backend + pipeline per format |
| **Backends** (20+) | `docling/backend/` | Format-specific parsing: extract pages, text, structure from raw files |
| **Pipelines** (5) | `docling/pipeline/` | Processing logic: ML inference, enrichment, assembly |
| **Models** (15+) | `docling/models/` | ML model wrappers for layout, OCR, table structure, VLM, picture analysis |
| **Factories** | `docling/models/factories/` | Registry + instantiation for pluggable model implementations |
| **Data Model** | `docling/datamodel/` | Pydantic models for options, settings, documents, pipeline config |
| **CLI** | `docling/cli/` | Command-line interface (11 commands) |
| **Service Client** | `docling/service_client/` | Async HTTP client for docling-serve |
| **Utilities** | `docling/utils/` | Profiling, resource management, accelerator detection, locking |

### 1.3 Technology Stack

| Layer | Technology |
|---|---|
| Language | Python 3.10+ |
| Data models | Pydantic v2 (BaseModel, BaseSettings) |
| ML inference | PyTorch, ONNX Runtime, Hugging Face Transformers, vLLM, MLX |
| PDF parsing | docling-parse (C++ accelerated), pypdfium2 |
| OCR | EasyOCR, Tesseract, RapidOCR, macOS Vision (OcrMac) |
| Office formats | python-docx, python-pptx, openpyxl |
| HTML | BeautifulSoup4, Playwright (optional, for rendering) |
| Build | uv (dependency management), pyproject.toml |
| Testing | pytest, markers for ML/cross-platform |
| Docs site | MkDocs with Material theme |
| Linting | ruff (format + lint), mypy |

### 1.4 Ecosystem Context

Docling is part of a family of packages:

| Package | Role |
|---|---|
| **docling** | This project. The main conversion framework. |
| **docling-core** | Shared data types (`DoclingDocument`, `BaseCell`, export mixins). The canonical document model. |
| **docling-ibm-models** | Pre-trained ML models for layout analysis and table structure recognition. |
| **docling-parse** | High-performance C++ PDF parser (text extraction, cell detection). |
| **docling-serve** | HTTP/gRPC serving layer that wraps the docling library. |

### 1.5 Data Flow

1. **Input**: User provides a source — local file path, HTTP(S) URL, or byte stream — along with optional per-format configuration.
2. **Format detection**: `DocumentConverter` inspects the file extension and MIME type to select the matching `FormatOption`, which pairs a `Backend` with a `Pipeline` and format-specific `Options`.
3. **Backend parsing**: The chosen backend (e.g., `DoclingParseDocumentBackend` for PDF) opens the file and exposes pages or document structure.
4. **Pipeline processing**: For paginated formats (PDF, images), the `StandardPdfPipeline` runs a multi-stage sequence: page preprocessing, layout analysis, OCR, table structure recognition, reading order determination, and page assembly. For declarative formats (DOCX, HTML, Markdown, CSV), the `SimplePipeline` delegates directly to the backend's `convert()` method.
5. **Enrichment** (optional): After assembly, optional enrichment models run: code detection, formula recognition, picture description, picture classification, chart extraction.
6. **Output**: A `ConversionResult` wraps the `DoclingDocument` (from docling-core), which can be exported to Markdown, JSON, YAML, HTML, DocTags, or other formats.

### 1.6 Pipeline Descriptions

**StandardPdfPipeline** — The primary pipeline for PDF and image documents. Runs six sequential stages (each parallelized across pages via threaded pipeline stages), then optional enrichments. This is the most resource-intensive path and where GPU acceleration matters most.

**VlmPipeline** — An alternative for PDF/image processing that sends page images to a vision-language model (e.g., Granite Vision, SmolDocling) for direct conversion. Trades the multi-model pipeline for a single VLM call per page. Supports local inference (Transformers, vLLM, MLX) or remote API.

**SimplePipeline** — Handles declarative/structured formats (DOCX, HTML, Markdown, LaTeX, CSV, XLSX, PPTX, AsciiDoc, WebVTT, XBRL, JATS XML, USPTO XML). Calls the backend's `convert()` method directly; no ML models involved.

**AsrPipeline** — Automatic speech recognition for audio/video files. Uses OpenAI Whisper models (standard or MLX variant on Apple Silicon).

**ExtractionVlmPipeline** — Experimental. Uses a VLM to extract structured information from documents according to a user-defined schema.

---

## 2. System Requirements

### 2.1 Python Version

Python **3.10 or higher** is required. The codebase uses modern type hints (`X | Y` union syntax, `TypeVar` with bounds) that require 3.10+.

### 2.2 Operating System Support

| OS | Status | Notes |
|---|---|---|
| Linux (x86_64) | Full support | Primary development/CI platform |
| macOS (Intel) | Full support | — |
| macOS (Apple Silicon) | Full support | MLX acceleration available; OcrMac uses native Vision framework |
| Windows | Supported | Some OCR backends (OcrMac) unavailable; Tesseract requires separate install |

### 2.3 Hardware Requirements

**CPU-only (minimum)**:
- 4+ cores recommended (controlled by `DOCLING_NUM_THREADS`, default 4)
- 8 GB RAM minimum; 16 GB recommended for large PDFs
- SSD storage for model cache (models download to `~/.cache/huggingface/`)

**GPU-accelerated (recommended for production)**:
- NVIDIA GPU with CUDA support (PyTorch CUDA backend)
- Apple Silicon MPS (Metal Performance Shaders) for macOS
- GPU memory: 4 GB minimum for layout + table models; 8+ GB for VLM models
- Flash Attention 2 support optional (set `DOCLING_CUDA_USE_FLASH_ATTENTION2=true`)

> [!TIP]
> Docling auto-detects the best available device (CUDA → MPS → CPU). Override with `DOCLING_DEVICE=cpu` to force CPU-only mode, useful for debugging or resource-constrained environments.

### 2.4 Dependency Groups

Docling uses optional dependency groups (extras) to keep the base install lean:

| Extra | What it installs | When needed |
|---|---|---|
| `tesserocr` | Tesseract OCR via tesserocr bindings | Using `TesseractOcrOptions` |
| `rapidocr` | RapidOCR engine | Using `RapidOcrOptions` |
| `easyocr` | EasyOCR engine | Using `EasyOcrOptions` |
| `ocrmac` | macOS Vision framework OCR | Using `OcrMacOptions` (macOS only) |
| `vlm` | Transformers + VLM model support | Using VLM pipeline with local models |
| `mlx` | MLX framework (Apple Silicon) | Using MLX-based VLM or ASR on macOS |
| `vllm` | vLLM inference engine | Using vLLM-based VLM inference |
| `asr` | Whisper + audio processing | Audio/video transcription |
| `htmlrender` | Playwright browser automation | HTML pages requiring JavaScript rendering |

Install example:

```bash
pip install "docling[vlm,rapidocr]"
```

### 2.5 Model Downloads

On first use, ML models download automatically from Hugging Face Hub to `~/.cache/huggingface/hub/`. Key models:

| Model | Approximate Size | Used By |
|---|---|---|
| Layout analysis (LayoutModel) | ~100 MB | StandardPdfPipeline |
| Table structure (TableStructureModel) | ~100 MB | StandardPdfPipeline |
| EasyOCR language packs | ~50-200 MB per language | EasyOCR backend |
| VLM models (e.g., SmolDocling) | 1-8 GB | VlmPipeline |
| Whisper models | 150 MB - 3 GB | AsrPipeline |

Pre-download models for air-gapped or Docker deployments:

```bash
# Uses the docling CLI to pre-download all default models
docling models download
```

---

## 3. Configuration Reference

### 3.1 Environment Variables

| Variable | Type | Default | Description |
|---|---|---|---|
| `DOCLING_NUM_THREADS` | `int` | `4` | Number of CPU threads for model inference. Controls ONNX Runtime and PyTorch intra-op parallelism. |
| `OMP_NUM_THREADS` | `int` | (unset) | OpenMP thread count. If set, used as fallback when `DOCLING_NUM_THREADS` is not set. |
| `DOCLING_DEVICE` | `str` | `auto` | Hardware device for inference. Values: `auto`, `cpu`, `cuda`, `mps`. `auto` selects the best available. |
| `DOCLING_CUDA_USE_FLASH_ATTENTION2` | `bool` | `false` | Enable Flash Attention 2 for CUDA devices. Requires `flash-attn` package installed. Reduces memory usage and improves throughput for VLM inference. |
| `DOCLING_PARTITION_SIZE` | `int` | (unset) | Partition size for multiprocessing-based document batching. Controls how many documents are grouped per worker process. |
| `DOCLING_HTML_WORKERS` | `int` | (unset) | Number of Playwright browser workers for HTML rendering. Only relevant when using `HTMLBackendOptions(render_page=True)`. |
| `HF_HOME` | `str` | `~/.cache/huggingface` | Hugging Face cache directory. Controls where downloaded models are stored. |
| `TORCH_HOME` | `str` | `~/.cache/torch` | PyTorch cache directory for pre-trained model weights. |

### 3.2 Application Settings (`AppSettings`)

Defined in `docling/datamodel/settings.py`. These are Pydantic `BaseSettings` fields with the `DOCLING_` environment variable prefix. Access at runtime via `docling_settings()`.

#### Performance Settings (`perf`)

| Setting | Type | Default | Description |
|---|---|---|---|
| `perf.page_batch_size` | `int` | varies | Number of pages processed per batch in the threaded pipeline. Larger values increase throughput but consume more memory. |

#### Debug Settings (`debug`)

| Setting | Type | Default | Description |
|---|---|---|---|
| `debug.visualize_cells` | `bool` | `False` | Render cell-level bounding boxes on page images for debugging. |
| `debug.visualize_layout` | `bool` | `False` | Render layout analysis results (regions, labels) on page images. |
| `debug.visualize_tables` | `bool` | `False` | Render table structure detection results on page images. |
| `debug.visualize_ocr` | `bool` | `False` | Render OCR text regions on page images. |
| `debug.profile_pipeline_timings` | `bool` | `False` | Log per-stage timing data for pipeline execution. Useful for identifying bottlenecks. |

#### Limit Settings (`limits`)

| Setting | Type | Default | Description |
|---|---|---|---|
| `limits.max_num_pages` | `int` | (unset) | Maximum number of pages to process per document. Documents exceeding this are truncated. |
| `limits.max_file_size` | `int` | (unset) | Maximum file size in bytes. Files exceeding this are rejected. |

#### Batch Settings

| Setting | Type | Default | Description |
|---|---|---|---|
| `batch_concurrency` | `int` | varies | Controls parallelism for batch document processing operations. |

### 3.3 Pipeline Options

#### 3.3.1 PdfPipelineOptions

The primary configuration object for `StandardPdfPipeline`. Pass as part of `FormatOption` when configuring `DocumentConverter`.

| Field | Type | Default | Description |
|---|---|---|---|
| `do_ocr` | `bool` | `True` | Enable OCR for scanned pages or images within PDFs. |
| `do_table_structure` | `bool` | `True` | Enable table structure recognition (cells, rows, columns). |
| `do_code_enrichment` | `bool` | `False` | Detect and label code blocks in the document. |
| `do_formula_enrichment` | `bool` | `False` | Detect and extract mathematical formulas. |
| `do_picture_description` | `bool` | `False` | Generate natural-language descriptions of images using a VLM. |
| `do_picture_classification` | `bool` | `False` | Classify images into categories (chart, photo, diagram, etc.). |
| `do_chart_extraction` | `bool` | `False` | Extract structured data from charts using Granite Vision. |
| `ocr_options` | `OcrOptions` | `OcrAutoOptions()` | OCR engine configuration. See Section 3.4. |
| `table_structure_options` | `TableStructureOptions` | (default) | Table structure model options. Key field: `mode` (`accurate` or `fast`). |
| `generate_page_images` | `bool` | `False` | Store rasterized page images in the output document. |
| `generate_picture_images` | `bool` | `False` | Extract and store individual picture images from the document. |
| `images_scale` | `float` | `1.0` | Scale factor for generated images. Higher values improve quality but increase memory. |
| `document_timeout` | `float` | `None` | Maximum time in seconds for processing a single document. `None` means no timeout. |
| `enable_remote_services` | `bool` | `False` | Allow the pipeline to call remote APIs (e.g., external VLM endpoints). Must be explicitly enabled. |
| `allow_external_plugins` | `bool` | `False` | Allow loading model implementations from third-party entry points. Disabled by default for security. |

Example configuration:

```python
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    TableStructureOptions,
    TableFormerMode,
)

pipeline_options = PdfPipelineOptions(
    do_ocr=True,
    do_table_structure=True,
    table_structure_options=TableStructureOptions(
        mode=TableFormerMode.ACCURATE,
    ),
    do_picture_description=True,
    generate_page_images=True,
    images_scale=2.0,
    document_timeout=300.0,
)

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

#### 3.3.2 VlmPipelineOptions

Configuration for the `VlmPipeline` (VLM-based conversion).

| Field | Type | Default | Description |
|---|---|---|---|
| `vlm_options` | `VlmConvertOptions` | (default) | VLM model and inference configuration. See Section 3.5. |
| `generate_page_images` | `bool` | `False` | Store rasterized page images. |
| `generate_picture_images` | `bool` | `False` | Extract picture images. |
| `images_scale` | `float` | `1.0` | Image scale factor. |
| `document_timeout` | `float` | `None` | Per-document timeout in seconds. |
| `enable_remote_services` | `bool` | `False` | Allow remote API calls. |

#### 3.3.3 AsrPipelineOptions

Configuration for the `AsrPipeline` (audio/video transcription).

| Field | Type | Default | Description |
|---|---|---|---|
| `asr_options` | `AsrOptions` | (default) | Whisper model configuration (model name, device, language). |

#### 3.3.4 VlmExtractionPipelineOptions

Configuration for `ExtractionVlmPipeline` (experimental structured extraction).

| Field | Type | Default | Description |
|---|---|---|---|
| `vlm_options` | `VlmConvertOptions` | (default) | VLM configuration for extraction. |

### 3.4 OCR Options

All OCR options inherit from `OcrOptions`. The `OcrAutoOptions` default automatically selects the best available engine.

#### OcrAutoOptions (default)

| Field | Type | Default | Description |
|---|---|---|---|
| (inherits base) | — | — | Auto-detects: EasyOCR → Tesseract → RapidOCR → OcrMac based on availability. |

#### EasyOcrOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `lang` | `list[str]` | `["en"]` | Languages for recognition (EasyOCR language codes). |
| `use_gpu` | `bool` | `True` | Use GPU for EasyOCR inference. |
| `confidence_threshold` | `float` | `0.5` | Minimum confidence to accept a text detection. |

#### TesseractCliOcrOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `lang` | `list[str]` | `["eng"]` | Languages (Tesseract language codes, e.g., `eng`, `deu`, `fra`). |
| `path` | `str` | (auto) | Path to the `tesseract` binary. Auto-detected if on `$PATH`. |
| `tesseract_cmd` | `str` | `"tesseract"` | Command name for the Tesseract executable. |

#### TesseractOcrOptions (tesserocr bindings)

| Field | Type | Default | Description |
|---|---|---|---|
| `lang` | `list[str]` | `["eng"]` | Languages for recognition. |

#### RapidOcrOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `lang` | `list[str]` | `["en"]` | Languages for recognition. |

#### OcrMacOptions (macOS only)

| Field | Type | Default | Description |
|---|---|---|---|
| `lang` | `list[str]` | `["en-US"]` | Languages (BCP 47 codes for macOS Vision). |
| `recognition` | `str` | `"accurate"` | Recognition level: `accurate` or `fast`. |

#### KserveV2OcrOptions (remote)

| Field | Type | Default | Description |
|---|---|---|---|
| `url` | `str` | (required) | KServe V2 inference endpoint URL. |
| `lang` | `list[str]` | `["en"]` | Languages for recognition. |

> [!IMPORTANT]
> `KserveV2OcrOptions` requires `enable_remote_services=True` in the pipeline options. Attempting to use it without this flag raises `OperationNotAllowed`.

### 3.5 VLM Options

VLM (Vision Language Model) options control how page images are converted to structured text.

#### VlmConvertOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `vlm_options` | `BaseVlmOptions` | (default) | The underlying VLM engine configuration. Either `InlineVlmOptions` or `ApiVlmOptions`. |
| (StagePresetMixin) | — | — | Preset system for selecting model + prompt combinations. |

#### InlineVlmOptions (local inference)

| Field | Type | Default | Description |
|---|---|---|---|
| `model_name` | `str` | (preset) | Hugging Face model ID (e.g., `ds4sd/SmolDocling-256M-preview`). |
| `engine` | `str` | `"transformers"` | Inference engine: `transformers`, `vllm`, or `mlx`. |
| `prompt` | `str` | (preset) | System/conversion prompt sent to the VLM. |
| `max_new_tokens` | `int` | (model) | Maximum output tokens per page. |
| `quantized` | `bool` | `False` | Use quantized model weights. |
| `dtype` | `str` | (auto) | Data type for model weights (`float16`, `bfloat16`, `float32`). |

#### ApiVlmOptions (remote API)

| Field | Type | Default | Description |
|---|---|---|---|
| `url` | `str` | (required) | API endpoint URL (OpenAI-compatible). |
| `api_key` | `str` | `""` | API authentication key. |
| `model_name` | `str` | (required) | Model name as recognized by the API. |
| `prompt` | `str` | (preset) | Conversion prompt. |
| `max_new_tokens` | `int` | `4096` | Maximum response tokens. |

### 3.6 Backend Options

#### HTMLBackendOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `render_page` | `bool` | `False` | Render the page via Playwright (headless browser) before parsing. Required for JavaScript-heavy pages. |
| `render_page_width` | `int` | `1280` | Viewport width in pixels for Playwright rendering. |
| `render_page_height` | `int` | `720` | Viewport height in pixels for Playwright rendering. |
| `render_print_media` | `bool` | `False` | Use print media type for CSS rendering. |
| `render_wait_until` | `str` | `"networkidle"` | Playwright wait condition: `load`, `domcontentloaded`, `networkidle`. |
| `fetch_images` | `bool` | `False` | Download and embed remote images referenced in the HTML. |
| `source_uri` | `str` | `None` | Base URI for resolving relative URLs in the HTML. |
| `add_title` | `bool` | `True` | Add the HTML `<title>` as a document title element. |
| `infer_furniture` | `bool` | `True` | Attempt to identify headers, footers, and navigation as furniture (non-content). |

#### MarkdownBackendOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `fetch_images` | `bool` | `False` | Download and embed remote images. |
| `source_uri` | `str` | `None` | Base URI for resolving relative image URLs. |

#### PdfBackendOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `password` | `str` | `None` | Password for encrypted/protected PDF files. |

#### MsExcelBackendOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `treat_singleton_as_text` | `bool` | `True` | Treat sheets with a single cell as plain text rather than a table. |
| `gap_tolerance` | `float` | `1.0` | Tolerance for detecting gaps between cell groups (affects table segmentation). |
| `sheet_names` | `list[str]` | `None` | Process only these named sheets. `None` processes all sheets. |

#### LatexBackendOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `parse_timeout` | `int` | `30` | Maximum time in seconds for LaTeX parsing. Prevents hangs on malformed documents. |

#### XBRLBackendOptions

| Field | Type | Default | Description |
|---|---|---|---|
| `taxonomy` | `str` | (default) | Path to the XBRL taxonomy for validation and parsing. |

---

## 4. Deployment & Scaling

### 4.1 Installation Methods

#### pip install (recommended for most users)

```bash
# Base install (PDF, DOCX, HTML, Markdown, CSV, PPTX, XLSX support)
pip install docling

# With specific OCR engine
pip install "docling[easyocr]"
pip install "docling[rapidocr]"
pip install "docling[tesserocr]"

# With VLM support
pip install "docling[vlm]"

# With audio/video support
pip install "docling[asr]"

# With HTML rendering (Playwright)
pip install "docling[htmlrender]"

# Multiple extras
pip install "docling[vlm,rapidocr,asr]"
```

After installing extras that require Playwright:

```bash
playwright install chromium
```

#### Docker

A `Dockerfile` is provided at the repository root. Build and run:

```bash
# Build
docker build -t docling:latest .

# Run with GPU support (NVIDIA)
docker run --gpus all -v /path/to/docs:/data docling:latest \
    docling convert /data/input.pdf --output /data/output/

# Run CPU-only
docker run -v /path/to/docs:/data docling:latest \
    docling convert /data/input.pdf --output /data/output/

# Pre-download models into a persistent volume
docker run -v docling-models:/root/.cache/huggingface docling:latest \
    docling models download
```

> [!TIP]
> Mount the Hugging Face cache directory (`~/.cache/huggingface`) as a Docker volume to avoid re-downloading models on every container restart: `-v docling-models:/root/.cache/huggingface`.

#### Development install

```bash
git clone https://github.com/docling-project/docling.git
cd docling

# Using uv (recommended, matches CI)
uv sync --all-extras

# Or pip in editable mode
pip install -e ".[vlm,rapidocr,asr,htmlrender,tesserocr]"

# Install pre-commit hooks
pre-commit install
```

### 4.2 Model Management

#### Pre-downloading models

For production deployments, air-gapped environments, or Docker images, pre-download all models:

```bash
# Download all default models
docling models download

# Models are cached in HF_HOME (~/.cache/huggingface/hub/ by default)
```

#### Custom model paths

Set `HF_HOME` to control where models are stored:

```bash
export HF_HOME=/opt/models/huggingface
docling models download
```

#### Model artifacts path

When models fail to load, the error `"The value of self.artifacts_path=... is not valid"` indicates the cached model directory is missing or corrupted. Delete the cache entry and re-download:

```bash
rm -rf ~/.cache/huggingface/hub/models--ds4sd--docling-models
docling models download
```

### 4.3 Service Client Setup (docling-serve)

The `DoclingServiceClient` connects to a running `docling-serve` instance. This is relevant for architectures where conversion is offloaded to a dedicated server.

```python
from docling.service_client import DoclingServiceClient

client = DoclingServiceClient(
    url="http://docling-serve:5001",
    api_key="your-api-key",  # optional
)

# Synchronous-style conversion (blocks until complete)
result = await client.convert(source="https://example.com/paper.pdf")

# Batch conversion
results = await client.convert_all(sources=[
    "paper1.pdf", "paper2.pdf", "paper3.pdf"
])

# Async submission with polling
task = await client.submit(source="large-document.pdf")
watcher = PollingWatcher(client, task.task_id, poll_interval=5.0)
result = await watcher.wait()
```

The client raises typed exceptions:

| Exception | Meaning |
|---|---|
| `ServiceUnavailableError` | Cannot connect to docling-serve |
| `TaskTimeoutError` | Conversion exceeded timeout |
| `ConversionError` | Server-side conversion failure |
| `BatchConversionError` | One or more batch items failed |
| `ServiceError` | Generic service error |

### 4.4 Scaling Strategies

**Vertical scaling** — increase resources on a single machine:
- Add GPU(s) for model inference
- Increase `DOCLING_NUM_THREADS` for CPU parallelism
- Increase `perf.page_batch_size` for larger batches

**Horizontal scaling** — run multiple instances:
- Deploy multiple `docling-serve` instances behind a load balancer
- Use the `DoclingServiceClient` from application code
- Each instance handles its own model loading and inference

**Batch processing** — for offline/bulk workloads:
- Use `DocumentConverter.convert_all()` for multi-document batches
- Control concurrency via `batch_concurrency` setting
- Set `document_timeout` to prevent single documents from blocking the batch

---

## 5. Operations

### 5.1 Batch Processing

```python
from docling.document_converter import DocumentConverter, DocumentStream
from pathlib import Path

converter = DocumentConverter()

# Convert multiple files
sources = [
    Path("doc1.pdf"),
    Path("doc2.docx"),
    "https://example.com/paper.pdf",
]

results = converter.convert_all(sources)

for result in results:
    if result.status == ConversionStatus.SUCCESS:
        result.document.save_as_markdown(Path(f"output/{result.input.file.stem}.md"))
    else:
        print(f"Failed: {result.input.file} — {result.errors}")
```

> [!WARNING]
> When processing untrusted documents in batch, always set `document_timeout` to prevent a single malformed file from stalling the entire batch. A timeout of 300-600 seconds is reasonable for most documents; very large PDFs (1000+ pages) may need more.

### 5.2 CLI Operations

The CLI provides 11 commands. Key operational commands:

```bash
# Convert a single file
docling convert input.pdf --output ./output/

# Convert with specific format options
docling convert input.pdf --ocr --table-structure --output ./output/

# Convert with VLM pipeline
docling convert input.pdf --pipeline vlm --output ./output/

# Batch convert a directory
docling convert ./input_dir/ --output ./output/

# Download models
docling models download

# List supported formats
docling formats list
```

Use `--allow-external-plugins` to enable third-party model plugins:

```bash
docling convert input.pdf --allow-external-plugins --output ./output/
```

### 5.3 Monitoring and Profiling

Enable pipeline profiling to identify bottlenecks:

```python
from docling.datamodel.settings import docling_settings

settings = docling_settings()
settings.debug.profile_pipeline_timings = True
```

Or via environment variable:

```bash
export DOCLING_DEBUG__PROFILE_PIPELINE_TIMINGS=true
```

This logs per-stage timing for each page, producing output like:

```
Stage preprocess: 0.12s
Stage layout: 1.45s
Stage ocr: 2.31s
Stage table_structure: 0.89s
Stage reading_order: 0.05s
Stage page_assembly: 0.03s
```

> [!NOTE]
> Enable debug visualization (`debug.visualize_layout`, `debug.visualize_tables`, etc.) to generate annotated page images. These are written alongside the output and are invaluable for diagnosing layout or table recognition issues.

### 5.4 Error Handling

Docling uses a structured error model. Key error scenarios and their handling:

| Error | Cause | Resolution |
|---|---|---|
| `ConversionError: "...no recognizable format..."` | File format not in `allowed_formats` or undetectable | Add the format to `allowed_formats` or check file extension/MIME |
| `RuntimeError: "Unexpected PDF backend type..."` | Misconfigured backend selection | Use `DoclingParseDocumentBackend` (default) or `PyPdfiumDocumentBackend` |
| `RuntimeError: "...artifacts_path...not valid"` | Missing/corrupt model cache | Delete cache entry, re-run `docling models download` |
| `ImportError: "whisper is not installed..."` | Missing `asr` extra | `pip install "docling[asr]"` |
| `ImportError: "Playwright is required..."` | Missing `htmlrender` extra | `pip install "docling[htmlrender]"` then `playwright install chromium` |
| `OperationNotAllowed: "Enable remote services..."` | Remote services not enabled | Set `enable_remote_services=True` in pipeline options |
| Document timeout | Processing exceeded `document_timeout` | Increase timeout or reduce document size (page limits) |

For batch operations, check `ConversionResult.status` per document — Docling does not abort the batch on individual failures.

### 5.5 Timeout Configuration

Timeouts operate at two levels:

1. **Document-level timeout** (`document_timeout` in pipeline options): Limits total processing time for a single document. Set in seconds. `None` means unlimited.

2. **Backend-level timeout** (`parse_timeout` in `LatexBackendOptions`): Limits parsing time for specific backends. The LaTeX backend defaults to 30 seconds to guard against pathological inputs.

For production batch processing, recommended settings:

```python
pipeline_options = PdfPipelineOptions(
    document_timeout=600.0,       # 10 minutes per document
    do_ocr=True,
    do_table_structure=True,
)
```

### 5.6 Logging

Docling uses Python's standard `logging` module. Configure log levels:

```python
import logging
logging.getLogger("docling").setLevel(logging.DEBUG)
```

Key loggers:

| Logger | Content |
|---|---|
| `docling.document_converter` | Conversion orchestration, format selection |
| `docling.pipeline` | Pipeline stage execution, timing |
| `docling.models` | Model loading, inference |
| `docling.backend` | Backend parsing operations |

---

## 6. Performance

### 6.1 GPU Acceleration

Docling's ML models (layout analysis, table structure, OCR, VLM) benefit significantly from GPU acceleration.

**Device selection priority** (when `DOCLING_DEVICE=auto`):
1. CUDA (NVIDIA GPU) — if `torch.cuda.is_available()`
2. MPS (Apple Silicon) — if `torch.backends.mps.is_available()`
3. CPU — fallback

**Force a specific device:**

```bash
export DOCLING_DEVICE=cuda    # NVIDIA GPU
export DOCLING_DEVICE=mps     # Apple Silicon
export DOCLING_DEVICE=cpu     # CPU only
```

### 6.2 Flash Attention 2

For CUDA devices with compatible hardware (Ampere or newer), Flash Attention 2 reduces memory usage and improves throughput for attention-heavy models (VLM, layout analysis):

```bash
pip install flash-attn
export DOCLING_CUDA_USE_FLASH_ATTENTION2=true
```

> [!IMPORTANT]
> Flash Attention 2 requires CUDA compute capability 8.0+ (A100, RTX 3090/4090, H100). It will silently fall back to standard attention on incompatible hardware without error.

### 6.3 Threading and Parallelism

**Threaded pipeline** — `StandardPdfPipeline` uses `ThreadedPipelineStage` for parallel page processing. Each stage (preprocess, layout, OCR, table structure, reading order, assembly) runs as a bounded producer-consumer queue, allowing pipeline-level parallelism across pages.

The `ThreadedQueue` implementation uses a bounded buffer to prevent memory exhaustion when processing documents with thousands of pages.

**CPU thread control:**

```bash
# Control inference threads (ONNX Runtime, PyTorch)
export DOCLING_NUM_THREADS=8

# Alternative (OpenMP)
export OMP_NUM_THREADS=8
```

**Batch size tuning:**

Increase `perf.page_batch_size` to process more pages per inference batch. This improves GPU utilization but increases peak memory:

```python
from docling.datamodel.settings import docling_settings

settings = docling_settings()
settings.perf.page_batch_size = 8  # Default varies; tune based on GPU memory
```

### 6.4 VLM Inference Engines

For VLM-based conversion, three local inference engines are available:

| Engine | Best For | Install |
|---|---|---|
| `transformers` | General use, broad model compatibility | `pip install "docling[vlm]"` |
| `vllm` | High-throughput server inference, continuous batching | `pip install "docling[vllm]"` |
| `mlx` | Apple Silicon native inference | `pip install "docling[mlx]"` |

vLLM typically provides the best throughput for batch processing on NVIDIA GPUs. MLX is optimal for Apple Silicon. Transformers is the most compatible fallback.

### 6.5 Performance Optimization Checklist

1. Use GPU if available (`DOCLING_DEVICE=cuda` or `auto`)
2. Enable Flash Attention 2 on compatible CUDA hardware
3. Tune `DOCLING_NUM_THREADS` to match available cores (avoid over-subscription)
4. Increase `perf.page_batch_size` for GPU workloads (monitor memory)
5. Disable unnecessary enrichments (`do_code_enrichment`, `do_formula_enrichment`, etc.) if not needed
6. Use `TableFormerMode.FAST` instead of `ACCURATE` when precision is less critical
7. Set `document_timeout` to prevent runaway processing
8. For VLM pipeline, prefer vLLM on NVIDIA GPUs for best throughput
9. Pre-download models to avoid first-run latency
10. Use `limits.max_num_pages` to cap processing for very large documents

### 6.6 Known Performance Issues

- **Issue #3182**: A 2x performance regression was reported in version 2.81.0. Check release notes for fixes in later versions.
- **Issue #3201**: SIGABRT on Python 3.12 in Databricks Serverless environments. Likely related to thread/process model incompatibility.
- **Issue #3303**: `ChartExtractionModel` crash with `transformers>=5.x`. Pin transformers version if using chart extraction.

---

## 7. Security

### 7.1 Input Validation

Docling validates inputs at multiple levels:

- **Format detection**: Files must match a recognized format (extension + MIME type). Unrecognized formats raise `ConversionError`.
- **File size limits**: Configurable via `limits.max_file_size`. Enforce this in production to prevent denial-of-service via oversized files.
- **Page limits**: Configurable via `limits.max_num_pages`. Prevents resource exhaustion from extremely large documents.
- **Parse timeouts**: Backend-level timeouts (e.g., `LatexBackendOptions.parse_timeout = 30s`) prevent pathological inputs from consuming unbounded CPU.

### 7.2 Password-Protected PDFs

Docling supports opening encrypted PDFs via `PdfBackendOptions`:

```python
from docling.datamodel.pipeline_options import PdfBackendOptions

backend_options = PdfBackendOptions(password="secret123")
```

> [!CAUTION]
> PDF passwords are passed in plaintext through the options object. Do not log pipeline options in production environments where password-protected documents are processed. Ensure options objects containing passwords are not serialized to disk or transmitted.

### 7.3 Remote Fetch Controls

Several features involve fetching remote resources:

| Feature | Controlled By | Default |
|---|---|---|
| HTML image download | `HTMLBackendOptions.fetch_images` | `False` |
| Markdown image download | `MarkdownBackendOptions.fetch_images` | `False` |
| HTML page rendering | `HTMLBackendOptions.render_page` | `False` |
| URL-based input sources | Always allowed | — |
| Remote OCR (KServe) | `enable_remote_services` | `False` |
| Remote VLM API | `enable_remote_services` | `False` |

> [!WARNING]
> Enabling `fetch_images=True` or `render_page=True` on untrusted HTML/Markdown inputs allows the process to make outbound HTTP requests to arbitrary URLs. In sandboxed or security-sensitive environments, keep these disabled or restrict network access at the OS/container level.

### 7.4 Remote Services Flag

The `enable_remote_services` flag in pipeline options is a global gate for any operation that contacts an external service during conversion. This includes:

- `KserveV2OcrOptions` (remote OCR)
- `ApiVlmOptions` (remote VLM API)
- Any future remote model integration

This flag is `False` by default. Attempting to use a remote service without it raises `OperationNotAllowed`.

### 7.5 Plugin Trust Model

The factory-based plugin system allows third-party packages to register custom OCR, layout, or table structure implementations via Python entry points.

**`allow_external_plugins=False` (default)**: Only built-in model implementations are loaded. Third-party entry points are ignored.

**`allow_external_plugins=True`**: The `BaseFactory.load_from_plugins()` method discovers and loads external implementations. This executes code from third-party packages at import time.

In production, only enable external plugins when you trust all installed packages. The CLI equivalent is `--allow-external-plugins`.

### 7.6 Dependency Supply Chain

Key security-sensitive dependencies:

| Dependency | Risk Surface | Mitigation |
|---|---|---|
| PyTorch / ONNX Runtime | Model inference, native code | Pin versions; use official PyPI packages |
| Playwright | Browser automation (Chromium) | Only installed with `htmlrender` extra; sandbox the browser |
| Hugging Face Hub | Model downloads | Verify model checksums; use `HF_HOME` to control storage |
| python-docx / openpyxl | Office format parsing | Potential for XML entity expansion; keep updated |

---

## 8. Developer Internals

### 8.1 Repository Structure

```
docling/
├── __init__.py               # Package init, version
├── document_converter.py     # Core orchestrator (DocumentConverter)
├── chunking.py               # Document chunking for RAG
├── exceptions.py             # Custom exception hierarchy
├── backend/                  # Format-specific backends (20+ files)
│   ├── abstract_backend.py   # AbstractDocumentBackend (ABC)
│   ├── pdf_backend.py        # PdfDocumentBackend
│   ├── docling_parse_backend.py  # DoclingParseDocumentBackend
│   ├── pypdfium_backend.py   # PyPdfiumDocumentBackend
│   ├── msword_backend.py     # MsWordDocumentBackend
│   ├── mspowerpoint_backend.py
│   ├── msexcel_backend.py
│   ├── html_backend.py
│   ├── md_backend.py
│   ├── csv_backend.py
│   ├── latex_backend.py
│   ├── asciidoc_backend.py
│   ├── image_backend.py
│   ├── webvtt_backend.py
│   ├── mets_gbs_backend.py
│   ├── jats_backend.py
│   ├── patent_uspto_backend.py
│   ├── xbrl_backend.py
│   └── noop_backend.py       # Pass-through backend
├── datamodel/                # Pydantic models (20 files)
│   ├── settings.py           # AppSettings (env-based config)
│   ├── pipeline_options.py   # All pipeline/backend/model options
│   ├── document.py           # InputDocument, ConversionResult
│   └── ...
├── pipeline/                 # Processing pipelines (9 files)
│   ├── base_pipeline.py      # BasePipeline (ABC)
│   ├── convert_pipeline.py   # ConvertPipeline base
│   ├── standard_pdf_pipeline.py  # StandardPdfPipeline
│   ├── vlm_pipeline.py       # VlmPipeline
│   ├── simple_pipeline.py    # SimplePipeline
│   ├── asr_pipeline.py       # AsrPipeline
│   ├── extraction_vlm_pipeline.py
│   ├── threaded_pipeline.py  # ThreadedPipelineStage, ThreadedQueue
│   └── ...
├── models/                   # ML model wrappers (5 base + 6 factories + 6 engines)
│   ├── base_model.py         # BasePageModel (ABC)
│   ├── base_ocr_model.py     # BaseOcrModel
│   ├── layout_model.py
│   ├── table_structure_model.py
│   ├── vlm_convert_model.py
│   ├── factories/            # Factory pattern implementations
│   │   ├── base_factory.py   # BaseFactory[A] generic
│   │   ├── ocr_factory.py
│   │   ├── layout_factory.py
│   │   ├── table_structure_factory.py
│   │   └── picture_description_factory.py
│   └── inference_engines/    # VLM inference backends
│       ├── transformers_engine.py
│       ├── vllm_engine.py
│       ├── mlx_engine.py
│       ├── api_engine.py
│       └── ...
├── service_client/           # Remote service SDK (6 files)
│   ├── client.py             # DoclingServiceClient
│   ├── watchers.py           # PollingWatcher, WebSocketWatcher
│   └── exceptions.py         # Service exceptions
├── cli/                      # CLI interface (3 files)
│   ├── main.py               # Entry point, command registration
│   └── ...
└── utils/                    # Utilities (13 files)
    ├── profiling.py          # Pipeline timing profiler
    ├── accelerator_utils.py  # Device detection (CUDA/MPS/CPU)
    ├── locks.py              # Thread-safe resource locking
    └── ...
```

### 8.2 Module Reference

#### `docling/document_converter.py` (37K chars)

The central orchestrator. `DocumentConverter` accepts format options (a dict mapping `InputFormat` to `FormatOption`), creates backends and pipelines per format, and runs conversion. Key methods:

- `convert(source)` — Convert a single document. Returns `ConversionResult`.
- `convert_all(sources)` — Convert multiple documents. Returns iterator of `ConversionResult`.
- `_get_pipeline(format_option)` — Instantiate or retrieve cached pipeline for a format option.
- `_determine_backend(source)` — Select the backend class based on source format.

#### `docling/backend/` (420K chars, 19 files)

Each backend implements `AbstractDocumentBackend` (or its subclasses `PaginatedDocumentBackend` / `DeclarativeDocumentBackend`). Key methods:

- `is_valid(source)` — Class method. Check if the backend can handle this source.
- `page_count()` — Return page count (paginated backends only).
- `load_page(page_no)` — Load a specific page (paginated backends only).
- `convert()` — Convert the entire document (declarative backends).

The `DoclingParseDocumentBackend` is the default PDF backend, using the C++-accelerated docling-parse library for text extraction and cell detection. `PyPdfiumDocumentBackend` is the fallback using pypdfium2.

#### `docling/datamodel/` (252K chars, 20 files)

All Pydantic models live here. The `pipeline_options.py` file is the largest and most important — it defines every configurable option for pipelines, backends, OCR engines, VLM models, and table structure.

#### `docling/pipeline/` (118K chars, 9 files)

Pipeline implementations. `StandardPdfPipeline` is the most complex, with six sequential stages plus optional enrichments. Each stage implements `BasePageModel` and is wrapped in a `ThreadedPipelineStage` for parallel execution.

The `ThreadedPipelineStage` creates a bounded producer-consumer queue (`ThreadedQueue`) where pages flow through stages in a streaming fashion, limiting memory usage.

#### `docling/utils/` (85K chars, 13 files)

Utilities including:
- `accelerator_utils.py` — Device detection and selection logic
- `profiling.py` — Pipeline timing instrumentation
- `locks.py` — Thread-safe resource management for shared model access

#### `docling/service_client/` (76K chars, 6 files)

Async HTTP client built on `httpx` for communicating with `docling-serve`. Supports both polling and WebSocket-based result watching.

#### `docling/cli/` (44K chars, 3 files)

CLI built with (likely Click or Typer). Provides commands for conversion, model management, and format listing. The `convert` command mirrors the Python API's `DocumentConverter.convert()` with CLI flags for all major options.

### 8.3 Class Hierarchy

#### Backend Hierarchy

```
AbstractDocumentBackend (ABC)
├── PaginatedDocumentBackend
│   ├── PdfDocumentBackend
│   │   ├── DoclingParseDocumentBackend  (default PDF)
│   │   └── PyPdfiumDocumentBackend      (fallback PDF)
│   ├── ImageDocumentBackend
│   └── MetsGbsDocumentBackend
└── DeclarativeDocumentBackend
    ├── HTMLDocumentBackend
    ├── MarkdownDocumentBackend
    ├── CsvDocumentBackend
    ├── MsWordDocumentBackend
    ├── MsPowerpointDocumentBackend
    ├── MsExcelDocumentBackend
    ├── AsciiDocBackend
    ├── WebVTTDocumentBackend
    ├── LatexDocumentBackend
    ├── JatsDocumentBackend
    ├── PatentUsptoDocumentBackend
    └── XBRLDocumentBackend
```

#### Pipeline Hierarchy

```
BasePipeline (ABC)
├── ConvertPipeline
│   ├── PaginatedPipeline
│   │   └── VlmPipeline
│   ├── SimplePipeline
│   └── StandardPdfPipeline
│       └── ThreadedStandardPdfPipeline
└── AsrPipeline
```

#### Model Hierarchy

```
BasePageModel (ABC)
├── BaseOcrModel → EasyOCR, TesseractCli, Tesseract, RapidOCR, OcrMac, AutoOcr, KserveV2
├── BaseLayoutModel → LayoutModel, LayoutObjectDetectionModel
├── BaseTableStructureModel → TableStructureModel, TableStructureModelV2, GraniteVisionTableStructure
├── BaseVlmPageModel (VLM page models)
└── GenericEnrichmentModel
    ├── BaseEnrichmentModel
    └── BaseItemAndImageEnrichmentModel
        ├── PictureDescriptionVlmModel
        ├── PictureDescriptionApiModel
        ├── DocumentPictureClassifier
        └── ChartExtractionModelGraniteVision
```

#### Options Hierarchy

```
PipelineOptions
├── ConvertPipelineOptions
│   └── PaginatedPipelineOptions
│       ├── PdfPipelineOptions
│       └── VlmPipelineOptions
├── AsrPipelineOptions
└── VlmExtractionPipelineOptions

OcrOptions
├── OcrAutoOptions
├── EasyOcrOptions
├── TesseractCliOcrOptions
├── TesseractOcrOptions
├── RapidOcrOptions
├── OcrMacOptions
└── KserveV2OcrOptions

BaseVlmOptions
├── InlineVlmOptions
└── ApiVlmOptions
```

### 8.4 Factory Pattern

Docling uses a generic `BaseFactory[A]` pattern for pluggable model implementations. Each factory:

1. Maintains a registry of model classes keyed by their option type
2. Provides `create(options)` to instantiate the matching implementation
3. Supports `load_from_plugins()` to discover external implementations via Python entry points

```python
# Simplified factory usage
from docling.models.factories.ocr_factory import OcrFactory
from docling.datamodel.pipeline_options import EasyOcrOptions

# Factory maps EasyOcrOptions → EasyOCR model class
ocr_model = OcrFactory.create(EasyOcrOptions(lang=["en", "de"]))
```

Factories:

| Factory | Options Base | Registered Implementations |
|---|---|---|
| `OcrFactory` | `OcrOptions` | AutoOcr, EasyOCR, TesseractCli, Tesseract, RapidOCR, OcrMac, KserveV2 |
| `LayoutFactory` | `LayoutOptions` | LayoutModel, LayoutObjectDetectionModel |
| `TableStructureFactory` | `TableStructureOptions` | TableStructureModel, TableStructureModelV2, GraniteVisionTableStructure |
| `PictureDescriptionFactory` | `PictureDescriptionOptions` | PictureDescriptionVlmModel, PictureDescriptionApiModel |

### 8.5 Plugin System

External plugins register model implementations via Python entry points in `pyproject.toml`:

```toml
[project.entry-points."docling.ocr"]
my_custom_ocr = "my_package.ocr:MyCustomOcrModel"
```

At runtime, when `allow_external_plugins=True`, `BaseFactory.load_from_plugins()`:

1. Scans the `docling.ocr` (or `docling.layout`, `docling.table_structure`) entry point group
2. Imports each discovered module
3. Registers the model class in the factory's registry
4. The model becomes available for use via its option type

### 8.6 Developing a Custom Backend

To add support for a new document format:

1. Create a new file in `docling/backend/` (e.g., `my_format_backend.py`)
2. Inherit from `DeclarativeDocumentBackend` (for structured formats) or `PaginatedDocumentBackend` (for page-based formats)
3. Implement required methods:

```python
from docling.backend.abstract_backend import DeclarativeDocumentBackend

class MyFormatBackend(DeclarativeDocumentBackend):
    @classmethod
    def is_valid(cls, source) -> bool:
        """Check if this backend can handle the source."""
        return source.suffix == ".myformat"

    def convert(self) -> DoclingDocument:
        """Parse the file and return a DoclingDocument."""
        doc = DoclingDocument(name=self.source.stem)
        # ... parse and populate doc ...
        return doc
```

4. Register the backend in `InputFormat` and the default `FormatOption` mapping in `document_converter.py`.

### 8.7 Extending a Pipeline

To add a new enrichment stage to `StandardPdfPipeline`:

1. Create a model class inheriting from `BaseEnrichmentModel` or `BaseItemAndImageEnrichmentModel`
2. Implement `__call__(self, page, doc_context)` to process pages
3. Add the enrichment to the pipeline's stage list in `standard_pdf_pipeline.py`
4. Add a `do_my_enrichment` flag to `PdfPipelineOptions`

### 8.8 Testing Strategy

The test suite contains 60+ test files organized by component:

```
tests/
├── test_document_converter.py    # Integration tests
├── test_backend_*.py             # Per-backend unit tests
├── test_pipeline_*.py            # Pipeline tests
├── test_cli_*.py                 # CLI tests
├── test_service_client.py        # Service client tests
├── data/                         # Test fixtures
│   ├── pdf/                      # PDF test documents
│   ├── docx/                     # Word test documents
│   ├── html/                     # HTML test documents
│   └── ...                       # All supported formats
└── groundtruth/                  # Expected output for regression tests
    ├── v1/                       # V1 format groundtruth
    └── v2/                       # V2 format groundtruth
```

**Running tests:**

```bash
# All tests
pytest

# Skip ML-dependent tests (fast)
pytest -m "not ml_asr"

# Specific component
pytest tests/test_backend_html.py

# Cross-platform tests only
pytest -m cross_platform
```

**Pytest markers:**
- `ml_asr` — Tests requiring Whisper models (slow, GPU-dependent)
- `cross_platform` — Tests that should pass on all OS platforms

**Groundtruth testing:** Many tests compare output against checked-in groundtruth files. When making changes that affect output format, update groundtruth files after verifying correctness.

### 8.9 Code Patterns

**Pydantic everywhere**: All configuration, options, and data transfer objects are Pydantic `BaseModel` subclasses. This provides automatic validation, serialization, and documentation.

**ABC + Protocol**: Base classes use `ABC` with `@abstractmethod` for required implementations. The type system enforces that all backends/pipelines/models implement the required interface.

**Generic factories**: `BaseFactory[A]` uses Python generics to type-safely map option types to model implementations.

**Threaded producer-consumer**: The pipeline uses bounded queues between stages. Each stage runs in its own thread, pulling from an input queue and pushing to an output queue. `ThreadedQueue` handles backpressure and graceful shutdown.

**Atomic file rename**: `ProcessingResult` tracks success/failure counts with thread-safe counters.

### 8.10 Pre-commit and CI

Pre-commit hooks (configured in `.pre-commit-config.yaml`):
- **ruff format** — Code formatting
- **ruff lint** — Linting (import sorting, style rules)
- **mypy** — Type checking
- **uv-lock** — Verify lockfile is up to date

```bash
# Run all hooks manually
pre-commit run --all-files

# Run specific hook
pre-commit run ruff-format --all-files
```

---

## 9. Integration Points

### 9.1 RAG Framework Integration

Docling provides chunking capabilities for Retrieval-Augmented Generation (RAG) workflows.

#### Built-in Chunking

```python
from docling.chunking import HybridChunker

converter = DocumentConverter()
result = converter.convert("paper.pdf")

chunker = HybridChunker()
chunks = list(chunker.chunk(result.document))

for chunk in chunks:
    print(chunk.text)
    print(chunk.meta)  # Source location metadata
```

#### LangChain

```python
from langchain_docling import DoclingLoader

loader = DoclingLoader(file_path="paper.pdf")
documents = loader.load()

# Use with a vector store
from langchain_community.vectorstores import Chroma
vectorstore = Chroma.from_documents(documents, embedding_function)
```

#### LlamaIndex

```python
from llama_index.readers.docling import DoclingReader

reader = DoclingReader()
documents = reader.load_data(file_path="paper.pdf")
```

#### Haystack

Docling integrates with Haystack via a converter component for the Haystack pipeline.

### 9.2 Export Formats

`ConversionResult.document` (a `DoclingDocument` from docling-core) supports these export methods:

| Method | Output Format | Use Case |
|---|---|---|
| `save_as_markdown()` | Markdown (.md) | Human-readable, LLM input |
| `save_as_json()` | JSON | Structured processing, storage |
| `save_as_yaml()` | YAML | Human-readable structured format |
| `save_as_html()` | HTML | Web display |
| `save_as_doctags()` | DocTags | Docling-native tagged format |
| `save_as_text()` | Plain text | Simple text extraction |

```python
from pathlib import Path

result = converter.convert("paper.pdf")
doc = result.document

# Save in multiple formats
doc.save_as_markdown(Path("output/paper.md"))
doc.save_as_json(Path("output/paper.json"))
doc.save_as_html(Path("output/paper.html"))
```

### 9.3 Docling Ecosystem Integration

| Integration | How |
|---|---|
| **docling-serve** | Deploy as HTTP/gRPC service; use `DoclingServiceClient` from this library |
| **docling-core** | Shared `DoclingDocument` model — all exports and imports use this type |
| **docling-ibm-models** | Pre-trained model weights downloaded automatically from Hugging Face |
| **docling-parse** | C++ PDF parser; `DoclingParseDocumentBackend` wraps it transparently |

### 9.4 Programmatic API Quick Reference

```python
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import (
    PdfPipelineOptions,
    EasyOcrOptions,
    TableStructureOptions,
    TableFormerMode,
)

# Configure
pipeline_options = PdfPipelineOptions(
    do_ocr=True,
    ocr_options=EasyOcrOptions(lang=["en", "de"]),
    do_table_structure=True,
    table_structure_options=TableStructureOptions(mode=TableFormerMode.ACCURATE),
    do_picture_description=True,
    generate_page_images=True,
    images_scale=2.0,
    document_timeout=300.0,
)

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

# Convert
result = converter.convert("paper.pdf")

# Access structured document
doc = result.document
print(doc.title)
print(doc.pages)

# Export
doc.save_as_markdown(Path("output.md"))

# Iterate tables
for table in doc.tables:
    print(table.to_dataframe())

# Chunking for RAG
from docling.chunking import HybridChunker
chunks = list(HybridChunker().chunk(doc))
```

### 9.5 Supported Format Matrix

| Input Format | Backend | Pipeline | OCR | Tables |
|---|---|---|---|---|
| PDF | DoclingParse / PyPdfium | StandardPdf or VLM | Yes | Yes |
| Images (PNG, JPG, TIFF, BMP) | ImageDocumentBackend | StandardPdf or VLM | Yes | Yes |
| DOCX | MsWordDocumentBackend | Simple | No | Preserved |
| PPTX | MsPowerpointDocumentBackend | Simple | No | Preserved |
| XLSX | MsExcelDocumentBackend | Simple | No | Preserved |
| HTML | HTMLDocumentBackend | Simple | No | Preserved |
| Markdown | MarkdownDocumentBackend | Simple | No | Preserved |
| CSV/TSV | CsvDocumentBackend | Simple | No | Yes |
| LaTeX | LatexDocumentBackend | Simple | No | Preserved |
| AsciiDoc | AsciiDocBackend | Simple | No | Preserved |
| WebVTT | WebVTTDocumentBackend | Simple | No | No |
| JATS XML | JatsDocumentBackend | Simple | No | Preserved |
| USPTO XML | PatentUsptoDocumentBackend | Simple | No | Preserved |
| XBRL | XBRLDocumentBackend | Simple | No | Preserved |
| METS/GBS | MetsGbsDocumentBackend | StandardPdf | Yes | Yes |
| Audio/Video | (via ASR) | AsrPipeline | No | No |

---

## Appendix A: Troubleshooting

### A.1 Model Download Failures

**Symptom**: `RuntimeError: "The value of self.artifacts_path=... is not valid"`

**Resolution**:
1. Check internet connectivity (models download from `huggingface.co`)
2. Verify `HF_HOME` points to a writable directory with sufficient space
3. Clear corrupted cache: `rm -rf ~/.cache/huggingface/hub/models--<model-name>`
4. Re-download: `docling models download`

> [!TIP]
> In corporate environments with HTTPS inspection, set `HF_HUB_DISABLE_TELEMETRY=1` and configure `REQUESTS_CA_BUNDLE` to point to the corporate CA bundle.

### A.2 OCR Not Working

**Symptom**: Scanned PDFs produce empty or garbled text.

**Resolution**:
1. Verify OCR is enabled: `do_ocr=True` (default)
2. Check which OCR engine is selected: `OcrAutoOptions` auto-detects, but may fall back to a suboptimal engine
3. Install a specific engine: `pip install "docling[easyocr]"` and set `ocr_options=EasyOcrOptions(lang=["en"])`
4. Verify language packs are correct for the document language
5. For Tesseract, ensure the binary is on `$PATH` and language data is installed

### A.3 GPU Not Detected

**Symptom**: Processing is slow; logs show CPU-only inference.

**Resolution**:
1. Verify PyTorch sees the GPU: `python -c "import torch; print(torch.cuda.is_available())"`
2. Check `DOCLING_DEVICE` is not set to `cpu`
3. For NVIDIA: verify CUDA toolkit and driver versions match PyTorch requirements
4. For Apple Silicon: verify `torch.backends.mps.is_available()` returns `True`
5. In Docker: ensure `--gpus all` is passed and the NVIDIA Container Toolkit is installed

### A.4 Memory Issues

**Symptom**: `OutOfMemoryError` or process killed during large document processing.

> [!CAUTION]
> Large documents (1000+ pages) with high-resolution images and multiple enrichments enabled can consume 32+ GB of RAM. Monitor memory usage and adjust settings accordingly.

**Resolution**:
1. Reduce `perf.page_batch_size`
2. Lower `images_scale` (e.g., from 2.0 to 1.0)
3. Disable unnecessary enrichments
4. Set `limits.max_num_pages` to process documents in chunks
5. Use `generate_page_images=False` if page images are not needed

### A.5 HTML Rendering Issues

**Symptom**: `ImportError: "Playwright is required for HTML rendering..."`

**Resolution**:
```bash
pip install "docling[htmlrender]"
playwright install chromium
```

For Docker deployments, ensure Chromium dependencies are installed:
```bash
playwright install-deps chromium
```

### A.6 LaTeX Timeout

**Symptom**: LaTeX conversion hangs or times out.

**Resolution**: Increase the parse timeout (default 30 seconds):

```python
from docling.datamodel.pipeline_options import LatexBackendOptions

options = LatexBackendOptions(parse_timeout=120)  # 2 minutes
```

Malformed LaTeX (unclosed environments, recursive macros) can cause pathological parsing behavior. The timeout prevents infinite hangs.

### A.7 Format Not Recognized

**Symptom**: `ConversionError: "Conversion failed because the provided file has no recognizable format..."`

**Resolution**:
1. Verify the file extension matches a supported format
2. Check that the file is not corrupt (open it manually)
3. For format `.txt`: As of the source version, plain text is not a supported input format (see issue #3259)
4. Ensure the format's backend is included in the `allowed_formats` configuration

---

_Generated May 2026 from docling-project/docling at 2bb0fa6. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
