Files
feedmill-recounter/docs/superpowers/plans/2026-09-18-model-grouping.md
T

4.9 KiB

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)
  2. updateSubmitState(): check grouped checkboxes
  3. initFormSubmit(): on submit, collect model_stem + format_{{stem}} values
  4. 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