Spaces:
Configuration error
Configuration error
Commit Β·
ed6ea78
1
Parent(s): 6a4b2fc
feat(backend): add Dockerfile, .dockerignore, and corrected .env schema for HF Spaces deploy
Browse files- .dockerignore +71 -0
- .env.example +32 -15
- Dockerfile +58 -0
- README.md +1 -1
.dockerignore
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =============================================================================
|
| 2 |
+
# .dockerignore β keep the build context tiny.
|
| 3 |
+
# Everything not needed by the backend runtime is excluded.
|
| 4 |
+
# =============================================================================
|
| 5 |
+
|
| 6 |
+
# --- VCS / IDE ---------------------------------------------------------------
|
| 7 |
+
.git
|
| 8 |
+
.github
|
| 9 |
+
.gitignore
|
| 10 |
+
.gitattributes
|
| 11 |
+
.vscode
|
| 12 |
+
.idea
|
| 13 |
+
*.swp
|
| 14 |
+
|
| 15 |
+
# --- Python caches & build artefacts -----------------------------------------
|
| 16 |
+
__pycache__
|
| 17 |
+
*.py[cod]
|
| 18 |
+
*$py.class
|
| 19 |
+
*.egg-info
|
| 20 |
+
.eggs
|
| 21 |
+
build
|
| 22 |
+
dist
|
| 23 |
+
.pytest_cache
|
| 24 |
+
.mypy_cache
|
| 25 |
+
.ruff_cache
|
| 26 |
+
.coverage
|
| 27 |
+
.coverage.*
|
| 28 |
+
htmlcov
|
| 29 |
+
.tox
|
| 30 |
+
|
| 31 |
+
# --- Virtual envs ------------------------------------------------------------
|
| 32 |
+
.venv
|
| 33 |
+
venv
|
| 34 |
+
env
|
| 35 |
+
|
| 36 |
+
# --- Frontend (deployed separately to Vercel) --------------------------------
|
| 37 |
+
frontend
|
| 38 |
+
node_modules
|
| 39 |
+
|
| 40 |
+
# --- Tests, notebooks, docs --------------------------------------------------
|
| 41 |
+
tests
|
| 42 |
+
notebooks
|
| 43 |
+
docs
|
| 44 |
+
assets
|
| 45 |
+
scripts
|
| 46 |
+
|
| 47 |
+
# --- Local dev / secrets -----------------------------------------------------
|
| 48 |
+
.env
|
| 49 |
+
.env.*
|
| 50 |
+
!.env.example
|
| 51 |
+
*.local
|
| 52 |
+
|
| 53 |
+
# --- OS junk -----------------------------------------------------------------
|
| 54 |
+
.DS_Store
|
| 55 |
+
Thumbs.db
|
| 56 |
+
|
| 57 |
+
# --- Docker / CI configs (not needed inside the image) -----------------------
|
| 58 |
+
Dockerfile
|
| 59 |
+
.dockerignore
|
| 60 |
+
.pre-commit-config.yaml
|
| 61 |
+
Makefile
|
| 62 |
+
CLAUDE.md
|
| 63 |
+
|
| 64 |
+
# --- Lockfiles / dev-only deps -----------------------------------------------
|
| 65 |
+
requirements-dev.txt
|
| 66 |
+
requirements-eval.txt
|
| 67 |
+
|
| 68 |
+
# --- Model artefacts: keep ONLY the production version -----------------------
|
| 69 |
+
# (Add explicit exceptions here if you publish multiple versions.)
|
| 70 |
+
models/**/*.tar
|
| 71 |
+
models/**/*.zip
|
.env.example
CHANGED
|
@@ -3,33 +3,50 @@
|
|
| 3 |
# -----------------------------------------------------------------------------
|
| 4 |
# Copy this file to `.env` (which is gitignored) and fill in real values.
|
| 5 |
# `pydantic-settings` automatically reads `.env` at startup and validates each
|
| 6 |
-
# field.
|
| 7 |
-
# `src/captioning/config/schema.py`); double underscore is the nesting delimiter.
|
| 8 |
#
|
| 9 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
# =============================================================================
|
| 11 |
|
| 12 |
# ---- App-wide ----------------------------------------------------------------
|
| 13 |
APP_ENV=development # development | staging | production
|
| 14 |
LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR
|
| 15 |
|
| 16 |
-
# ----
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
# -
|
| 27 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
HF_REPO_ID=your-username/captioning-weights
|
| 29 |
HF_REVISION=v1.0.0 # Pin a specific tag for reproducibility
|
| 30 |
# Optional: only needed for private repos or higher rate limits.
|
| 31 |
# Generate at https://huggingface.co/settings/tokens (read-only is enough).
|
| 32 |
HF_TOKEN=
|
|
|
|
| 33 |
|
| 34 |
# ---- Experiment tracking (MLflow) --------------------------------------------
|
| 35 |
# Local SQLite during dev; DagsHub URL in production.
|
|
|
|
| 3 |
# -----------------------------------------------------------------------------
|
| 4 |
# Copy this file to `.env` (which is gitignored) and fill in real values.
|
| 5 |
# `pydantic-settings` automatically reads `.env` at startup and validates each
|
| 6 |
+
# field.
|
|
|
|
| 7 |
#
|
| 8 |
+
# Two prefixes are read by the application:
|
| 9 |
+
# BACKEND_* -> backend/app/core/config.py (BackendSettings)
|
| 10 |
+
# CAPTIONING__<sec>__<k> -> src/captioning/config/schema.py (AppConfig)
|
| 11 |
+
# Nested AppConfig fields use a double-underscore delimiter:
|
| 12 |
+
# CAPTIONING__TRAIN__BATCH_SIZE=32 overrides AppConfig.train.batch_size
|
| 13 |
# =============================================================================
|
| 14 |
|
| 15 |
# ---- App-wide ----------------------------------------------------------------
|
| 16 |
APP_ENV=development # development | staging | production
|
| 17 |
LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR
|
| 18 |
|
| 19 |
+
# ---- BackendSettings (FastAPI process) --------------------------------------
|
| 20 |
+
BACKEND_CONFIG_PATH=configs/base.yaml
|
| 21 |
+
BACKEND_WEIGHTS_PATH=models/v1.0.0/model.h5
|
| 22 |
+
BACKEND_TOKENIZER_DIR=models/v1.0.0
|
| 23 |
+
BACKEND_MODEL_VERSION=v1.0.0
|
| 24 |
+
BACKEND_API_VERSION=0.1.0
|
| 25 |
+
BACKEND_WARMUP=true
|
| 26 |
+
BACKEND_REQUEST_ID_HEADER=x-request-id
|
| 27 |
+
|
| 28 |
+
# ---- AppConfig overrides (research-side hyperparameters) --------------------
|
| 29 |
+
# CORS allow-list lives in configs/base.yaml under `serve.cors_allowed_origins`.
|
| 30 |
+
# Override it for prod by setting the env var below to a JSON list.
|
| 31 |
+
# CAPTIONING__SERVE__CORS_ALLOWED_ORIGINS=["https://your-frontend.vercel.app"]
|
| 32 |
+
# CAPTIONING__SERVE__MAX_UPLOAD_BYTES=10485760
|
| 33 |
+
# CAPTIONING__INFERENCE__DECODE_STRATEGY=beam
|
| 34 |
+
# CAPTIONING__INFERENCE__BEAM_WIDTH=3
|
| 35 |
+
|
| 36 |
+
# ---- TensorFlow runtime tuning (optional, for HF Spaces cpu-basic) ----------
|
| 37 |
+
# TF_CPP_MIN_LOG_LEVEL=2 # silence INFO/WARNING from TF
|
| 38 |
+
# OMP_NUM_THREADS=2 # match cpu-basic vCPU count
|
| 39 |
+
# TF_NUM_INTEROP_THREADS=1
|
| 40 |
+
# TF_NUM_INTRAOP_THREADS=2
|
| 41 |
+
|
| 42 |
+
# ---- HuggingFace Hub (model artefact storage β wired up in WS-A4) -----------
|
| 43 |
+
# Public model repo holding the trained weights + vocab.json.
|
| 44 |
HF_REPO_ID=your-username/captioning-weights
|
| 45 |
HF_REVISION=v1.0.0 # Pin a specific tag for reproducibility
|
| 46 |
# Optional: only needed for private repos or higher rate limits.
|
| 47 |
# Generate at https://huggingface.co/settings/tokens (read-only is enough).
|
| 48 |
HF_TOKEN=
|
| 49 |
+
# HF_HOME=/home/user/.cache/huggingface
|
| 50 |
|
| 51 |
# ---- Experiment tracking (MLflow) --------------------------------------------
|
| 52 |
# Local SQLite during dev; DagsHub URL in production.
|
Dockerfile
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# syntax=docker/dockerfile:1.7
|
| 2 |
+
# =============================================================================
|
| 3 |
+
# Dockerfile β FastAPI inference backend for HuggingFace Spaces (Docker SDK).
|
| 4 |
+
# -----------------------------------------------------------------------------
|
| 5 |
+
# Target: HF Spaces, hardware = cpu-basic (2 vCPU / 16 GB RAM).
|
| 6 |
+
# Port: 7860 (HF Spaces convention).
|
| 7 |
+
# User: UID 1000 named "user" (HF Spaces requirement).
|
| 8 |
+
# Workdir: /home/user/app (HF Spaces convention).
|
| 9 |
+
# Worker: uvicorn single worker β keeps the TF model loaded once in RAM.
|
| 10 |
+
# =============================================================================
|
| 11 |
+
|
| 12 |
+
FROM python:3.11-slim-bookworm
|
| 13 |
+
|
| 14 |
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
| 15 |
+
PYTHONUNBUFFERED=1 \
|
| 16 |
+
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
| 17 |
+
PIP_NO_CACHE_DIR=1 \
|
| 18 |
+
TF_CPP_MIN_LOG_LEVEL=2 \
|
| 19 |
+
HF_HOME=/home/user/.cache/huggingface
|
| 20 |
+
|
| 21 |
+
# libgomp1 is required by tensorflow-cpu (OpenMP runtime).
|
| 22 |
+
# curl is used by HEALTHCHECK.
|
| 23 |
+
RUN apt-get update \
|
| 24 |
+
&& apt-get install -y --no-install-recommends libgomp1 curl \
|
| 25 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 26 |
+
|
| 27 |
+
# HF Spaces requires a non-root user with UID 1000 named "user".
|
| 28 |
+
RUN useradd --create-home --uid 1000 user
|
| 29 |
+
USER user
|
| 30 |
+
ENV PATH="/home/user/.local/bin:${PATH}"
|
| 31 |
+
WORKDIR /home/user/app
|
| 32 |
+
|
| 33 |
+
# --- Dependency layer (cached across code changes) ---------------------------
|
| 34 |
+
COPY --chown=user:user requirements.txt ./
|
| 35 |
+
RUN pip install --user --no-cache-dir -r requirements.txt
|
| 36 |
+
|
| 37 |
+
# --- Application source ------------------------------------------------------
|
| 38 |
+
# Copy only what the runtime needs. Build context is pruned by .dockerignore.
|
| 39 |
+
COPY --chown=user:user pyproject.toml README.md ./
|
| 40 |
+
COPY --chown=user:user src/ ./src/
|
| 41 |
+
COPY --chown=user:user backend/ ./backend/
|
| 42 |
+
COPY --chown=user:user configs/ ./configs/
|
| 43 |
+
COPY --chown=user:user models/ ./models/
|
| 44 |
+
|
| 45 |
+
# Install the local captioning package without re-resolving deps.
|
| 46 |
+
RUN pip install --user --no-cache-dir --no-deps -e .
|
| 47 |
+
|
| 48 |
+
EXPOSE 7860
|
| 49 |
+
|
| 50 |
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \
|
| 51 |
+
CMD curl --fail --silent http://127.0.0.1:7860/healthz || exit 1
|
| 52 |
+
|
| 53 |
+
CMD ["uvicorn", "app.main:app", \
|
| 54 |
+
"--app-dir", "backend", \
|
| 55 |
+
"--host", "0.0.0.0", \
|
| 56 |
+
"--port", "7860", \
|
| 57 |
+
"--workers", "1", \
|
| 58 |
+
"--log-level", "info"]
|
README.md
CHANGED
|
@@ -542,7 +542,7 @@ The backend test suite ([`backend/app/tests/`](backend/app/tests/)) introduced i
|
|
| 542 |
|
| 543 |
### Phase 2C β Public deployment π§ (in progress)
|
| 544 |
|
| 545 |
-
- [
|
| 546 |
- [ ] **WS-A4** β Lifespan integration with HuggingFace Hub: extend `BackendSettings` with `weights_hub_repo` / `weights_hub_revision`, call `huggingface_hub.snapshot_download` on startup when set
|
| 547 |
- [ ] **WS-B** β Upload trained weights + tokenizer to a HuggingFace Hub model repo
|
| 548 |
- [ ] **WS-C** β First manual deploy to a HuggingFace Space (Docker SDK, cpu-basic, port 7860, single worker)
|
|
|
|
| 542 |
|
| 543 |
### Phase 2C β Public deployment π§ (in progress)
|
| 544 |
|
| 545 |
+
- [x] **WS-A** β Backend containerisation: `Dockerfile` (python:3.11-slim, non-root UID 1000, EXPOSE 7860, HEALTHCHECK on `/healthz`) + `.dockerignore` + corrected `.env.example` schema
|
| 546 |
- [ ] **WS-A4** β Lifespan integration with HuggingFace Hub: extend `BackendSettings` with `weights_hub_repo` / `weights_hub_revision`, call `huggingface_hub.snapshot_download` on startup when set
|
| 547 |
- [ ] **WS-B** β Upload trained weights + tokenizer to a HuggingFace Hub model repo
|
| 548 |
- [ ] **WS-C** β First manual deploy to a HuggingFace Space (Docker SDK, cpu-basic, port 7860, single worker)
|