feat: add video reuse — re-analyze previous uploads without re-uploading

This commit is contained in:
jetson committed 2026-09-21 09:35:29 +07:00
1 parent a75db4ca49
commit f779f05190
7 files changed
+453 -62

No files matched your search

@@ -0,0 +1,128 @@
# Model Grouping by Stem with Format Selection
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Combine model files with the same stem (e.g., `best.pt`, `best.onnx`, `best.engine`) into a single selectable model entry with a format dropdown (`.pt` / `.onnx` / `.engine`), reducing UI clutter while preserving format choice.
**Current State:** 17 model files displayed as 17 separate checkboxes (e.g., `best.pt`, `best.onnx`, `best.engine` as three separate entries). Each has its own filter dropdown.
**Desired State:** 6 model entries (one per stem: `best`, `model_karung_truk`, `truck-detector`, `v4-best`, `yolo11n-bbox-100ep-sack+box-20260909-best`, `karung-dimuat-detection-di-feedmill-yolo26n-seg-200e`). Each entry has:
- One checkbox to enable the model
- A format dropdown showing available formats (e.g., `.pt`, `.onnx`, `.engine`)
- One filter dropdown (shared across formats, since classes are the same per stem)
**Architecture:**
1. Modify `scan_models()` to return grouped models (one per stem) with format options
2. Update `ModelConfig` dataclass to include `formats: list[str]` and `format_paths: dict[str, str]`
3. Update `/` route to pass grouped models
4. Update upload endpoint to handle the new format
5. Rewrite template to render grouped cards with format dropdown
6. Update JavaScript to handle grouped model selection
**Tech Stack:** Python, Flask, vanilla JS
---
## Global Constraints
- Python >= 3.10
- No new Python dependencies
- Keep backward compatibility where reasonable
- Flat Design CSS with teal primary, orange accent
- Accessible: semantic HTML, ARIA, keyboard navigation
- Responsive: mobile-first
---
### Task 1: Update Model Registry — Group by Stem
**Files:**
- Modify: `src/model_registry.py`
**Requirements:**
1. New dataclass `ModelGroup`:
- `stem: str` — the model stem (e.g., "best")
- `formats: list[str]` — available formats (e.g., [".pt", ".onnx", ".engine"])
- `format_paths: dict[str, str]` — format -> full path mapping
- `known_classes: list[str]` — from KNOWN_MODEL_CLASSES
- `default_format: str` — preferred format order: .engine > .pt > .onnx
2. New function `scan_model_groups(models_dir: str) -> list[ModelGroup]`:
- Scan all files with MODEL_EXTENSIONS
- Group by stem
- Sort formats by preference (.engine first)
- Return list of ModelGroup
3. Keep `scan_models()` for backward compatibility (API endpoint, tests)
**Interfaces:**
- Produces: `ModelGroup` with fields above
- Consumes: `KNOWN_MODEL_CLASSES`, `MODEL_EXTENSIONS`
**Tests:** Add tests for grouping logic
---
### Task 2: Update Flask Routes — Use Grouped Models
**Files:**
- Modify: `app.py`
**Requirements:**
1. `index()` route: call `scan_model_groups()` instead of `scan_models()`, pass `model_groups` to template
2. `upload()` route:
- Accept `model_stem` and `model_format` from form (e.g., `model_stem=best`, `model_format=.engine`)
- Look up group by stem, then get path from `format_paths[format]`
- Build `model_configs` with single selected format per group
- Keep class filter logic (per stem, not per file)
3. `api_models()` endpoint: return grouped format (include formats + paths)
**Backward Compatibility:**
- If `models` (filenames) still sent, support legacy path
- But prefer new `model_stem` + `model_format` approach
---
### Task 3: Update Template — Grouped Model Cards
**Files:**
- Modify: `templates/index.html`
**Requirements:**
1. Iterate over `model_groups` instead of `models`
2. Each card:
- Checkbox with `value="{{ group.stem }}"` and `data-format="{{ group.default_format }}"`
- Format dropdown (`<select name="format_{{ group.stem }}">`) with options for each format in `group.formats`
- Filter dropdown (same as before, but `name="filter_{{ group.stem }}"`)
- Badges from `group.known_classes`
3. Update "Select All" / "Deselect All" to work with grouped checkboxes
4. Update submit hint logic: enable submit when video + at least one group selected
---
### Task 4: Update JavaScript — Handle Grouped Models
**Files:**
- Modify: `static/app.js`
**Requirements:**
1. `initModelCards()`: work with grouped cards (same logic, different selectors)
3. `updateSubmitState()`: check grouped checkboxes
4. `initFormSubmit()`: on submit, collect `model_stem` + `format_{{stem}}` values
5. Format dropdown change: update hidden input or data attribute so form submits correct format
---
### Task 5: Verification & Testing
**Files:** None (verification only)
**Requirements:**
1. Run existing tests: `python -m pytest tests/ -v`
2. Verify Flask app starts
3. Test UI manually:
- Open `/` -> see 6 model entries (not 17)
- Each entry has format dropdown with correct options
- Select multiple models with different formats
- Submit -> job processes with selected formats
4. Verify `/api/models` returns grouped format