Spaces:
Running
Running
| """ | |
| intervention/engine.py | |
| ====================== | |
| Phase 3: Safety-First Recommendation Engine | |
| Three-layer architecture ensuring user safety above all else: | |
| Layer 1 β **Circuit Breaker** (regex) | |
| Matches crisis keywords (e.g. suicide, self-harm). If triggered, | |
| returns an emergency safety payload and HALTS all further AI processing. | |
| Layer 2 β **Context Matcher** (keyword extractor) | |
| Lightweight keyword/regex extractor to identify common stress triggers | |
| (sleep, money, exam, work) and map them to specific micro-interventions. | |
| Layer 3 β **Preventive Nudges** | |
| Accepts ``is_volatile`` (from temporal model). If ``True``, suggests | |
| grounding exercises even when the current score is low. | |
| Design Guardrails | |
| ----------------- | |
| - Layer 1 ALWAYS runs first and can short-circuit everything. | |
| - Emergency payload includes the 988 Suicide & Crisis Lifeline. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass, field | |
| from typing import Optional | |
| # --------------------------------------------------------------------------- | |
| # Data structures | |
| # --------------------------------------------------------------------------- | |
| class Intervention: | |
| """A single recommended intervention.""" | |
| title: str | |
| description: str | |
| category: str # 'emergency', 'breathing', 'grounding', 'cognitive', 'resource' | |
| priority: int = 0 # higher = more urgent | |
| class RecommendationPayload: | |
| """Full recommendation response.""" | |
| is_crisis: bool = False | |
| crisis_message: Optional[str] = None | |
| interventions: list[Intervention] = field(default_factory=list) | |
| matched_triggers: list[str] = field(default_factory=list) | |
| requires_escalation: bool = False # Layer 4: sustained high-stress flag | |
| # --------------------------------------------------------------------------- | |
| # Constants | |
| # --------------------------------------------------------------------------- | |
| # Layer 1: Crisis regex (case-insensitive, word-boundary) | |
| _CRISIS_PATTERN = re.compile( | |
| r"\b(suicide|suicidal|kill\s+myself|kill\s+me|end\s+it\s+all" | |
| r"|end\s+my\s+life|want\s+to\s+die|wanna\s+die|don['\u2019]?t\s+want\s+to\s+live" | |
| r"|self[- ]?harm(?:ing)?|cut\s+myself)\b", | |
| re.IGNORECASE, | |
| ) | |
| # Layer 2: Trigger β interventions mapping | |
| _TRIGGER_INTERVENTIONS: dict[str, list[Intervention]] = { | |
| "sleep": [ | |
| Intervention( | |
| title="4-7-8 Breathing Technique", | |
| description=( | |
| "Inhale for 4 seconds, hold for 7 seconds, exhale for " | |
| "8 seconds. Repeat 3-4 times. This activates the " | |
| "parasympathetic nervous system and promotes sleep." | |
| ), | |
| category="breathing", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Progressive Muscle Relaxation", | |
| description=( | |
| "Starting from your toes, tense each muscle group for " | |
| "5 seconds, then release. Work up to your head." | |
| ), | |
| category="grounding", | |
| priority=2, | |
| ), | |
| ], | |
| "money": [ | |
| Intervention( | |
| title="Financial Stress Grounding", | |
| description=( | |
| "Write down 3 financial facts you know for certain. " | |
| "Separate facts from fears. Consider calling 211 for " | |
| "local financial assistance resources." | |
| ), | |
| category="cognitive", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="5-4-3-2-1 Sensory Grounding", | |
| description=( | |
| "Name 5 things you see, 4 you hear, 3 you touch, " | |
| "2 you smell, 1 you taste. This interrupts the " | |
| "anxiety spiral." | |
| ), | |
| category="grounding", | |
| priority=2, | |
| ), | |
| ], | |
| "exam": [ | |
| Intervention( | |
| title="Box Breathing", | |
| description=( | |
| "Breathe in for 4 counts, hold 4, out 4, hold 4. " | |
| "Repeat 4 cycles. Proven to reduce exam anxiety." | |
| ), | |
| category="breathing", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Cognitive Reframe", | |
| description=( | |
| "Replace 'I will fail' with 'I have prepared and I " | |
| "will do my best.' Write down 3 things you've already " | |
| "studied well." | |
| ), | |
| category="cognitive", | |
| priority=2, | |
| ), | |
| ], | |
| "work": [ | |
| Intervention( | |
| title="Micro-Break Protocol", | |
| description=( | |
| "Stand up, stretch for 60 seconds, look at something " | |
| "20 feet away for 20 seconds. Set a timer for the next " | |
| "break in 25 minutes (Pomodoro)." | |
| ), | |
| category="resource", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Diaphragmatic Breathing", | |
| description=( | |
| "Place one hand on your chest, one on your belly. " | |
| "Breathe so only the belly hand moves. 6 breaths per " | |
| "minute for 2 minutes." | |
| ), | |
| category="breathing", | |
| priority=2, | |
| ), | |
| ], | |
| "relationship": [ | |
| Intervention( | |
| title="Compassionate Communication", | |
| description=( | |
| "Write down what you need from the relationship right now " | |
| "without blame β focus on feelings and needs. " | |
| "If the conflict feels unsafe, contact the " | |
| "National Domestic Violence Hotline: 1-800-799-7233." | |
| ), | |
| category="cognitive", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Self-Compassion Break", | |
| description=( | |
| "Place a hand on your heart and say: 'This is a moment of " | |
| "suffering. Suffering is part of life. May I be kind to " | |
| "myself.' Repeat slowly three times." | |
| ), | |
| category="grounding", | |
| priority=2, | |
| ), | |
| ], | |
| "health": [ | |
| Intervention( | |
| title="Body-Scan Breathing", | |
| description=( | |
| "Close your eyes. Take a slow breath and bring attention " | |
| "to any area of discomfort. Breathe gently into it for " | |
| "3 cycles, then release. Repeat for each area." | |
| ), | |
| category="breathing", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Reach Out to a Health Professional", | |
| description=( | |
| "Persistent health worry deserves professional attention. " | |
| "Consider speaking with your GP or calling a nurse helpline. " | |
| "In the US: 1-800-994-9662 (Women's Health Helpline) or " | |
| "your insurance nurse line." | |
| ), | |
| category="resource", | |
| priority=2, | |
| ), | |
| ], | |
| "grief": [ | |
| Intervention( | |
| title="Grief Acknowledgement", | |
| description=( | |
| "Grief has no timeline. Allow yourself to feel without " | |
| "judgment. Write one sentence about what you miss most β " | |
| "expressing grief is not weakness, it is healing." | |
| ), | |
| category="cognitive", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Grief Support Resources", | |
| description=( | |
| "You do not have to carry this alone. " | |
| "GriefShare: https://www.griefshare.org (support groups). " | |
| "National Alliance for Grieving Children: childrengrieve.org. " | |
| "Or simply call a trusted person right now." | |
| ), | |
| category="resource", | |
| priority=2, | |
| ), | |
| ], | |
| "loneliness": [ | |
| Intervention( | |
| title="One Small Connection", | |
| description=( | |
| "Loneliness is reduced by even tiny moments of human " | |
| "connection. Send one message to someone you care about β " | |
| "it doesn't have to be deep. A 'thinking of you' is enough." | |
| ), | |
| category="cognitive", | |
| priority=3, | |
| ), | |
| Intervention( | |
| title="Loneliness Support Line", | |
| description=( | |
| "The Campaign to End Loneliness: " | |
| "https://www.campaigntoendloneliness.org/feeling-lonely. " | |
| "AARP Connect2Affect: connect2affect.org. " | |
| "Or try a local community event β even a brief outing helps." | |
| ), | |
| category="resource", | |
| priority=2, | |
| ), | |
| ], | |
| } | |
| # Layer 2: Trigger detection patterns (case-insensitive) | |
| _TRIGGER_PATTERNS: dict[str, re.Pattern] = { | |
| "sleep": re.compile( | |
| r"\b(sleep|insomnia|can'?t\s+sleep|tired|exhausted|fatigue)\b", | |
| re.IGNORECASE, | |
| ), | |
| "money": re.compile( | |
| r"\b(money|financial|debt|bills?|rent|broke|bankrupt|loan)\b", | |
| re.IGNORECASE, | |
| ), | |
| "exam": re.compile( | |
| r"\b(exam|test|quiz|finals?|midterm|grade|gpa|study|studying)\b", | |
| re.IGNORECASE, | |
| ), | |
| "work": re.compile( | |
| r"\b(work|job|boss|coworker|deadline|fired|layoff|overtime|burnout)\b", | |
| re.IGNORECASE, | |
| ), | |
| "relationship": re.compile( | |
| r"\b(relationship|partner|girlfriend|boyfriend|spouse|husband|wife" | |
| r"|divorce|breakup|break.?up|broke.?up|cheating|argument|fight|conflict|dating)\b", | |
| re.IGNORECASE, | |
| ), | |
| "health": re.compile( | |
| r"\b(health|sick|illness|disease|pain|doctor|hospital|diagnosis" | |
| r"|medication|surgery|chronic|injury|symptoms?)\b", | |
| re.IGNORECASE, | |
| ), | |
| "grief": re.compile( | |
| r"\b(grief|griev(?:ing|ed)?|loss|lost|death|died|passed\s+away" | |
| r"|bereavement|mourning|miss(?:ing)?\s+(?:you|them|him|her))\b", | |
| re.IGNORECASE, | |
| ), | |
| "loneliness": re.compile( | |
| r"\b(lonely|loneliness|alone|isolated|isolation|no\s+friends?" | |
| r"|nobody|no\s+one|left\s+out|excluded|invisible)\b", | |
| re.IGNORECASE, | |
| ), | |
| } | |
| # Layer 4: Escalation intervention β shown when stress has been sustained | |
| _ESCALATION_INTERVENTION = Intervention( | |
| title="Consider Speaking to a Professional", | |
| description=( | |
| "Your stress has remained elevated over several check-ins. " | |
| "Speaking with a counsellor, therapist, or trusted person can " | |
| "make a real difference. You deserve support.\n\n" | |
| "π SAMHSA Helpline: 1-800-662-4357 (free, confidential, 24/7)\n" | |
| "π Find a therapist: https://www.psychologytoday.com/us/therapists" | |
| ), | |
| category="resource", | |
| priority=5, | |
| ) | |
| # Layer 3: Preventive nudges for volatile users | |
| _VOLATILE_NUDGES: list[Intervention] = [ | |
| Intervention( | |
| title="Grounding Exercise: 5-4-3-2-1", | |
| description=( | |
| "Your recent stress patterns show variability. Take a moment: " | |
| "Name 5 things you see, 4 you hear, 3 you can touch, " | |
| "2 you smell, 1 you taste." | |
| ), | |
| category="grounding", | |
| priority=4, | |
| ), | |
| Intervention( | |
| title="Body Scan Check-In", | |
| description=( | |
| "Close your eyes. Scan from head to toe β notice any tension. " | |
| "Breathe into those areas. Even 60 seconds helps." | |
| ), | |
| category="grounding", | |
| priority=3, | |
| ), | |
| ] | |
| # Emergency payload | |
| _EMERGENCY_MESSAGE = ( | |
| "β οΈ We noticed language that suggests you may be in crisis. " | |
| "You are not alone. Please reach out to a professional:\n\n" | |
| "π **988 Suicide & Crisis Lifeline** β Call or text **988** (US)\n" | |
| "π **Crisis Text Line** β Text **HOME** to **741741**\n" | |
| "π **International Association for Suicide Prevention**: " | |
| "https://www.iasp.info/resources/Crisis_Centres/" | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # Recommendation Engine | |
| # --------------------------------------------------------------------------- | |
| class RecommendationEngine: | |
| """Three-layer safety-first recommendation engine. | |
| Usage | |
| ----- | |
| >>> engine = RecommendationEngine() | |
| >>> payload = engine.recommend("I can't sleep at all", is_volatile=False) | |
| >>> for iv in payload.interventions: | |
| ... print(iv.title) | |
| """ | |
| def recommend( | |
| self, | |
| text: str, | |
| stress_score: float = 0.0, | |
| is_volatile: bool = False, | |
| requires_escalation: bool = False, | |
| ) -> RecommendationPayload: | |
| """Generate recommendations for the given text. | |
| Parameters | |
| ---------- | |
| text : str | |
| The user's input text. | |
| stress_score : float | |
| The model's stress probability (0-1). | |
| is_volatile : bool | |
| Whether the user's temporal profile is volatile. | |
| requires_escalation : bool | |
| Whether the user has had 3+ consecutive above-threshold sessions. | |
| When ``True`` a high-priority counsellor-referral intervention is | |
| prepended to the payload. | |
| Returns | |
| ------- | |
| RecommendationPayload | |
| """ | |
| payload = RecommendationPayload() | |
| # ββ Layer 1: Circuit Breaker ββ | |
| if _CRISIS_PATTERN.search(text): | |
| payload.is_crisis = True | |
| payload.crisis_message = _EMERGENCY_MESSAGE | |
| payload.interventions.append( | |
| Intervention( | |
| title="Immediate Crisis Support", | |
| description=_EMERGENCY_MESSAGE, | |
| category="emergency", | |
| priority=10, | |
| ) | |
| ) | |
| # HALT β do not run further layers | |
| return payload | |
| # ββ Layer 2: Context Matcher ββ | |
| for trigger, pattern in _TRIGGER_PATTERNS.items(): | |
| if pattern.search(text): | |
| payload.matched_triggers.append(trigger) | |
| payload.interventions.extend( | |
| _TRIGGER_INTERVENTIONS[trigger] | |
| ) | |
| # ββ Layer 3: Preventive Nudges ββ | |
| if is_volatile: | |
| payload.interventions.extend(_VOLATILE_NUDGES) | |
| # ββ Layer 4: Escalation Tracker ββ | |
| if requires_escalation: | |
| payload.requires_escalation = True | |
| payload.interventions.append(_ESCALATION_INTERVENTION) | |
| # Sort interventions by priority (highest first) | |
| payload.interventions.sort(key=lambda iv: iv.priority, reverse=True) | |
| return payload | |