Shresthh03 commited on
Commit
08d3ef2
·
verified ·
1 Parent(s): 3650e12

Update it all .

Browse files
Files changed (1) hide show
  1. app.py +164 -396
app.py CHANGED
@@ -1,407 +1,175 @@
 
 
1
  import os
2
- import json
3
- import re
4
  import random
5
- import datetime
6
- from flask import Flask, request, jsonify, send_from_directory
7
-
8
- # Optional libraries - loaded if available
9
- try:
10
- import openai
11
- OPENAI_AVAILABLE = bool(os.environ.get("OPENAI_API_KEY"))
12
- if OPENAI_AVAILABLE:
13
- openai.api_key = os.environ.get("OPENAI_API_KEY")
14
- except Exception:
15
- OPENAI_AVAILABLE = False
16
-
17
- # Try to load HF emotion model (optional, may be large)
18
- try:
19
- from transformers import pipeline
20
- HF_AVAILABLE = True
21
- except Exception:
22
- HF_AVAILABLE = False
23
-
24
- emotion_model = None
25
- if HF_AVAILABLE:
26
- try:
27
- emotion_model = pipeline("text-classification", model="j-hartmann/emotion-english-distilroberta-base", top_k=5)
28
- except Exception:
29
- emotion_model = None
30
-
31
- app = Flask(__name__, static_folder=".", static_url_path="/")
32
-
33
- # Memory file
34
- MEMORY_FILE = "session_memory.json"
35
- MEMORY_KEEP_DAYS = 15
36
-
37
- # Crisis keywords and helplines
38
- CRISIS_KEYWORDS = [
39
- "suicide", "kill myself", "end my life", "want to die", "hurt myself", "i'm going to die",
40
- "i want to die", "i cant go on", "can't go on"
41
- ]
42
- HELPLINES = {
43
- "US": "USA: Call or text 988 (Suicide & Crisis Lifeline)",
44
- "IN": "India: AASRA Helpline +91-9820466726",
45
- "GB": "UK: Samaritans 116 123",
46
- "CA": "Canada: Talk Suicide Canada 1-833-456-4566",
47
- "AU": "Australia: Lifeline 13 11 14",
48
- "DEFAULT": "If you're in immediate danger, contact local emergency services or search for a local helpline."
49
- }
50
-
51
- # Personalities -> small descriptor (informs OpenAI prompt if used)
52
- PERSONA_TEXT = {
53
- "calm": "Calm, grounding, gentle friend.",
54
- "friendly": "Warm, slightly chatty and encouraging friend.",
55
- "deep": "Reflective, thoughtful, soulful friend.",
56
- "spiritual": "Peaceful, nurturing, mindful tone.",
57
- "neutral": "Balanced, non-gendered, soothing voice."
58
- }
59
-
60
- # Utility: load & save memory
61
- def load_memory():
62
- if os.path.exists(MEMORY_FILE):
63
- try:
64
- with open(MEMORY_FILE, "r") as f:
65
- data = json.load(f)
66
- except Exception:
67
- data = {}
68
  else:
69
- data = {}
70
- # prune entries older than MEMORY_KEEP_DAYS
71
- cutoff = datetime.datetime.utcnow() - datetime.timedelta(days=MEMORY_KEEP_DAYS)
72
- good = {}
73
- for k, v in data.items():
74
- try:
75
- t = datetime.datetime.fromisoformat(v.get("last_seen"))
76
- if t >= cutoff:
77
- good[k] = v
78
- except Exception:
79
- good[k] = v
80
- return good
81
-
82
- def save_memory(mem):
83
- with open(MEMORY_FILE, "w") as f:
84
- json.dump(mem, f, indent=2)
85
-
86
- memory = load_memory()
87
-
88
- # Small NLP helpers
89
- def extract_name(text):
90
- text = text.strip()
91
- patterns = [
92
- r"^(?:i am|i'm|im|i’m)\s+([A-Za-z][A-Za-z'\- ]{1,40})",
93
- r"my name is\s+([A-Za-z][A-Za-z'\- ]{1,40})",
94
- r"^([A-Z][a-z]{1,30})$"
95
  ]
96
- for p in patterns:
97
- m = re.search(p, text, flags=re.IGNORECASE)
98
- if m:
99
- name = m.group(1).strip()
100
- return " ".join([w.capitalize() for w in name.split()])
101
- return None
102
-
103
- def extract_age(text):
104
- nums = re.findall(r"\b([1-9][0-9]?)\b", text)
105
- for n in nums:
106
- val = int(n)
107
- if 8 <= val <= 120:
108
- return val
109
- return None
110
-
111
- def detect_crisis(text):
112
- t = text.lower()
113
- return any(kw in t for kw in CRISIS_KEYWORDS)
114
-
115
- def get_helpline_by_ip(ip):
116
- # best-effort via ipapi.co (may fail); fallback to DEFAULT
117
- try:
118
- import requests
119
- if ip and ":" not in ip:
120
- url = f"https://ipapi.co/{ip}/json/"
121
- else:
122
- url = "https://ipapi.co/json/"
123
- r = requests.get(url, timeout=2)
124
- if r.status_code == 200:
125
- data = r.json()
126
- code = data.get("country_code", "").upper()
127
- return HELPLINES.get(code, HELPLINES["DEFAULT"])
128
- except Exception:
129
- pass
130
- return HELPLINES["DEFAULT"]
131
-
132
- def classify_emotion(text):
133
- # first attempt HF model if available
134
- if emotion_model:
135
- try:
136
- out = emotion_model(text)
137
- # pipeline returns list or list-of-lists. Get top label.
138
- first = out[0]
139
- if isinstance(first, list):
140
- label = first[0]["label"]
141
- else:
142
- label = first["label"]
143
- return label.lower()
144
- except Exception:
145
- pass
146
- # fallback keywords
147
- low = text.lower()
148
- if any(w in low for w in ["happy","glad","joy","great","good","awesome","yay"]):
149
- return "joy"
150
- if any(w in low for w in ["sad","down","depress","lonely","cry","unhappy"]):
151
- return "sadness"
152
- if any(w in low for w in ["angry","mad","furious","annoy"]):
153
- return "anger"
154
- if any(w in low for w in ["scared","afraid","anxious","panic","worried"]):
155
- return "fear"
156
- if any(w in low for w in ["love","loving","fond","cherish"]):
157
- return "love"
158
- return "neutral"
159
-
160
- # Intent detection simple rules
161
- def detect_intent(text):
162
- t = text.lower()
163
- if detect_crisis(t):
164
- return "CRISIS"
165
- if any(q in t for q in ["how are you","how're you","how you doing","are you okay","are you mad","you okay","are you fine"]):
166
- return "ASK_BOT"
167
- if any(w in t for w in ["motivate","motivation","guidance","inspire","give me guidance","need motivation"]):
168
- return "REQUEST_MOTIVATION"
169
- if any(w in t for w in ["lol","haha","jk","dude","bro","have you gone","are you mad?","you mad"]):
170
- return "CASUAL"
171
- if any(w in t for w in ["sad","down","depressed","anxious","anxiety","lonely","suicidal","hurt myself"]):
172
- return "SUPPORT"
173
- if len(t.split()) <= 6:
174
- return "CASUAL"
175
- return "SUPPORT"
176
-
177
- # Non repetitive picks
178
- def pick_nonrep(slot, choices):
179
- recent = slot.get("recent", [])
180
- options = [c for c in choices if c not in recent]
181
- if not options:
182
- slot["recent"] = []
183
- options = choices[:]
184
- pick = random.choice(options)
185
- slot.setdefault("recent", []).insert(0, pick)
186
- slot["recent"] = slot["recent"][:8]
187
- return pick
188
-
189
- # Templates
190
- CASUAL_TEMPLATES = [
191
- "Haha — you got me! What's up?",
192
- "I’m here for that laugh and also for the real talk. Tell me more.",
193
- "LOL — I might be a little wired, but I’m listening. Go on.",
194
- "Okay that’s funny — but seriously, how are you?"
195
- ]
196
- SUPPORT_OPENERS = [
197
- "That sounds really heavy — thank you for sharing that with me.",
198
- "I can feel how much that means. I'm here with you.",
199
- "That must be hard — I'm listening and I care.",
200
- "You did well telling me that. Would you like to tell me more?"
201
- ]
202
- SUPPORT_FOLLOWUPS = [
203
- "Would you like a calming exercise or some small practical steps?",
204
- "How has this been affecting your daily life recently?",
205
- "What helps you even a little when you feel like that?"
206
- ]
207
- MOTIVATIONAL = [
208
- "Even small steps matter — you don't have to fix everything at once.",
209
- "You’ve made it this far; that already shows strength.",
210
- "Rest is allowed. Healing isn't a straight line.",
211
- "Breath by breath — keep going."
212
- ]
213
- BOT_SELF_REPLIES = [
214
- "I’m doing well — glad to be here with you. How are you?",
215
- "Feeling calm and ready to listen — how about you?",
216
- "I’m okay! My favorite thing is talking with you. How are you doing?"
217
- ]
218
-
219
- # OpenAI reply wrapper (if available)
220
- def openai_reply(user_text, persona_desc, session_slot):
221
- if not OPENAI_AVAILABLE:
222
- return None
223
  try:
