roverdevkit / webapp /README.md
jjreif's picture
Deploy roverdevkit @ 2676a67
b3d14e3
|
Raw
History Blame Contribute Delete
7.27 kB
# RoverDevKit Web App
The web app provides an interactive interface for RoverDevKit's mission
evaluator, surrogate predictions, parametric sweeps, multi-objective design
optimization, and SHAP-style design explanations.
```
webapp/
├── backend/ FastAPI app over the roverdevkit Python package
└── frontend/ React + Vite + TypeScript single-page app
```
## Backend
The backend is a thin FastAPI layer over the Python evaluator and trained
surrogate artifacts. The API keeps the browser UI aligned with the same models
used by scripts and notebooks.
Common routes:
| Method | Path | Purpose |
| --- | --- | --- |
| GET | `/healthz` | Liveness and artifact-presence probe. |
| GET | `/version` | Dataset, surrogate, and git version metadata. |
| GET | `/scenarios` | List bundled mission scenarios. |
| GET | `/scenarios/{name}` | Return one scenario and its nominal soil parameters. |
| GET | `/registry` | Return published rover registry entries. |
| POST | `/predict` | Surrogate median and 90% interval for one design. |
| POST | `/evaluate` | Physics evaluator output for one design. |
| POST | `/sweep` | One- or two-dimensional parametric sweep. |
| POST | `/optimize` | Start an NSGA-II multi-objective optimization job. |
| GET | `/optimize/{job_id}/stream` | Stream optimization progress with server-sent events. |
| GET | `/optimize/{job_id}/result` | Fetch a completed optimization result. |
| POST | `/shap/explain` | Explain one current design prediction. |
## Run Locally
From the repository root, with the `roverdevkit` conda environment activated:
```bash
conda activate roverdevkit
pip install -e ".[webapp]"
uvicorn webapp.backend.main:app --reload --port 8000
```
OpenAPI docs are available at <http://localhost:8000/docs>.
## Frontend
The frontend is a Vite + React + TypeScript app. Its typed fetch client lives in
`src/lib/api.ts`, and the dev server proxies backend routes to
`http://localhost:8000`.
```bash
cd webapp/frontend
npm install
npm run dev
npm run build
npm run lint
```
Run both servers together from the repository root:
```bash
make webapp-dev
```
Open <http://localhost:5173> after the frontend server starts.
## UI Sections
- **Current Design** evaluates the active rover design under the mission inputs
(scenario, scientific-payload mass and power, operational duty cycle). Payload
is a mission requirement set at the top of the panel, not a design variable.
- **Parametric Sweep** explores one- and two-variable design sensitivities.
- **Optimize Design** runs NSGA-II searches and visualizes completed Pareto
fronts.
- **Explain Design** shows SHAP-style feature attributions for the active
design and selected target.
## Canonical Pareto Fronts
The Optimize Design tab always runs NSGA-II live against the corrected
physics evaluator. There is no in-app "load reference" affordance because
the live job completes in ~30–60 seconds at the default budget and produces
evaluator-truth points anyway.
The repo still ships a precomputed reference set under
`reports/pareto_fronts/` (one CSV + metadata JSON per canonical scenario,
plus a top-level `manifest.json`). These are reference artifacts for
documentation figures and notebook fixtures; the evaluator is
deterministic and each file is small (~14 kB), so they are committed
to the repo for reproducibility.
Regenerate them whenever scenario configs change:
```bash
make pareto-fronts
```
Pass extra arguments through `SCRIPT_ARGS`:
```bash
make pareto-fronts SCRIPT_ARGS="--population-size 80 --generations 80"
```
The default settings (50-point population, 60 generations, analytical
Bekker-Wong evaluator) complete all four canonical scenarios in about
4 minutes on a laptop.
## Docker / Hosted Deploy
A multi-stage [`webapp/Dockerfile`](Dockerfile) builds the React frontend
with Node 20 LTS, then installs the Python package + the `[webapp]`
extras on top of `python:3.12-slim` and bakes in:
- the analytical Bekker-Wong mission evaluator,
- the v9 quantile-XGB surrogate bundles
(`models/surrogate_v9/quantile_bundles.joblib`),
- the canonical Pareto fronts (`reports/pareto_fronts/`),
- the built React frontend at `/app/static`.
The runtime image runs a single `uvicorn` process that serves the
FastAPI backend at `/healthz`, `/predict`, `/evaluate`, `/sweep`,
`/optimize`, `/shap`, `/registry`, `/scenarios`, and serves the React SPA off
`ROVERDEVKIT_STATIC_DIR=/app/static` with a history-mode catch-all so
deep links survive a hard refresh.
### Local boot via Docker Compose
```bash
docker compose -f webapp/docker-compose.yml up --build
```
Open <http://localhost:8000>. First boot takes 2-3 min for the
`pip install` layer; subsequent rebuilds reuse the wheel cache and
finish in ~30 s for a code-only edit.
### Direct `docker build` (e.g. for CI or a one-off image push)
```bash
# Build context must be the repo root so the Dockerfile can reach
# pyproject.toml, roverdevkit/, data/, models/, reports/, and webapp/.
docker build -f webapp/Dockerfile -t roverdevkit/webapp:dev .
docker run --rm -p 8000:8000 roverdevkit/webapp:dev
```
### Hosted-demo readiness checklist
The image is intentionally hosting-platform agnostic. To stand it up
on Hugging Face Spaces, Fly.io, Railway, or a Duke container, walk
through this checklist:
- [ ] `docker build -f webapp/Dockerfile -t roverdevkit/webapp:dev .`
succeeds locally; record the resulting image size (~700 MB
compressed for the v9 surrogate bundle).
- [ ] `docker run --rm -p 8000:8000 roverdevkit/webapp:dev` boots
cleanly; `curl localhost:8000/healthz` returns
`{"status":"ok","surrogate_loaded":true,...}`.
- [ ] Set `ROVERDEVKIT_CORS_ORIGINS` to the platform's hosted origin
(e.g. `https://huggingface.co,https://<user>-<space>.hf.space`).
Defaults to `http://localhost:5173` (Vite dev server) which
will block browser calls in prod.
- [ ] If the platform fronts the container with TLS, leave the
Dockerfile's `--proxy-headers --forwarded-allow-ips=*` flags
in place so client IP / scheme propagate from the edge.
- [ ] Confirm the image runs as `roverdevkit` (UID 1000) — Fly.io,
HF Spaces, and most K8s pod-security policies require non-root.
- [ ] If the deploy uses a persistent volume to mount alternate
surrogate artefacts, point the volume at
`/app/models/surrogate_v9/quantile_bundles.joblib` (or
override via `ROVERDEVKIT_QUANTILE_BUNDLES`); see
`webapp/backend/config.py` for the full env-var surface.
- [ ] (HF Spaces) drop a `Dockerfile` symlink or a one-line
`Spaces config: docker` block at the repo root that points at
`webapp/Dockerfile`.
### Image size and build context
`.dockerignore` at the repo root excludes the LHS training corpora
(`data/analytical/`), the training-time reports, any superseded
surrogate versions, and Node / Python build caches. Only the runtime
artefacts the backend actually loads — the current surrogate bundle
(`models/surrogate_v9/quantile_bundles.joblib`) and the Pareto fronts
— are baked into the image.
## Tests
```bash
pytest webapp/backend/tests -q
cd webapp/frontend && npm run lint && npm run build
```
The top-level helper runs the same checks:
```bash
make webapp-test
```