File size: 3,330 Bytes
21f1a73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""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)