Spaces:
Sleeping
Sleeping
Update it.
Browse files
app.py
CHANGED
|
@@ -1,176 +1,124 @@
|
|
| 1 |
import os
|
| 2 |
import json
|
| 3 |
-
import
|
| 4 |
-
from datetime import datetime, timedelta
|
| 5 |
from flask import Flask, request, jsonify, send_from_directory
|
| 6 |
from transformers import pipeline
|
| 7 |
-
|
| 8 |
-
import requests
|
| 9 |
|
| 10 |
app = Flask(__name__)
|
| 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 |
-
json.dump(data, f)
|
| 39 |
-
|
| 40 |
-
def load_chat_log():
|
| 41 |
-
with open(CHAT_LOG_FILE, "r") as f:
|
| 42 |
-
return json.load(f)
|
| 43 |
-
|
| 44 |
-
def save_chat_log(logs):
|
| 45 |
-
cutoff = datetime.now() - timedelta(days=15)
|
| 46 |
-
logs = [l for l in logs if datetime.strptime(l["time"], "%Y-%m-%d %H:%M:%S") > cutoff]
|
| 47 |
-
with open(CHAT_LOG_FILE, "w") as f:
|
| 48 |
-
json.dump(logs, f)
|
| 49 |
-
|
| 50 |
-
def get_country():
|
| 51 |
-
try:
|
| 52 |
-
res = requests.get("https://ipapi.co/json/").json()
|
| 53 |
-
return res.get("country_name", "default").lower()
|
| 54 |
-
except:
|
| 55 |
-
return "default"
|
| 56 |
-
|
| 57 |
-
HELPLINES = {
|
| 58 |
-
"united states": "If you are in the U.S., please contact the **988 Suicide and Crisis Lifeline** by dialing 988 (24/7).",
|
| 59 |
-
"united kingdom": "If you’re in the UK, contact **Samaritans** at 116 123 (24/7).",
|
| 60 |
-
"india": "If you’re in India, you can reach **AASRA** at 91-9820466726 or **Snehi** at 91-9582208181.",
|
| 61 |
-
"canada": "If you’re in Canada, dial or text **988** for the Talk Suicide Canada line (24/7).",
|
| 62 |
-
"australia": "If you’re in Australia, contact **Lifeline Australia** at 13 11 14 (24/7).",
|
| 63 |
-
"default": "If you’re in crisis, please reach out to your local emergency number or trusted mental health service. You are not alone 💛"
|
| 64 |
-
}
|
| 65 |
-
|
| 66 |
-
MOTIVATIONAL_QUOTES = [
|
| 67 |
-
"Even the darkest night will end and the sun will rise 🌅",
|
| 68 |
-
"You are stronger than you think 💪",
|
| 69 |
-
"It’s okay to rest. Healing takes time 🌿",
|
| 70 |
-
"Every storm runs out of rain ⛈️",
|
| 71 |
-
"Be kind to yourself — you’re doing your best 💛",
|
| 72 |
-
"Peace begins the moment you let things be 🌸",
|
| 73 |
-
"The fact that you’re trying means you haven’t given up 🌼",
|
| 74 |
]
|
| 75 |
|
| 76 |
-
|
| 77 |
-
"
|
|
|
|
|
|
|
|
|
|
| 78 |
]
|
| 79 |
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
def chat():
|
| 82 |
data = request.get_json()
|
| 83 |
-
user_message = data.get("message", "")
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
"You don’t have to face this alone. "
|
| 93 |
-
+ HELPLINES.get(country, HELPLINES["default"])
|
| 94 |
-
+ "\n\nWould you like me to stay with you while you calm down a bit?"
|
| 95 |
-
)
|
| 96 |
-
return jsonify({"reply": crisis_msg, "emotion": "crisis"})
|
| 97 |
-
|
| 98 |
-
# Collect name
|
| 99 |
-
if not user["name"]:
|
| 100 |
-
user["name"] = user_message.capitalize()
|
| 101 |
-
save_user(user)
|
| 102 |
-
return jsonify({"reply": f"Nice to meet you, {user['name']} 🌼 Can you tell me your age?", "emotion": "calm"})
|
| 103 |
-
|
| 104 |
-
# Collect age
|
| 105 |
-
if not user["age"]:
|
| 106 |
-
try:
|
| 107 |
-
user["age"] = int(user_message)
|
| 108 |
-
save_user(user)
|
| 109 |
-
return jsonify({"reply": "Thank you 💛 Now tell me, how have you been feeling lately?", "emotion": "curious"})
|
| 110 |
-
except ValueError:
|
| 111 |
-
return jsonify({"reply": "Could you please tell me your age in numbers? 😊", "emotion": "neutral"})
|
| 112 |
-
|
| 113 |
-
# Follow-up if user felt bad last time
|
| 114 |
-
if user["last_interaction"]:
|
| 115 |
-
last_time = datetime.strptime(user["last_interaction"], "%Y-%m-%d %H:%M:%S")
|
| 116 |
-
if datetime.now() - last_time > timedelta(hours=12):
|
| 117 |
-
if user["mood"] in ["sadness", "anger", "fear"]:
|
| 118 |
-
follow_up = f"Hey {user['name']} 💛 You were feeling low last time we talked. How are you feeling now?"
|
| 119 |
-
user["last_interaction"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 120 |
-
save_user(user)
|
| 121 |
-
return jsonify({"reply": follow_up, "emotion": "warm"})
|
| 122 |
-
|
| 123 |
-
# Emotion detection
|
| 124 |
-
emotion_result = emotion_model(user_message)[0]
|
| 125 |
-
emotion = emotion_result["label"].lower()
|
| 126 |
-
|
| 127 |
-
# Update logs
|
| 128 |
-
user["mood"] = emotion
|
| 129 |
-
user["last_interaction"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 130 |
-
user["mood_history"].append({"emotion": emotion, "time": user["last_interaction"]})
|
| 131 |
-
save_user(user)
|
| 132 |
-
chat_log.append({
|
| 133 |
-
"message": user_message,
|
| 134 |
-
"emotion": emotion,
|
| 135 |
-
"time": user["last_interaction"]
|
| 136 |
-
})
|
| 137 |
-
save_chat_log(chat_log)
|
| 138 |
-
|
| 139 |
-
# Tone setup
|
| 140 |
-
tone_instruction = (
|
| 141 |
-
"You are Serenity, an emotionally intelligent AI companion. "
|
| 142 |
-
"Be warm, human-like, calm, and empathetic. Show that you care deeply and remember feelings. "
|
| 143 |
-
"Do not repeat 'I'm sorry to hear that'; instead vary your empathetic responses naturally. "
|
| 144 |
-
"Encourage reflection and hope. "
|
| 145 |
-
)
|
| 146 |
-
|
| 147 |
-
if user["age"] < 18:
|
| 148 |
-
tone_instruction += "Speak in a gentle, caring tone suited for teenagers."
|
| 149 |
-
else:
|
| 150 |
-
tone_instruction += "Speak with emotional maturity and calm wisdom."
|
| 151 |
-
|
| 152 |
-
ai_response = client.chat.completions.create(
|
| 153 |
-
model="gpt-4o-mini",
|
| 154 |
-
messages=[
|
| 155 |
-
{"role": "system", "content": tone_instruction},
|
| 156 |
-
{"role": "user", "content": user_message},
|
| 157 |
-
],
|
| 158 |
-
)
|
| 159 |
-
reply = ai_response.choices[0].message.content.strip()
|
| 160 |
-
|
| 161 |
-
# Add motivational quote if sad
|
| 162 |
-
if emotion in ["sadness", "fear", "anger"]:
|
| 163 |
-
reply += f"\n\n💬 *Motivational Thought:* {random.choice(MOTIVATIONAL_QUOTES)}"
|
| 164 |
|
| 165 |
-
#
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
|
| 173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
|
| 176 |
@app.route("/")
|
|
@@ -179,4 +127,4 @@ def index():
|
|
| 179 |
|
| 180 |
|
| 181 |
if __name__ == "__main__":
|
| 182 |
-
app.run(host="0.0.0.0", port=7860)
|
|
|
|
| 1 |
import os
|
| 2 |
import json
|
| 3 |
+
import datetime
|
|
|
|
| 4 |
from flask import Flask, request, jsonify, send_from_directory
|
| 5 |
from transformers import pipeline
|
| 6 |
+
import random
|
|
|
|
| 7 |
|
| 8 |
app = Flask(__name__)
|
| 9 |
|
| 10 |
+
# ========= BASIC CONFIG =========
|
| 11 |
+
USER_MEMORY_FILE = "user_memory.json"
|
| 12 |
+
|
| 13 |
+
# Load lightweight emotion model (tiny)
|
| 14 |
+
emotion_analyzer = pipeline("text-classification", model="j-hartmann/emotion-english-distilroberta-base", top_k=None)
|
| 15 |
+
|
| 16 |
+
# ========== SIMPLE MEMORY ==========
|
| 17 |
+
def load_memory():
|
| 18 |
+
if os.path.exists(USER_MEMORY_FILE):
|
| 19 |
+
with open(USER_MEMORY_FILE, "r") as f:
|
| 20 |
+
return json.load(f)
|
| 21 |
+
return {}
|
| 22 |
+
|
| 23 |
+
def save_memory(memory):
|
| 24 |
+
with open(USER_MEMORY_FILE, "w") as f:
|
| 25 |
+
json.dump(memory, f)
|
| 26 |
+
|
| 27 |
+
memory = load_memory()
|
| 28 |
+
|
| 29 |
+
# ========= PREDEFINED RESPONSES =========
|
| 30 |
+
supportive_openers = [
|
| 31 |
+
"That sounds tough, but I’m here for you.",
|
| 32 |
+
"It takes courage to talk about that.",
|
| 33 |
+
"I appreciate you sharing that with me.",
|
| 34 |
+
"You’re not alone in this, and I’m here to listen.",
|
| 35 |
+
"Thank you for trusting me with that.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
]
|
| 37 |
|
| 38 |
+
motivational_followups = [
|
| 39 |
+
"You’ve got more strength than you think.",
|
| 40 |
+
"Every step, no matter how small, is progress.",
|
| 41 |
+
"Healing takes time, and that’s perfectly okay.",
|
| 42 |
+
"Would you like to talk about what might help today?",
|
| 43 |
]
|
| 44 |
|
| 45 |
+
crisis_reply = (
|
| 46 |
+
"I’m really sorry that you’re feeling like this. "
|
| 47 |
+
"You’re not alone, and help is available. "
|
| 48 |
+
"If you are in immediate danger, please call your local emergency number or a trusted person. "
|
| 49 |
+
"If you're in India, you can contact AASRA Helpline at 91-9820466726. "
|
| 50 |
+
"In the U.S., call or text **988** for the Suicide and Crisis Lifeline."
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
# ========= HELPER FUNCTIONS =========
|
| 54 |
+
def analyze_emotion(text):
|
| 55 |
+
try:
|
| 56 |
+
res = emotion_analyzer(text)
|
| 57 |
+
top_emotion = res[0][0]['label']
|
| 58 |
+
return top_emotion.lower()
|
| 59 |
+
except Exception:
|
| 60 |
+
return "neutral"
|
| 61 |
+
|
| 62 |
+
def crisis_check(text):
|
| 63 |
+
crisis_keywords = ["suicide", "end my life", "kill myself", "can't go on", "hurt myself"]
|
| 64 |
+
return any(k in text.lower() for k in crisis_keywords)
|
| 65 |
+
|
| 66 |
+
def get_supportive_response(user_name, text, emotion):
|
| 67 |
+
if crisis_check(text):
|
| 68 |
+
return crisis_reply
|
| 69 |
+
|
| 70 |
+
sympathy = random.choice(supportive_openers)
|
| 71 |
+
motivation = random.choice(motivational_followups)
|
| 72 |
+
|
| 73 |
+
if emotion in ["sadness", "fear", "anger"]:
|
| 74 |
+
return f"{sympathy} {motivation}"
|
| 75 |
+
elif emotion in ["joy", "love"]:
|
| 76 |
+
return f"That’s wonderful to hear, {user_name if user_name else 'friend'}! Keep that energy going."
|
| 77 |
+
else:
|
| 78 |
+
return f"I understand, {user_name if user_name else 'friend'}. Would you like to share a bit more?"
|
| 79 |
+
|
| 80 |
+
# ========= ROUTES =========
|
| 81 |
+
@app.route("/api/chat", methods=["POST"])
|
| 82 |
def chat():
|
| 83 |
data = request.get_json()
|
| 84 |
+
user_message = data.get("message", "")
|
| 85 |
+
user_name = data.get("name", "friend")
|
| 86 |
+
user_age = data.get("age", None)
|
| 87 |
+
|
| 88 |
+
if not user_message:
|
| 89 |
+
return jsonify({"response": "Please say something so I can respond."})
|
| 90 |
+
|
| 91 |
+
# analyze mood
|
| 92 |
+
emotion = analyze_emotion(user_message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
+
# load & update memory
|
| 95 |
+
memory[user_name] = {
|
| 96 |
+
"last_emotion": emotion,
|
| 97 |
+
"last_message": user_message,
|
| 98 |
+
"timestamp": datetime.datetime.now().isoformat()
|
| 99 |
+
}
|
| 100 |
+
save_memory(memory)
|
| 101 |
|
| 102 |
+
response_text = get_supportive_response(user_name, user_message, emotion)
|
| 103 |
+
|
| 104 |
+
return jsonify({"response": response_text, "emotion": emotion})
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
@app.route("/api/check_mood", methods=["POST"])
|
| 108 |
+
def check_mood():
|
| 109 |
+
data = request.get_json()
|
| 110 |
+
user_name = data.get("name", "")
|
| 111 |
+
if not user_name or user_name not in memory:
|
| 112 |
+
return jsonify({"message": "Hello! How are you feeling today?"})
|
| 113 |
+
|
| 114 |
+
last_entry = memory[user_name]
|
| 115 |
+
last_time = datetime.datetime.fromisoformat(last_entry["timestamp"])
|
| 116 |
+
days_since = (datetime.datetime.now() - last_time).days
|
| 117 |
+
|
| 118 |
+
if days_since <= 15 and last_entry["last_emotion"] in ["sadness", "fear", "anger"]:
|
| 119 |
+
return jsonify({"message": f"Hey {user_name}, you were feeling a bit down last time. How are you feeling today?"})
|
| 120 |
+
else:
|
| 121 |
+
return jsonify({"message": f"Welcome back, {user_name}! How’s everything going?"})
|
| 122 |
|
| 123 |
|
| 124 |
@app.route("/")
|
|
|
|
| 127 |
|
| 128 |
|
| 129 |
if __name__ == "__main__":
|
| 130 |
+
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
|