224
- system = f"You are Serenity, {persona_desc} Respond empathetically, avoid repeating the same short phrase, be human and varied."
225
- messages = [
226
- {"role":"system","content":system},
227
- {"role":"user","content":user_text}
228
- ]
229
- resp = openai.ChatCompletion.create(
230
- model = os.environ.get("OPENAI_MODEL", "gpt-4o-mini"),
231
- messages = messages,
232
- temperature = 0.8,
233
- max_tokens = 300,
234
- n = 1
235
  )
236
- return resp.choices[0].message.content.strip()
237
- except Exception:
238
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
 
240
- # Main /chat endpoint
241
- @app.route("/chat", methods=["POST"])
242
- def chat():
243
- data = request.get_json() or {}
244
- session = data.get("session") or request.remote_addr or "default"
245
- message = (data.get("message") or "").strip()
246
- personality = data.get("personality") or data.get("voice_profile") or "neutral"
247
- init_flag = bool(data.get("init", False))
248
-
249
- # ensure session slot
250
- slot = memory.get(session, {})
251
- if not slot:
252
- slot = {"name": None, "age": None, "last_mood": None, "last_seen": datetime.datetime.utcnow().isoformat(), "recent": [], "history": []}
253
-
254
- # init greeting logic (frontend uses init to fetch greeting)
255
- if init_flag:
256
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
257
- memory[session] = slot
258
- save_memory(memory)
259
- if not slot.get("name"):
260
- return jsonify({"reply":"Hey — I'm Serenity. What’s your name?", "emotion":"calm", "intent":"INIT"})
261
- else:
262
- last_mood = slot.get("last_mood")
263
- last_seen = slot.get("last_seen")
264
- try:
265
- t = datetime.datetime.fromisoformat(last_seen)
266
- if last_mood in ("sadness","anger","fear") and (datetime.datetime.utcnow() - t).days <= MEMORY_KEEP_DAYS:
267
- return jsonify({"reply":f"Hey {slot.get('name')}, I remember you were having a tough time last session. How are you today?", "emotion":"warm", "intent":"FOLLOWUP"})
268
- except Exception:
269
- pass
270
- return jsonify({"reply":f"Welcome back {slot.get('name','friend')} — I'm here for you. What's on your mind?", "emotion":"calm", "intent":"INIT"})
271
-
272
- if not message:
273
- return jsonify({"reply":"I’m here whenever you’re ready to share — anything on your mind?", "emotion":"neutral", "intent":"NONE"})
274
-
275
- # If awaiting name/age flows (simple)
276
- awaiting = slot.get("awaiting")
277
- if not slot.get("name") and not awaiting:
278
- # try to extract name from message
279
- nm = extract_name(message)
280
- if nm:
281
- slot["name"] = nm
282
- slot["awaiting"] = "age"
283
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
284
- memory[session] = slot
285
- save_memory(memory)
286
- return jsonify({"reply":f"Lovely to meet you, {nm}! How old are you?", "emotion":"curious", "intent":"ASK_AGE"})
287
- else:
288
- slot["awaiting"] = "name"
289
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
290
- memory[session] = slot
291
- save_memory(memory)
292
- return jsonify({"reply":"Hey — what should I call you? What's your name?", "emotion":"calm", "intent":"ASK_NAME"})
293
-
294
- if awaiting == "name":
295
- guessed = extract_name(message) or message.split()[0].capitalize()
296
- slot["name"] = guessed
297
- slot.pop("awaiting", None)
298
- slot["awaiting"] = "age"
299
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
300
- memory[session] = slot
301
- save_memory(memory)
302
- return jsonify({"reply":f"Nice to meet you, {guessed}! How old are you?", "emotion":"curious", "intent":"ASK_AGE"})
303
-
304
- if awaiting == "age":
305
- age = extract_age(message)
306
- if age:
307
- slot["age"] = age
308
- slot.pop("awaiting", None)
309
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
310
- memory[session] = slot
311
- save_memory(memory)
312
- return jsonify({"reply":f"Thanks — got it. {slot.get('name')}, how have you been feeling lately?", "emotion":"curious", "intent":"ASK_MOOD"})
313
- else:
314
- return jsonify({"reply":"Could you tell me your age as a number (for example: 24)?", "emotion":"neutral", "intent":"ASK_AGE"})
315
-
316
- # Crisis detection
317
- if detect_crisis(message):
318
- helpline = get_helpline_by_ip(request.remote_addr)
319
- slot["last_mood"] = "crisis"
320
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
321
- memory[session] = slot
322
- save_memory(memory)
323
- reply = (f"I’m really concerned about how you're feeling. You are not alone. "
324
- f"Please consider contacting emergency services or this helpline: {helpline}")
325
- return jsonify({"reply":reply, "emotion":"crisis", "intent":"CRISIS"})
326
-
327
- # Normal flow: detect intent & emotion
328
- intent = detect_intent(message)
329
- emotion = classify_emotion(message)
330
-
331
- # Behavior by intent
332
- # 1) Asking about bot -> casual short human reply then pivot to user
333
- if intent == "ASK_BOT":
334
- bot_line = random.choice(BOT_SELF_REPLIES := BOT_SELF_REPLIES if 'BOT_SELF_REPLIES' in globals() else [
335
- "I’m doing well — glad to be here with you.",
336
- "Feeling calm and ready to listen — how about you?",
337
- "I’m okay! Just happy we’re chatting. How are you?"
338
- ])
339
- pivot = random.choice(["How are you doing right now?", "And how about you?"])
340
- reply = f"{bot_line} {pivot}"
341
- slot["last_mood"] = emotion
342
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
343
- memory[session] = slot
344
- save_memory(memory)
345
- return jsonify({"reply": reply, "emotion": emotion, "intent": intent})
346
-
347
- # 2) Casual -> friendly replies
348
- if intent == "CASUAL":
349
- reply = openai_reply(message, PERSONA_TEXT.get(personality, "friendly"), slot) if OPENAI_AVAILABLE else None
350
- if not reply or reply.strip().lower() in ("i understand","i see","okay"):
351
- reply = pick_nonrep(slot, CASUAL_TEMPLATES)
352
- slot["last_mood"] = emotion
353
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
354
- slot.setdefault("history", []).append({"in": message, "out": reply, "time": slot["last_seen"], "intent": intent})
355
- memory[session] = slot
356
- save_memory(memory)
357
- return jsonify({"reply": reply, "emotion": emotion, "intent": intent})
358
-
359
- # 3) Request motivation
360
- if intent == "REQUEST_MOTIVATION":
361
- reply = pick_nonrep(slot, MOTIVATIONAL)
362
- slot["last_mood"] = emotion
363
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
364
- memory[session] = slot
365
- save_memory(memory)
366
- return jsonify({"reply": reply, "emotion": emotion, "intent": intent})
367
-
368
- # 4) Support mode (default)
369
- # Attempt OpenAI for the best reply
370
- reply = None
371
- if OPENAI_AVAILABLE:
372
- reply = openai_reply(message, PERSONA_TEXT.get(personality, ""), slot)
373
- if not reply:
374
- opener = pick_nonrep(slot, SUPPORT_OPENERS)
375
- follow = pick_nonrep(slot, SUPPORT_FOLLOWUPS)
376
- if random.random() < 0.35:
377
- reply = f"{opener} {random.choice(MOTIVATIONAL)} {follow}"
378
- else:
379
- reply = f"{opener} {follow}"
380
-
381
- # store and return
382
- slot["last_mood"] = emotion
383
- slot["last_seen"] = datetime.datetime.utcnow().isoformat()
384
- slot.setdefault("history", []).append({"in": message, "out": reply, "time": slot["last_seen"], "intent": intent})
385
- memory[session] = slot
386
- save_memory(memory)
387
-
388
- return jsonify({"reply": reply, "emotion": emotion, "intent": intent})
389
-
390
- # Reset session endpoint
391
- @app.route("/reset_session", methods=["POST"])
392
- def reset_session():
393
- data = request.get_json() or {}
394
- session = data.get("session")
395
- if session and session in memory:
396
- memory.pop(session, None)
397
- save_memory(memory)
398
- return jsonify({"ok": True})
399
-
400
- # Serve frontend (index.html)
401
  @app.route("/")
