Background
docs/01-introduction-and-goals/README.md notes that the image-service classifier is a stub today and that real ML integration is "planned." This issue makes that pipeline real and operable so that downstream features can plug in without a Dockerfile rebuild for every model swap.
Why it matters
Almost every feature on the wishlist (cell-occupation timeline, hatching prediction, species ID, time-lapse triage) depends on a real model running in image-service. Without a hot-swap-capable pipeline, every new model is a redeploy.
Proposal
- Model directory mounted as a volume:
/models/<name>/<version>/{weights, config.json, README.md}.
- Model registry loaded at startup, with optional reload-on-SIGHUP (or admin endpoint) for swap-in.
- Inference contract: each model exposes a common
predict(image) -> {detections, scores, model_version} interface.
- Telemetry: every inference logs
model_version so downstream consumers can filter or retroactively understand drift.
- First real model: a small object detector (YOLO-nano-class or similar) replacing the stub — even baseline accuracy is fine; the point is the integration, not SOTA numbers.
Acceptance criteria
Out of scope
- Choosing the production model — that is a follow-up tracked separately.
- GPU inference — CPU-only is fine for now (ESP-side latencies dwarf inference time).
Background
docs/01-introduction-and-goals/README.mdnotes that the image-service classifier is a stub today and that real ML integration is "planned." This issue makes that pipeline real and operable so that downstream features can plug in without a Dockerfile rebuild for every model swap.Why it matters
Almost every feature on the wishlist (cell-occupation timeline, hatching prediction, species ID, time-lapse triage) depends on a real model running in
image-service. Without a hot-swap-capable pipeline, every new model is a redeploy.Proposal
/models/<name>/<version>/{weights, config.json, README.md}.predict(image) -> {detections, scores, model_version}interface.model_versionso downstream consumers can filter or retroactively understand drift.Acceptance criteria
/models/...volume mount indocker-compose.ymlmodel_versionrecorded with every output that crosses a service boundarydocs/09-architecture-decisions/covering the choice + model lifecycleOut of scope