Spaces:
Sleeping
Sleeping
Commit History
-
fix: pass ruff lint+format, clean README, remove stray script
Priya Monishafa0ce5b -
fix: production audit β security hardening + observability + code qualityβ
Priya MonishaC-1 api/routes/classify.py: add missing logger (was NameError on unknown class) M-1 src/models/base_classifier.py: remove print() β logger.info already covers epoch progress m-1 src/data/dataset.py: assert -> ValueError for invalid split param SEC config.py + redis_cache.py + api/main.py: Redis password support (REDIS_PASSWORD env) SEC docker-compose.yml: conditional Redis auth (no-op when REDIS_PASSWORD empty) SEC docker-compose.airflow.yml: replace hardcoded airflow:airflow/admin:admin with env vars OBS api/prometheus_metrics.py: add http_errors Counter + models_loaded Gauge OBS api/main.py: middleware counts 4xx/5xx; models_loaded.set(1) on successful startup DOC .env.example: document REDIS_PASSWORD, AIRFLOW_DB_PASSWORD, AIRFLOW_ADMIN_PASSWORD6319415 -
feat: bonus features β model ensemble + webcam detectionβ
Priya MonishaEnsemble (POST /ensemble): - Weighted average of ResNet50 + EfficientNetB0 + MobileNetV2 - Weights proportional to test accuracy (36.2% / 32.5% / 31.3%) - Per-model breakdown + combined top-K predictions - Redis cached with combined model hash key - EnsembleResponse schema added to api/schemas.py Webcam detection (pages/7_Webcam.py): - st.camera_input() β POST /detect β annotated frame - Inference time + wall time + object count metrics - Continuous mode toggle (auto-rerun for live-detection feel) - Same 24-colour bbox palette as pages/2_Detect.py Updated pages/1_Classify.py: - Two tabs: Single Model and Ensemble (3 CNNs) - Per-model bar charts in ensemble breakdown39291ad -
section-10: Streamlit multi-page app -- classify, detect, comparison, drift, EDAβ
Priya Monishastreamlit_app.py: Home page with API health badge + champion stats from model_metrics.json pages/1_Classify.py: POST /classify -> top-K Plotly bar chart, cache hit badge, validation pages/2_Detect.py: POST /detect -> EXIF-corrected PIL bbox drawing, 24-colour palette pages/3_Model_Comparison.py: 4 tabs (accuracy/speed-accuracy/detection/full table), mtime cache pages/4_Drift_Monitor.py: GET /drift/status -> go.Indicator gauge, session_state, numeric sort pages/5_EDA_Insights.py: static EDA artifact display, missing-file guard streamlit_app/api_client.py: module-level singleton session, raise_for_status + catch-all RuntimeError streamlit_app/plotting.py: accuracy_bar, speed_accuracy_scatter (normalised bubbles), drift_gauge api/routes/detect.py: ImageOps.exif_transpose before YOLO inference (C3 fix)6e6b313
-
section-9: KS drift detection + Prometheus -- DriftDetector, /drift/status, alert rulesβ
Priya Monisha- src/monitoring/drift_detector.py: DriftDetector class Double-gate KS alert (stat > 0.10 AND p < 0.05) -- stat alone has ~95% FP rate at n=30 baseline Rate-limited KS_RUN_EVERY_N=10 -- prevents blocking asyncio event loop at 100 req/s Redis list buffer sv:drift:live:{class} with deque fallback (Rule 23) All 22 Gauge series initialized at startup -- Prometheus has time series from day 1 Redis buffer restoration on restart: reversed(get_list) preserves chronological order _safe_float() guards nan/inf from degenerate KS inputs (zero-variance live data) - api/routes/drift.py: GET /drift/status -- Pydantic DriftStatusResponse model - api/main.py: DriftDetector in lifespan after Redis init; drift router registered - api/routes/classify.py: record(top1, confidence) after inference; unknown_predictions Counter - api/prometheus_metrics.py: unknown_predictions Counter (surfaces invisible model failures) - src/inference/redis_cache.py: push_to_list (LPUSH+LTRIM pipeline) + get_list mβ¦dacce7e -
section-8: FastAPI + Redis -- classify, detect, health, metrics endpointsβ
Priya Monisha- api/main.py: FastAPI lifespan (Rule 32), get_running_loop (Rule 31), non-blocking load_all_models via run_in_executor, eval_transform built once - api/routes/classify.py: POST /classify -- UploadFile+Form, Redis cache-aside, cached-key-pop fix (prevents TypeError on cache hit), Prometheus labels - api/routes/detect.py: POST /detect -- np.array(PIL) YOLO input, results[0].names, graceful 503 if YOLO unavailable - api/routes/health.py: GET /health -- 503 when loading (Docker healthcheck waits) - api/routes/metrics.py: GET /metrics -- CONTENT_TYPE_LATEST text/plain (Rule 30) - api/prometheus_metrics.py: Counter/Histogram singletons, class_name cardinality guard - api/schemas.py: ClassifyResponse, DetectResponse, HealthResponse Pydantic models - src/inference/model_loader.py: local-first weight resolution, HF Hub fallback with 120s ThreadPoolExecutor timeout, chunked MD5 hash, 3-pass warmup, FAST_MODE support - src/inference/redis_cache.py: socket_connect_timeout=1s (Rule 23), 32β¦9cb1db0
-
section-0+1: project foundation β config.py, requirements, gitignore, project-docsβ
Priya Monisha- .claude/settings.json: permission allowlist + PostToolUse git-commit hook - .claude/rules/: no_model_in_pages, fast_mode, one_model_per_turn - config.py: Pydantic Settings + all 25 CLASSES with COCO ID comments + 38-rule reference - requirements.txt / requirements-docker.txt / requirements-hf.txt (CPU-only PyTorch index-url) - .gitignore: anchored /data/raw/, /models/*.pt, notebooks/*.ipynb, /runs/ - pyrightconfig.json: extraPaths=["."] for Pylance import resolution - All src/ and api/ __init__.py files - project-docs: 38 rules table, progress tracker, locked decisions - CLAUDE_CONTEXT.md: full session bootstrap contextd091717