Pant0x commited on
Commit
a770703
·
verified ·
1 Parent(s): 5024c86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -70
app.py CHANGED
@@ -4,48 +4,45 @@ import random
4
  import re
5
  import torch
6
  from transformers import Wav2Vec2ForSequenceClassification, Wav2Vec2Processor
7
- from transformers import Wav2Vec2FeatureExtractor
8
  import librosa
9
  from gtts import gTTS
10
- import numpy as np
11
  import tempfile
12
  import os
13
 
14
- # ------------------------------
15
- # Allowed mental health keywords
16
  MENTAL_KEYWORDS = [
17
  "depression", "depressed", "anxiety", "anxious", "panic", "stress", "sad", "lonely",
18
- "trauma", "mental", "therapy", "therapist", "counselor", "mood", "overwhelmed", "anger",
19
- "fear", "worry", "self-esteem", "confidence", "motivation", "relationship", "cope", "coping",
20
- "relax", "calm", "sleep", "emotion", "feeling", "feel", "thoughts", "help", "life", "advice",
21
- "unmotivated", "lost", "hopeless", "tired", "burnout", "cry", "hurt", "love", "breakup",
22
- "friend", "family", "alone", "heartbroken", "scared", "fearful",
23
- "ana", "zahqan", "daye2", "ha2t", "mota3ab", "mota3eb", "za3lan", "malo", "khalni", "mash3or",
24
- "bakhaf", "w7ed", "msh 3aref", "mash fahem", "malish", "3ayez", "ayez", "7azeen", "mdaye2",
 
 
 
 
25
  "حزين", "تعبان", "قلق", "خايف", "وحدة", "ضيق", "توتر", "زعلان", "اكتئاب", "علاج",
26
  "مشاعر", "مضغوط", "قلقان", "وحدي", "مش مبسوط", "زهقان", "ضايق", "تعب", "مش مرتاح",
27
  ]
28
 
29
- # Off-topic keywords
30
  OFF_TOPIC = [
31
- "recipe", "song", "music", "lyrics", "joke", "funny", "laugh", "code", "python", "program",
32
- "game", "food", "cook", "movie", "film", "series", "sport", "football", "instagram",
33
- "tiktok", "money", "business", "crypto", "ai", "computer",
 
34
  "نكتة", "ضحك", "اغنية", "اغاني", "طبخ", "اكل", "فيلم", "مسلسل", "كورة", "رياضة",
35
  "بيزنس", "فلوس", "العاب", "لعبة", "كود", "برمجة", "ذكاء اصطناعي"
36
  ]
37
 
38
- # Random off-topic responses
39
  OFF_TOPIC_RESPONSES = [
40
- "I'm here to help with emotional and mental well-being. Let's focus on how you're feeling today.",
41
- "I specialize in mental and emotional health conversations. Tell me what’s on your mind.",
42
- "Lets bring it back to your feelings — Im here to help you talk through emotions or stress.",
43
- "My goal is to support your mental health. How have things been emotionally lately?",
44
- "I’m here for emotional support only. What’s been bothering you recently?",
45
  ]
46
 
47
- # ------------------------------
48
- # Arabic detection
49
  def contains_arabic(text: str) -> bool:
50
  return bool(re.search(r"[\u0600-\u06FF]", text))
51
 
@@ -59,11 +56,10 @@ def is_mental_health_related(text: str) -> bool:
59
  return True
60
  return False
61
 
62
- # ------------------------------
63
- # Load voice emotion model
64
  voice_model_name = "Hatman/audio-emotion-detection"
65
  voice_model = Wav2Vec2ForSequenceClassification.from_pretrained(voice_model_name)
66
- voice_processor = Wav2Vec2FeatureExtractor.from_pretrained(voice_model_name)
67
 
68
  def detect_voice_emotion(audio_file):
69
  audio, sr = librosa.load(audio_file, sr=16000)
@@ -73,53 +69,55 @@ def detect_voice_emotion(audio_file):
73
  predicted_id = torch.argmax(logits, dim=-1).item()
74
  return voice_model.config.id2label[predicted_id]
75
 
