ai-decision-maker / app /engine /decision.py
rashimittal's picture
Upload 34 files
d9ac377 verified
Raw
History Blame Contribute Delete
2.52 kB
from typing import Callable, NamedTuple
class _Rule(NamedTuple):
name: str
decision: str
matches: Callable[[dict, dict], bool]
confidence: Callable[[dict, dict], float]
# Floor ESCALATE at 0.5 — we'd rather over-escalate than miss something urgent.
# Other rules scale proportionally with sentiment confidence.
RULES: list[_Rule] = [
_Rule(
name="negative_high_urgency",
decision="ESCALATE",
matches=lambda s, sig: s["label"] == "NEGATIVE" and sig["urgency"] == "HIGH",
confidence=lambda s, sig: round(min(1.0, 0.5 + s["confidence"] * 0.5), 3),
),
_Rule(
name="negative_complaint",
decision="FOLLOW_UP",
matches=lambda s, sig: s["label"] == "NEGATIVE" and sig["intent"] == "COMPLAINT",
confidence=lambda s, sig: round(min(1.0, 0.4 + s["confidence"] * 0.4), 3),
),
_Rule(
name="positive_praise",
decision="LOG_FEEDBACK",
matches=lambda s, sig: s["label"] == "POSITIVE" and sig["intent"] == "PRAISE",
confidence=lambda s, sig: round(min(1.0, 0.3 + s["confidence"] * 0.6), 3),
),
_Rule(
name="question_any_sentiment",
decision="AUTO_RESOLVE",
matches=lambda s, sig: sig["intent"] == "QUESTION",
confidence=lambda s, sig: 0.75,
),
]
_FALLBACK_DECISION = "FOLLOW_UP"
_FALLBACK_RULE = "fallback"
def _fallback_confidence(sentiment: dict) -> float:
# Low ceiling (0.4) signals that no strong rule fired.
return round(min(0.4, 0.2 + sentiment["confidence"] * 0.2), 3)
def decide(sentiment: dict, signals: dict) -> dict:
for rule in RULES:
if rule.matches(sentiment, signals):
return {
"decision": rule.decision,
"confidence": rule.confidence(sentiment, signals),
"signals_used": {
"label": sentiment["label"],
"sentiment_confidence": sentiment["confidence"],
"urgency": signals["urgency"],
"intent": signals["intent"],
"rule_matched": rule.name,
},
}
return {
"decision": _FALLBACK_DECISION,
"confidence": _fallback_confidence(sentiment),
"signals_used": {
"label": sentiment["label"],
"sentiment_confidence": sentiment["confidence"],
"urgency": signals["urgency"],
"intent": signals["intent"],
"rule_matched": _FALLBACK_RULE,
},
}