Skip to content

feat: Make docling core optional#1003

Merged
edwinjosechittilappilly merged 26 commits into
mainfrom
make-docling-core-optional
Feb 24, 2026
Merged

feat: Make docling core optional#1003
edwinjosechittilappilly merged 26 commits into
mainfrom
make-docling-core-optional

Conversation

@edwinjosechittilappilly

@edwinjosechittilappilly edwinjosechittilappilly commented Feb 19, 2026

Copy link
Copy Markdown
Collaborator

Reduced Backend Image size from ~4GB to ~500MB

Move docling-related packages into an optional 'docling' dependency group and add zxcvbn. Add runtime checks (is_docling_available) and a DoclingNotInstalledError to detect missing openrag[docling]. Make the document converter lazy-initialized in AppClients.converter and guard usages in processors and DocumentService to raise a clear error when docling isn't present. Add HTTP handlers and upload-specific returns that map missing-docling errors to 503 responses and skip warm-up when docling is not installed. Also update warm_up_docling to exit early if docling is absent.
Revamp Dockerfile.backend to a multi-stage build with an INSTALL_DOCLING build-arg: the builder stage installs dependencies and (optionally) downloads docling/EasyOCR models when INSTALL_DOCLING=1, while the final stage is a minimal runtime that copies the installed app. pyproject.toml now moves torch to an optional 'torch' extra and ensures docling-serve is managed via extras so heavy ML runtimes are not required by default. src/main.py defers and guards the torch import, logging CUDA info only when torch is present. src/tui/managers/docling_manager.py adds a runtime check for docling-serve and fails gracefully with guidance if it's not installed. These changes allow smaller images by default and make startup resilient when optional ML packages are absent.
Convert Dockerfile.backend to a multi-stage BuildKit-friendly layout (syntax header + base/builder/runtime stages). Install uv in a lightweight base image, move build-time deps to a builder stage, and make docling/model installation optional via ARG INSTALL_DOCLING=1. Use --no-install-recommends for apt, add cache mount for uv, conditionally run uv sync --extra docling and download docling/EasyOCR models into /app/.EasyOCR when requested, and clean temporary caches. The final runtime stage remains minimal and copies the prepared /app from the builder.
@edwinjosechittilappilly

Copy link
Copy Markdown
Collaborator Author

once #1002 merges this PR would point to Main branch

@edwinjosechittilappilly edwinjosechittilappilly marked this pull request as ready for review February 19, 2026 21:52
Copilot AI review requested due to automatic review settings February 19, 2026 21:52
@edwinjosechittilappilly edwinjosechittilappilly changed the base branch from dockling-serve-uvx to main February 19, 2026 21:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request makes docling and torch optional dependencies to significantly reduce the backend Docker image size from ~4GB to ~500MB. The changes introduce a pattern of lazy initialization and availability checks for heavy dependencies, allowing the application to run without these packages installed while providing clear error messages when optional features are attempted without the required extras.

Changes:

  • Moved docling, docling-core, easyocr, and torch from core dependencies to optional extras in pyproject.toml
  • Added availability checks and custom exception handling for missing optional dependencies
  • Implemented lazy initialization for the document converter to defer imports until actual use
  • Refactored Dockerfile to use multi-stage builds with conditional installation of optional dependencies

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pyproject.toml Moved docling and torch dependencies to optional extras section
uv.lock Updated dependency markers to reflect optional status with extra == conditions
warm_up_docling.py Added availability check to skip warm-up when docling is not installed
src/utils/document_processing.py Added is_docling_available() function, DoclingNotInstalledError exception class, and proper import guards
src/tui/managers/docling_manager.py Added availability check for docling_serve package
src/services/document_service.py Added availability check before importing docling_core
src/models/processors.py Added availability check before using docling converter
src/main.py Made torch import optional and added global exception handler for DoclingNotInstalledError
src/config/settings.py Changed converter to lazy-initialized property to defer docling imports
src/api/upload.py Added local exception handling for DoclingNotInstalledError (redundant with global handler)
Dockerfile.backend Refactored to multi-stage build with conditional docling installation via build arg

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/tui/managers/docling_manager.py Outdated
Comment thread src/api/upload.py Outdated
Comment thread src/api/upload.py Outdated
Comment thread Dockerfile.backend

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Introduce require_docling() in utils.document_processing to raise DoclingNotInstalledError when the docling extra is missing, and replace scattered is_docling_available() checks with require_docling() in processors and services. Update create_document_converter and get_worker_converter to call require_docling(). Remove the special-case DoclingNotInstalledError handling from the upload endpoint so docling-related errors are raised consistently. Aims to centralize docling availability logic and simplify error handling across the codebase.
Capture and log docling start output and architecture in Makefile; extract endpoint from output, default to http://localhost:5001 if missing, run status checks, and emit a clear error if health checks fail. Refactor docling host detection to try well-known hostnames first, use container-specific fallbacks (gateway/bridge) and add clearer logging. Treat .md files like .txt for simple processing to skip docling in processors and document service. Also add several local documentation PDFs to .gitignore.
Introduce a configurable startup timeout for docling and make CI fail-fast with cleanup. Added a --timeout argument to scripts/docling_ctl.py and forwarded it to DoclingManager.start; DoclingManager.start now accepts a timeout and waits up to that many seconds for the service to listen (with periodic log updates). Updated Makefile test-ci and test-ci-local to pass --timeout 180, and on startup failure the pipeline now stops docling, brings down compose services, and exits with error. Also clarified some startup/failure log messages.
Simplify how the external docling serve process is started by removing shutil-based checks and fallbacks for `uv` or `python -m docling_serve`. The code now always builds a fixed `uvx ... docling-serve==1.5.0 run` command (keeping platform-specific OCR package selection). Also small whitespace added in the docstring. This reduces branching and assumes `uvx` is available in the runtime environment.
Remove the apt-get install libgl1 step from the integration workflow and add --with opencv-python-headless to the uvx install args for docling-serve==1.5.0. This switches OpenCV to a headless Python package to avoid needing system GL libraries on the CI runner.
On non-mac platforms, create a temporary uvx override file to replace opencv-python with opencv-python-headless so headless CI runners lacking libGL can run docling. Add tempfile import, build the uvx command to pass --override and --with opencv-python-headless, and ensure the override file is removed after resolution or on errors. Minor command assembly refactor and cleanup on FileNotFoundError/exception paths.
@edwinjosechittilappilly

Copy link
Copy Markdown
Collaborator Author

@phact Mike have fixed the Tests and will merge it soon.
That would help to make integration test in this PR also pass ideally.

@edwinjosechittilappilly edwinjosechittilappilly merged commit 0a8e315 into main Feb 24, 2026
4 checks passed
@edwinjosechittilappilly edwinjosechittilappilly added the enhancement 🔵 New feature or request label Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement 🔵 New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants