opinder2906/Software_engineering
0
1import torch2import torch.nn as nn3import torch.nn.functional as F4import random5from textblob import TextBlob6import pandas as pd7import requests8from io import StringIO9import gradio as gr10import speech_recognition as sr11import json12 13# ----- Dummy Model and vocab -----14vocab = {'<PAD>': 0, '<UNK>': 1, 'i': 2, 'am': 3, 'feeling': 4, 'sad': 5, 'happy': 6, 'angry': 7, 'love': 8, 'stressed': 9, 'anxious': 10}15MAX_LEN = 1616 17class DummyLabelEncoder:18 def __init__(self):19 self.classes_ = ['sadness', 'anger', 'love', 'happiness', 'neutral']20 def transform(self, x): return [self.classes_.index(i) for i in x]21 def inverse_transform(self, x): return [self.classes_[i] for i in x]22 23le = DummyLabelEncoder()24 25class DummyModel(nn.Module):26 def __init__(self):27 super().__init__()28 self.embedding = nn.Embedding(len(vocab), 8)29 self.fc = nn.Linear(8, len(le.classes_))30 def forward(self, x):31 x = self.embedding(x)32 x = x.mean(dim=1)33 return self.fc(x)34 35model = DummyModel()36 37def preprocess_input(text):38 tokens = text.lower().split()39 encoded = [vocab.get(token, vocab['<UNK>']) for token in tokens]40 padded = encoded[:MAX_LEN] + [vocab['<PAD>']] * max(0, MAX_LEN - len(encoded))41 return torch.tensor([padded], dtype=torch.long).to(next(model.parameters()).device)42 43# ----- Load CSV from Google Drive -----44file_id = "1yVJh_NVL4Y4YqEXGym47UCK5ZNZgVZYv"45url = f"https://drive.google.com/uc?export=download&id={file_id}"46response = requests.get(url)47csv_text = response.text48 49if csv_text.strip().startswith('<'):50 raise Exception("ERROR: Google Drive link is not returning CSV! Check your sharing settings.")51 52solutions_df = pd.read_csv(StringIO(csv_text), header=0, on_bad_lines='skip')53 54used_solutions = {emotion: set() for emotion in solutions_df['emotion'].unique()}55 56# ----- Data and responses -----57negative_words = [58 "not", "bad", "sad", "anxious", "anxiety", "depressed", "upset", "shit", "stress",59 "worried", "unwell", "struggling", "low", "down", "terrible", "awful",60 "nervous", "panic", "afraid", "scared", "tense", "overwhelmed", "fear", "uneasy"61]62 63responses = {64 "sadness": [65 "It’s okay to feel down sometimes. I’m here to support you.",66 "I'm really sorry you're going through this. Want to talk more about it?",67 "You're not alone — I’m here for you."68 ],69 "anger": [70 "That must have been frustrating. Want to vent about it?",71 "It's okay to feel this way. I'm listening.",72 "Would it help to talk through it?"73 ],74 "love": [75 "That’s beautiful to hear! What made you feel that way?",76 "It’s amazing to experience moments like that.",77 "Sounds like something truly meaningful."78 ],79 "happiness": [80 "That's awesome! What’s bringing you joy today?",81 "I love hearing good news. 😊",82 "Yay! Want to share more about it?"83 ],84 "neutral": [85 "Got it. I’m here if you want to dive deeper.",86 "Thanks for sharing that. Tell me more if you’d like.",87 "I’m listening. How else can I support you?"88 ]89}90 91# --- Helper functions ---92 93def correct_spelling(text):94 return str(TextBlob(text).correct())95 96def get_sentiment(text):97 return TextBlob(text).sentiment.polarity98 99def is_negative_input(text):100 text_lower = text.lower()101 return any(word in text_lower for word in negative_words)102 103def get_unique_solution(emotion):104 available = solutions_df[solutions_df['emotion'] == emotion]105 unused = available[~available['solution'].isin(used_solutions[emotion])]106 if unused.empty:107 used_solutions[emotion] = set()108 unused = available109 solution_row = unused.sample(1).iloc[0]110 used_solutions[emotion].add(solution_row['solution'])111 return solution_row['solution']112 113def get_emotion(user_input):114 if is_negative_input(user_input):115 return "sadness"116 sentiment = get_sentiment(user_input)117 x = preprocess_input(user_input)118 model.train()119 with torch.no_grad():120 probs = torch.stack([F.softmax(model(x), dim=1) for _ in range(5)])121 avg_probs = probs.mean(dim=0)122 prob, idx = torch.max(avg_probs, dim=1)123 pred_emotion = le.classes_[idx.item()]124 if prob.item() < 0.6:125 return "neutral"126 if sentiment < -0.25 and pred_emotion == "happiness":127 return "sadness"128 if sentiment > 0.25 and pred_emotion == "sadness":129 return "happiness"130 return pred_emotion131 132def audio_to_text(audio_file):133 if audio_file is None:134 return ""135 recog = sr.Recognizer()136 with sr.AudioFile(audio_file) as source:137 audio = recog.record(source)138 try:139 text = recog.recognize_google(audio)140 return text141 except Exception:142 return ""143 144# ----- Chat function -----145GLOBAL_CONVO_HISTORY = []146USER_FEEDBACK_STATE = {}147 148def emoti_chat(audio, text, history_json=""):149 if text and text.strip():150 user_input = text151 elif audio is not None:152 user_input = audio_to_text(audio)153 else:154 user_input = ""155 if not user_input.strip():156 return "Please say something or type your message.", json.dumps(GLOBAL_CONVO_HISTORY[-5:], indent=2), ""157 158 user_input = correct_spelling(user_input)159 160 exit_phrases = ["exit", "quit", "goodbye", "bye", "close"]161 if user_input.lower().strip() in exit_phrases:162 return "Take care! I’m here whenever you want to talk. 👋", json.dumps(GLOBAL_CONVO_HISTORY[-5:], indent=2), gr.update(visible=False)163 164 user_id = "default_user"165 state = USER_FEEDBACK_STATE.get(user_id, {"emotion": None, "pending": False})166 167 if state["pending"]:168 feedback = user_input.lower().strip()169 GLOBAL_CONVO_HISTORY[-1]["feedback"] = feedback170 if feedback == "no":171 suggestion = get_unique_solution(state["emotion"])172 reply = f"Here's another suggestion for you: {suggestion}\nDid this help? (yes/no/skip)"173 USER_FEEDBACK_STATE[user_id]["pending"] = True174 return reply, json.dumps(GLOBAL_CONVO_HISTORY[-5:], indent=2), ""175 else:176 USER_FEEDBACK_STATE[user_id] = {"emotion": None, "pending": False}177 return "How can I help you further?", json.dumps(GLOBAL_CONVO_HISTORY[-5:], indent=2), ""178 179 pred_emotion = get_emotion(user_input)180 support = random.choice(responses.get(pred_emotion, responses["neutral"]))181 try:182 suggestion = get_unique_solution(pred_emotion)183 except Exception:184 suggestion = get_unique_solution("neutral")185 186 reply = f"{support}\n\nHere's a suggestion for you: {suggestion}\nDid this help? (yes/no/skip)"187 GLOBAL_CONVO_HISTORY.append({188 "user_input": user_input,189 "emotion": pred_emotion,190 "bot_support": support,191 "bot_suggestion": suggestion,192 "feedback": ""193 })194 USER_FEEDBACK_STATE[user_id] = {"emotion": pred_emotion, "pending": True}195 return reply, json.dumps(GLOBAL_CONVO_HISTORY[-5:], indent=2), ""196 197# ---- Gradio interface ----198iface = gr.Interface(199 fn=emoti_chat,200 inputs=[201 gr.Audio(type="filepath", label="🎤 Speak your message"),202 gr.Textbox(lines=2, placeholder="Or type your message here...", label="💬 Type message"),203 gr.Textbox(lines=1, value="", visible=False) # hidden, history state204 ],205 outputs=[206 gr.Textbox(label="EmotiBot Reply"),207 gr.Textbox(label="Hidden", visible=False)208 ],209 title="EmotiBot Connect",210 description="Talk to EmotiBot using your voice or by typing. Detects your emotion, gives dynamic suggestions, remembers your feedback, and keeps a conversation history! Type 'exit' to leave."211)212 213if __name__ == "__main__":214 iface.launch(debug=True) 215 