Model Tester GUI
The test_model.py script provides a standalone web GUI for testing exported models on individual images. It auto-discovers all available checkpoints and lets you visually predict the species and breed of any cattle or buffalo image.
Quick Start
This opens a browser at http://localhost:8501 with the GUI.
Features
- Drag & Drop / File Upload: Supports PNG, JPG, JPEG, BMP, and WebP formats
- Model Selector: Auto-discovers all available checkpoints:
- Phase 1/2/3 training checkpoints (
outputs/checkpoints/) - INT8 quantized models (
lite2_quantized.pt) - Portable export bundles (
outputs/export/portable/) - Prediction Results:
- Species classification: Cattle or Buffalo with confidence %
- Top-5 breed predictions with animated confidence bars
- Model metadata footer (which model was used, device info)
- Dual Modes (
--devvs--present): - Developer Mode (
--dev): The default mode providing full technical insights (EXIF metadata, detailed stats, data json viewer, and presenter configuration). - Presenter Mode (
--present): A clean, distraction-free UI ideal for demonstrations, which hides technical clutter and removes export functionalities. - Presenter Configuration: Interactive toggles in dev mode let you control branding, visible sections, and confidence metrics. Settings are persisted seamlessly across server restarts via
outputs/logs/presenter_config.json. - Comprehensive Logging: Every action (server start, model load, prediction trace) is logged out to
outputs/logs/automatically. - Zero Config: Works out of the box with any trained checkpoint
Usage
# Auto-open browser at http://localhost:8501
python test_model.py
# Custom port
python test_model.py --port 9000
# Don't auto-open browser
python test_model.py --no-browser
CLI Flags
| Flag | Description |
|---|---|
--port N |
Port to serve on (default: 8501) |
--no-browser |
Don't auto-open the browser window |
--dev |
Start in developer mode (default). Shows full technical UI and presenter settings. |
--present |
Start in presenter mode. Hides detailed stats and limits confidence metrics. |
How It Works
┌─────────────┐ POST /api/predict ┌──────────────────┐
│ Browser UI │ ─────────────────────────▶│ test_model.py │
│ (HTML/JS) │ │ HTTP Server │
│ │◀───────────────────────── │ │
│ Shows Top-5 │ JSON response │ ModelManager │
│ breed bars │ │ ├─ load model │
└─────────────┘ │ ├─ preprocess │
│ └─ predict │
└──────────────────┘
- ModelManager scans
outputs/checkpoints/andoutputs/export/portable/on startup - User uploads an image and selects a model in the browser
- Image is sent as
multipart/form-datatoPOST /api/predict - The model runs inference and returns species + top-5 breeds as JSON
- The browser renders animated confidence bars
API Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/ |
Serves the HTML GUI |
GET |
/api/models |
Returns available models + device info |
POST |
/api/predict |
Accepts image (file) + model (name), returns prediction |
GET |
/api/cattle-data |
Returns cattle class mappings |
GET |
/api/buffalo-data |
Returns buffalo class mappings |
GET |
/api/presenter-config |
Returns saved presenter UI configuration |
POST |
/api/presenter-config |
Saves updated presenter UI configuration |
Example /api/predict Response
{
"species": "Cattle",
"species_confidence": 98.4,
"top_breed": "Gir",
"top_breed_confidence": 91.2,
"top5_breeds": [
{"breed": "Gir", "confidence": 91.2},
{"breed": "Sahiwal", "confidence": 3.1},
{"breed": "Red Sindhi", "confidence": 1.8},
{"breed": "Tharparkar", "confidence": 1.1},
{"breed": "Kankrej", "confidence": 0.6}
],
"gender": {
"label": "Female (Cow)",
"short_label": "Female",
"confidence": 86.5,
"method": "clip_zeroshot",
"note": "Visual estimation from body/udder profile"
},
"age_group": {
"label": "Adult (> 3 yrs)",
"short_label": "Adult",
"confidence": 89.1,
"method": "clip_zeroshot",
"note": "Visual stage estimate; verify via dentition (teeth) for exact age"
},
"traits": {
"hump": "Large / Prominent",
"horn": "Curved (Half-moon)",
"ear": "Long & Pendulous",
"dewlap": "Large & Pendulous",
"size": "Medium-Large"
},
"knowledge": {
"headline": "Gir adult female — protect lactation: 8 - 12 L/day ...",
"priority_actions": ["Milk 2-3 times a day ..."],
"nutrition": {"green_fodder": "22 - 30 kg/day", "...": "..."},
"production": {"milk": {"daily_yield": "8 - 12 L/day", "...": "..."}},
"economics": {"market_price": "₹45,000 - ₹100,000", "schemes": ["..."]},
"disclaimer": "General guidance only — confirm with your veterinarian ..."
},
"ood": false,
"model_used": "lite2_phase2_best_v26_1012-2332_f9ce"
}
The same enriched payload (gender, age_group, traits, knowledge, plus
traits_detail / attributes_meta for developer views) is returned by the
Flask server's POST /api/predict in server/routes/predict.py. See
docs/attributes.md for how each attribute is produced and
docs/breed-knowledge.md for the advisory engine and the
/api/breed-knowledge/... + /api/advisory-recalculate endpoints.
Workflow
After training with local_train.py:
# 1. Train (any mode)
python local_train.py --quarter-data
# 2. Test exported models visually
python test_model.py
# 3. Upload any cattle/buffalo image in the browser
# 4. See species + breed prediction with confidence
OOD Calibration from a Breed-Named Folder
The OOD tools card (🧪 OOD Calibration & Dataset) now calibrates thresholds
from any folder of breed-named images for the model selected in Inspect
Model:
| Control | Meaning |
|---|---|
| Breed-named image folder | Free text with a picker of repository folders. Flat (Deoni_01.jpg) and nested (cattle/deoni/…) layouts are both supported |
| Percentile | Energy percentile used as the threshold (default 95) |
| Max images | Upper bound on images used (default 500) |
Press 🔄 Recalibrate OOD to run it. The result shows the new thresholds,
the sample count, matched/unmatched images, the per-breed coverage and the path
of the saved profile (outputs/ood/<model>.json). Unmatched names are listed so
a mis-named folder is visible instead of silently skewing the thresholds.
Leave the folder empty to recalibrate on the generated validation split, as before.
Requirements
- Trained model checkpoint(s) in
outputs/checkpoints/oroutputs/export/portable/ - No class-map JSON required — maps, resolution, normalization mode and OOD
thresholds are read from the model itself (
src/model_introspect.py). Legacydata/splits/*.json/outputs/ood/*.jsonare still honoured as a fallback. Runpython scripts/embed_metadata.py --allto bake the contract into older artifacts. See Self-Describing Models. - Python packages:
torch,torchvision,Pillow(installed bylocal_train.py)