Add the core labeling data model (label sets, ad-hoc Main->Sub class hierarchy, frames, bounding-box labels, per-frame/per-set label status) behind a FastAPI app, with SQLite as the default swappable DATABASE_URL. Multi-user support is attribution-only for now (get-or-create by username, no login flow yet). Dataset versioning/promotion is intentionally deferred - it needs its own design pass around snapshot semantics. Each test gets a fully isolated app+DB via create_app(database_url=...) rather than relying on process-global state. 13/13 tests pass; also verified live end-to-end against a running uvicorn instance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
59 lines
2.1 KiB
Markdown
59 lines
2.1 KiB
Markdown
# Labeling Tool — Backend
|
|
|
|
API + data model for the bounding-box labeling tool. See CLAUDE.md §3.2 for the
|
|
full requirements this is built against.
|
|
|
|
**Status:** core data model + CRUD API implemented (sets, hierarchical classes,
|
|
frames, labels, per-frame/per-set status). **Not yet implemented:** dataset
|
|
versioning/promotion (`enemy-v1`, `enemy-v2`, ...) — deferred since it needs its
|
|
own design pass (snapshot semantics: labels are editable at any time, but a
|
|
promoted dataset version must stay reproducible). Also not yet implemented: any
|
|
frontend, auth/login (see below), or the active-learning auto-label workflow.
|
|
|
|
## Stack
|
|
|
|
- **FastAPI** + **SQLAlchemy** (2.0), **SQLite** by default (`./labeling.db`),
|
|
swappable via the `DATABASE_URL` env var (e.g. to Postgres later without code
|
|
changes — one Postgres-compatible ORM).
|
|
- **Multi-user, no auth yet:** labels/status changes take a plain `created_by` /
|
|
`updated_by` username string, resolved via get-or-create (`users.py`). There's no
|
|
login flow — attribution only, since there's no UI yet that would need real auth.
|
|
|
|
## Data model
|
|
|
|
- `LabelSet` — a label set (`Enemy`, `Items`, `Traps`, ...), one per detector model.
|
|
- `MainClass` / `SubClass` — the per-set Main → Sub class hierarchy (e.g. `Enemy` →
|
|
`Bat`, `Snake`), created ad hoc via the API, no migration needed to add classes.
|
|
- `Frame` — one labelable image, identified by `(session_name, frame_index)` —
|
|
matches the recording tool's frame-extraction output 1:1.
|
|
- `Label` — one bounding box (`x, y, width, height` in pixel space), scoped to a
|
|
frame + set + sub-class.
|
|
- `FrameSetStatus` — per-frame, per-set label state (`unlabeled` / `auto_labeled` /
|
|
`reviewed`).
|
|
|
|
## Setup
|
|
|
|
```
|
|
python -m venv .venv
|
|
source .venv/bin/activate
|
|
pip install -e ".[dev]"
|
|
```
|
|
|
|
## Run
|
|
|
|
```
|
|
spelunkai-labeling-backend
|
|
# or: uvicorn spelunkai_labeling_backend.main:create_app --factory --reload
|
|
```
|
|
|
|
Interactive API docs at `http://127.0.0.1:8000/docs` once running.
|
|
|
|
## Testing
|
|
|
|
```
|
|
pytest
|
|
```
|
|
|
|
Each test gets a fully isolated app + SQLite file via `create_app(database_url=...)`
|
|
(see `tests/conftest.py`) — no shared state between tests, no real server needed.
|