Docling Serve

repository·main·Indexed 23 days ago

https://github.com/docling-project/docling-serve

A webserver implementation for the Docling project that provides APIs and interfaces for document conversion and analysis. It supports synchronous and asynchronous conversion of documents via URLs or file uploads, document chunking using Hybrid and Hierarchical chunkers, and a demonstration UI. The service can be deployed via Python package or container images optimized for CPU, CUDA 12.8, and CUDA 13.0, and includes health checks, Prometheus metrics, and WebSocket task monitoring.

Tokens
26.6K
Snippets
50
Records
140
Agent score
82%

What's inside docling-serve

  1. Make extra models available in Docling Serve

    main

    The standard Docling Serve container image includes only default models. If you enable features like picture classification, table detection, or vision-language modules, you must provide the required models. Docling Serve will not download missing models automatically at runtime; it will instead raise a runtime error to prevent unexpected external network calls.

    There are four primary approaches to providing these models:

    1. Disable Local Models (Auto-Download): Clear the artifacts path to trigger a download at startup. Best for local development, not recommended for production.
    2. Build a Custom Image: Use a Dockerfile to download models during the image build process. Best for production stability.
    3. Override Entrypoint: Use a shell command to download models immediately before starting the service. Useful for keeping the base image unchanged.
    4. Mount a Volume: Download models to a local directory and mount that directory into the container. This is robust for both local and production use.
  2. Understand the API error contract for Ray dispatcher unavailability

    main

    When the Ray dispatcher is unavailable or in an invalid state, the docling-serve API follows a specific error contract to ensure clients can handle the failure gracefully:

    • HTTP Status Code: 503 Service Unavailable (not 500 Internal Server Error).
    • Header: Includes Retry-After: 1 to signal to clients that they should wait before retrying.
    • Scope: This applies to both asynchronous Ray submissions and synchronous submissions that internally enqueue work.
    • Error Type: The system uses DispatcherUnavailableError to normalize various lower-level Ray exceptions (including process-exit style failures) into this controlled response.
  3. Understand the Docling Serve API endpoints

    main

    The Docling Serve API provides two distinct endpoints to handle different input types. This separation allows users to send files directly in binary format, which is more efficient than using base64-encoded strings.

    • URL endpoint: Used for processing documents via web URLs.
    • File endpoint: Used for processing documents sent as direct binary file uploads.
  4. Understand Ray Orchestrator deadlock protection

    main

    The Ray Orchestrator avoids deadlocks by splitting processing into two separate Ray Serve deployment pools: Coordinator replicas and Converter replicas.

    In a single-deployment model, a replica waiting on its own deployment can exhaust all available slots, causing a hang. In the split model:

    • Coordinator replicas handle task dispatching and wait asynchronously for child slices. They do not occupy converter slots.
    • Converter replicas perform the actual conversion. They are limited by max_ongoing_requests=1 for thread safety, but because they are in a separate pool, a busy converter does not block a coordinator from receiving new tasks.
    • If all converter replicas are busy, requests queue in Ray Serve's internal backlog. Coordinators remain async-blocked without consuming converter slots.

    Saturation Risk: If max_page_slice_parallelism is unset, a very large PDF may create more slice requests than there are converter replicas, causing requests to queue in the converter backlog and increasing latency for other tasks.

  5. Handle Partial Success in Page-Slicing Fan-Out

    main

    When using the page-slicing fan-out feature, a task might experience partial failures (where some page slices succeed and others fail).

    Understanding the status hierarchy is critical:

    1. Task-level TaskStatus: This remains binary. If at least one slice succeeds, the overall task status is SUCCESS. If all slices fail, the task status is FAILURE.
    2. Document-level ConversionStatus: To identify if a document is incomplete, check the result document's ConversionStatus. If some slices failed but others succeeded, the status will be PARTIAL_SUCCESS. The errors from the failed slices are carried within the result document.
  6. How distributed tracing works with the RQ engine

    main

    When running with the RQ engine (DOCLING_SERVE_ENG_KIND=rq), Docling Serve provides end-to-end visibility by propagating trace contexts from the API to the workers:

    1. API Request: FastAPI creates a trace when a document conversion request arrives.
    2. Job Enqueue: The trace context is injected into the RQ job metadata.
    3. Worker Execution: The RQ worker extracts the trace context and continues the trace.

    This allows you to track document processing latency across the distributed system and identify bottlenecks in the conversion pipeline using tools like Grafana Tempo.

  7. Understand the Ray Orchestrator Page-Slicing Architecture

    main

    The cau/ray-page-slicing branch introduces a split in the Ray Serve deployment model to improve efficiency when processing large PDFs. Instead of a single DocumentProcessorDeployment, the system now uses two cooperating deployments:

    1. DoclingProcessorCoordinatorDeployment: Manages the parent task lifecycle, including Redis heartbeats, source materialization (downloading/decoding), and the fan-out/collect logic. It does not hold heavy model weights or GPUs.
    2. DoclingProcessorConverterDeployment: A specialized worker that holds the warm DoclingConverterManager (model weights). It is responsible for converting either a single task or a specific page slice.

    This separation allows the system to scale worker replicas (Converters) independently of the task management (Coordinator), ensuring that expensive GPU resources are only occupied during actual conversion work, not while waiting for I/O or managing task state.

  8. Understand Ray Task status continuity and Redis fallback

    main

    The Ray dispatcher provides durable task status by using Redis as a fallback. If a task is requested via task_status() or get_raw_task() but is not present in the dispatcher's local in-memory self.tasks (which can happen after an API restart), the dispatcher will:

    1. Attempt to reconstruct the task from Redis metadata.
    2. Repopulate its local self.tasks cache from the Redis record.

    This ensures that task status remains visible and prevents false 404 errors following service restarts. Reconstructed tasks preserve status, task_type, timestamps, and error messages.

  9. Understand the conversion response format

    main

    The response format depends on the input and the target parameter:

    • Single File: Returns a JSON document containing document (with md_content, json_content, html_content, text_content, and doctags_content), status, processing_time, timings, and errors.
    • Zip Mode: If target is set to zip mode, or if multiple files are processed, the response is a .zip file containing the results.
    {
      "document": {
        "md_content": "",
        "json_content": {},
        "html_content": "",
        "text_content": "",
        "doctags_content": ""
      },
      "status": "<success|partial_success|skipped|failure>",
      "processing_time": 0.0,
      "timings": {},
      "errors": []
    }
  10. How PDF Page-Slicing Fan-Out Works

    main

    When enable_pdf_page_slice_fanout=true is configured and a single-source PDF exceeds the max_page_slice_size threshold, the system follows the Fan-out path:

    1. Materialization: The Coordinator downloads/decodes the PDF and places the bytes into the Ray Plasma Object Store using ray.put(pdf_bytes), obtaining an ObjectRef.
    2. Fan-out: The Coordinator creates a SlicePlan and issues multiple parallel SliceConvertRequest calls to DoclingProcessorConverterDeployment replicas. Each request specifies a page_range and a slice_index.
    3. Parallel Conversion: Converter replicas use ray.get(artifact_ref) to retrieve the shared PDF bytes from the Plasma store and convert their assigned pages.
    4. Assembly: Once all slices are collected, the Coordinator calls _assemble_slice_results(), which sorts the results by slice_index and uses DoclingDocument.concatenate() to reconstruct the full document.
    5. Finalization: The Coordinator processes exportable results and publishes the final task result to Redis.

    Concurrency Control: Fan-out concurrency is bounded by max_page_slice_parallelism. If this is unset, it defaults to max_concurrent_tasks.

  11. Understand the role of the RayTaskDispatcher

    main

    The RayTaskDispatcher is a named detached actor (created with get_if_exists=True) that manages work distribution. It is important to note its specific responsibilities and limitations:

    • Fairness: It enforces fairness across different tenants.
    • Admission Control: It prevents a tenant from admitting more work than their configured limits allow.
    • Queue Management: It moves work from per-tenant Redis queues into Ray Serve in a fair order.
    • Not an Execution Queue: It is not the authoritative execution queue for all downstream work. Because Ray Serve can queue work internally, a task counted as "active" by the dispatcher might already be admitted downstream but not yet executing on a Serve replica. Therefore, max_concurrent_tasks acts as an admission-control bound at the dispatcher layer, rather than a strict count of currently executing replicas.
  12. Understand the task reconciliation policy

    main

    To handle cases where a dispatcher actor dies during an active task, the system implements a specific reconciliation policy to recover or fail tasks based on their durable metadata:

    • Auto-Recovery (Started Tasks): If an active task has status=started in its durable metadata but its task:{id}:processing key is missing, the system marks the task as FAILURE, clears its dispatch_state, publishes an update, and releases its capacity.
    • Pre-start Tasks: If an active task is still in pending or dispatched states and has no processing key, it remains unresolved.
    • Active Processing: If a task has processing state with status=processing, the system leaves it alone (it is assumed to be making progress).
    • Capacity Resync: After each tenant reconciliation, the system resyncs counters from the canonical Redis structures.