Skip to content

Commit 2b80e02

Browse files
polinabinder1claude
andcommitted
evo2-sae dashboard: rewrite feature_explorer README for the three run modes
Document the actual ways to run now that the API is under /api and the frontend can be baked into the image: (1) single container (docker run, UI + /api on one port, no Node at runtime) for sharing; (2) local dev (Vite + backend, Node >=18, tsh tunnel of :5176, /api proxied straight through with no rewrite); (3) offline/static (precompute artifacts, atlas always + sequence-UMAP from a bundle). Adds a tab summary and notes the in-app per-tab Limitations. Touches only this PR's README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Polina Binder <pbinder@nvidia.com>
1 parent 0f0e6ca commit 2b80e02

1 file changed

Lines changed: 70 additions & 29 deletions

File tree

  • interpretability/sparse_autoencoders/recipes/evo2/feature_explorer
Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,62 @@
11
# Evo2 SAE Feature Explorer (front-end)
22

3-
Interactive dashboard for Evo2 SAE features — feature atlas, sequence inspector, and
4-
generative steering.
3+
Interactive dashboard for Evo2 SAE features, with four tabs:
4+
**Feature atlas**, **Sequence inspector**, **Generative steering**, and **Sequence UMAP**.
55

6-
This directory is the **front-end only**. Its backend is the standalone
7-
[`evo2_sae`](../src/evo2_sae) engine — the viz is just a UI over its
8-
`serve` mode, so there is no model code here.
6+
This directory is the **front-end only** (React + Vite). Its backend is the standalone
7+
[`evo2_sae`](../src/evo2_sae) engine — the viz is just a UI over its HTTP API, so there is no
8+
model code here. The front-end always calls the API under **`/api`** (same path in dev and
9+
production), so the only thing that ever changes is *where* `/api` is served from.
10+
11+
## Three ways to run
12+
13+
### 1. One container — recommended for sharing / deploy
14+
15+
The recipe [`Dockerfile`](../Dockerfile) builds this front-end to static files and bakes them
16+
into the image, so a **single container serves the dashboard and the API on one port** — no
17+
Node and no second process at runtime. This is what to hand a coworker or put behind an SSO proxy.
18+
19+
```bash
20+
# build from the REPO ROOT (the build context needs the recipes/evo2_megatron sibling):
21+
docker build -f interpretability/sparse_autoencoders/recipes/evo2/Dockerfile -t evo2-sae .
22+
23+
# run with a GPU + your checkpoints, then open http://localhost:8001
24+
docker run --gpus all -p 8001:8001 \
25+
-e EVO2_CKPT_DIR=/ckpt/evo2 -e SAE_CKPT_PATH=/ckpt/sae.pt -e EMBEDDING_LAYER=26 \
26+
-v /path/to/checkpoints:/ckpt evo2-sae scripts/launch_inference.sh serve
27+
# -> dashboard + API both on http://localhost:8001 (/ = UI, /api = backend)
28+
```
29+
30+
The first build compiles the megatron stack (~30 min) and is layer-cached afterward; a Node build
31+
stage produces the static bundle (`DASHBOARD_DIST`) and the server mounts it at `/`. No Node ends
32+
up in the runtime image. See the [recipe Dockerfile](../Dockerfile) for the layer layout.
33+
34+
### 2. Local dev — UI iteration with hot reload
35+
36+
Needs **Node ≥ 18** (for Vite), plus a GPU + checkpoints for the live tabs. Two processes:
937

1038
```bash
11-
# 1. Backend: loads Evo2 + the SAE and serves the HTTP API on :8001
12-
../scripts/launch_inference.sh serve # or: python -m evo2_sae.cli serve
39+
# backend: loads Evo2 + the SAE, serves the API under /api on :8001
40+
../scripts/launch_inference.sh serve # or: python -m evo2_sae.cli serve
1341

14-
# 2. Dashboard (from recipes/evo2): stages data (if any) + starts Vite
15-
python ../scripts/launch_dashboard.py # inspector + steering tabs
16-
python ../scripts/launch_dashboard.py --data-dir /path/to/data # + Feature-atlas tab
42+
# front-end: Vite dev server on :5176 (hot reload)
43+
../scripts/launch_dashboard.py # stages atlas data if --data-dir is given, then runs Vite
44+
# or, for raw front-end dev: npm install && npm run dev
1745
```
1846

