| from __future__ import annotations |
|
|
| import argparse |
| import json |
| import sys |
| from pathlib import Path |
|
|
|
|
| PROJECT_ROOT = Path(__file__).resolve().parents[1] |
| METRICS_PATH = PROJECT_ROOT / "models" / "sales_conversion_metrics.json" |
|
|
|
|
| def main() -> int: |
| parser = argparse.ArgumentParser(description="Validate saved conversion-model performance metrics.") |
| parser.add_argument("--min-accuracy", type=float, default=0.73) |
| parser.add_argument("--min-recall", type=float, default=0.80) |
| parser.add_argument("--min-f1", type=float, default=0.74) |
| args = parser.parse_args() |
|
|
| if not METRICS_PATH.exists(): |
| print(json.dumps({"status": "failed", "failures": [f"{METRICS_PATH.name} not found"]}, indent=2)) |
| return 2 |
|
|
| metrics = json.loads(METRICS_PATH.read_text(encoding="utf-8")) |
| failures = [] |
| if float(metrics.get("accuracy", 0)) < args.min_accuracy: |
| failures.append(f"accuracy {metrics.get('accuracy')} is below {args.min_accuracy}") |
| if float(metrics.get("recall", 0)) < args.min_recall: |
| failures.append(f"recall {metrics.get('recall')} is below {args.min_recall}") |
| if float(metrics.get("f1", 0)) < args.min_f1: |
| failures.append(f"f1 {metrics.get('f1')} is below {args.min_f1}") |
|
|
| print( |
| json.dumps( |
| { |
| "status": "passed" if not failures else "failed", |
| "model": metrics.get("model_name"), |
| "accuracy": metrics.get("accuracy"), |
| "precision": metrics.get("precision"), |
| "recall": metrics.get("recall"), |
| "f1": metrics.get("f1"), |
| "roc_auc": metrics.get("roc_auc"), |
| "threshold": metrics.get("classification_threshold"), |
| "failures": failures, |
| }, |
| indent=2, |
| ) |
| ) |
| return 1 if failures else 0 |
|
|
|
|
| if __name__ == "__main__": |
| sys.exit(main()) |
|
|