import gradio as gr import torch import torch.nn as nn from transformers import AutoTokenizer, AutoModel import numpy as np # Configuration MODEL_NAME = "roberta-base" MAX_LEN = 200 EMOTIONS = ["anger", "fear", "joy", "sadness", "surprise"] EMOTION_EMOJIS = ["๐Ÿ˜ ", "๐Ÿ˜จ", "๐Ÿ˜Š", "๐Ÿ˜ข", "๐Ÿ˜ฒ"] EMOTION_COLORS = ["#ef4444", "#f59e0b", "#10b981", "#3b82f6", "#8b5cf6"] # Model Architecture (MUST MATCH TRAINING) class RobertaEmotion(nn.Module): def __init__(self, model_name=MODEL_NAME, dropout=0.35, num_labels=5): super().__init__() self.backbone = AutoModel.from_pretrained(model_name) hidden_size = self.backbone.config.hidden_size self.dropout = nn.Dropout(dropout) self.head = nn.Linear(hidden_size, num_labels) def forward(self, input_ids, attention_mask): out = self.backbone(input_ids=input_ids, attention_mask=attention_mask) if hasattr(out, "pooler_output") and out.pooler_output is not None: pooled = out.pooler_output else: pooled = out.last_hidden_state[:, 0] x = self.dropout(pooled) logits = self.head(x) return logits # Load model and tokenizer print("๐Ÿ”„ Loading EmotiScan model...") device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') print(f"๐Ÿ“ฑ Device: {device}") try: tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) model = RobertaEmotion(num_labels=len(EMOTIONS)) # Load trained weights state_dict = torch.load('roberta.pth', map_location=device) model.load_state_dict(state_dict) model = model.to(device) model.eval() print("โœ… EmotiScan ready!") except Exception as e: print(f"โš ๏ธ Error loading model: {e}") raise e # Optimized thresholds from training BEST_THRESHOLDS = np.array([0.5, 0.5, 0.5, 0.5, 0.5]) def predict_emotions(text): """Predict emotions from text with enhanced visualization""" if not text or not text.strip(): return """
๐Ÿค”
Waiting for your text...
Enter some text above to analyze emotions
""" try: # Tokenize encoding = tokenizer( text, truncation=True, padding="max_length", max_length=MAX_LEN, return_tensors="pt" ) input_ids = encoding["input_ids"].to(device) attention_mask = encoding["attention_mask"].to(device) # Predict with torch.no_grad(): logits = model(input_ids, attention_mask) probs = torch.sigmoid(logits).cpu().numpy()[0] # Apply thresholds predictions = (probs > BEST_THRESHOLDS).astype(int) # Build beautiful HTML output html = """ """ # Detected emotions section detected = [(emotion, emoji, prob, color) for emotion, emoji, prob, pred, color in zip(EMOTIONS, EMOTION_EMOJIS, probs, predictions, EMOTION_COLORS) if pred == 1] if detected: html += """
๐ŸŽฏ Detected Emotions
""" for emotion, emoji, prob, color in detected: html += f"""
{emoji} {emotion} {prob:.0%}
""" html += "
" else: html += """
๐Ÿ˜
No Strong Emotions Detected
All emotions below threshold
""" # All emotions with progress bars html += """
๐Ÿ“Š Emotion Breakdown
""" for emotion, emoji, prob, color in zip(EMOTIONS, EMOTION_EMOJIS, probs, EMOTION_COLORS): html += f"""
{emoji} {emotion}
{prob:.1%}
""" html += "
" return html except Exception as e: return f"""
โš ๏ธ
Analysis Error
{str(e)}
""" # Example texts examples = [ ["I just got promoted at work! I can't believe it!"], ["I'm so worried about the exam tomorrow. What if I fail?"], ["This is absolutely unacceptable! I demand to speak to the manager!"], ["I miss my family so much. It's been months since I've seen them."], ["Wow! I never expected to see you here!"], ["I'm excited but also nervous about starting my new job next week."], ] # Create Gradio Interface with gr.Blocks() as demo: gr.HTML("""
๐ŸŽญ

EmotiScan

AI-Powered Multi-Emotion Detection

๐Ÿ˜  Anger ๐Ÿ˜จ Fear ๐Ÿ˜Š Joy ๐Ÿ˜ข Sadness ๐Ÿ˜ฒ Surprise
""") with gr.Row(): with gr.Column(scale=1): text_input = gr.Textbox( label="๐Ÿ“ Your Text", placeholder="Type or paste your text here to discover the emotions within...", lines=8, max_lines=12 ) with gr.Row(): analyze_btn = gr.Button("๐Ÿ”ฎ Analyze Emotions", variant="primary", size="lg") clear_btn = gr.Button("๐Ÿ—‘๏ธ Clear", size="lg") with gr.Column(scale=1): output = gr.HTML(label="Analysis Results", value="""
๐ŸŽญ
Welcome to EmotiScan
Enter text to begin emotional analysis
""") gr.Examples( examples=examples, inputs=text_input, outputs=output, fn=predict_emotions, cache_examples=False, label="๐Ÿ’ก Try These Examples" ) gr.HTML("""

๐Ÿง  About EmotiScan

EmotiScan uses state-of-the-art deep learning to detect multiple emotions simultaneously in text. Unlike traditional single-emotion classifiers, our model recognizes that human expression is complex and nuancedโ€”one piece of text can convey multiple emotions at once.

๐Ÿค–
Model
RoBERTa-base (125M params)
๐ŸŽฏ
Accuracy
Optimized F1-Score per class
โšก
Speed
Real-time inference
๐Ÿ“š Technical Details

Built with PyTorch โ€ข Transformers โ€ข Gradio

2025 Sep DLGenAI Course Project

""") # Event handlers analyze_btn.click(fn=predict_emotions, inputs=text_input, outputs=output) clear_btn.click( fn=lambda: ("", """
๐ŸŽญ
Welcome to EmotiScan
Enter text to begin emotional analysis
"""), inputs=None, outputs=[text_input, output] ) text_input.submit(fn=predict_emotions, inputs=text_input, outputs=output) if __name__ == "__main__": demo.launch(share=True, server_name="0.0.0.0")