This backend connects Label Studio to IBM Docling SaaS using the Python DoclingServiceClient from the docling package (from docling.service_client import DoclingServiceClient). Conversion runs on Docling’s servers, not inside this container. For each task it resolves the file (usually via Label Studio–hosted storage), calls client.convert(source=…) with a local Path or an https:// URL string, then maps result.document into reactcode predictions for the annotator.
Use the exact service URL your tenant gives you (Integrate / Python snippet), including the path segment ending in /v1—for example
https://api.aws-c1.dcls.saas.ibm.com/<instance>/v1.
The docling DoclingServiceClient builds paths like /v1/convert/... on top of its url= argument. IBM’s URL already ends with /v1, which would otherwise produce …/v1/v1/… requests (404/400). This example strips one trailing /v1 from DOCLING_SERVICE_URL before creating the client—keep pasting the Workbench value unchanged.
Typical workflow:
- Tasks include a file URL (PDF, image, etc.)—often an upload or storage URL managed by Label Studio.
- Annotators run predictions (or batch predict); this ML backend fetches the file (unless you use remote-URL-only mode), calls
DoclingServiceClient.convert, and returns layout as reactcode regions. - Reviewers adjust regions or labels on top of Docling’s structure.
You need the full SaaS service URL and API key from Workbench. Separately, the backend must often download task files through Label Studio when URLs point at your instance—see Label Studio URL and API key below.
Set LABEL_STUDIO_URL and LABEL_STUDIO_API_KEY in docker-compose.yml (or your shell) whenever tasks reference files hosted by Label Studio—uploads, cloud storage integrations, or other URLs that Label Studio resolves for the ML backend.
By default it downloads to a cache path and passes a Path into convert. Set DOCLING_CONVERT_REMOTE_URL_ONLY=true to pass the task’s https:// URL directly to SaaS (works only for URLs the Docling service can fetch without Label Studio auth).
Practical notes:
LABEL_STUDIO_URLmust be reachable from where the ML backend runs. From Docker on your laptop,http://localhost:8080usually does not work inside the container; use your machine’s hostname/IP,http://host.docker.internal:8080(Docker Desktop), or another URL the container can route to. This compose file includesextra_hostsforhost.docker.internalon macOS/Linux-friendly setups.LABEL_STUDIO_API_KEYshould be a Personal Access Token (or equivalent) for a user that can read the project’s tasks and attachments.
Always include http:// or https:// in LABEL_STUDIO_URL. More background is in the repository README under allowing the ML backend to access Label Studio data.
DOCLING_SERVICE_URL— full URL ending in/v1from IBM Docling Workbench (same asDoclingServiceClient(url=…)).DOCLING_SERVE_API_KEY— API key forX-Api-Key(name kept for backward compatibility).LABEL_STUDIO_URL/LABEL_STUDIO_API_KEYwhen tasks use Label Studio–hosted files (typical for uploads).
cd label_studio_ml/examples/docling
# Set DOCLING_SERVICE_URL, DOCLING_SERVE_API_KEY, LABEL_STUDIO_URL, LABEL_STUDIO_API_KEY in docker-compose.yml
docker compose up --buildThe ML backend listens on http://localhost:9090. Register that URL in your Label Studio project’s machine learning settings.
| Variable | Required | Description |
|---|---|---|
DOCLING_SERVICE_URL |
Yes | Full DoclingServiceClient URL including path to /v1 (fallback env name: DOCLING_SERVE_URL). |
DOCLING_SERVE_API_KEY |
Often | API key (X-Api-Key). Alias: DOCLING_API_KEY. |
DOCLING_CONVERT_REMOTE_URL_ONLY |
No | If true, pass the task https:// URL as convert(source=url) instead of downloading via Label Studio first. |
DOCLING_CONVERT_SOURCE_HEADERS_JSON |
No | Extra HTTP headers (JSON object) merged into convert when using remote URLs / headers the client supports. |
DOCLING_SERVE_TIMEOUT |
No | Job / read timeout in seconds (default 600). |
DOCLING_HTTP_CONNECT_TIMEOUT |
No | Connect timeout (default 30). |
Optional tuning: DOCLING_PAGE_NO, DOCLING_PREDICT_READING_ORDER, DOCLING_READING_ORDER_LEVEL, DOCLING_CONTENT_LAYERS, DOCLING_REACTCODE_FROM_NAME, DOCLING_REACTCODE_TO_NAME, DOCLING_TASK_DATA_KEY.
The docling PyPI package (≥2.90) provides DoclingServiceClient; behavior follows your SaaS tenant, not necessarily open-source Docling docs.
| Variable | Description |
|---|---|
LABEL_STUDIO_URL |
Base URL of Label Studio, reachable from this backend (see above). |
LABEL_STUDIO_API_KEY |
Token so the backend can download task attachments when needed. |
Predictions are reactcode regions (rectangle / polyline payloads with percent coordinates), aligned with the Label Studio Enterprise ReactCode UI—see docling_labeling_config.xml in this folder.
pip install -r requirements-base.txt -r requirements.txt
export DOCLING_SERVICE_URL=https://api.aws-c1.dcls.saas.ibm.com/your-instance/v1
export DOCLING_SERVE_API_KEY=your-api-key
export LABEL_STUDIO_URL=http://host.docker.internal:8080
export LABEL_STUDIO_API_KEY=your-label-studio-token
python _wsgi.py -p 9090Adjust LABEL_STUDIO_URL if Label Studio runs on the same machine without Docker (for example http://127.0.0.1:8080).
curl http://localhost:9090/Expected: {"status":"UP"}.
DOCLING_SERVICE_URL must match the URL Workbench gives you (through /v1). The backend normalizes it so routes are not doubled—see the note above if you see /v1/v1/ in logs.
Label Studio often shows no message when the ML backend returns empty results (HTTP 200 with an empty list). Check Docker logs for this container:
docker compose logs -f doclingYou should see a line like Docling predict: N task(s) whenever you run predictions. If you see Docling produced zero predictions, scroll up in the same log for No file URL found or Docling API error lines.
Common fixes:
- Placeholder URL — Replace
YOUR_INSTANCE_SEGMENTinDOCLING_SERVICE_URLwith the real path from Workbench. - Wrong task field — Tasks must expose a file URL under the key your labeling config expects (often
undefined). Override withDOCLING_TASK_DATA_KEYif needed. LOG_LEVEL— Defaults toINFOin_wsgi.pywhen unset.- Upload /
/storage-data/URLs —model.pydownloads vialabel_studio_sdkusingLABEL_STUDIO_URL(same scheme + host + port as in your browser; wrong host breaks auth headers),LABEL_STUDIO_API_KEY, and network reachability from this container (host.docker.internalinstead oflocalhoston Docker Desktop). Self-signed HTTPS: setVERIFY_SSL=falseon the ML backend. Logs now include HTTP status / snippet when the download fails.
Sanity checks:
curl -s http://localhost:9090/health
curl -s http://localhost:9090/Both should return JSON including "status":"UP".
Check LABEL_STUDIO_URL / LABEL_STUDIO_API_KEY and logs for Docling task … local_path=… size=…. A size of 0 or failed stat (-1 in logs) usually means the file did not download correctly before conversion.
Like other backends under label_studio_ml/examples/ (for example easyocr/), this directory includes _wsgi.py, model.py, requirements-base.txt, requirements.txt, Dockerfile, docker-compose.yml, and tests. docker-compose.yml bind-mounts ./data/server and ./data/.file-cache for runtime caches; Docker creates those paths on the host when you first run Compose—they are not checked into git (see .gitignore).