402
  def index():
403
- return send_from_directory(".", "index.html")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
 
405
  if __name__ == "__main__":
406
- port = int(os.environ.get("PORT", 7860))
407
- app.run(host="0.0.0.0", port=port)
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
  import os
4
+ import openai
 
5
  import random
6
+ from transformers import pipeline
7
+ from datetime import datetime, timedelta
8
+ import json
9
+
10
+ app = Flask(__name__)
11
+ CORS(app)
12
+
13
+ # ======================
14
+ # 🔐 CONFIGURATION
15
+ # ======================
16
+ openai.api_key = os.getenv("OPENAI_API_KEY")
17
+
18
+ # Emotion detection model
19
+ emotion_analyzer = pipeline(
20
+ "text-classification",
21
+ model="j-hartmann/emotion-english-distilroberta-base",
22
+ top_k=None
23
+ )
24
+
25
+ # Temporary in-memory user data (can be saved to file if needed)
26
+ USER_MEMORY = {}
27
+
28
+ # ======================
29
+ # 🎭 UTILITIES
30
+ # ======================
31
+
32
+ def detect_intent(text):
33
+ """Detect if user wants emotional support or factual info."""
34
+ question_words = ["what", "how", "why", "when", "who", "explain", "tell me", "define", "where"]
35
+ if any(word in text.lower() for word in question_words):
36
+ return "knowledge"
37
+ return "support"
38
+
39
+
40
+ def analyze_emotion(text):
41
+ """Analyze emotion using Hugging Face model."""
42
+ result = emotion_analyzer(text)[0]
43
+ top_emotion = max(result, key=lambda x: x['score'])['label']
44
+ return top_emotion
45
+
46
+
47
+ def get_supportive_prompt(emotion, user_name, last_mood=None):
48
+ """Builds empathetic response prompt."""
49
+ mood_followups = [
50
+ f"{user_name}, I remember last time you were feeling {last_mood}. How have you been since then?",
51
+ f"Hey {user_name}, how’s your heart today?",
52
+ f"It’s good to see you again, {user_name}. How are you holding up?",
53
+ ]
54
+
55
+ sympathy_openers = [
56
+ "That sounds really tough.",
57
+ "I can sense there’s a lot on your mind.",
58
+ "You’re doing your best, and that already means a lot.",
59
+ "I’m here with you right now, and I care about what you’re going through."
60
+ ]
61
+
62
+ prompt = random.choice(sympathy_openers)
63
+
64
+ if last_mood:
65
+ prompt += " " + random.choice(mood_followups)
 
 
 
