File size: 7,005 Bytes
b5d2527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"""
══════════════════════════════════════════════════════════════════════════════
PolicyBridge β€” Master Agent Training Runner
══════════════════════════════════════════════════════════════════════════════
Trains all 4 ML agents in sequence from the Bronze layer data.
Run this ONCE after loading bronze_historical_data.sql.

Usage:
    cd agents/
    pip install pymysql pandas scikit-learn xgboost sqlalchemy
    python train_all_agents.py

Output models saved to agents/models/:
    agent1_kyc_classifier.pkl     β€” KYC binary classifier
    agent2_property_risk.pkl      β€” Property peril regressors + risk classifier
    agent3_underwriting.pkl       β€” UW binary classifier
    agent4_pricing.pkl            β€” Premium XGBoost + GLM ensemble

Agent 5 (Issuance) is deterministic β€” no training required.

Environment:
    Local         β†’ connects to localhost:3306 / bronze  (root / root@123)
    HuggingFace   β†’ reads MYSQL_ADDON_* or MYSQL_* Secrets β†’ Clever Cloud
══════════════════════════════════════════════════════════════════════════════
"""

import sys
import os
import time
import datetime
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent))

# ── Dynamic environment detection (mirrors agent DB config) ───────────────────
def _is_huggingface() -> bool:
    return (
        os.environ.get("SPACE_ID")            is not None
        or os.environ.get("HUGGINGFACE_SPACE") is not None
        or os.environ.get("MYSQL_ADDON_HOST")  is not None
        or os.environ.get("MYSQL_HOST")        is not None
    )

def _env(addon_key: str, generic_key: str, default: str = "") -> str:
    return os.environ.get(addon_key) or os.environ.get(generic_key) or default

def _db_display() -> str:
    """Returns a human-readable DB connection string for the startup banner."""
    if _is_huggingface():
        host = _env("MYSQL_ADDON_HOST", "MYSQL_HOST", "clever-cloud")
        port = _env("MYSQL_ADDON_PORT", "MYSQL_PORT", "3306")
        db   = _env("MYSQL_ADDON_DB",   "MYSQL_DATABASE", "btvbbpqhvnttzvptguj3")
        return f"Clever Cloud  {host}:{port}/{db}  (bronze_* prefix)"
    return "localhost:3306/bronze  (separate schemas)"

# ─────────────────────────────────────────────────────────────────────────────

def print_banner(title):
    print(f"\n{'═'*65}")
    print(f"  {title}")
    print(f"{'═'*65}")

def train_all():
    env_label = "HuggingFace β†’ Clever Cloud" if _is_huggingface() else "Local β†’ MySQL"

    print_banner("PolicyBridge β€” Agent Training Pipeline")
    print(f"  Started:     {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print(f"  Environment: {env_label}")
    print(f"  DB Target:   {_db_display()}")
    print(f"  Records:     500 historical submissions (2024)")

    results = {}
    total_start = time.time()

    # ── Agent 1: KYC ─────────────────────────────────────────────────────────
    try:
        from agent1_ssn_kyc import train_kyc_model
        t0  = time.time()
        art = train_kyc_model()
        results["Agent1_KYC"] = {"status": "OK", "elapsed": round(time.time()-t0, 1)}
    except Exception as e:
        results["Agent1_KYC"] = {"status": f"FAILED: {e}", "elapsed": 0}

    # ── Agent 2: Property Risk ────────────────────────────────────────────────
    try:
        from agent2_property_risk import train_property_model
        t0  = time.time()
        art = train_property_model()
        results["Agent2_Property"] = {"status": "OK", "elapsed": round(time.time()-t0, 1)}
    except Exception as e:
        results["Agent2_Property"] = {"status": f"FAILED: {e}", "elapsed": 0}

    # ── Agent 3: Underwriting ────────────────────────────────────────────────
    try:
        from agent3_underwriting import train_uw_model
        t0  = time.time()
        art = train_uw_model()
        results["Agent3_UW"] = {"status": "OK", "elapsed": round(time.time()-t0, 1)}
    except Exception as e:
        results["Agent3_UW"] = {"status": f"FAILED: {e}", "elapsed": 0}

    # ── Agent 4: Pricing ─────────────────────────────────────────────────────
    try:
        from agent4_pricing import train_pricing_model
        t0  = time.time()
        art = train_pricing_model()
        results["Agent4_Pricing"] = {"status": "OK", "elapsed": round(time.time()-t0, 1)}
    except Exception as e:
        results["Agent4_Pricing"] = {"status": f"FAILED: {e}", "elapsed": 0}

    # ── Summary ───────────────────────────────────────────────────────────────
    total = round(time.time() - total_start, 1)
    print_banner("Training Summary")

    all_ok = True
    for agent, res in results.items():
        status = res["status"]
        icon   = "βœ“" if status == "OK" else "βœ—"
        print(f"  {icon}  {agent:<25}  {status:<10}  {res['elapsed']}s")
        if status != "OK":
            all_ok = False

    print(f"\n  Total elapsed: {total}s")
    print(f"\n  Models saved to: agents/models/")
    for pkl in sorted(Path("models").glob("*.pkl")):
        size = pkl.stat().st_size // 1024
        print(f"    {pkl.name:<40} {size} KB")

    if all_ok:
        print(f"\n  All 4 agents trained successfully.")
        print(f"  Run the pipeline:")
        print(f"    python agent5_issuance_orchestrator.py")
        print(f"    python agent5_issuance_orchestrator.py --submission SUB-2024-00001")
        print(f"    python agent5_issuance_orchestrator.py --batch --limit 100")
    else:
        print(f"\n  Some agents failed. Check errors above.")
        if _is_huggingface():
            print(f"  HuggingFace: verify MYSQL_ADDON_* Secrets are set in Space Settings.")
        else:
            print(f"  Local: ensure MySQL is running and bronze_historical_data.sql is loaded.")

    return results

if __name__ == "__main__":
    train_all()