feat: SQLite persistence, non-blocking inference, modular frontend

Backend:
- Persist alert events and robot delivery counters in SQLite (data/app.db,
  YOLO_DB_PATH override); EventStore keeps its interface, DeliveryStatsStore
  uses read/write-through UPSERT; in-memory fallback remains for standalone
  AlertManager use
- Serve /api/detect from a sync endpoint and serialize YOLO inference with a
  lock, so concurrent requests no longer block the event loop
- Unify single-image and session detection: requests without session_id
  share the fixed single-image session and run full frame confirmation
- Store UTC Z-suffixed timestamps for sortable string comparison; close
  executor and database on shutdown via FastAPI lifespan

Frontend:
- Split app.js into ES modules (main.js + modules/{dom,api,ui,charts,store}
  + views/{dashboard,inspection,events,robots,robotCards}), no build step
- Escape all server data interpolated into innerHTML; guard missing
  event.classes; replace lazy element ID list with memoized qs()
- Remove hardcoded fake stats (trend badge, device donut segment)

Docs:
- Rewrite README: accurate weight policy (only trained best.pt committed,
  no Git LFS), SQLite persistence, single-worker note, data asset inventory
- Align models/pretrained/README.md with actual files; add YOLO_DB_PATH to
  .env.example; add persistence unit tests; ruff clean
This commit is contained in:
2026-08-13 16:50:23 +08:00
parent 4dee7f664d
commit 25fa0c5825
25 changed files with 1058 additions and 669 deletions

View File

@@ -1,18 +1,20 @@
# Smoke and Fire YOLO
Ultralytics YOLO training, validation, prediction, and export pipeline for the Smoke-Fire-Detection-YOLO dataset.
Ultralytics YOLO training, validation, prediction, and export pipeline for the Smoke-Fire-Detection-YOLO dataset, plus an integrated fire prevention management platform (FastAPI + browser frontend).
## Project layout
```text
configs/datasets/smoke_fire.yaml Dataset configuration
models/pretrained/yolo11s.pt Default pretrained model
models/pretrained/ Locally cached base weights (not committed)
src/yolo/cli.py Command-line entry point
src/yolo/config.py Training configuration
src/yolo/defaults.py Project defaults
src/yolo/engine.py Train, validate, predict, and export
src/yolo/checkpoints.py Checkpoint discovery and resume support
src/yolo/reporting.py Training result reporting
backend/ FastAPI inference API and alerting
frontend/ Browser management platform (no build step)
```
## Setup
@@ -21,6 +23,8 @@ src/yolo/reporting.py Training result reporting
uv sync
```
Trained deployment weights are committed as regular files under `runs/detect/*/weights/best.pt`, so the API works right after cloning. Checkpoint files (`epoch*.pt`, `last.pt`) and re-downloadable base weights are excluded by `.gitignore`.
## Commands
Fine-tune from the current best YOLO11s checkpoint:
@@ -69,6 +73,9 @@ uv run fire-yolo export --weights runs/detect/<run-name>/weights/best.pt --forma
- Output: `runs/detect`
Training writes `last.pt`, `best.pt`, periodic checkpoints, and `best_point.json` to the run directory.
The committed best weights and evaluation evidence are summarized in [`docs/model_comparison.md`](docs/model_comparison.md). Only trained `best.pt` files are committed; to make a newly trained model available for deployment, commit its `weights/best.pt` after the run finishes.
## Web Detection Service
After training finishes, install the web dependencies and run the integrated frontend and inference API:
@@ -80,6 +87,16 @@ uv run uvicorn backend.main:app --host 127.0.0.1 --port 8000
Open `http://127.0.0.1:8000` to use the fire prevention management platform. It provides a system overview, local-video inspection, alert event handling, a risk register, robot channel status, and effective model settings. The browser plays selected videos locally and sends sequential JPEG frames to `POST /api/detect`; requests do not overlap.
Management endpoints include `GET /api/dashboard`, `GET /api/events`, `PATCH /api/events/{event_id}`, and `GET /api/robots`. Alert events can be marked as pending, acknowledged, or resolved. The robot endpoint reports Enterprise WeChat and Feishu configuration and delivery statistics without exposing webhook credentials. Use `POST /api/robots/{channel}/test` to send a connection test to a configured group robot. The current implementation retains the most recent 500 events and robot delivery counters in process memory, so they are cleared when the API service restarts.
Management endpoints include `GET /api/dashboard`, `GET /api/events`, `PATCH /api/events/{event_id}`, and `GET /api/robots`. Alert events can be marked as pending, acknowledged, or resolved. The robot endpoint reports Enterprise WeChat and Feishu configuration and delivery statistics without exposing webhook credentials. Use `POST /api/robots/{channel}/test` to send a connection test to a configured group robot.
Events and robot delivery counters are persisted in SQLite (`data/app.db` by default, override with `YOLO_DB_PATH`), so they survive service restarts. The event store keeps the most recent 500 events. Run the API with a single uvicorn worker: per-session consecutive-frame state lives in the process.
The local `.env` file contains optional robot settings. Set `WECHAT_WEBHOOK_URL` for an Enterprise WeChat group robot, `FEISHU_WEBHOOK_URL` for a Feishu custom group robot, or both. If Feishu signature verification is enabled, also set `FEISHU_SECRET`. Alerts require three consecutive positive frames by default and use separate 60-second cooldowns for fire and smoke. `ALERT_CONFIRM_FRAMES` and `ALERT_COOLDOWN_SECONDS` override these settings. Without a webhook, video detection still works and the UI reports that notifications are disabled.
Detection requests without a `session_id` share the fixed `single-image` session, so the consecutive-frame confirmation also applies to them; reset it with `DELETE /api/sessions/single-image`.
## Data assets
- `data/Smoke-Fire-Detection-YOLO/` — main smoke/fire dataset (train/val/test).
- `data/fire-dataset/` — incremental hard-negative collection (395 train / 87 val images, Pascal VOC XML plus YOLO labels); not yet wired to a training config.
- `runs/audit/` — label audit tooling: `scan_missing_labels.py` finds unlabeled images that the current model detects, `render_missing_label_candidates.py` renders them for review.