76
- # ------------------------------
77
- # Chat + voice response with TTS
78
- def respond(message, history: list[dict[str, str]], system_message, max_tokens, temperature, top_p, hf_token: gr.OAuthToken, audio=None):
79
- transcript = {"user": "", "bot": "", "tts": None}
80
  response_text = ""
81
-
82
- # Detect audio emotion
83
  if audio:
84
- emotion = detect_voice_emotion(audio)
85
- response_text += f"[Detected mood: {emotion}] "
86
-
87
- transcript["user"] = message
88
  if not is_mental_health_related(message):
89
  response_text += random.choice(OFF_TOPIC_RESPONSES)
90
- transcript["bot"] = response_text
91
- else:
92
- locked_system_message = (
93
- "You are a licensed mental health therapy assistant. "
94
- "You respond with empathy, emotional intelligence, and a therapeutic tone. "
95
- "Never answer questions unrelated to emotional or mental wellness, even if they are in another language."
96
- )
97
-
98
- client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b")
99
- messages = [{"role": "system", "content": locked_system_message}]
100
- messages.extend(history)
101
- messages.append({"role": "user", "content": message})
102
-
103
- # Stream response
104
- for msg in client.chat_completion(messages, max_tokens=max_tokens, stream=True, temperature=temperature, top_p=top_p):
105
- choices = msg.choices
106
- token = ""
107
- if len(choices) and choices[0].delta.content:
108
- token = choices[0].delta.content
109
- response_text += token
110
- transcript["bot"] = response_text
111
-
112
- # Convert response to speech (TTS)
113
- tts = gTTS(text=transcript["bot"], lang='ar' if contains_arabic(transcript["bot"]) else 'en')
114
- tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
115
- tts.save(tmp_file.name)
116
- transcript["tts"] = tmp_file.name
117
-
118
- return transcript
119
-
120
- # ------------------------------
121
- # Gradio UI
 
 
 
 
122
  with gr.Blocks() as demo:
 
123
  with gr.Row():
124
  with gr.Column():
125
  chatbot = gr.ChatInterface(
@@ -130,8 +128,12 @@ with gr.Blocks() as demo:
130
  gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
131
  gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
132
  gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)"),
133
- gr.Audio(source="microphone", type="filepath", label="Record your voice (optional)"),
134
  gr.OAuthToken(label="Hugging Face Token"),
135
  ],
136
  )
137
- demo.launch()
 
 
 
 
 
4
  import re
5
  import torch
6
  from transformers import Wav2Vec2ForSequenceClassification, Wav2Vec2Processor
 
7
  import librosa
8
  from gtts import gTTS
 
9
  import tempfile
10
  import os
11
 
12
+ # ===== Mental health keywords (EN + AR + transliterated AR)
 
13
  MENTAL_KEYWORDS = [
14
  "depression", "depressed", "anxiety", "anxious", "panic", "stress", "sad", "lonely",
15
+ "trauma", "mental", "therapy", "therapist", "counselor", "mood", "overwhelmed",
16
+ "anger", "fear", "worry", "self-esteem", "confidence", "motivation", "relationship",
17
+ "cope", "coping", "relax", "calm", "sleep", "emotion", "feeling", "feel", "thoughts",
18
+ "help", "life", "advice", "unmotivated", "lost", "hopeless", "tired", "burnout",
19
+ "cry", "hurt", "love", "breakup", "friend", "family", "alone", "heartbroken",
20
+ "scared", "fearful",
21
+ # Transliterated Arabic
22
+ "ana", "zahqan", "daye2", "ha2t", "mota3ab", "mota3eb", "za3lan", "malo", "khalni",
23
+ "mash3or", "bakhaf", "w7ed", "msh 3aref", "mash fahem", "malish", "3ayez", "ayez",
24
+ "7azeen", "mdaye2",
25
+ # Arabic
26
  "حزين", "تعبان", "قلق", "خايف", "وحدة", "ضيق", "توتر", "زعلان", "اكتئاب", "علاج",
27
  "مشاعر", "مضغوط", "قلقان", "وحدي", "مش مبسوط", "زهقان", "ضايق", "تعب", "مش مرتاح",
28
  ]