19-
`launch_dashboard.py` is the entry point — it validates/stages the atlas parquets into
20-
`public/` (when `--data-dir` is given) and runs Vite. The **inspector** and **steering** tabs
21-
work with no atlas data (they call the backend); the **Feature-atlas** tab needs the three
22-
parquets (`features_atlas`, `feature_metadata`, `feature_examples`) via `--data-dir`
23-
producing them is a separate offline step. (`npm install && npm run dev` also works for raw
24-
front-end dev, but skips data staging.)
47+
Vite proxies `/api` **straight through** to `http://localhost:8001` (no path rewrite — see
48+
`vite.config.js`), so dev hits the same `/api/*` paths as the single-container build. Point it at a
49+
different backend with `VITE_BACKEND`. Configure the backend via the env vars in `launch_inference.sh`.
2550

26-
The Vite dev server proxies `/api``http://localhost:8001` (see `vite.config.js`); point it
27-
elsewhere with `VITE_BACKEND`. Configure the backend via the env vars in `launch_inference.sh`.
51+
To reach a remote box, tunnel the Vite port only (Vite proxies `/api` on the box):
52+
53+
```bash
54+
tsh ssh -L 5176:localhost:5176 <gpu-box> # then open http://localhost:5176
55+
```
2856

29-
## Running without a backend (offline / static)
57+
### 3. Offline / static — no backend
3058

31-
The dashboard degrades gracefully: it probes `/health`, and when there's **no live backend** it
59+
The dashboard degrades gracefully: it probes `/api/health`, and when there's **no live backend** it
3260
hides the tabs that need the model and keeps the ones that read static files.
3361

3462
| Tab | Needs backend? | Offline source |
@@ -38,22 +66,35 @@ hides the tabs that need the model and keeps the ones that read static files.
3866
| **Generative steering** | yes | hidden offline |
3967
| **Sequence inspector** | yes | hidden offline |
4068

41-
So with no backend you get the **Feature atlas** always, and **Sequence UMAP** if you precompute
42-
its bundle. Steering and the live inspector require `serve`.
69+
So with no backend you always get the **Feature atlas**, plus **Sequence UMAP** if you precompute its
70+
bundle. Steering and the live inspector require `serve`.
4371

4472
```bash
45-
# (one-time, needs the 7B) precompute all the static artifacts into one dir:
73+
# (one-time, needs the model) precompute the static artifacts into one dir:
4674
python ../scripts/dashboard.py atlas --activations-dir $STORE --output-dir dashboard_data # atlas tab
4775
python ../scripts/dashboard.py examples --examples-fasta lib.fa --output-dir dashboard_data # example cards
4876
python ../scripts/dashboard.py embeddings --examples-fasta lib.fa --output-dir dashboard_data # Sequence-UMAP bundle
4977
# (env: SAE_CKPT_PATH, EVO2_CKPT_DIR, FEATURE_ANNOTATIONS — same as launch_inference.sh)
5078

51-
# serve the static dashboard — NO backend, NO GPU:
79+
# serve the static dashboard — NO backend, NO GPU (needs Node for the dev server, or `npm run build`):
5280
python ../scripts/launch_dashboard.py --data-dir dashboard_data
5381
```
5482

55-
`dashboard.py embeddings` writes `sequmap_embeddings.json` (the same shape `/gene_embed` returns;
56-
bounded by sequence count). The viz auto-detects it (override the path with `?embeddings=<url>`).
57-
With all artifacts staged, `npm run build` produces a fully static site you can host anywhere
58-
(HF Spaces static / S3 / Pages) — interactive steering/inspector light up automatically if a
59-
backend is later reachable.
83+
`dashboard.py embeddings` writes `sequmap_embeddings.json` (the same shape `/api/gene_embed` returns).
84+
The viz auto-detects it (override the path with `?embeddings=<url>`). With all artifacts staged,
85+
`npm run build` produces a fully static site you can host anywhere (HF Spaces static / S3 / Pages) —
86+
the interactive steering/inspector tabs light up automatically if a backend later becomes reachable.
87+
88+
## Tabs
89+
90+
- **Feature atlas** — browse every SAE feature: firing rate, decoder-space UMAP, top-activating
91+
examples, labels. Reads precomputed static files.
92+
- **Sequence inspector** — paste a sequence, see per-base SAE activations (top-k or picked features).
93+
Live encode.
94+
- **Generative steering** — generate DNA while clamping chosen features on the continuation, vs. the
95+
unsteered baseline. Live generation.
96+
- **Sequence UMAP** — embed a set of sequences (pooled per-feature vectors), UMAP them, color/re-project
97+
by a feature. Live backend or a precomputed bundle.
98+
99+
Each tab shows its own **Limitations** note in-app (context-length caps, the ±300 steering clamp,
100+
stochastic 2-D UMAP, etc.).

0 commit comments

Comments
 (0)