unknown Claude Opus 4.6 commited on
Commit
eb7afc8
·
1 Parent(s): 2cb9a77

Add Hugging Face Spaces deployment ($0/month)

Browse files

- Dockerfile.hf: HF-specific Dockerfile (port 7860, UID 1000)
- scripts/deploy_hf.sh: one-command deploy to HF Spaces
- .github/workflows/keep-alive.yml: pings Space every 12h to
prevent 48h inactivity sleep
- Updated CLAUDE.md with all three deployment options

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

.github/workflows/keep-alive.yml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Keep HF Space Alive
2
+
3
+ # Ping the Hugging Face Space every 12 hours to prevent 48h sleep.
4
+ # The Space URL is stored as a repository variable (not secret — it's public).
5
+
6
+ on:
7
+ schedule:
8
+ # Every 12 hours: at 06:00 and 18:00 UTC
9
+ - cron: "0 6,18 * * *"
10
+ workflow_dispatch: # Allow manual trigger
11
+
12
+ jobs:
13
+ ping:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Ping HF Space health endpoint
17
+ env:
18
+ SPACE_URL: ${{ vars.HF_SPACE_URL }}
19
+ run: |
20
+ if [ -z "$SPACE_URL" ]; then
21
+ echo "HF_SPACE_URL variable not set — skipping"
22
+ exit 0
23
+ fi
24
+
25
+ echo "Pinging $SPACE_URL/api/health ..."
26
+
27
+ # First request may wake the Space (takes up to 2 min)
28
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
29
+ --max-time 180 \
30
+ "$SPACE_URL/api/health")
31
+
32
+ echo "Response: HTTP $HTTP_CODE"
33
+
34
+ if [ "$HTTP_CODE" = "200" ]; then
35
+ echo "Space is alive!"
36
+ else
37
+ echo "Space returned $HTTP_CODE — it may be starting up"
38
+ # Retry after 60 seconds (Space may still be booting)
39
+ sleep 60
40
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
41
+ --max-time 180 \
42
+ "$SPACE_URL/api/health")
43
+ echo "Retry response: HTTP $HTTP_CODE"
44
+ fi
CLAUDE.md CHANGED
@@ -120,7 +120,22 @@ Services: `api` (FastAPI :8000), `ollama` (LLM :11434), `ingest`/`enrich` (one-s
120
 
121
  ## Infrastructure (Terraform)
122
 
123
- Two deployment options:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
  ### Oracle Cloud — Always Free ($0/month, recommended for demos)
126
 
 
120
 
121
  ## Infrastructure (Terraform)
122
 
123
+ Three deployment options:
124
+
125
+ ### Hugging Face Spaces — Free ($0/month, easiest)
126
+
127
+ `Dockerfile.hf` + `scripts/deploy_hf.sh` — Docker Space on HF free tier (2 vCPU, 16 GB RAM).
128
+
129
+ ```bash
130
+ # One-time: create Space at huggingface.co/new-space (Docker SDK, CPU basic)
131
+ # Set GROQ_API_KEY as a Secret in Space Settings
132
+ huggingface-cli login
133
+ ./scripts/deploy_hf.sh <username>/researchradar
134
+ ```
135
+
136
+ - Sleeps after 48h inactivity; `.github/workflows/keep-alive.yml` pings every 12h to prevent this
137
+ - Set `HF_SPACE_URL` as a GitHub repo variable for the keep-alive to work
138
+ - Redeployments: re-run `deploy_hf.sh` or push to the HF Space repo directly
139
 
140
  ### Oracle Cloud — Always Free ($0/month, recommended for demos)
141
 
Dockerfile.hf ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Spaces Dockerfile
2
+ # Free tier: 2 vCPU, 16 GB RAM, 50 GB ephemeral disk
3
+ # Must listen on port 7860, runs as UID 1000
4
+
5
+ # ── Stage 1: Build frontend ─────────────────────────────────────────
6
+ FROM node:22-slim AS frontend
7
+
8
+ WORKDIR /frontend
9
+ COPY frontend/package.json frontend/package-lock.json* ./
10
+ RUN npm ci --no-audit --no-fund 2>/dev/null || npm install --no-audit --no-fund
11
+ COPY frontend/ .
12
+ RUN npm run build
13
+
14
+ # ── Stage 2: Build Python dependencies ──────────────────────────────
15
+ FROM python:3.12-slim AS builder
16
+
17
+ WORKDIR /build
18
+
19
+ RUN apt-get update && apt-get install -y --no-install-recommends \
20
+ gcc g++ && \
21
+ rm -rf /var/lib/apt/lists/*
22
+
23
+ COPY requirements.txt .
24
+ RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
25
+
26
+ # ── Stage 3: Runtime ────────────────────────────────────────────────
27
+ FROM python:3.12-slim
28
+
29
+ WORKDIR /app
30
+
31
+ # Copy installed packages from builder
32
+ COPY --from=builder /install /usr/local
33
+
34
+ # NLTK data (punkt tokenizer for BM25)
35
+ RUN python -m nltk.downloader -d /usr/share/nltk_data punkt punkt_tab
36
+
37
+ ENV NLTK_DATA=/usr/share/nltk_data
38
+ ENV PYTHONUNBUFFERED=1
39
+ ENV PYTHONDONTWRITEBYTECODE=1
40
+
41
+ # HF Spaces runs as UID 1000 — create matching user
42
+ RUN useradd -m -u 1000 user
43
+
44
+ # Copy application code (owned by user)
45
+ COPY --chown=user src/ ./src/
46
+ COPY --chown=user scripts/ ./scripts/
47
+
48
+ # Copy frontend build
49
+ COPY --chown=user --from=frontend /frontend/dist ./frontend/dist
50
+
51
+ # Data dir — writable by user
52
+ RUN mkdir -p /app/data && chown user:user /app/data
53
+
54
+ # Model cache
55
+ ENV HF_HOME=/app/.cache/huggingface
56
+ RUN mkdir -p /app/.cache/huggingface && chown -R user:user /app/.cache
57
+
58
+ # Default to Groq (cloud LLM) — key set via HF Spaces secrets
59
+ ENV LLM_BACKEND=groq
60
+ ENV SQLITE_DB_PATH=/app/data/researchradar.db
61
+ ENV CHROMA_DB_PATH=/app/data/chroma_db
62
+
63
+ USER user
64
+ ENV HOME=/home/user
65
+ ENV PATH=/home/user/.local/bin:$PATH
66
+
67
+ EXPOSE 7860
68
+
69
+ CMD ["uvicorn", "src.api.app:app", "--host", "0.0.0.0", "--port", "7860"]
scripts/deploy_hf.sh ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Deploy ResearchRadar to Hugging Face Spaces.
3
+ #
4
+ # Prerequisites:
5
+ # 1. Create a Space at huggingface.co/new-space (Docker SDK)
6
+ # 2. Set GROQ_API_KEY as a Secret in Space Settings
7
+ # 3. Install: pip install huggingface_hub
8
+ # 4. Login: huggingface-cli login
9
+ #
10
+ # Usage:
11
+ # ./scripts/deploy_hf.sh <hf_username>/<space_name>
12
+ #
13
+ # Example:
14
+ # ./scripts/deploy_hf.sh arkgithubforyou/researchradar
15
+
16
+ set -e
17
+
18
+ SPACE_ID="${1:?Usage: deploy_hf.sh <hf_username>/<space_name>}"
19
+ SPACE_REPO="https://huggingface.co/spaces/${SPACE_ID}"
20
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
21
+ PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
22
+
23
+ echo "=== Deploying ResearchRadar to HF Space: ${SPACE_ID} ==="
24
+
25
+ # Create a temp directory for the HF Space repo
26
+ TMPDIR=$(mktemp -d)
27
+ trap "rm -rf $TMPDIR" EXIT
28
+
29
+ echo "1. Cloning HF Space repo..."
30
+ git clone "${SPACE_REPO}" "$TMPDIR/space" 2>/dev/null || {
31
+ echo " Space doesn't exist yet or clone failed."
32
+ echo " Create it first at: https://huggingface.co/new-space"
33
+ echo " - Select 'Docker' as the SDK"
34
+ echo " - Set hardware to 'CPU basic (Free)'"
35
+ exit 1
36
+ }
37
+
38
+ echo "2. Copying project files..."
39
+ # Copy everything needed for the Docker build
40
+ rsync -a --delete \
41
+ --exclude='.git/' \
42
+ --exclude='data/' \
43
+ --exclude='.venv/' \
44
+ --exclude='venv/' \
45
+ --exclude='__pycache__/' \
46
+ --exclude='*.pyc' \
47
+ --exclude='.env' \
48
+ --exclude='terraform/' \
49
+ --exclude='terraform-oci/' \
50
+ --exclude='frontend/node_modules/' \
51
+ --exclude='frontend/dist/' \
52
+ --exclude='.pytest_cache/' \
53
+ --exclude='.ruff_cache/' \
54
+ --exclude='htmlcov/' \
55
+ "$PROJECT_DIR/" "$TMPDIR/space/"
56
+
57
+ echo "3. Setting up HF Space config..."
58
+ # Use the HF-specific Dockerfile
59
+ cp "$TMPDIR/space/Dockerfile.hf" "$TMPDIR/space/Dockerfile"
60
+
61
+ # Create the required README.md with YAML frontmatter
62
+ cat > "$TMPDIR/space/README.md" << 'EOF'
63
+ ---
64
+ title: ResearchRadar
65
+ emoji: 🔬
66
+ colorFrom: indigo
67
+ colorTo: blue
68
+ sdk: docker
69
+ app_port: 7860
70
+ short_description: RAG-powered NLP research paper explorer
71
+ startup_duration_timeout: 30m
72
+ pinned: false
73
+ ---
74
+
75
+ # ResearchRadar
76
+
77
+ RAG-powered NLP/ML research paper explorer. Hybrid retrieval (BM25 + vector + cross-encoder reranking) + LLM generation over ACL Anthology papers.
78
+
79
+ **Features:**
80
+ - 🔍 Ask natural language questions about NLP research
81
+ - 📄 Browse and filter papers by venue, year, method, dataset
82
+ - 📊 Interactive analytics dashboard with trends, top entities, and co-occurrence
83
+ - ⚡ Powered by Groq API for fast LLM inference
84
+
85
+ Built with FastAPI, React, ChromaDB, and sentence-transformers.
86
+ EOF
87
+
88
+ echo "4. Pushing to HF Space..."
89
+ cd "$TMPDIR/space"
90
+ git add -A
91
+ git commit -m "Deploy ResearchRadar $(date +%Y-%m-%d)" 2>/dev/null || {
92
+ echo " No changes to deploy."
93
+ exit 0
94
+ }
95
+ git push
96
+
97
+ echo ""
98
+ echo "=== Deployed! ==="
99
+ echo "Space URL: ${SPACE_REPO}"
100
+ echo ""
101
+ echo "NOTE: First build takes ~5-10 minutes."
102
+ echo "Set GROQ_API_KEY as a Secret in Space Settings:"
103
+ echo " ${SPACE_REPO}/settings"