29
 
 
30
  OFF_TOPIC = [
31
+ "recipe", "song", "music", "lyrics", "joke", "funny", "laugh", "code", "python",
32
+ "program", "game", "food", "cook", "movie", "film", "series", "sport", "football",
33
+ "instagram", "tiktok", "money", "business", "crypto", "ai", "computer",
34
+ # Arabic
35
  "نكتة", "ضحك", "اغنية", "اغاني", "طبخ", "اكل", "فيلم", "مسلسل", "كورة", "رياضة",
36
  "بيزنس", "فلوس", "العاب", "لعبة", "كود", "برمجة", "ذكاء اصطناعي"
37
  ]
38
 
 
39
  OFF_TOPIC_RESPONSES = [
40
+ "I'm here to help with emotional and mental well-being. Let's focus on your feelings.",
41
+ "I specialize in mental and emotional health conversations. How have you been feeling?",
42
+ "Let's bring it back to your emotions — I'm here to help process stress or challenges.",
 
 
43
  ]
44
 
45
+ # Detect Arabic text
 
46
  def contains_arabic(text: str) -> bool:
47
  return bool(re.search(r"[\u0600-\u06FF]", text))
48
 
 
56
  return True
57
  return False
58
 
59
+ # ===== Voice emotion detection
 
60
  voice_model_name = "Hatman/audio-emotion-detection"
61
  voice_model = Wav2Vec2ForSequenceClassification.from_pretrained(voice_model_name)
62
+ voice_processor = Wav2Vec2Processor.from_pretrained(voice_model_name)
63
 
64
  def detect_voice_emotion(audio_file):
65
  audio, sr = librosa.load(audio_file, sr=16000)
 
69
  predicted_id = torch.argmax(logits, dim=-1).item()
70
  return voice_model.config.id2label[predicted_id]
71
 
72
+ # ===== Chat function with mood, TTS, transcript
73
+ def respond(message, history, system_message, max_tokens, temperature, top_p, hf_token: gr.OAuthToken, audio=None):
74
+ transcript = []
 
75
  response_text = ""
76
+
 
77
  if audio:
78
+ mood = detect_voice_emotion(audio)
79
+ response_text += f"[Detected mood: {mood}] "
80
+
 
81
  if not is_mental_health_related(message):
82
  response_text += random.choice(OFF_TOPIC_RESPONSES)
83
+ transcript.append(("User", message))
84
+ transcript.append(("Bot", response_text))
85
+ tts_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
86
+ tts = gTTS(response_text)
87
+ tts.save(tts_file)
88
+ return response_text, tts_file, transcript
89
+
90
+ locked_system_message = (
91
+ "You are a licensed mental health therapy assistant. "
92
+ "You respond with empathy, emotional intelligence, and a therapeutic tone. "
93
+ "Never answer questions unrelated to emotional or mental wellness."
94
+ )
95
+
96
+ client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b")
97
+ messages = [{"role": "system", "content": locked_system_message}]
98
+ messages.extend(history)
99
+ messages.append({"role": "user", "content": message})
100
+
101
+ for msg in client.chat_completion(messages, max_tokens=max_tokens, stream=True,
102
+ temperature=temperature, top_p=top_p):
103
+ choices = msg.choices
104
+ token = ""
105
+ if len(choices) and choices[0].delta.content:
106
+ token = choices[0].delta.content
107
+ response_text += token
108
+
109
+ transcript.append(("User", message))
110
+ transcript.append(("Bot", response_text))
111
+
112
+ tts_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
113
+ tts = gTTS(response_text)
114
+ tts.save(tts_file)
115
+
116
+ return response_text, tts_file, transcript
117
+
118
+ # ===== Gradio UI
119
  with gr.Blocks() as demo:
120
+ gr.Markdown("## Mental Health Chatbot with Voice Mood Detection")
121
  with gr.Row():
122
  with gr.Column():
123
  chatbot = gr.ChatInterface(
 
128
  gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
129
  gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
130
  gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)"),
131
+ gr.Audio(label="Record your voice (optional)", type="filepath"),
132
  gr.OAuthToken(label="Hugging Face Token"),
133
  ],
134
  )
135
+
136
+ # Output area for transcript
137
+ transcript_box = gr.Textbox(label="Transcript (User & Bot)", interactive=False)
138
+
139
+ demo.launch()