Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import openai | |
| import os | |
| import json | |
| import random | |
| import requests | |
| from transformers import pipeline | |
| from datetime import datetime | |
| # --- Setup --- | |
| openai.api_key = os.getenv("OPENAI_API_KEY") | |
| emotion_classifier = pipeline("text-classification", | |
| model="j-hartmann/emotion-english-distilroberta-base") | |
| USER_FILE = "user_data.json" | |
| QUOTE_API = "https://api.quotable.io/random" | |
| LOCAL_QUOTES = [ | |
| "Every sunrise brings new hope. Keep shining.", | |
| "You are capable of more than you realize.", | |
| "Each step, no matter how small, is progress.", | |
| "Difficult roads often lead to beautiful destinations.", | |
| "The best time for new beginnings is now.", | |
| "Your inner light never fades—let it guide you." | |
| ] | |
| # --- Helper functions --- | |
| def load_user_data(): | |
| if os.path.exists(USER_FILE): | |
| with open(USER_FILE, "r") as f: | |
| return json.load(f) | |
| return {} | |
| def save_user_data(data): | |
| with open(USER_FILE, "w") as f: | |
| json.dump(data, f, indent=2) | |
| def fetch_quote(): | |
| try: | |
| r = requests.get(QUOTE_API, timeout=5) | |
| if r.status_code == 200: | |
| q = r.json() | |
| return f"“{q['content']}” — {q['author']}" | |
| except Exception: | |
| pass | |
| return random.choice(LOCAL_QUOTES) | |
| def classify_emotion(text): | |
| try: | |
| result = emotion_classifier(text) | |
| return result[0]["label"].lower() | |
| except Exception: | |
| return "neutral" | |
| def get_color_for_emotion(e): | |
| palette = { | |
| "happy": "#fff59d", | |
| "joy": "#fff59d", | |
| "sad": "#90caf9", | |
| "angry": "#ff8a65", | |
| "calm": "#a5d6a7", | |
| "motivated": "#ffcc80", | |
| "neutral": "#eeeeee", | |
| } | |
| return palette.get(e.lower(), "#f5f5f5") | |
| # --- Core logic --- | |
| def chat_with_bot(message, name, age, audio=None): | |
| if not message and audio: | |
| # if user spoke instead of typed | |
| import speech_recognition as sr | |
| recognizer = sr.Recognizer() | |
| with sr.AudioFile(audio) as src: | |
| audio_data = recognizer.record(src) | |
| try: | |
| message = recognizer.recognize_google(audio_data) | |
| except Exception: | |
| message = "..." | |
| if not message: | |
| return "Please say or type something.", None, None | |
| user_id = "default" | |
| users = load_user_data() | |
| user = users.get(user_id, {"name": name, "age": age, "recent_mood": "neutral"}) | |
| emotion = classify_emotion(message) | |
| # Motivational triggers | |
| if "motivate" in message.lower() or "guidance" in message.lower(): | |
| quote = fetch_quote() | |
| user["recent_mood"] = "motivated" | |
| users[user_id] = user | |
| save_user_data(users) | |
| return quote, None, get_color_for_emotion("motivated") | |
| # Normal empathetic reply | |
| prompt = f""" | |
| You are a warm, empathetic emotional support companion. | |
| The user's name is {name}, age {age}, currently feeling {emotion}. | |
| Reply with kindness, encouragement, and positivity. | |
| Avoid therapy or diagnosis. | |
| User: {message} | |
| Assistant: | |
| """ | |
| try: | |
| response = openai.ChatCompletion.create( | |
| model="gpt-4o-mini", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.8 | |
| ) | |
| reply = response.choices[0].message["content"].strip() | |
| except Exception: | |
| reply = "I'm here for you. Tell me how you’re feeling today." | |
| # Save user state | |
| user["recent_mood"] = emotion | |
| user["last_active"] = datetime.utcnow().strftime("%Y-%m-%d") | |
| users[user_id] = user | |
| save_user_data(users) | |
| return reply, reply, get_color_for_emotion(emotion) | |
| # --- Gradio UI --- | |
| with gr.Blocks(title="Empathetic Voice Chatbot 🌼") as app: | |
| gr.Markdown( | |
| "## 🌼 Empathetic Voice Chatbot\n" | |
| "Speak or type your feelings — your friendly listener will respond with warmth and understanding." | |
| ) | |
| with gr.Row(): | |
| name = gr.Textbox(label="Your Name", value="Alex") | |
| age = gr.Number(label="Your Age", value=25) | |
| chatbox = gr.Textbox(label="Type your message", placeholder="Say something or click record below...") | |
| mic = gr.Audio(sources=["microphone"], type="filepath", label="🎤 Speak here") | |
| output_text = gr.Textbox(label="Assistant's Response") | |
| audio_reply = gr.Audio(label="🔊 Spoken Reply") | |
| send_btn = gr.Button("Send / Talk 💬") | |
| def respond(msg, n, a, aud): | |
| text_reply, tts_text, color = chat_with_bot(msg, n, a, aud) | |
| if tts_text: | |
| speech = openai.audio.speech.with_streaming_response.create( | |
| model="gpt-4o-mini-tts", | |
| voice="alloy", | |
| input=tts_text | |
| ) | |
| out_path = "reply.mp3" | |
| with open(out_path, "wb") as f: | |
| f.write(speech.read()) | |
| else: | |
| out_path = None | |
| # Dynamically change background color | |
| app.theme = None | |
| return gr.update(value=text_reply), out_path | |
| send_btn.click(respond, [chatbox, name, age, mic], [output_text, audio_reply]) | |
| app.launch() |