# src/sla_predictor.py # SLA Breach Predictor — XGBoost at T=0 # SupportMind v1.0 — Asmitha import numpy as np import os import logging logger = logging.getLogger(__name__) try: import xgboost as xgb HAS_XGBOOST = True except ImportError: HAS_XGBOOST = False logger.warning("XGBoost not installed.") FEATURE_NAMES = [ 'text_complexity_score', 'agent_queue_depth', 'customer_tier', 'hour_of_day', 'day_of_week', 'similar_ticket_avg_hrs', 'sentiment_score', 'repeat_issue', 'escalated_before', ] class SLABreachPredictor: def __init__(self, model_path='models/sla_predictor/sla_xgb.json'): self.model = None self.model_path = model_path if HAS_XGBOOST and os.path.exists(model_path): self.model = xgb.Booster() self.model.load_model(model_path) elif HAS_XGBOOST: logger.warning( f"Model not found at {model_path}. " "Run train_sla.py to generate it. Using heuristic fallback." ) def predict(self, features: dict) -> float: if self.model and HAS_XGBOOST: vec = np.array([[features.get(f, 0) for f in FEATURE_NAMES]]) dm = xgb.DMatrix(vec, feature_names=FEATURE_NAMES) return round(float(self.model.predict(dm)[0]), 4) # Heuristic fallback s = 0.3 s += features.get('agent_queue_depth', 10) * 0.01 s += features.get('repeat_issue', 0) * 0.15 s += features.get('escalated_before', 0) * 0.10 s -= features.get('sentiment_score', 0) * 0.15 s += max(0, features.get('similar_ticket_avg_hrs', 4) - 4) * 0.03 if features.get('customer_tier', 2) >= 4: s += 0.10 h = features.get('hour_of_day', 12) if h < 6 or h > 20: s += 0.08 return round(min(max(s, 0.0), 1.0), 4) def explain(self, features: dict) -> dict: prob = self.predict(features) risk = 'high' if prob >= 0.7 else 'medium' if prob >= 0.4 else 'low' factors = [] if features.get('agent_queue_depth', 0) > 20: factors.append('High queue depth') if features.get('sentiment_score', 0) < -0.5: factors.append('Negative sentiment') if features.get('repeat_issue', 0): factors.append('Repeat issue') if features.get('escalated_before', 0): factors.append('Previously escalated') if features.get('customer_tier', 1) >= 4: factors.append('Enterprise SLA') return {'breach_probability': prob, 'risk_level': risk, 'contributing_factors': factors, 'recommendation': 'Prioritize' if prob >= 0.6 else 'Standard'}