66
  else:
67
+ prompt += " How have you been feeling lately?"
68
+
69
+ return prompt
70
+
71
+
72
+ def generate_response(intent, user_name, text, last_mood=None):
73
+ """Main logic for generating AI replies."""
74
+ if intent == "knowledge":
75
+ # Friendly factual tone
76
+ system_prompt = (
77
+ "You are Serenity, a calm and intelligent emotional support companion. "
78
+ "If user asks factual questions, explain them simply and clearly in a friendly tone. "
79
+ "Then, connect gently to emotion — e.g., ‘That’s fascinating! What made you curious about that?’"
80
+ )
81
+ else:
82
+ # Emotional support tone
83
+ system_prompt = (
84
+ "You are Serenity, a compassionate emotional support friend. "
85
+ "Offer empathy, ask caring questions, validate feelings, and use varied, natural language. "
86
+ "Avoid repeating the same phrases like 'I'm sorry to hear that'."
87
+ )
88
+
89
+ # Compose conversation context
90
+ messages = [
91
+ {"role": "system", "content": system_prompt},
92
+ {"role": "user", "content": text}
93
  ]
94
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  try:
96
+ response = openai.ChatCompletion.create(
97
+ model="gpt-4o-mini",
98
+ messages=messages,
99
+ temperature=0.9,
100
+ max_tokens=200
 
 
 
 
 
 
101
  )
