FROM python:3.12-slim AS base ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 WORKDIR /app # System packages: # tesseract-ocr / -eng — fallback OCR # poppler-utils — pdf2image rasterization # libgl1, libglib2.0-0 — Paddle/Pillow/OpenCV image deps # ffmpeg — video audio-track extraction + opencv decoders # build-essential — for any wheels that need compilation RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ curl \ tesseract-ocr \ tesseract-ocr-eng \ poppler-utils \ libgl1 \ libglib2.0-0 \ ffmpeg \ && rm -rf /var/lib/apt/lists/* COPY pyproject.toml README.md ./ RUN mkdir -p app && touch app/__init__.py \ && pip install --upgrade pip # Install API deps first; install worker extras best-effort (Paddle wheels # don't exist on every arch — Tesseract is the fallback in that case). RUN pip install -e ".[dev]" \ && (pip install ".[worker]" || (echo "WARN: full worker extras failed; installing without paddle" \ && pip install pytesseract pdf2image Pillow numpy)) \ && rm -rf /usr/local/lib/python3.12/site-packages/app # Pre-bake the three retrieval models (embedder, reranker, BM25 sparse). # Retry on HF 429s; FAIL the build if retries exhaust so the CI error is # loud instead of producing an image whose worker can't embed/rerank. ENV HF_HOME=/app/.cache/huggingface \ XDG_CACHE_HOME=/app/.cache RUN mkdir -p /app/.cache/huggingface && \ for i in 1 2 3 4 5; do \ if python -c "\ from sentence_transformers import SentenceTransformer, CrossEncoder; \ from fastembed import SparseTextEmbedding; \ SentenceTransformer('BAAI/bge-small-en-v1.5'); \ CrossEncoder('BAAI/bge-reranker-base'); \ list(SparseTextEmbedding(model_name='Qdrant/bm25').embed(['warmup']))\ "; then \ break; \ fi; \ if [ "$i" = "5" ]; then \ echo "FATAL: HF model download failed after 5 attempts"; exit 1; \ fi; \ echo "HF download attempt $i failed; sleeping $((i*15))s"; \ sleep $((i*15)); \ done COPY app ./app COPY alembic ./alembic COPY alembic.ini ./alembic.ini ENV PYTHONPATH=/app CMD ["arq", "app.workers.config.WorkerSettings"]