Pant0x commited on
Commit
9643bf2
·
verified ·
1 Parent(s): b49817d

Upload app.py

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