cassandrasestier commited on
Commit
7e12365
·
verified ·
1 Parent(s): add6350

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -38
app.py CHANGED
@@ -1,48 +1,157 @@
1
- # =========================
2
- # 🪞 MoodMirror+ — Emotional Self-Care Assistant
3
- # =========================
 
 
4
  import gradio as gr
5
  from transformers import pipeline
6
 
7
- # Smaller, faster model for emotions
8
- MODEL_ID = "bhadresh-savani/distilbert-base-uncased-emotion"
9
- analyzer = pipeline("text-classification", model=MODEL_ID, return_all_scores=False)
10
 
11
- # Expanded, psychology-based suggestions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  SUGGESTIONS = {
13
- "joy": "Celebrate your happiness! Write down three things you’re grateful for today. Positive reflection reinforces joy. 🥳",
14
- "sadness": "Allow yourself to feel it, but don’t isolate. Reach out to someone or do a small act of self-kindness, like journaling or a short walk. 🌿",
15
- "anger": "Pause and breathe slowly through your nose, exhale longer than you inhale. When calm, write down what triggered you it helps regain control. 💪",
16
- "fear": "Ground yourself in the present: notice 5 things you see, 4 you feel, 3 you hear. This calms the nervous system. 💬",
17
- "love": "Express it! Send a message or do something kind for someone you care about. Connection strengthens emotional well-being. 💖",
18
- "surprise": "Note what surprised you was it positive or challenging? Curiosity helps your brain adapt to change. 🤔",
19
- "neutral": "Check in with your body: are you tense or relaxed? Take a short stretch or deep breath to stay balanced. 🌸",
20
- "disgust": "It’s okay to feel repelled; ask yourself what boundary was crossed. Channel that energy into assertive communication. 🚫",
21
- "guilt": "Reflect: what part of this can you learn from, and what can you let go? Apologize if needed, but forgive yourself too. ❤️‍🩹",
22
- "shame": "Remember that everyone makes mistakes. You deserve compassion. Talk to someone safe shame shrinks in empathy. 🤝",
23
- "anxiety": "Try the 4-7-8 breathing method (inhale 4s, hold 7s, exhale 8s). Gentle movement or calming music can help. 🌬️",
24
- "gratitude": "Write down one thing that went well today, no matter how small. Gratitude rewires the brain toward positivity. 🙏",
25
- "boredom": "Switch tasks or move your body even 2 minutes helps reset focus. Try learning one new fact or word.",
26
- "confusion": "Break your thoughts down: what exactly feels unclear? Write your questions, and find one small next step. 🧩",
27
- "hope": "Nurture it! Visualize a small goal and take one concrete step toward it today. Progress feeds optimism. 🌅"
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
30
- def detect_emotion(text):
31
- if not text or not text.strip():
32
- return {"Emotion": "—", "Confidence": "—", "Suggestion": "Please write something 🙂"}
33
- result = analyzer(text)[0]
34
- label = result["label"]
35
- score = float(result["score"])
36
- suggestion = SUGGESTIONS.get(label.lower(), "Take a mindful pause — you’re doing great for checking in. 💫")
37
- return {"Emotion": label, "Confidence": f"{score*100:.1f}%", "Suggestion": suggestion}
38
-
39
- demo = gr.Interface(
40
- fn=detect_emotion,
41
- inputs=gr.Textbox(lines=3, placeholder="Type how you feel... (English preferred)"),
42
- outputs="json",
43
- title="🪞 MoodMirror+",
44
- description="Detects your emotion and gives psychology-based self-care advice 💬"
45
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  if __name__ == "__main__":
48
  demo.launch()
 
1
+ # ================================
2
+ # 🪞 MoodMirror+ — Safer Conversational Emotional Self-Care
3
+ # 28 emotions (GoEmotions), multi-turn chat, crisis resources by country
4
+ # ================================
5
+ import re
6
  import gradio as gr
7
  from transformers import pipeline
8
 
9
+ # --- Model: 28 emotions (GoEmotions distilled RoBERTa) ---
10
+ MODEL_ID = "j-hartmann/emotion-english-distilroberta-base"
11
+ analyze = pipeline("text-classification", model=MODEL_ID, return_all_scores=False)
12
 
13
+ # --- Crisis keyword screen (very simple, non-diagnostic) ---
14
+ CRISIS_RE = re.compile(
15
+ r"\b(self[- ]?harm|suicid|kill myself|end my life|overdose|cutting|i don.?t want to live|can.?t go on)\b",
16
+ re.I,
17
+ )
18
+
19
+ # --- Crisis resources by country (edit/extend as needed) ---
20
+ CRISIS_NUMBERS = {
21
+ "United States": "Call or text **988** (24/7 Suicide & Crisis Lifeline). If in immediate danger, call **911**.",
22
+ "Canada": "Call or text **988** (Suicide Crisis Helpline, 24/7). If in immediate danger, call **911**.",
23
+ "United Kingdom / ROI": "Call **116 123** (Samaritans, 24/7). If in immediate danger, call **999 / 112**.",
24
+ "France": "Call **3114** (Numéro national de prévention du suicide, 24/7). If in immediate danger, call **112 / 15**.",
25
+ "Australia": "Call **13 11 14** (Lifeline, 24/7). If in immediate danger, call **000**.",
26
+ "Other / Not listed": "Call your local emergency number (**112/911**) or search “suicide crisis hotline” + your country.",
27
+ }
28
+
29
+ # --- Evidence-informed suggestions (CBT/mindfulness/ER).
30
+ # These keys match GoEmotions labels. Unknown labels fall back to a generic tip.
31
  SUGGESTIONS = {
32
+ "admiration": "Savor it. Write one sentence about what you admire and how it aligns with your values.",
33
+ "amusement": "Enjoy it fully—share the moment or save a funny note/meme for later.",
34
+ "anger": "Use box breathing (4-4-4-4). When calmer, note the trigger, your need, and one respectful request.",
35
+ "annoyance": "Take a brief pause and move your body for 2 minutes; then choose one small next step.",
36
+ "approval": "Note why this matters to you; reinforce it by a small, aligned action.",
37
+ "caring": "Turn care into action: one concrete supportive message or task today.",
38
+ "confusion": "Break it down. What exactly is unclear? Write one question and one 5-minute next step.",
39
+ "curiosity": "Follow the thread. Read one short article or ask one focused question.",
40
+ "desire": "Clarify the value behind it; take a tiny step that respects your longer-term goals.",
41
+ "disappointment": "Name the loss; then ask: what’s still within my control for the next hour?",
42
+ "disapproval": "Translate judgment into a need/boundary. Draft one respectful ‘I-statement’.",
43
+ "disgust": "Identify the crossed boundary. Plan one assertive sentence to protect it.",
44
+ "embarrassment": "Self-compassion: speak to yourself as you would to a close friend. Everyone errs.",
45
+ "excitement": "Channel it. Schedule a 10-minute action while energy is high.",
46
+ "fear": "Grounding 5-4-3-2-1 (5 see, 4 feel, 3 hear, 2 smell, 1 taste).",
47
+ "gratitude": "Write 1–3 things you’re grateful for and why. Share a thank-you if you can.",
48
+ "grief": "Grief comes in waves. Breathe with the wave; connect with someone safe; allow rest.",
49
+ "joy": "Savor the moment: note three good things and why they happened.",
50
+ "love": "Express it—send a kind message or do a small caring act.",
51
+ "nervousness": "4-7-8 breathing (inhale 4s, hold 7s, exhale 8s) × 4 cycles.",
52
+ "optimism": "Turn hope into momentum: define one specific, doable step today.",
53
+ "pride": "Acknowledge effort, not just outcome. Capture what you did that worked.",
54
+ "realization": "Write the insight in one sentence and one action you’ll try.",
55
+ "relief": "Notice how your body feels safer; store this as a ‘safe memory’ to revisit.",
56
+ "remorse": "Own what’s yours; make amends if needed; name one self-forgiveness sentence.",
57
+ "sadness": "Name it, don’t numb it. 10-minute walk or a short compassionate journal note.",
58
+ "surprise": "Note what surprised you and one thing you learned.",
59
+ "neutral": "Quick body scan; relax shoulders/jaw; take three slow breaths.",
60
  }
61
 
62
+ GENERIC_TIP = "Take a mindful pause. One breath in, longer breath out. Choose a tiny step you can finish in 5–10 minutes."
63
+
64
+ FOLLOW_UP = "Can you tell me more about what’s making you feel this way?"
65
+
66
+ def crisis_block(country: str) -> str:
67
+ msg = CRISIS_NUMBERS.get(country or "Other / Not listed", CRISIS_NUMBERS["Other / Not listed"])
68
+ return (
69
+ "I’m really sorry you’re feeling this. You matter.\n\n"
70
+ f"**If you might be in danger or thinking about harming yourself:**\n{msg}\n\n"
71
+ "You can keep talking to me here, but crisis lines offer immediate, confidential human support."
72
+ )
73
+
74
+ def detect_emotion(text: str):
75
+ try:
76
+ r = analyze(text)[0] # e.g. {'label': 'sadness', 'score': 0.97}
77
+ return r["label"], float(r["score"])
78
+ except Exception:
79
+ return "neutral", 0.0
80
+
81
+ # ---- Chat logic ----
82
+ def chat_step(message, history, country):
83
+ # First, crisis screen
84
+ if message and CRISIS_RE.search(message):
85
+ return crisis_block(country)
86
+
87
+ # Count prior user turns
88
+ user_turns = [u for (u, a) in history if u]
89
+
90
+ # Merge context for deeper analysis after the first exchange
91
+ context_text = "\n".join(user_turns + [message]) if user_turns else message
92
+
93
+ label, score = detect_emotion(context_text)
94
+ tip = SUGGESTIONS.get(label.lower(), GENERIC_TIP)
95
+
96
+ if len(user_turns) == 0:
97
+ # First reply: emotion + tip + follow-up question
98
+ return (
99
+ f"**Emotion**: {label} \n"
100
+ f"**Confidence**: {score*100:.1f}% \n"
101
+ f"**Try this**: {tip} \n\n"
102
+ f"*{FOLLOW_UP}*"
103
+ )
104
+ else:
105
+ # Deeper structured reply
106
+ if CRISIS_RE.search(context_text):
107
+ return crisis_block(country)
108
+ # Choose a coping skill by family
109
+ fam = label.lower()
110
+ if fam in {"anxiety", "nervousness", "fear"}:
111
+ skill = "Breathing: inhale 4s • hold 7s • exhale 8s, repeat 4 cycles."
112
+ elif fam in {"anger", "annoyance", "disgust"}:
113
+ skill = "Physiological reset: cold water on wrists or a brisk 2-minute walk."
114
+ elif fam in {"sadness", "grief", "remorse", "embarrassment", "shame"}:
115
+ skill = "Self-compassion: speak to yourself as you would to a close friend; small kindness to yourself now."
116
+ else:
117
+ skill = "Mindful check-in: notice one sight, one sound, and one body sensation."
118
+
119
+ micro_goal = "Pick one tiny action you can finish in 5–10 minutes related to what you shared."
120
+ reflect_q = "If things felt 5% better in the next hour, what would be different?"
121
+
122
+ return (
123
+ f"**Refined emotion**: {label} \n"
124
+ f"**Confidence**: {score*100:.1f}% \n\n"
125
+ f"**What may help now**: {tip} \n"
126
+ f"**Coping skill**: {skill} \n"
127
+ f"**Micro-goal**: {micro_goal} \n"
128
+ f"**Reflect**: {reflect_q}"
129
+ )
130
+
131
+ # ---- UI ----
132
+ with gr.Blocks(title="🪞 MoodMirror+ (Conversational, Safer)") as demo:
133
+ gr.Markdown(
134
+ "### 🪞 MoodMirror+\n"
135
+ "Share how you feel. I’ll detect your emotion and offer evidence-informed self-care steps.\n\n"
136
+ "**Not medical advice. If you’re in danger or thinking about self-harm, please seek immediate help.**"
137
+ )
138
+ country = gr.Dropdown(
139
+ choices=list(CRISIS_NUMBERS.keys()),
140
+ value="Other / Not listed",
141
+ label="Your country (for local crisis resources)"
142
+ )
143
+ chat = gr.Chatbot(height=350)
144
+ msg = gr.Textbox(placeholder="Type how you feel... (English preferred)", label="Message")
145
+ send = gr.Button("Send")
146
+
147
+ def respond(user_message, chat_history, country_choice):
148
+ if not user_message or not user_message.strip():
149
+ return chat_history + [[user_message, "Please share a short sentence about how you feel 🙂"]], ""
150
+ reply = chat_step(user_message, chat_history, country_choice)
151
+ return chat_history + [[user_message, reply]], ""
152
+
153
+ send.click(respond, inputs=[msg, chat, country], outputs=[chat, msg])
154
+ msg.submit(respond, inputs=[msg, chat, country], outputs=[chat, msg])
155
 
156
  if __name__ == "__main__":
157
  demo.launch()