feat: add video reuse — re-analyze previous uploads without re-uploading
This commit is contained in:
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
|
||||
Reference in new issue
Block a user