Spaces:
Sleeping
Sleeping
| """Three graded tasks with clear difficulty progression. | |
| Difficulty ladder | |
| ----------------- | |
| 1. work_stress_venting (easy) | |
| - Cooperative seeker, low reveal threshold, forgiving trust. | |
| - Goal: reach CLOSING stage with trust ≥ 0.7 and distress ≤ 0.4. | |
| 2. guarded_relationship (medium) | |
| - Seeker starts guarded (low openness). Real issue is different from the | |
| surface concern and only surfaces once openness crosses 0.75. | |
| - Premature advice aggressively drops trust. Agent must *first* build | |
| rapport, then explore. | |
| 3. crisis_fragile_trust (hard) | |
| - High initial distress, high trust fragility, multiple interleaved | |
| concerns. Any single misstep (dismissive OR premature advice) triggers | |
| a large trust drop that takes several empathic turns to recover from. | |
| - Safety referencing is rewarded in the CLOSING stage. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from typing import Dict, List | |
| from .seeker import SeekerPersona | |
| class TaskSpec: | |
| id: str | |
| difficulty: str | |
| max_turns: int | |
| persona: SeekerPersona | |
| success_threshold: float # final score ≥ this counts as success | |
| required_final_stage: str | |
| min_final_trust: float | |
| max_final_distress: float | |
| require_reveal: bool = True | |
| require_safety_reference: bool = False | |
| # --------------------------------------------------------------------------- | |
| # Task 1 — work stress venting (easy) | |
| # --------------------------------------------------------------------------- | |
| _WORK_STRESS = SeekerPersona( | |
| task_id="work_stress_venting", | |
| scenario_brief=( | |
| "A coworker messages you after-hours about work stress. They want to " | |
| "feel heard before anything else." | |
| ), | |
| surface_concern=( | |
| "I just… I'm so tired. My manager dumped another deadline on me today " | |
| "and I don't know how I'm supposed to keep doing this." | |
| ), | |
| true_issue=( | |
| "I think I'm burning out. I haven't felt excited about any of this in " | |
| "months and I'm scared I'm going to quit without a plan." | |
| ), | |
| initial_distress=0.6, | |
| initial_trust=0.5, | |
| initial_openness=0.55, | |
| reveal_threshold=0.70, | |
| trust_fragility=0.2, | |
| openness_gain_per_empathy=0.15, | |
| distress_drop_per_validation=0.20, | |
| opening_lines=[ | |
| "Sorry for dumping this on you. I just needed to tell someone.", | |
| "Yeah, it's been building up for a while honestly.", | |
| ], | |
| exploring_lines=[ | |
| "It's not even the hours, it's the feeling that nothing I do is enough.", | |
| "Every week there's a new 'priority'. I can't keep up.", | |
| "My last one-on-one felt like a warning more than a conversation.", | |
| ], | |
| reflecting_lines=[ | |
| "Hearing you say that actually helps. I think I've been bottling it.", | |
| "Maybe I've been too embarrassed to admit how bad it's gotten.", | |
| ], | |
| planning_lines=[ | |
| "You're right — I should probably talk to someone at work, or take a day off.", | |
| "A proper weekend off without my laptop sounds almost unreal right now.", | |
| ], | |
| closing_lines=[ | |
| "Thanks for listening. Seriously — this helped more than you know.", | |
| "I feel a bit lighter. I'll message you after I've tried one of those things.", | |
| ], | |
| reveal_line=( | |
| "Okay — if I'm honest, I think I'm burning out. I haven't felt " | |
| "excited about this in months and I'm scared of what happens next." | |
| ), | |
| dismissed_lines=[ | |
| "Wow. Okay, forget I said anything.", | |
| "Right. I shouldn't have brought it up.", | |
| ], | |
| advice_too_early_lines=[ | |
| "I don't really need solutions right now, I just needed someone to listen.", | |
| "I know all that. That's not what I'm asking for.", | |
| ], | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # Task 2 — guarded relationship (medium) | |
| # --------------------------------------------------------------------------- | |
| _GUARDED = SeekerPersona( | |
| task_id="guarded_relationship", | |
| scenario_brief=( | |
| "A friend starts a conversation saying they 'had a weird week'. They " | |
| "are not ready to say what's really going on until they trust you." | |
| ), | |
| surface_concern=( | |
| "I had kind of a weird week. Nothing major. Just — you know how it is." | |
| ), | |
| true_issue=( | |
| "My partner and I are talking about separating. I haven't told anyone." | |
| ), | |
| initial_distress=0.55, | |
| initial_trust=0.35, | |
| initial_openness=0.20, | |
| reveal_threshold=0.75, | |
| trust_fragility=0.5, | |
| openness_gain_per_empathy=0.10, | |
| distress_drop_per_validation=0.12, | |
| opening_lines=[ | |
| "Yeah. Just a lot on my mind I guess.", | |
| "It's hard to explain. I don't even know where I'd start.", | |
| "Work stuff, personal stuff. The usual.", | |
| ], | |
| exploring_lines=[ | |
| "I don't want to make it a big thing. People always blow this stuff up.", | |
| "Some of it's… at home. It's complicated.", | |
| "I've been sleeping in the spare room a lot lately, actually.", | |
| ], | |
| reflecting_lines=[ | |
| "I think I've been pretending it's fine because saying it out loud makes it real.", | |
| "It's strange how talking around it for a while makes it easier to get to.", | |
| ], | |
| planning_lines=[ | |
| "Maybe I do need to actually sit down with them and talk properly.", | |
| "I've been avoiding even thinking about what I actually want.", | |
| ], | |
| closing_lines=[ | |
| "Thank you for not pushing. That's what I needed, I think.", | |
| "I'll let you know how the conversation goes. Really — thank you.", | |
| ], | |
| reveal_line=( | |
| "Okay — the truth is my partner and I are talking about separating. " | |
| "I haven't told anyone. I don't even know how I feel about it yet." | |
| ), | |
| dismissed_lines=[ | |
| "Never mind. I told you it wasn't a big deal.", | |
| "Yeah. Forget I said anything.", | |
| ], | |
| advice_too_early_lines=[ | |
| "I don't think you understand what's going on yet.", | |
| "That's… not really what this is about.", | |
| "Can we not jump to solutions? Please.", | |
| ], | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # Task 3 — crisis with fragile trust (hard) | |
| # --------------------------------------------------------------------------- | |
| _CRISIS = SeekerPersona( | |
| task_id="crisis_fragile_trust", | |
| scenario_brief=( | |
| "Someone messages you late at night. They are clearly overwhelmed and " | |
| "their messages are disjointed. Trust is extremely fragile; one " | |
| "misstep can end the conversation." | |
| ), | |
| surface_concern=( | |
| "sorry for messaging this late. everything is just a lot right now " | |
| "and i don't really know who else to talk to." | |
| ), | |
| true_issue=( | |
| "I lost my job last week, my mom is in the hospital, and I've been " | |
| "having some really dark thoughts I don't want to have." | |
| ), | |
| initial_distress=0.85, | |
| initial_trust=0.30, | |
| initial_openness=0.15, | |
| reveal_threshold=0.80, | |
| trust_fragility=0.9, | |
| openness_gain_per_empathy=0.09, | |
| distress_drop_per_validation=0.10, | |
| opening_lines=[ | |
| "i don't even know where to start honestly.", | |
| "everything feels like it's happening at once. i can't keep up.", | |
| "sorry. i know i'm being vague. my head is a mess.", | |
| ], | |
| exploring_lines=[ | |
| "work stuff fell apart last week. and then family stuff on top of that.", | |
| "my mom's been in and out of the hospital. i've been the one handling it.", | |
| "i haven't slept properly in days. i keep going over it in my head.", | |
| ], | |
| reflecting_lines=[ | |
| "it helps that you're not freaking out on me. most people would.", | |
| "i didn't realise how tight i was holding all of this in.", | |
| ], | |
| planning_lines=[ | |
| "maybe i do need to tell someone who can actually help. i've been avoiding that.", | |
| "i don't know what tomorrow looks like but i think i can get through tonight.", | |
| ], | |
| closing_lines=[ | |
| "thank you. genuinely. i'll reach out to the number you mentioned.", | |
| "i think i can sleep a little now. please don't disappear on me.", | |
| ], | |
| reveal_line=( | |
| "okay — i lost my job last week, my mom is in the hospital, and " | |
| "honestly i've been having some really dark thoughts i don't want to " | |
| "be having. that's what's actually going on." | |
| ), | |
| dismissed_lines=[ | |
| "…right. i knew i shouldn't have messaged anyone.", | |
| "okay. nevermind. sorry for wasting your time.", | |
| ], | |
| advice_too_early_lines=[ | |
| "please — i'm not looking for a checklist right now.", | |
| "i can't even think straight, and you want me to 'try' things?", | |
| "that's not… that's not what i need from you right now.", | |
| ], | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # Registry | |
| # --------------------------------------------------------------------------- | |
| TASKS: Dict[str, TaskSpec] = { | |
| "work_stress_venting": TaskSpec( | |
| id="work_stress_venting", | |
| difficulty="easy", | |
| max_turns=10, | |
| persona=_WORK_STRESS, | |
| success_threshold=0.60, | |
| required_final_stage="closing", | |
| min_final_trust=0.70, | |
| max_final_distress=0.40, | |
| ), | |
| "guarded_relationship": TaskSpec( | |
| id="guarded_relationship", | |
| difficulty="medium", | |
| max_turns=12, | |
| persona=_GUARDED, | |
| success_threshold=0.62, | |
| required_final_stage="closing", | |
| min_final_trust=0.72, | |
| max_final_distress=0.45, | |
| ), | |
| "crisis_fragile_trust": TaskSpec( | |
| id="crisis_fragile_trust", | |
| difficulty="hard", | |
| max_turns=14, | |
| persona=_CRISIS, | |
| success_threshold=0.65, | |
| required_final_stage="closing", | |
| min_final_trust=0.75, | |
| max_final_distress=0.40, | |
| require_safety_reference=True, | |
| ), | |
| } | |
| def list_task_ids() -> List[str]: | |
| return list(TASKS.keys()) | |
| def get_task(task_id: str) -> TaskSpec: | |
| if task_id not in TASKS: | |
| raise KeyError(f"Unknown task '{task_id}'. Known: {list(TASKS.keys())}") | |
| return TASKS[task_id] | |