Spaces:
Sleeping
Sleeping
File size: 5,141 Bytes
a77725d | 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 | """
tasks/hard_task.py β Hard scenario: angry VIP customer threatening legal action
after a 3-week unresolved product failure
Grader used: HardTaskGrader (requires de-escalation + concrete resolution)
"""
from models import Task, StepName, DifficultyLevel
HARD_TASK = Task(
task_id = "HARD_001",
difficulty = DifficultyLevel.HARD,
customer_emotion = "angry",
escalation_risk = True,
customer_message = (
"I am ABSOLUTELY FURIOUS. I purchased your premium standing desk "
"(βΉ45,000) three weeks ago and it arrived broken. I've called five times, "
"sent four emails, and NOBODY has fixed this. I'm a VIP member and this "
"is how you treat me?! I am going to post this on every review site, "
"contact consumer court, and make sure everyone knows how pathetic your "
"company's service is. I want this resolved TODAY or I'm cancelling my "
"entire βΉ2 lakh annual contract!"
),
scenario_context = (
"Customer: Rajesh Mehta | VIP Tier | Annual contract: βΉ2,00,000. "
"Order #ORD-VIP-2241 β Premium Standing Desk Pro (βΉ45,000) delivered "
"on 12 March with a broken motorised lift mechanism. "
"5 prior support tickets (TKT-001 to TKT-005) β all marked 'pending'. "
"No technician dispatched yet. Replacement stock available (3β5 days). "
"Policy: VIP customers get same-day escalation + compensation up to 20% "
"of order value for delays > 7 days."
),
required_steps = [
StepName.EMPATHY,
StepName.COLLECT_INFO,
StepName.INVESTIGATE,
StepName.RESOLUTION,
],
step_keywords = {
StepName.EMPATHY: [
"i am personally and deeply sorry",
"deeply sorry",
"sincerely apologize",
"i completely understand",
"that is completely unacceptable",
"you have every right",
"i take full responsibility",
"this should not have happened",
"i hear your frustration",
],
StepName.COLLECT_INFO: [
"order number", "ticket number", "vip", "account",
"could you confirm", "full name", "email", "contact",
],
StepName.INVESTIGATE: [
"reviewing your tickets", "i can see", "five tickets",
"all marked pending", "this is unacceptable internally",
"i have escalated", "our records show", "found that",
"i found", "looking into",
],
StepName.RESOLUTION: [
"replacement", "technician today", "within 24 hours",
"βΉ9,000", "9000", "20%", "compensation",
"personally ensure", "i will personally",
"waive", "free of charge", "priority",
],
},
)
# ββ Hard-task specific scoring weights ββββββββββββββββββββββββββββββββββββββββ
HARD_TASK_SCORING = {
"emotional_control": 0.30, # calm + empathetic tone
"conflict_handling": 0.25, # de-escalation phrases
"professional_tone": 0.20, # no blame, no dismissal
"resolution_accuracy": 0.25, # correct refund % + timeline
}
def evaluate_hard_response(response: str, step: StepName) -> dict:
"""
Returns a breakdown dict for hard-task evaluation display.
Used by the UI to show per-dimension scores.
"""
r = response.lower()
scores = {}
if step == StepName.EMPATHY:
emotional_hits = sum(1 for kw in HARD_TASK.step_keywords[StepName.EMPATHY]
if kw in r)
scores["emotional_control"] = min(1.0, emotional_hits / 3)
deesc = ["completely understand", "every right", "full responsibility",
"should not have happened", "hear your frustration"]
deesc_hits = sum(1 for kw in deesc if kw in r)
scores["conflict_handling"] = min(1.0, deesc_hits / 2)
bad = ["calm down", "your fault", "nothing we can do", "policy says"]
scores["professional_tone"] = 0.0 if any(b in r for b in bad) else 1.0
scores["resolution_accuracy"] = 0.0 # N/A at empathy step
elif step == StepName.RESOLUTION:
scores["emotional_control"] = 1.0 if "personally ensure" in r else 0.5
scores["conflict_handling"] = 1.0 if "priority" in r else 0.5
scores["professional_tone"] = 1.0 if "i will personally" in r else 0.5
# Check resolution accuracy: compensation + timeline
has_comp = any(c in r for c in ["9,000", "9000", "20%", "compensation"])
has_timeline = any(t in r for t in ["24 hours", "today", "tomorrow", "3 days"])
scores["resolution_accuracy"] = (0.5 * int(has_comp)) + (0.5 * int(has_timeline))
else:
# Default neutral for mid steps
scores = {k: 0.5 for k in HARD_TASK_SCORING}
weighted = sum(HARD_TASK_SCORING[k] * scores.get(k, 0.0)
for k in HARD_TASK_SCORING)
scores["weighted_total"] = round(weighted, 3)
return scores |