Jonas 4c9deda66a Implement labeling backend: FastAPI + SQLAlchemy data model and CRUD API
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>
2026-07-16 11:24:57 +02:00

2.1 KiB

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. EnemyBat, 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.