Spaces:
Sleeping
Sleeping
| from gtts import gTTS | |
| import tempfile | |
| import json | |
| import datetime | |
| import gradio as gr | |
| import re | |
| import os | |
| from openai import OpenAI | |
| # OpenAI Configuration | |
| # API key is loaded from environment variable OPENAI_API_KEY | |
| OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") | |
| if not OPENAI_API_KEY: | |
| raise ValueError("OPENAI_API_KEY environment variable is required") | |
| client = OpenAI(api_key=OPENAI_API_KEY) | |
| # System prompt for ChatGPT to act as a compassionate therapist | |
| SYSTEM_PROMPT = """You are StrongMind Therapist - a compassionate, empathetic AI therapist designed to provide emotional support and mental health guidance. | |
| Your role is to: | |
| - Listen actively and validate the person's feelings | |
| - Provide thoughtful, compassionate responses | |
| - Offer practical coping strategies and mental health tips when appropriate | |
| - Be supportive and non-judgmental | |
| - Encourage them to seek professional help if needed | |
| - Keep responses conversational and natural, like talking to a caring human counselor | |
| - Be brief but warm (2-3 sentences typically, unless they ask for more detail)""" | |
| # User data | |
| user_info = {"name": "", "age": "", "gender": "", "language": "english" , "Guardian_info": ""} | |
| chat_history = [] | |
| journal_entries = [] | |
| calm_tips = [ | |
| "Take 3 deep breaths.", "Listen to nature.", "Stretch your body.", | |
| "Drink water.", "Think of one good thing today.", "Close your eyes for 1 minute.", | |
| "Write your feelings.", "Smile at yourself.", "Imagine a peaceful place.", | |
| "Say a positive affirmation." | |
| ] | |
| study_tips = [ | |
| "Use Pomodoro: 25min study, 5min break", "Make a daily to-do list", | |
| "Avoid multitasking", "Use color-coded notes", "Take 10-min exercise breaks", | |
| "Sleep 7–9 hrs daily", "Drink water during study", "Use active recall", | |
| "Study hardest topics first", "Test yourself often" | |
| ] | |
| tip_index = {"calm": 0, "study": 0} | |
| lang_codes = { | |
| "english": "en", "hindi": "hi", "marathi": "mr", "bengali": "bn", | |
| "tamil": "ta", "telugu": "te", "malayalam": "ml", "spanish": "es", | |
| "french": "fr", "german": "de" | |
| } | |
| # List of harmful or dangerous keywords | |
| harmful_keywords = [ | |
| "abomination", "annihilate", "arson", "ass", "assault", "atrocity", | |
| "backstab", "barbaric", "barbarian", "beast", "belittle", "berserk", | |
| "betray", "betrayal", "bigot", "blacklist", "blood", "bloodbath", | |
| "bloody", "bomb", "bonehead", "brainless", "brutal", "brute", "burn", | |
| "butcher", "cage", "callous", "cancer", "chaos", "cheater", "cold-blooded", | |
| "conman", "corrupt", "cowardly", "crash", "crime", "criminality", "crook", | |
| "cruel", "cruelty", "curseword", "damage", "danger", "dangerous", "deadly", | |
| "deceive", "defame", "defeat", "degenerate", "demon", "despise", "destroy", | |
| "destruction", "destructive", "devastate", "devil", "diabolical", "dictator", | |
| "dirty", "disaster", "dishonor", "disrespect", "disturb", "divisive", "drunk", | |
| "dumbass", "dungeon", "enemies", "enemy", "enrage", "evilness", "exile", | |
| "exploit", "exterminate", "fake", "fanatic", "fascist", "fatal", "fire", | |
| "forgery", "fraud", "fraudster", "freakish", "gang", "gangster", "ghastly", | |
| "ghoul", "gory", "grotesque", "gruesome", "hag", "halfwit", "hardhearted", | |
| "harm", "hateable", "hateful", "havoc", "hell", "hellish", "heretic", | |
| "hideous", "horrid", "horrific", "hostility", "howl", "hypocrite", "illegal", | |
| "illicit", "immoral", "imposter", "injure", "insensitive", "insidious", | |
| "intolerant", "irate", "jerky", "joke", "joker", "kidnap", "killjoy", "liar", | |
| "loath", "loathsome", "lowlife", "madness", "malicious", "malign", | |
| "manipulate", "menace", "monster", "monstrous", "mug", "murderous", | |
| "mutant", "mutiny", "nasty", "nefarious", "neglect", "negative", "offend", | |
| "offender", "ominous", "oppress", "outrage", "outrageous", "parasite", | |
| "penalty", "perish", "pest", "plague", "poison", "poisonous", "pollute", | |
| "psychopath", "punch", "punish", "punishment", "quarrel", "rage", "rat", | |
| "rebellion", "reckless", "repel", "repulsive", "revolt", "revolting", | |
| "rioter", "rob", "robber", "rotten", "ruin", "savage", "scare", "scary", | |
| "schemer", "scold", "scorn", "scoundrel", "scream", "screwed", "serpent", | |
| "shady", "sham", "shameful", "shatter", "shocking", "sin", "sinister", | |
| "slavey", "slimy", "smash", "smite", "snob", "spite", "spiteful", "stab", | |
| "stench", "stink", "strike", "subvert", "suspicious", "target", "tease", | |
| "terrible", "terrify", "thief", "threat", "threaten", "thug", "torment", | |
| "torture", "trap", "trick", "trigger", "trouble", "uncivilized", "undermine", | |
| "unfair", "unjust", "unkind", "usurper", "vandal", "vandalize", "venom", | |
| "venomous", "villain", "villainous", "vindictive", "violent", "viper", | |
| "vulgarity", "war", "warmonger", "waste", "wickedness", "wild", "wound", | |
| "wrath", "wreck", "wrong", "yell", "zombie","suicide", "kill myself", "end my life", "harm myself", "cut myself", | |
| "want to die", "die", "jump off", "self-harm", | |
| "suicide", "kill myself", "end my life", "harm myself", "cut myself", | |
| "want to die", "die", "jump off", "self-harm", "give up", "not worth it", | |
| "ending it all", "self-hate", "suicidal", "tragic", "trauma", "pain", | |
| "painful", "sorrow", | |
| "unworthy", "hurt", "grief", "agony", "doom", "doomed" | |
| ] | |
| # Harmful word detection response | |
| harmful_response = ( | |
| "⚠️ It sounds like you're going through a really tough time.\n\n" | |
| "Please reach out to a professional:\n\n" | |
| "🇮🇳 **India Helplines**\n" | |
| "🧠 *Dr. Rachna Khanna Singh* – +91 99103 90559\n" | |
| "📞 *iCall Helpline* – +91 9152987821\n" | |
| "📞 *Vandrevala Foundation* – 1860 266 2345 or 1800 233 3330\n\n" | |
| "🌍 **International Helplines**\n" | |
| "📞 *Lifeline (USA)* – 988\n" | |
| "📞 *Samaritans (UK)* – 116 123\n" | |
| "📞 *Lifeline (Australia)* – 13 11 14\n\n" | |
| "You are not alone. There are people who care and want to help 💚" | |
| ) | |
| # Emotions dictionary removed - ChatGPT now handles all responses naturally | |
| # Functions | |
| def set_personal_info(name, age, gender, language, Guardian_info): | |
| user_info.update({"name": name, "age": age, "gender": gender, "language": language, "Guardian_info": Guardian_info,}) | |
| return gr.update(visible=True), f"✅ Welcome {name}! Preferences saved." | |
| def show_personal_data(): | |
| today = datetime.date.today().strftime("%Y-%m-%d (%A)") | |
| return f"📅 {today}\n👤 Name: {user_info['name']}\n🎂 Age: {user_info['age']}\n♀ Gender: {user_info['gender']}\n🌐 Language: {user_info['language']}\n Guardian_info: {user_info['Guardian_info']}" | |
| def generate_reply(input_text): | |
| text = input_text.lower() | |
| # Check for harmful keywords with word boundaries - crisis intervention | |
| for word in harmful_keywords: | |
| pattern = r'\b' + re.escape(word) + r'\b' | |
| if re.search(pattern, text): | |
| return harmful_response | |
| # Use OpenAI ChatGPT for natural conversation | |
| try: | |
| response = client.chat.completions.create( | |
| model="gpt-3.5-turbo", # or "gpt-4" for better responses | |
| messages=[ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": input_text} | |
| ], | |
| temperature=0.7, | |
| max_tokens=200 | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| return f"I'm having trouble connecting right now, but I'm here to listen. Can you tell me more about what you're feeling?" | |
| def chat_function(audio_input, text_input): | |
| user_text = text_input.strip() | |
| if not user_text: | |
| return "Please type something or try again.", None | |
| try: | |
| reply = generate_reply(user_text) | |
| chat_history.append({"user": user_text, "bot": reply}) | |
| lang_code = lang_codes.get(user_info["language"], "en") | |
| tts = gTTS(reply, lang=lang_code) | |
| audio_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") | |
| tts.save(audio_file.name) | |
| return reply, audio_file.name | |
| except Exception as e: | |
| error_msg = f"Something went wrong: {str(e)}" | |
| return error_msg, None | |
| def get_chat_history(): | |
| if not chat_history: | |
| return "No conversations yet." | |
| return "\n\n".join([f"You: {c['user']}\nBot: {c['bot']}" for c in chat_history]) | |
| def save_journal(entry): | |
| if not entry.strip(): | |
| return "⚠️ Please write something before saving." | |
| try: | |
| journal_entries.append(entry) | |
| with open("journal.json", "w") as f: | |
| json.dump(journal_entries, f, indent=2) | |
| return "✅ Journal entry saved successfully!" | |
| except Exception as e: | |
| return f"❌ Error saving journal: {str(e)}" | |
| def show_journal_history(): | |
| return "\n---\n".join(journal_entries) if journal_entries else "No journal entries yet." | |
| def next_calm_tip(): | |
| tip = calm_tips[tip_index["calm"] % len(calm_tips)] | |
| tip_index["calm"] += 1 | |
| return tip | |
| def next_study_tip(): | |
| tip = study_tips[tip_index["study"] % len(study_tips)] | |
| tip_index["study"] += 1 | |
| return tip | |
| # -------------- Gradio App -------------- | |
| with gr.Blocks() as app: | |
| welcome_screen = gr.Column(visible=True) | |
| full_app = gr.Tabs(visible=False) | |
| with welcome_screen: | |
| gr.HTML(""" | |
| <style> | |
| #main-title { | |
| text-align: center; | |
| font-size: 2.5em; | |
| } | |
| #subtitle { | |
| text-align: center; | |
| font-size: 1.2em; | |
| color: #ccc; | |
| margin-bottom: 30px; | |
| } | |
| #start-btn { | |
| background-color: #ff69b4; | |
| color: white; | |
| font-weight: bold; | |
| border: none; | |
| border-radius: 10px; | |
| padding: 14px 45px; | |
| font-size: 1.1em; | |
| cursor: pointer; | |
| display: block; | |
| margin: 0 auto; | |
| } | |
| #start-btn:hover { | |
| background-color: #ff85c1; | |
| } | |
| </style> | |
| """) | |
| gr.Markdown("<h1 id='main-title'>StrongMind Therapist 2.0</h1>") | |
| gr.Markdown("<h3 id='subtitle'>Your peaceful space to talk, journal, and focus.</h3>") | |
| start_button = gr.Button("🌸 Get Started", elem_id="start-btn") | |
| def start_app(): | |
| return gr.update(visible=False), gr.update(visible=True) | |
| start_button.click(start_app, outputs=[welcome_screen, full_app]) | |
| with full_app: | |
| with gr.Tab("1️⃣ Personal Info"): | |
| name = gr.Textbox(label="Name") | |
| age = gr.Textbox(label="Age") | |
| gender = gr.Dropdown(["Male", "Female", "Other"], label="Gender") | |
| language = gr.Dropdown(list(lang_codes.keys()), label="Preferred Language") | |
| Guardian_info = gr.Textbox(label="Guardian information") | |
| btn = gr.Button("Save Info") | |
| popup = gr.Markdown(visible=False, elem_classes="alert-box") | |
| btn.click(set_personal_info, [name, age, gender, language,Guardian_info], [popup, popup]) | |
| with gr.Tab("2️⃣ Personal Info Data"): | |
| show = gr.Button("Show My Info") | |
| info_display = gr.Textbox(lines=6) | |
| show.click(show_personal_data, outputs=info_display) | |
| with gr.Tab("3️⃣ Chat"): | |
| gr.Markdown("🗣️ Describe your day in one word.") | |
| audio_input = gr.Audio(type="filepath", label="🎧 Say something") | |
| text_input = gr.Textbox(label="⌨️ Or type here") | |
| send = gr.Button("Send") | |
| bot_reply = gr.Textbox(label="🧠 Therapist") | |
| voice = gr.Audio(label="🔊 Voice Reply") | |
| send.click(chat_function, [audio_input, text_input], [bot_reply, voice]) | |
| with gr.Tab("4️⃣ Chat History"): | |
| show_history = gr.Button("📜 Show Chats") | |
| chat_out = gr.Textbox(lines=20, label="History") | |
| show_history.click(get_chat_history, outputs=chat_out) | |
| with gr.Tab("5️⃣ Journal"): | |
| journal_input = gr.Textbox(lines=6, label="Write your thoughts") | |
| save = gr.Button("Save") | |
| journal_status = gr.Textbox() | |
| save.click(save_journal, journal_input, journal_status) | |
| with gr.Tab("6️⃣ Journal History"): | |
| view = gr.Button("View Past Entries") | |
| past = gr.Textbox(lines=15, label="Previous Journals") | |
| view.click(show_journal_history, outputs=past) | |
| with gr.Tab("7️⃣ Calm Space"): | |
| tip_btn = gr.Button("🌿 Give Me a Calm Tip") | |
| calm_text = gr.Textbox() | |
| tip_btn.click(next_calm_tip, outputs=calm_text) | |
| with gr.Tab("8️⃣ Study Tips"): | |
| tip_btn2 = gr.Button("📚 Study Tip") | |
| study_text = gr.Textbox() | |
| tip_btn2.click(next_study_tip, outputs=study_text) | |
| with gr.Tab("9️⃣ Pomodoro"): | |
| gr.Markdown("⏱️ Use 25 min study + 5 min break cycles.\n(For real timer, use front-end JavaScript or Android timers)") | |
| with gr.Tab("💠 Games"): | |
| gr.Markdown("🎮 Play from the game portal below:") | |
| gr.HTML( | |
| ''' | |
| <iframe | |
| src="https://www.onlinegames.io/embed/portal/" | |
| width="100%" | |
| height="600" | |
| frameborder="0" | |
| allowfullscreen> | |
| </iframe> ''' ) | |
| if __name__ == "__main__": | |
| app.launch() | |