feat: reveal all hidden shapes with Shift+H, release SAM3 VRAM on idle and on demand (REQ-191, REQ-192)
This commit is contained in:
1 parent
f5be7880b0
commit
fd608848bf
16 files changed
+290
-20
No files matched your search
@@ -1565,6 +1565,59 @@ read it.
|
||||
frame already holding an overlapping truck → banner `skipped K overlapping truck`, dot, count
|
||||
unchanged, while a frame holding a truck elsewhere gets its own second box.
|
||||
|
||||
## Task — Reveal all hidden shapes with Shift+H (REQ-191) `[DONE]`
|
||||
|
||||
- `frontend/src/pages/ReviewPage.jsx` — third piece of hide state, `revealAll`, is a boolean
|
||||
**overlay**: `isShapeVisible` answers yes for everything while it is on, and neither
|
||||
`hiddenShapeIds` nor `hiddenClasses`/`overriddenShapeIds` is touched, which is what makes the
|
||||
second `Shift+H` restore the previous hidden state exactly. In the keydown handler,
|
||||
`Shift+H` toggles the overlay, a plain `H` clears an active overlay first (so it edits the
|
||||
real hidden state) and otherwise falls through to `toggleHideSelected()`.
|
||||
- `frontend/src/components/ReviewSidebar.jsx` — `revealing hidden` chip (SVG `EyeIcon`, accent
|
||||
pill, `title` naming `Shift+H`) in the *Shapes on this frame* header while the overlay is on;
|
||||
dimming of rows is unchanged, so the chip and the dims together say what is actually hidden.
|
||||
- `frontend/src/components/ShortcutsPanel.jsx` — `Shift+H` row next to `H`.
|
||||
- `frontend/src/app.css` — `.reveal-chip` on `--accent` tokens (works in both themes).
|
||||
- Docs: `requirements.md` REQ-191, `design.md` sidebar block, `ui-spec.md` keyboard table +
|
||||
shapes-panel bullet.
|
||||
→ verify: **[DONE]** `npm run build` green; `git diff --check` clean. **Still needs a browser
|
||||
pass:** hide a class and one shape, `Shift+H` → both drawn + chip up, `Shift+H` again → back
|
||||
to the same dims, plain `H` → overlay drops and only then hides the selection.
|
||||
|
||||
## Task — Free SAM3's VRAM on idle and on demand (REQ-192) `[DONE]`
|
||||
|
||||
- Question answered first: nothing freed the model before — `release_engine()` had exactly one
|
||||
caller (`backend/training.py`, REQ-065), so the ~3.9 GB stayed in the card until a training
|
||||
run or the process exited. The YOLO loads elsewhere are transient locals, no leak found.
|
||||
- `backend/sam3_engine.py` — `IDLE_UNLOAD_S` (env `SAM3_IDLE_UNLOAD_S`, default 1200, `0`
|
||||
disables), `_touch()` stamped by `get_engine()` and by the four model methods that actually
|
||||
run inference (so a long autolabel job counts as use, not as idle), and one daemon watcher
|
||||
started on first `get_engine()`: every `min(60 s, IDLE_UNLOAD_S)` it releases the engine,
|
||||
but only after taking `jobs.gpu_lock` **without blocking** — a job or assist in flight just
|
||||
postpones the release, never gets interrupted (same one-holder rule as REQ-065).
|
||||
- `backend/api/sam3.py` — `POST /api/sam3/release`: same non-blocking `gpu_lock`, `409` while
|
||||
the GPU is busy, `{"released", "model_loaded"}` otherwise; wired in `backend/main.py`.
|
||||
- `docker-compose.yml` + `.env.example` — the variable is passed through, so the container
|
||||
sees a value set in `.env` (empty/unset → Python falls back to 1200).
|
||||
- `frontend/src/components/Sidebar.jsx` + `api.js` + `roboflow.css` — badge is now three-state:
|
||||
`SAM3: Loaded` (green **button**, click releases, optimistic flip, 3 s poll confirms) /
|
||||
`SAM3: Idle` / `SAM3: Off`; a failed release shows its `detail` for 4 s instead of failing
|
||||
silently.
|
||||
- Docs: `requirements.md` REQ-192, `design.md` module row + API contract, `ui-spec.md` badge
|
||||
block, `.env.example` GPU section.
|
||||
→ verify: **[DONE]** `uv run python /tmp/opencode/test_idle_unload.py` — ALL PASS: unload after
|
||||
idle, release postponed while `gpu_lock` held then fires, `0` disables the watcher, endpoint
|
||||
answers `409` when busy and `{"released": true, "model_loaded": false}` when free; app imports
|
||||
with `/api/sam3/release` in the OpenAPI paths; `npm run build` green; `git diff --check` clean.
|
||||
**Live run against the rebuilt container:** assist on a batch frame loads the model (VRAM free
|
||||
7.39 → 3.15 GB), `POST /api/sam3/release` answers `{"released": true, "model_loaded": false}`
|
||||
and VRAM goes back to 7.32 GB (+4.2 GB freed), the next assist rebuilds in 6 s and works,
|
||||
badge strings present in the served `index-BGbzE_yy.js`. Container env shows
|
||||
`SAM3_IDLE_UNLOAD_S` empty → falls back to the 1200 s default as designed. **Watcher verified
|
||||
live too:** with `SAM3_IDLE_UNLOAD_S=10` on one container run, a loaded model (3.15 GB free)
|
||||
went to `model_loaded: false` / 7.32 GB free on its own within the 10 s tick, then the
|
||||
container was put back on the default 1200 s.
|
||||
|
||||
## Known open points
|
||||
|
||||
- *Not closed by any task, by choice:* **any rebuild kills the running job.** Task 14's resume
|
||||
|
||||
Reference in new issue
Block a user