Spaces:
Sleeping
Sleeping
| # FALSIFY — Deployment Guide | |
| Two ways to put FALSIFY online. **Do Plan A first** — it's one container, one URL, | |
| and the realtime stream "just works." Fall back to Plan B only if the HF build | |
| won't cooperate. | |
| | | **Plan A — Hugging Face Spaces** | **Plan B — Vercel + Render** | | |
| |---|---|---| | |
| | Pieces | 1 container (frontend + API + SSE) | Vercel (frontend) + Render (API + SSE) | | |
| | CORS | none (same origin) | required (handled in `server.py`) | | |
| | Realtime | SSE on port 7860, native | SSE lives on Render; Vercel serves static only | | |
| | Cost | free | free (Render cold-starts) / $7 always-on | | |
| | Best when | **default — start here** | HF Docker build fails twice | | |
| The **same Docker image** runs on both (it binds `$PORT`, default 7860). Demo mode is | |
| **keyless** — a judge can open the URL and hit ▶ Run investigation with no setup. | |
| --- | |
| ## Plan A — Hugging Face Spaces (PRIMARY) | |
| ### What's already in the repo | |
| - `Dockerfile` — single-stage, non-root uid 1000, pre-warms `fastembed`, binds `$PORT`. | |
| - `README.md` frontmatter — `sdk: docker`, `app_port: 7860` (HF reads this). | |
| - `.dockerignore` — trims the build context. | |
| - `static/` — the frontend, served by `server.py`. | |
| ### Steps | |
| 1. **Create the Space.** huggingface.co → *New* → *Space*. Name it `falsify`, | |
| **SDK: Docker**, **Blank** template, visibility **Public**. | |
| 2. **Push the repo to the Space remote:** | |
| ```bash | |
| git remote add space https://huggingface.co/spaces/<your-username>/falsify | |
| git push space main | |
| ``` | |
| *(If your local branch is `main` and the Space expects `main`, this is enough. | |
| HF authenticates with a write token — when prompted for a password, paste a | |
| token from huggingface.co/settings/tokens.)* | |
| 3. **Watch the build.** Open the Space's **Container** / **Logs** tab. First build is | |
| slow (Cognee pulls Kuzu/LanceDB/litellm — several minutes). Wait for **Running**. | |
| 4. **Open the Space URL.** The graph should load pre-seeded. Hit **▶ Run | |
| investigation** and watch the cascade. That URL is your submission link. | |
| ### Secrets (OPTIONAL — demo needs none) | |
| Space → **Settings** → **Variables and secrets**. Add only if you want Live mode / | |
| upload / the recall completion: | |
| - `LLM_API_KEY` = your key · `LLM_MODEL` = `gpt-4o-mini` | |
| - non-OpenAI endpoint: `LLM_PROVIDER=custom`, `LLM_ENDPOINT=https://…/v1` | |
| - Cognee Cloud toggle: `COGNEE_CLOUD_URL`, `COGNEE_CLOUD_API_KEY` | |
| Absent a key, the app **stays in keyless demo mode** — nothing errors. | |
| ### Alternative push (CLI) | |
| ```bash | |
| pip install -U huggingface_hub | |
| huggingface-cli login # paste a write token | |
| huggingface-cli upload <user>/falsify . --repo-type space | |
| ``` | |
| --- | |
| ## Plan B — Vercel (frontend) + Render (backend) | |
| Use this if HF won't build. **Deploy Render first**, then Vercel, then wire CORS. | |
| ### Why the split looks the way it does | |
| - **Vercel can't host the SSE stream** — its serverless functions can't hold a | |
| long-lived connection. So Vercel serves **only** the static `static/` files. | |
| - **Render runs the whole backend** (API + SSE) from the same Dockerfile. The | |
| browser opens `EventSource` **directly against Render**, not Vercel. | |
| ### Step 1 — Backend on Render | |
| 1. render.com → **New +** → **Web Service** → connect the GitHub repo. | |
| 2. **Runtime: Docker** (it finds `./Dockerfile`). *(Or use **Blueprint** and pick | |
| `render.yaml`.)* | |
| 3. **Instance type:** Free to try; **Starter ($7/mo)** to avoid the 15-min-idle | |
| cold start during judging. (Free spins down; first hit after idle takes 30–60s.) | |
| 4. **Env vars** (Settings → Environment): | |
| - `FRONTEND_ORIGIN` = your Vercel URL (fill in after Step 2, then redeploy) | |
| - optional: `LLM_API_KEY`, `LLM_MODEL`, `COGNEE_CLOUD_URL`, `COGNEE_CLOUD_API_KEY` | |
| 5. Deploy → note the URL, e.g. `https://falsify-backend.onrender.com`. | |
| Verify: `curl https://falsify-backend.onrender.com/api/health` → `{"ok": true, …}`. | |
| ### Step 2 — Frontend on Vercel | |
| 1. **Point the frontend at Render.** Edit `static/config.js`: | |
| ```js | |
| window.__API_BASE__ = "https://falsify-backend.onrender.com"; // no trailing slash | |
| ``` | |
| Commit + push. | |
| 2. vercel.com → **Add New** → **Project** → import the repo. | |
| 3. Framework preset: **Other**. `vercel.json` already sets output dir = `static` | |
| and no build. Deploy. | |
| 4. Note the URL, e.g. `https://falsify.vercel.app`. | |
| ### Step 3 — Close the CORS loop | |
| 1. Back in Render → set `FRONTEND_ORIGIN` = `https://falsify.vercel.app` → **redeploy**. | |
| 2. Open the Vercel URL. If it was a free Render instance, hit it once to **warm it** | |
| (~30–60s), then reload. ▶ Run investigation should stream live. | |
| --- | |
| ## Pre-demo checklist (do this right before judging) | |
| - [ ] Open the live URL in a fresh incognito window (no cache). | |
| - [ ] Graph loads pre-seeded; connection dot (top bar) shows **live**. | |
| - [ ] **▶ Run investigation** → E_qa strikes red, K dissolves, B rises green. | |
| - [ ] Scoreboard shows **FALSIFY ✅ Jan 2021** vs **RAG ⚠ still cites the refuted March report**. | |
| - [ ] **Diamond** → K2 survives phase 1, collapses phase 2. | |
| - [ ] **Verify persistence** → reads truth-state from the on-disk graph store and confirms refuted/superseded nodes are there. | |
| - [ ] (Plan B) Render warmed within the last 10 min so there's no cold-start pause. | |
| --- | |
| ## Troubleshooting | |
| | Symptom | Cause → Fix | | |
| |---|---| | |
| | HF build fails on a heavy wheel | Transient hub/network. Re-run the build (Space → *Factory rebuild*). The deps layer caches after the first success. | | |
| | First request hangs ~20s | `fastembed` model download. The Dockerfile pre-warms it; if skipped, the first embed pays it once. | | |
| | SSE events arrive in a clump, not live | A proxy is buffering. We already send `X-Accel-Buffering: no` + `Cache-Control: no-cache`; confirm no extra CDN sits in front. | | |
| | Graph loads but ▶ does nothing | Open devtools → Network. If `/api/*` calls 404/blocked, check `window.__API_BASE__` (empty on HF, Render URL on Vercel). | | |
| | Vercel UI can't reach backend (CORS error) | `FRONTEND_ORIGIN` on Render ≠ the Vercel origin. Set it exactly (scheme + host, no path) and redeploy. | | |
| | Render cold start every time | Free tier idle spin-down. Warm it before judging or use Starter. | | |
| | Upload says "Set LLM_API_KEY" | `cognify` needs an LLM key. Add it as a secret/env var, or just use the keyless demo/diamond. | | |
| | Permission error writing cache on HF | Container runs as uid 1000; `HF_HOME` is under `$HOME`. Don't write outside `/home/user/app`. | | |
| --- | |
| ## Local sanity check (optional, before deploying) | |
| ```bash | |
| pip install -r requirements.txt | |
| uvicorn server:app --port 8000 | |
| # open http://localhost:8000 → same UI the deploy serves | |
| ``` | |