# CASCADE → Hugging Face Spaces: Deployment Guide ## Overview The HF Space replaces Django with Flask but keeps the exact same Redis job-queue pattern and frontend JS. The app is mounted at `/cascade_v1/` so the live URL is: ``` https://patonlab-cascade.hf.space/cascade_v1/predict/ ``` The Space is named `cascade` on HF — the `_v1` is a subpath in Flask, not the repo name. This means you can add `cascade_v2` later under the same Space without creating a new repo. ``` hf_space/ ├── Dockerfile # Python 3.7, Redis, TF1.15, Keras 2.2.5 ├── requirements.txt ├── start.sh # Redis → worker → gunicorn ├── app.py # Flask Blueprint mounted at /cascade_v1 ├── worker.py # Redis consumer, runs GNN inference ├── setup_assets.sh # One-time script: copies binaries from nova app ├── README.md # HF Space card (YAML front-matter required) ├── .gitattributes # Git LFS tracking for .hdf5 and .p files ├── .gitignore ├── NMR_Prediction/ │ ├── __init__.py │ ├── apply.py # ← copied + path-fixed by setup_assets.sh │ ├── genConf.py # ← copied by setup_assets.sh │ ├── valid.py # new (simple RDKit SMILES check) │ ├── preprocessor.p # ← copied by setup_assets.sh │ └── schnet_edgeupdate/ │ └── best_model.hdf5 # ← copied by setup_assets.sh (31 MB) ├── nfp/ # ← copied by setup_assets.sh ├── static/ # ← copied by setup_assets.sh │ ├── main.css │ ├── sketch.css │ ├── JSmol.min.js │ ├── images/ │ ├── j2s/ │ ├── jquery/ │ ├── js/ │ └── jsme/ └── templates/ └── cascade/ ├── base.html ├── home.html ├── predict.html ├── results.html └── about.html ``` --- ## Step 1 — Copy assets from the nova app Run the setup script (copies model weights, inference code, static files, and applies the preprocessor path fix automatically): ```bash cd ~/Documents/huggingface/cascade/hf_space bash setup_assets.sh ``` You should see a ✓ for each of the 5 asset groups. Afterwards confirm: ```bash ls NMR_Prediction/ # apply.py genConf.py preprocessor.p schnet_edgeupdate/ valid.py __init__.py ls nfp/ # __init__.py layers/ models/ preprocessing/ ls static/ # main.css JSmol.min.js j2s/ jsme/ jquery/ js/ images/ ``` --- ## Step 2 — Test locally with Docker ```bash cd ~/Documents/huggingface/cascade/hf_space # Build (takes ~5 min first time — TF1.15 + RDKit are large) docker build -t cascade-local . # Run docker run -p 7860:7860 cascade-local # Open in browser open http://localhost:7860/cascade_v1/predict/ ``` **What to check:** - Page loads, JSME editor opens - Submitting `CC(=O)O` (acetic acid) returns a task_id (check browser Network tab) - `check_task` eventually returns the results HTML with 2D SVG and shift table - Worker logs appear in the Docker terminal: `Processing task ...` **Common first-run issues:** | Symptom | Fix | |---|---| | `ModuleNotFoundError: nfp` | Check `nfp/` is in the root of hf_space, not nested inside another folder | | `OSError: preprocessor.p not found` | Re-run `setup_assets.sh` — the path fix may not have applied | | `keras load_model` custom layer error | Check custom_objects in worker.py match the nfp layer class names exactly | | Redis connection refused | Redis takes ~1 s to start; the worker retries automatically — wait a moment | | 500 on `/cascade_v1/predict/` | Check `templates/cascade/predict.html` exists | | JSME editor blank | Check `static/jsme/jsme.nocache.js` was copied across | --- ## Step 3 — Create the Hugging Face Space ```bash # Install HF CLI if needed pip install huggingface_hub # Login (needs a write token from hf.co/settings/tokens) huggingface-cli login # Create the Space — named 'cascade', Docker SDK, public, under patonlab org huggingface-cli repo create cascade \ --type space \ --space-sdk docker \ --organization patonlab # This creates: https://huggingface.co/spaces/patonlab/cascade # Live URL will be: https://patonlab-cascade.hf.space/cascade_v1/predict/ ``` --- ## Step 4 — Push to Hugging Face ```bash cd ~/Documents/huggingface/cascade/hf_space git init git lfs install # Required — .hdf5 and .p are tracked via Git LFS # .gitattributes is already written; just add it git add .gitattributes git remote add origin https://huggingface.co/spaces/patonlab/cascade git add . git commit -m "Initial CASCADE HF Space deployment" git push origin main ``` The Space builds automatically. Build logs at: `https://huggingface.co/spaces/patonlab/cascade` → Logs tab Build time is typically **8–12 minutes** (TF1.15 + RDKit are large). --- ## Step 5 — Verify the live Space Once the build is green: 1. `https://patonlab-cascade.hf.space/cascade_v1/predict/` — page loads 2. Submit `CC(=O)O` (acetic acid) — result in ~10–15 s 3. Submit `CC1=CC(=CC(=C1)O)C` — result in ~30–45 s 4. Test the JSME drawing tool → OK → predicted shifts labelled on 2D structure --- ## Step 6 — Update the GitHub README Update `patonlab/CASCADE` on GitHub to point to the new URL: ```markdown The production web server can be found here: https://patonlab-cascade.hf.space/cascade_v1/predict/ ``` --- ## Ongoing maintenance **Pushing updates:** ```bash cd ~/Documents/huggingface/cascade/hf_space git add . && git commit -m "your message" && git push origin main ``` HF rebuilds automatically on each push. **Checking logs:** HF Space → Logs tab (worker output streams there in real time) **Cold starts:** The free HF tier sleeps after inactivity. First request after sleep takes ~30 s. Upgrade to HF Pro ($9/mo) for persistent Spaces if needed. **Redis:** Results have a 1-hour TTL and do not persist across container restarts. This is fine for interactive use. --- ## What changed from the original Django app | Original (nova) | New HF Space | |---|---| | Django 2.1 | Flask 2.0 with Blueprint at `/cascade_v1` | | `uwsgi` | `gunicorn` | | `django.template` tags | Plain Jinja2 (`/static/...` paths) | | `ALLOWED_HOSTS = ['129.82.62.62']` | Flask `HOST=0.0.0.0` | | Hard-coded `SECRET_KEY` | Not needed (no sessions/auth) | | `db.sqlite3` | Removed (unused) | | `cascade/preprocessor.p` path | `NMR_Prediction/preprocessor.p` | | Model loaded in Django views at startup | Loaded once in worker.py at startup | | Manual file copies + sed fix | Automated via `setup_assets.sh` |