Saravanakumar R Claude Sonnet 4.6 commited on
Commit
24fe4dc
·
1 Parent(s): 31ce85c

Add HF Spaces deployment openspec change

Browse files

Documents the model-hub upload script, Dockerfile build flow, and
README deployment section (code already committed prior).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

openspec/changes/hf-spaces-deployment/.openspec.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ schema: spec-driven
2
+ created: 2026-06-22
openspec/changes/hf-spaces-deployment/design.md ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Context
2
+
3
+ G.U.I.D.E. currently runs as two processes launched by `start.py`: FastAPI on `:8000` (model inference + agent API) and Gradio on `:7860` (UI). The Gradio frontend calls `http://localhost:8000` — an internal URL that works within any single container.
4
+
5
+ HF Spaces Dockerfile Spaces expose exactly one public port (`:7860`) but allow arbitrary internal processes. This maps cleanly onto the existing architecture without modification.
6
+
7
+ Three trained model artifacts exist locally:
8
+ - `models/domain_classifier/` — DistilBERT fine-tuned on CFPB data (~256MB safetensors)
9
+ - `models/evidence_ner/` — DistilBERT NER, root-level files only (~270MB safetensors); `checkpoint-*` subdirs are training artifacts (~3.2GB total, not needed at inference)
10
+ - `models/next_action/model.pt` — MLP state dict (~24KB)
11
+
12
+ ## Goals / Non-Goals
13
+
14
+ **Goals:**
15
+ - Public HF Spaces demo accessible via browser with no local setup
16
+ - Full pipeline (DomainClassifier + EvidenceNER + NextActionPredictor) using trained weights
17
+ - One-time upload script for model weights with checkpoint filtering
18
+ - Two-server design preserved exactly as-is
19
+
20
+ **Non-Goals:**
21
+ - Modifying any `predict.py`, `start.py`, or `ui/app.py` files
22
+ - Single-process refactor
23
+ - CI/CD automation
24
+ - User-supplied API key input in the UI
25
+
26
+ ## Decisions
27
+
28
+ ### Decision 1: Dockerfile Space over SDK Space
29
+
30
+ HF SDK Spaces require `app.py` as the entrypoint and expect a single Gradio `demo.launch()` call. Wiring FastAPI as a background thread from inside `app.py` is fragile and breaks the existing process model.
31
+
32
+ Dockerfile Spaces let us use `CMD ["python", "start.py", "--no-train"]` exactly as-is.
33
+
34
+ **Alternatives considered:** SDK Space with threading — rejected because it requires changes to `ui/app.py` and creates a coupled process model that's harder to debug.
35
+
36
+ ### Decision 2: Download weights at Docker build time, not runtime
37
+
38
+ Cold-start download (~800MB) would block HF Spaces visitors for 2-3 minutes. Baking weights into the image layer via `RUN huggingface-cli download` at build time means the container starts in seconds.
39
+
40
+ **Alternatives considered:** Download at container startup in `start.py` — rejected due to cold-start UX on free-tier HF Spaces.
41
+
42
+ ### Decision 3: One HF Model Hub repo, three subdirectories
43
+
44
+ `your-username/guide-models` with `domain_classifier/`, `evidence_ner/`, `next_action/` subdirs. A single `huggingface-cli download` in the Dockerfile fetches everything into `models/` — matching the existing local path structure that all `predict.py` files already expect.
45
+
46
+ **Alternatives considered:** Three separate HF repos — cleaner HF Hub browsing but requires three download commands and complicates the upload script.
47
+
48
+ ### Decision 4: Filter checkpoint-* at upload time via script
49
+
50
+ `models/evidence_ner/checkpoint-*/` directories are intermediate training snapshots (~3.2GB). Only the root-level `models/evidence_ner/` files are needed for inference. The upload script explicitly skips any path component matching `checkpoint-*` and `.DS_Store`.
51
+
52
+ ## Risks / Trade-offs
53
+
54
+ - **[Risk] HF Spaces free-tier memory limit (~16GB RAM)** → Mitigation: spaCy `en_core_web_lg` (~750MB) + two DistilBERT models (~540MB each) + ViT + Tesseract fits within 16GB. Monitor via HF Spaces logs on first deploy.
55
+ - **[Risk] Build time timeout on HF Spaces** → Mitigation: `spacy download` + Hub download is ~1.5GB at build time; HF Spaces build timeout is 30 min, well within budget.
56
+ - **[Risk] ANTHROPIC_API_KEY exposure** → Mitigation: Key is set only via HF Spaces Secrets UI, never in Dockerfile or committed code. `ENV ANTHROPIC_API_KEY=""` in Dockerfile is a placeholder only.
57
+ - **[Risk] HF Hub model repo must be public for free-tier download** → Mitigation: Models contain no PII (trained on synthetic data + CFPB public dataset); public repo is acceptable for academic use.
58
+
59
+ ## Migration Plan
60
+
61
+ 1. Run `scripts/upload_models_to_hub.py` locally (one-time, requires `huggingface-cli login`)
62
+ 2. Create HF Space (Dockerfile type) via HF UI or CLI
63
+ 3. Push repo code to HF Space git remote
64
+ 4. Set `ANTHROPIC_API_KEY` in HF Space Secrets UI
65
+ 5. HF builds the Docker image — downloads weights, installs deps
66
+ 6. Space goes live at `https://huggingface.co/spaces/<username>/guide`
67
+
68
+ Rollback: Delete the HF Space. No changes to the local codebase.
69
+
70
+ ## Open Questions
71
+
72
+ - HF username to use for the model repo (affects the `huggingface-cli download` line in Dockerfile) — parameterise via a build ARG or hardcode after account is confirmed
openspec/changes/hf-spaces-deployment/proposal.md ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Why
2
+
3
+ G.U.I.D.E. runs locally today with no public access. Deploying to Hugging Face Spaces makes the academic demo accessible to evaluators without requiring a local setup, while keeping the existing two-server architecture (FastAPI + Gradio) intact.
4
+
5
+ ## What Changes
6
+
7
+ - New `scripts/upload_models_to_hub.py` — uploads only inference-needed model files to HF Model Hub, filtering out `checkpoint-*` training artifacts
8
+ - New `Dockerfile` — HF Spaces Dockerfile Space entry point; downloads weights from Hub at build time, starts both servers with `--no-train`
9
+ - Updated `README.md` — deployment instructions and HF Spaces architecture note
10
+
11
+ ## Capabilities
12
+
13
+ ### New Capabilities
14
+
15
+ - `hf-spaces-deployment`: Containerised deployment to Hugging Face Spaces using a Dockerfile Space; FastAPI on `:8000` (internal) and Gradio on `:7860` (public-facing)
16
+ - `model-hub-upload`: One-time script to push inference weights for `domain_classifier`, `evidence_ner`, and `next_action` models to HF Model Hub, filtering training-only artifacts
17
+
18
+ ### Modified Capabilities
19
+
20
+ ## Non-goals
21
+
22
+ - No changes to predict.py files, start.py, or ui/app.py
23
+ - No single-process refactor of the two-server design
24
+ - No CI/CD pipeline for automated re-deployment
25
+ - No user-facing API key input in the UI (key is a HF Space Secret)
26
+
27
+ ## Impact
28
+
29
+ - New files: `Dockerfile`, `scripts/upload_models_to_hub.py`
30
+ - Modified files: `README.md`
31
+ - New dependency at build time: `huggingface_hub` CLI (already in requirements via `huggingface_hub` transitive dep from `transformers`)
32
+ - `ANTHROPIC_API_KEY` must be set as an HF Spaces Secret before the Space goes live
openspec/changes/hf-spaces-deployment/specs/hf-spaces-deployment/spec.md ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Dockerfile Space entrypoint
4
+ The project SHALL include a `Dockerfile` at the repo root that builds a runnable HF Spaces image. The Dockerfile MUST install all system and Python dependencies, download spaCy model and HF Hub weights at build time, expose port 7860, and start both servers via `python start.py --no-train`.
5
+
6
+ #### Scenario: Successful Docker build
7
+ - **WHEN** `docker build` is run on the repo root
8
+ - **THEN** the image builds without error, all dependencies are installed, and model weights are present at `models/`
9
+
10
+ #### Scenario: Container starts both servers
11
+ - **WHEN** the built container is started
12
+ - **THEN** FastAPI is accessible at `localhost:8000` and Gradio at `localhost:7860` within 90 seconds
13
+
14
+ #### Scenario: ANTHROPIC_API_KEY injected at runtime
15
+ - **WHEN** the container starts with `ANTHROPIC_API_KEY` set as an environment variable (e.g., via HF Spaces Secrets)
16
+ - **THEN** the agent uses the injected key and no key is baked into the image
17
+
18
+ #### Scenario: No training at container startup
19
+ - **WHEN** the container starts
20
+ - **THEN** `start.py` runs with `--no-train` and no model training is attempted
21
+
22
+ ### Requirement: Tesseract available in container
23
+ The Dockerfile SHALL install `tesseract-ocr` via `apt-get` so document OCR functions correctly.
24
+
25
+ #### Scenario: OCR on uploaded document
26
+ - **WHEN** a user uploads an image or PDF in the Documents tab
27
+ - **THEN** Tesseract processes the file without a missing-binary error
28
+
29
+ ---
30
+
31
+ ## ADDED Requirements
32
+
33
+ ### Requirement: Model weights upload script
34
+ The project SHALL include `scripts/upload_models_to_hub.py` that uploads inference-only model files to a specified HF Model Hub repository. The script MUST skip `checkpoint-*` subdirectories and `.DS_Store` files.
35
+
36
+ #### Scenario: Upload filters checkpoint directories
37
+ - **WHEN** the upload script is run with `models/evidence_ner/` present (including `checkpoint-225/`, `checkpoint-450/`, etc.)
38
+ - **THEN** only root-level files (`config.json`, `model.safetensors`, `tokenizer*.json`, `training_args.bin`) are uploaded; no `checkpoint-*` files are uploaded
39
+
40
+ #### Scenario: Upload three model subdirs
41
+ - **WHEN** the upload script completes successfully
42
+ - **THEN** HF Model Hub repo contains `domain_classifier/`, `evidence_ner/`, and `next_action/` subdirectories with correct files
43
+
44
+ #### Scenario: Missing local model directory
45
+ - **WHEN** the upload script is run but a model directory does not exist locally
46
+ - **THEN** the script logs a clear warning for that model and continues uploading the others
47
+
48
+ #### Scenario: Unauthenticated run
49
+ - **WHEN** the upload script is run without a valid HF token (`huggingface-cli login` not done)
50
+ - **THEN** the script exits with a clear authentication error message before attempting any upload
openspec/changes/hf-spaces-deployment/specs/model-hub-upload/spec.md ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Inference-only file filtering
4
+ The upload script SHALL determine which files are inference-needed by excluding any path under a `checkpoint-*` directory and any `.DS_Store` file. It MUST upload: `config.json`, `model.safetensors`, `tokenizer_config.json`, `tokenizer.json`, `training_args.bin` for HuggingFace-format models; and `model.pt` for the next_action MLP.
5
+
6
+ #### Scenario: Checkpoint dirs excluded
7
+ - **WHEN** `models/evidence_ner/` contains both root-level files and `checkpoint-225/`, `checkpoint-450/`, `checkpoint-675/`, `checkpoint-900/` subdirs
8
+ - **THEN** the script uploads only files directly under `models/evidence_ner/` (not inside any `checkpoint-*` subdir)
9
+
10
+ #### Scenario: DS_Store excluded
11
+ - **WHEN** any `models/` directory contains a `.DS_Store` file
12
+ - **THEN** that file is not uploaded
13
+
14
+ ### Requirement: HF repo target is configurable
15
+ The upload script SHALL accept the HF Hub repo ID (e.g., `username/guide-models`) as a CLI argument or environment variable so it can be used with any HF account.
16
+
17
+ #### Scenario: Repo ID via CLI argument
18
+ - **WHEN** the script is run as `python scripts/upload_models_to_hub.py --repo-id myuser/guide-models`
19
+ - **THEN** files are uploaded to `myuser/guide-models` on HF Hub
20
+
21
+ #### Scenario: Missing repo ID
22
+ - **WHEN** the script is run without `--repo-id`
23
+ - **THEN** the script prints usage instructions and exits with a non-zero code
openspec/changes/hf-spaces-deployment/tasks.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## 1. Model Upload Script
2
+
3
+ - [x] 1.1 Create `scripts/upload_models_to_hub.py` with `parse_args()` function that accepts `--repo-id` CLI argument and validates it is provided (exits with usage message if missing)
4
+ - [x] 1.2 Implement `filter_inference_files(model_dir: Path) -> list[Path]` that returns only root-level files (skipping any path under a `checkpoint-*` subdir and any `.DS_Store` file)
5
+ - [x] 1.3 Implement `upload_models(repo_id: str) -> None` that iterates over `domain_classifier/`, `evidence_ner/`, and `next_action/` under `models/`, calls `filter_inference_files()` for each, and uploads via `huggingface_hub.upload_file()` — logging a warning and continuing if a model directory does not exist locally
6
+
7
+ ## 2. Dockerfile
8
+
9
+ - [x] 2.1 Create `Dockerfile` at repo root: base `python:3.11-slim`, install `tesseract-ocr` and `git` via `apt-get`, copy `requirements.txt` and run `pip install`
10
+ - [x] 2.2 Add `RUN python -m spacy download en_core_web_lg` layer after pip install
11
+ - [x] 2.3 Add `ARG HF_MODEL_REPO` and `RUN huggingface-cli download $HF_MODEL_REPO --local-dir models` layer to pull weights at build time; add `COPY . /app`, `WORKDIR /app`, `EXPOSE 7860`, `ENV ANTHROPIC_API_KEY=""`, and `CMD ["python", "start.py", "--no-train"]`
12
+
13
+ ## 3. README Update
14
+
15
+ - [x] 3.1 Add a "Deploying to HF Spaces" section to `README.md` documenting: (a) upload script usage with `--repo-id`, (b) Dockerfile build ARG `HF_MODEL_REPO`, (c) setting `ANTHROPIC_API_KEY` in HF Spaces Secrets UI, and (d) the two-server port layout (FastAPI `:8000` internal, Gradio `:7860` public)