"""Explainability utilities for decision transparency.""" from typing import Dict, Any, List class DecisionExplainer: """Generate human-readable explanations for decisions.""" @staticmethod def explain_decision(decision: str, factors: Dict[str, Any]) -> str: """Generate explanation for claim decision.""" if decision == "APPROVED": return DecisionExplainer._explain_approval(factors) elif decision == "REJECTED": return DecisionExplainer._explain_rejection(factors) elif decision == "REVIEW": return DecisionExplainer._explain_review(factors) else: return "Decision could not be explained." @staticmethod def _explain_approval(factors: Dict[str, Any]) -> str: """Explain approval decision.""" parts = ["Claim APPROVED based on:"] if factors.get("severity_score", 0) < 0.5: parts.append("- Low severity score indicates routine claim") if not factors.get("fraud_risk", False): parts.append("- No fraud indicators detected") if factors.get("coverage_valid", True): parts.append("- Coverage rules satisfied") if factors.get("amount_within_limits", True): parts.append("- Claim amount within policy limits") return "\n".join(parts) @staticmethod def _explain_rejection(factors: Dict[str, Any]) -> str: """Explain rejection decision.""" parts = ["Claim REJECTED due to:"] if factors.get("fraud_risk", False): signals = factors.get("fraud_signals", []) parts.append(f"- Fraud risk detected: {', '.join(signals)}") if not factors.get("coverage_valid", True): parts.append("- Coverage requirements not met") if not factors.get("amount_within_limits", True): parts.append("- Claim amount exceeds policy limits") if factors.get("policy_expired", False): parts.append("- Policy expired at time of incident") return "\n".join(parts) @staticmethod def _explain_review(factors: Dict[str, Any]) -> str: """Explain manual review requirement.""" parts = ["Claim requires MANUAL REVIEW because:"] if factors.get("severity_score", 0) > 0.7: parts.append("- High severity score requires expert assessment") if factors.get("ambiguous_coverage", False): parts.append("- Coverage determination is ambiguous") if factors.get("high_amount", False): parts.append("- Claim amount requires senior approval") if factors.get("missing_documentation", False): parts.append("- Additional documentation required") if factors.get("edge_case", False): parts.append("- Unusual circumstances detected") return "\n".join(parts) @staticmethod def format_fraud_signals(signals: List[str]) -> str: """Format fraud signals for display.""" if not signals: return "No fraud indicators detected." return "Fraud indicators:\n" + "\n".join(f"- {signal}" for signal in signals)