102
+ ai_reply = response.choices[0].message["content"].strip()
103
+ except Exception as e:
104
+ ai_reply = f"Oops — I ran into an issue while thinking. ({e})"
105
+
106
+ return ai_reply
107
+
108
+
109
+ def get_helpline_info(country="IN"):
110
+ """Return suicide helpline information based on country."""
111
+ helplines = {
112
+ "IN": "AASRA Helpline (India): 91-9820466726",
113
+ "US": "National Suicide Prevention Lifeline (US): 988",
114
+ "UK": "Samaritans (UK): 116 123",
115
+ "CA": "Talk Suicide Canada: 1-833-456-4566",
116
+ "AU": "Lifeline Australia: 13 11 14"
117
+ }
118
+ return helplines.get(country, "If you’re in danger, please reach your local emergency services.")
119
+
120
+
121
+ # ======================
122
+ # 💬 API ENDPOINTS
123
+ # ======================
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  @app.route("/")
126
  def index():
127
+ return jsonify({"message": "🌸 Serenity Emotional Support Chatbot API is running!"})
128
+
129
+
130
+ @app.route("/chat", methods=["POST"])
131
+ def chat():
132
+ data = request.get_json()
133
+ user_input = data.get("message", "")
134
+ user_name = data.get("name", "friend")
135
+ country = data.get("country", "IN")
136
+
137
+ # Retrieve or initialize memory
138
+ user_data = USER_MEMORY.get(user_name, {"last_seen": datetime.now(), "last_mood": None})
139
+ last_mood = user_data.get("last_mood")
140
+
141
+ # Detect potential crisis
142
+ crisis_keywords = ["end my life", "kill myself", "suicide", "can't go on", "hurt myself"]
143
+ if any(k in user_input.lower() for k in crisis_keywords):
144
+ helpline = get_helpline_info(country)
145
+ return jsonify({
146
+ "response": (
147
+ "I'm really sorry you’re feeling this way. You’re not alone, and you deserve care. ❤️\n"
148
+ f"If you are in danger, please reach out now:\n{helpline}"
149
+ )
150
+ })
151
+
152
+ # Detect intent
153
+ intent = detect_intent(user_input)
154
+
155
+ # Analyze emotion
156
+ emotion = analyze_emotion(user_input)
157
+
158
+ # Generate empathetic or factual response
159
+ ai_reply = generate_response(intent, user_name, user_input, last_mood)
160
+
161
+ # Update memory
162
+ USER_MEMORY[user_name] = {
163
+ "last_seen": datetime.now(),
164
+ "last_mood": emotion
165
+ }
166
+
167
+ return jsonify({
168
+ "response": ai_reply,
169
+ "emotion": emotion,
170
+ "intent": intent
171
+ })
172
+
173
 
174
  if __name__ == "__main__":
175
+ app.run(host="0.0.0.0", port=7860)