docling separation

This commit is contained in:
Pavel committed 2026-08-27 17:36:38 +04:00
1 parent e101c0a7f1
commit d7a7d4d084
12 files changed
+100 -13

No files matched your search

+2
View File
@@ -29,6 +29,8 @@ Use these commands once the dev prerequisites above are satisfied.
```bash
source .venv/bin/activate # macOS/Linux
uv pip install -r application/requirements.txt # or: pip install -r application/requirements.txt
# Optional docling parser engine (OCR / read_document structured output):
# uv pip install -r application/requirements-docling.txt
```
Run the API. For local dev, prefer the ASGI entrypoint under uvicorn — it
+11 -2
View File
@@ -28,8 +28,8 @@ RUN wget -q -O - https://sh.rustup.rs | sh -s -- -y
# Clean up to reduce container size
RUN apt-get remove --purge -y wget unzip && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
# Copy requirements.txt
COPY requirements.txt .
# Copy requirements manifests
COPY requirements.txt requirements-docling.txt ./
# Setup Python virtual environment
RUN python3.12 -m venv /venv
@@ -42,6 +42,15 @@ RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir tiktoken && \
pip install --no-cache-dir -r requirements.txt
# Optional docling parser engine (DOC_PARSER_ENGINE=docling, OCR for scanned
# PDFs/images, read_document's structured output) — OFF by default: it pulls
# the layout/OCR model stack and adds gigabytes to the image. anydoc (in
# requirements.txt) is the default parser and needs none of it.
ARG INSTALL_DOCLING=false
RUN if [ "$INSTALL_DOCLING" = "true" ]; then \
pip install --no-cache-dir -r requirements-docling.txt; \
fi
# Final Stage
FROM ubuntu:24.04 as final
+14
View File
@@ -0,0 +1,14 @@
# Optional docling parser engine.
#
# Needed only for: DOC_PARSER_ENGINE=docling, OCR of scanned PDFs and images
# (DOCLING_OCR_ENABLED / DOCLING_OCR_ATTACHMENTS_ENABLED), .adoc/.vtt/.xml
# source parsing, and the read_document tool's `structured` output. The
# default anydoc engine needs none of this.
#
# Install ON TOP of requirements.txt (torch/transformers stay pinned there,
# shared with sentence-transformers):
# pip install -r requirements.txt -r requirements-docling.txt
# Docker: build with --build-arg INSTALL_DOCLING=true
docling==2.119.0
rapidocr==3.9.2
onnxruntime==1.28.0
+9 -7
View File
@@ -12,12 +12,10 @@ cryptography==50.0.0
dataclasses-json==0.6.7
daytona==0.205.1
defusedxml==0.7.1
docling==2.119.0
# Default document converter (DOC_PARSER_ENGINE=anydoc); docling above is
# the optional heavy engine for OCR/structured output.
# Default document converter (DOC_PARSER_ENGINE=anydoc). The docling engine
# (OCR, layout/table models, read_document's structured output) is an
# optional extra: pip install -r requirements-docling.txt
firecrawl-anydoc==0.2.3
rapidocr==3.9.2
onnxruntime==1.28.0
docx2txt==0.9
ddgs>=8.0.0
fast-ebook
@@ -98,10 +96,14 @@ sqlalchemy>=2.0,<3
starlette>=1.0,<2
tiktoken==0.13.0
tokenizers==0.22.2
# torch stays in core: sentence-transformers (local embeddings) needs it even
# with the docling extra uninstalled.
torch==2.11.0
tqdm==4.67.3
# Capped <5.9.0 to match docling-core's own darwin pin: 5.9+ breaks docling's
# PDF layout model on Apple Silicon ("Cannot convert a MPS Tensor to float64").
# Kept in core for sentence-transformers, so installing the optional docling
# extra never changes the shared model stack. Capped <5.9.0 to match
# docling-core's own darwin pin: 5.9+ breaks docling's PDF layout model on
# Apple Silicon ("Cannot convert a MPS Tensor to float64").
transformers==5.8.1
typing-extensions==4.16.0
typing-inspect==0.9.0
+10 -2
View File
@@ -15,7 +15,12 @@ services:
backend:
user: root
build: ../application
build:
context: ../application
args:
# Bake the optional docling engine (OCR, structured output) into the
# image: set INSTALL_DOCLING=true in ../.env or the shell.
INSTALL_DOCLING: ${INSTALL_DOCLING:-false}
env_file:
- ../.env
environment:
@@ -38,7 +43,10 @@ services:
worker:
user: root
build: ../application
build:
context: ../application
args:
INSTALL_DOCLING: ${INSTALL_DOCLING:-false}
# Consumes the default queue AND the dedicated `parsing` queue (read_document /
# parse_document). Without `parsing` here the read_document await never resolves.
# For heavy/OCR parsing run a separate worker with `-Q parsing`.
@@ -96,6 +96,13 @@ To run the DocsGPT backend locally, you'll need to set up a Python environment a
pip install -r application/requirements.txt
```
Optionally add the docling parser engine (OCR, `structured` output for
`read_document`; the default anydoc engine does not need it):
```bash
pip install -r application/requirements-docling.txt
```
5. **Run the Backend:**
For local development, run the ASGI composition under uvicorn. It serves the **whole** application, hot-reloads on source changes, and matches the production runtime:
+1 -1
View File
@@ -206,7 +206,7 @@ for the engines and flows.
| Setting | Default | Description |
| --- | --- | --- |
| `DOC_PARSER_ENGINE` | `anydoc` | Parser engine: `anydoc` (fast Rust converter, no ML models) or `docling` (layout/table models, OCR, structured output; heavy optional install). Files anydoc cannot read fall back to Docling when installed. |
| `DOC_PARSER_ENGINE` | `anydoc` | Parser engine: `anydoc` (fast Rust converter, no ML models) or `docling` (layout/table models, OCR, structured output). Files anydoc cannot read fall back to Docling when installed. Docling is an optional extra: `pip install -r application/requirements-docling.txt`, or Docker builds with `--build-arg INSTALL_DOCLING=true`. |
| `DOCLING_OCR_ENABLED` | `false` | OCR for source ingestion (Docling only). |
| `DOCLING_OCR_ATTACHMENTS_ENABLED` | `false` | OCR for chat attachments (Docling only). |
| `ATTACHMENT_PDF_TEXT_FAST_PATH` | `true` | Under the `docling` engine, read PDF attachments through their text layer (pypdfium2) and only hand scans to Docling. Not needed under `anydoc`. |
+23
View File
@@ -41,6 +41,29 @@ sources, and the fallback for files anydoc rejects. Without Docling those
formats use the standard parsers, and images are only read when
`PARSE_IMAGE_REMOTE=true`.
## Installing the docling engine
docling is not part of the base install. Add it when you need OCR,
`.adoc`/`.vtt`/`.xml` source parsing, or `read_document`'s `structured`
output:
```bash
pip install -r application/requirements-docling.txt
```
Docker images build without it by default; opt in with the build argument:
```bash
docker build --build-arg INSTALL_DOCLING=true ./application
```
`deployment/docker-compose.yaml` forwards the same switch, so setting
`INSTALL_DOCLING=true` in `.env` (or the shell) bakes docling into locally
built backend and worker images. `setup.sh` writes it automatically when you
answer yes to the OCR question. Either way no code changes are needed —
docling is picked up as the fallback engine as soon as it is importable, and
`DOC_PARSER_ENGINE=docling` makes it the primary one.
## Docling OCR
OCR is optional, Docling-only, and controlled by two settings:
+4 -1
View File
@@ -365,7 +365,10 @@ configure_doc_processing() {
read -p "$(echo -e "${DEFAULT_FG}Enable OCR for document processing (Docling)? (y/N): ${NC}")" ocr_enabled
if [[ "$ocr_enabled" =~ ^[yY]$ ]]; then
echo "DOCLING_OCR_ENABLED=true" >> "$ENV_FILE"
echo -e "${GREEN}Docling OCR enabled.${NC}"
# OCR needs the optional docling engine; locally built images include
# it via this build arg (hub images must be published with it baked in).
echo "INSTALL_DOCLING=true" >> "$ENV_FILE"
echo -e "${GREEN}Docling OCR enabled (locally built images will include the docling engine).${NC}"
fi
}
+12
View File
@@ -910,6 +910,12 @@ class TestApplyInferenceSettings:
and buys nothing for one-shot parses.
"""
@pytest.fixture(autouse=True)
def _requires_docling(self):
# These tests reach into docling.datamodel.settings for real; a base
# install (docling is an optional extra) skips them.
pytest.importorskip("docling")
def test_disables_torch_compile_by_default(self, monkeypatch):
from application.parser.file.docling_parser import _apply_inference_settings
@@ -1412,6 +1418,12 @@ class TestOCRDropoutHelpers:
class TestForceFullPageOCRWiring:
"""``force_full_page_ocr`` must reach the pipeline for any OCR engine."""
@pytest.fixture(autouse=True)
def _requires_docling(self):
# Builds real ``docling.datamodel.pipeline_options``; a base install
# (docling is an optional extra) skips these.
pytest.importorskip("docling")
def _pipeline_options(self, monkeypatch, **kwargs):
import docling.datamodel.pipeline_options as dpo
+4
View File
@@ -158,6 +158,10 @@ def test_threshold_sends_sparse_text_to_fallback(tmp_path, parser_cls):
@pytest.fixture
def docling_engine(monkeypatch):
# The wiring assertions below expect the docling map; on a base install
# (docling is an optional extra) the engine degrades to the legacy
# parsers and these tests do not apply.
pytest.importorskip("docling")
from application.core.settings import settings
monkeypatch.setattr(settings, "DOC_PARSER_ENGINE", "docling")
+3
View File
@@ -12,3 +12,6 @@ jupyter-client>=8.0
# (python-pptx and openpyxl already ship in application/requirements.txt).
python-docx>=1.1
reportlab>=4.0,<5
# The optional docling engine stays installed in the test env so its parser
# paths keep CI coverage even though production installs it on demand.
-r ../application/requirements-docling.txt