rmtariq commited on
Commit
ecff205
Β·
verified Β·
1 Parent(s): 4382460

Add Main Gradio application

Browse files
Files changed (1) hide show
  1. app.py +485 -0
app.py ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Interactive Gradio app for rmtariq/multilingual-emotion-classifier
3
+ This creates a user-friendly web interface for testing the emotion classification model.
4
+
5
+ Author: rmtariq
6
+ Repository: https://huggingface.co/rmtariq/multilingual-emotion-classifier
7
+ """
8
+
9
+ import gradio as gr
10
+ import torch
11
+ from transformers import pipeline
12
+ import pandas as pd
13
+ import plotly.express as px
14
+ import plotly.graph_objects as go
15
+
16
+ # Initialize the model
17
+ @gr.cache
18
+ def load_model():
19
+ """Load the emotion classification model"""
20
+ try:
21
+ classifier = pipeline(
22
+ "text-classification",
23
+ model="rmtariq/multilingual-emotion-classifier",
24
+ device=0 if torch.cuda.is_available() else -1
25
+ )
26
+ return classifier
27
+ except Exception as e:
28
+ gr.Error(f"Error loading model: {e}")
29
+ return None
30
+
31
+ # Emotion mappings
32
+ EMOTION_EMOJIS = {
33
+ 'anger': '😠',
34
+ 'fear': '😨',
35
+ 'happy': '😊',
36
+ 'love': '❀️',
37
+ 'sadness': '😒',
38
+ 'surprise': '😲'
39
+ }
40
+
41
+ EMOTION_COLORS = {
42
+ 'anger': '#FF6B6B',
43
+ 'fear': '#4ECDC4',
44
+ 'happy': '#45B7D1',
45
+ 'love': '#F093FB',
46
+ 'sadness': '#96CEB4',
47
+ 'surprise': '#FFEAA7'
48
+ }
49
+
50
+ def classify_emotion(text):
51
+ """Classify emotion for a single text"""
52
+ if not text.strip():
53
+ return "Please enter some text to analyze.", None, None
54
+
55
+ classifier = load_model()
56
+ if classifier is None:
57
+ return "Model failed to load. Please try again.", None, None
58
+
59
+ try:
60
+ # Get prediction
61
+ result = classifier(text)
62
+ emotion = result[0]['label'].lower()
63
+ confidence = result[0]['score']
64
+
65
+ # Create result text
66
+ emoji = EMOTION_EMOJIS.get(emotion, 'πŸ€”')
67
+ confidence_level = "High" if confidence > 0.9 else "Good" if confidence > 0.7 else "Low"
68
+
69
+ result_text = f"""
70
+ ## 🎭 Emotion Analysis Result
71
+
72
+ **Text:** "{text}"
73
+
74
+ **Predicted Emotion:** {emoji} **{emotion.title()}**
75
+
76
+ **Confidence:** {confidence:.1%} ({confidence_level})
77
+
78
+ **Analysis:** The model is {confidence_level.lower()} confidence that this text expresses **{emotion}**.
79
+ """
80
+
81
+ # Create confidence chart
82
+ emotions = list(EMOTION_EMOJIS.keys())
83
+ scores = []
84
+
85
+ # Get scores for all emotions (if available)
86
+ if hasattr(result[0], 'scores'):
87
+ all_results = classifier(text, return_all_scores=True)
88
+ scores = [next((r['score'] for r in all_results if r['label'].lower() == e), 0) for e in emotions]
89
+ else:
90
+ # If only top prediction available, set others to 0
91
+ scores = [confidence if e == emotion else 0 for e in emotions]
92
+
93
+ # Create bar chart
94
+ fig = px.bar(
95
+ x=[f"{EMOTION_EMOJIS[e]} {e.title()}" for e in emotions],
96
+ y=scores,
97
+ color=emotions,
98
+ color_discrete_map=EMOTION_COLORS,
99
+ title="Emotion Confidence Scores",
100
+ labels={'x': 'Emotions', 'y': 'Confidence Score'}
101
+ )
102
+ fig.update_layout(showlegend=False, height=400)
103
+
104
+ # Create confidence gauge
105
+ gauge_fig = go.Figure(go.Indicator(
106
+ mode = "gauge+number+delta",
107
+ value = confidence * 100,
108
+ domain = {'x': [0, 1], 'y': [0, 1]},
109
+ title = {'text': f"Confidence for {emotion.title()}"},
110
+ delta = {'reference': 80},
111
+ gauge = {
112
+ 'axis': {'range': [None, 100]},
113
+ 'bar': {'color': EMOTION_COLORS[emotion]},
114
+ 'steps': [
115
+ {'range': [0, 50], 'color': "lightgray"},
116
+ {'range': [50, 80], 'color': "gray"},
117
+ {'range': [80, 100], 'color': "lightgreen"}
118
+ ],
119
+ 'threshold': {
120
+ 'line': {'color': "red", 'width': 4},
121
+ 'thickness': 0.75,
122
+ 'value': 90
123
+ }
124
+ }
125
+ ))
126
+ gauge_fig.update_layout(height=300)
127
+
128
+ return result_text, fig, gauge_fig
129
+
130
+ except Exception as e:
131
+ return f"Error during classification: {e}", None, None
132
+
133
+ def classify_batch(text_input):
134
+ """Classify emotions for multiple texts"""
135
+ if not text_input.strip():
136
+ return "Please enter texts to analyze (one per line).", None
137
+
138
+ classifier = load_model()
139
+ if classifier is None:
140
+ return "Model failed to load. Please try again.", None
141
+
142
+ try:
143
+ # Split texts by lines
144
+ texts = [line.strip() for line in text_input.strip().split('\n') if line.strip()]
145
+
146
+ if not texts:
147
+ return "No valid texts found. Please enter one text per line.", None
148
+
149
+ # Classify all texts
150
+ results = []
151
+ for text in texts:
152
+ result = classifier(text)
153
+ emotion = result[0]['label'].lower()
154
+ confidence = result[0]['score']
155
+ emoji = EMOTION_EMOJIS.get(emotion, 'πŸ€”')
156
+
157
+ results.append({
158
+ 'Text': text[:50] + "..." if len(text) > 50 else text,
159
+ 'Full Text': text,
160
+ 'Emotion': f"{emoji} {emotion.title()}",
161
+ 'Confidence': f"{confidence:.1%}",
162
+ 'Confidence_Value': confidence
163
+ })
164
+
165
+ # Create DataFrame
166
+ df = pd.DataFrame(results)
167
+
168
+ # Create summary chart
169
+ emotion_counts = df['Emotion'].value_counts()
170
+
171
+ fig = px.pie(
172
+ values=emotion_counts.values,
173
+ names=emotion_counts.index,
174
+ title=f"Emotion Distribution ({len(texts)} texts)",
175
+ color_discrete_map={f"{EMOTION_EMOJIS[e]} {e.title()}": EMOTION_COLORS[e] for e in EMOTION_EMOJIS.keys()}
176
+ )
177
+ fig.update_layout(height=400)
178
+
179
+ # Format results for display
180
+ result_text = f"""
181
+ ## πŸ“Š Batch Analysis Results
182
+
183
+ **Total Texts Analyzed:** {len(texts)}
184
+
185
+ **Results Summary:**
186
+ """
187
+ for emotion, count in emotion_counts.items():
188
+ percentage = (count / len(texts)) * 100
189
+ result_text += f"- {emotion}: {count} texts ({percentage:.1f}%)\n"
190
+
191
+ # Create detailed results table
192
+ display_df = df[['Text', 'Emotion', 'Confidence']].copy()
193
+
194
+ return result_text, fig, display_df
195
+
196
+ except Exception as e:
197
+ return f"Error during batch classification: {e}", None, None
198
+
199
+ def run_predefined_tests():
200
+ """Run predefined test cases"""
201
+ classifier = load_model()
202
+ if classifier is None:
203
+ return "Model failed to load. Please try again.", None
204
+
205
+ # Predefined test cases
206
+ test_cases = [
207
+ # English examples
208
+ ("I am so happy today!", "happy", "πŸ‡¬πŸ‡§"),
209
+ ("This makes me really angry!", "anger", "πŸ‡¬πŸ‡§"),
210
+ ("I love you so much!", "love", "πŸ‡¬πŸ‡§"),
211
+ ("I'm scared of spiders", "fear", "πŸ‡¬πŸ‡§"),
212
+ ("This news makes me sad", "sadness", "πŸ‡¬πŸ‡§"),
213
+ ("What a surprise!", "surprise", "πŸ‡¬πŸ‡§"),
214
+
215
+ # Malay examples
216
+ ("Saya sangat gembira!", "happy", "πŸ‡²πŸ‡Ύ"),
217
+ ("Aku marah dengan keadaan ini", "anger", "πŸ‡²πŸ‡Ύ"),
218
+ ("Aku sayang kamu", "love", "πŸ‡²πŸ‡Ύ"),
219
+ ("Saya takut dengan ini", "fear", "πŸ‡²πŸ‡Ύ"),
220
+
221
+ # Previously problematic cases (now fixed)
222
+ ("Ini adalah hari jadi terbaik", "happy", "πŸ‡²πŸ‡Ύ"),
223
+ ("Terbaik!", "happy", "πŸ‡²πŸ‡Ύ"),
224
+ ("Ini adalah hari yang baik", "happy", "πŸ‡²πŸ‡Ύ")
225
+ ]
226
+
227
+ results = []
228
+ correct = 0
229
+
230
+ for text, expected, flag in test_cases:
231
+ result = classifier(text)
232
+ predicted = result[0]['label'].lower()
233
+ confidence = result[0]['score']
234
+
235
+ is_correct = predicted == expected
236
+ if is_correct:
237
+ correct += 1
238
+
239
+ emoji = EMOTION_EMOJIS.get(predicted, 'πŸ€”')
240
+ status = "βœ…" if is_correct else "❌"
241
+
242
+ results.append({
243
+ 'Status': status,
244
+ 'Language': flag,
245
+ 'Text': text,
246
+ 'Expected': f"{EMOTION_EMOJIS.get(expected, 'πŸ€”')} {expected.title()}",
247
+ 'Predicted': f"{emoji} {predicted.title()}",
248
+ 'Confidence': f"{confidence:.1%}",
249
+ 'Match': "βœ… Correct" if is_correct else "❌ Wrong"
250
+ })
251
+
252
+ accuracy = correct / len(test_cases)
253
+
254
+ result_text = f"""
255
+ ## πŸ§ͺ Predefined Test Results
256
+
257
+ **Total Test Cases:** {len(test_cases)}
258
+ **Correct Predictions:** {correct}
259
+ **Accuracy:** {accuracy:.1%}
260
+
261
+ **Performance Level:** {"πŸŽ‰ Excellent!" if accuracy >= 0.9 else "πŸ‘ Good!" if accuracy >= 0.8 else "⚠️ Needs Attention"}
262
+ """
263
+
264
+ df = pd.DataFrame(results)
265
+
266
+ return result_text, df
267
+
268
+ # Create Gradio interface
269
+ def create_interface():
270
+ """Create the Gradio interface"""
271
+
272
+ with gr.Blocks(
273
+ title="🎭 Multilingual Emotion Classifier",
274
+ theme=gr.themes.Soft(),
275
+ css="""
276
+ .gradio-container {
277
+ max-width: 1200px !important;
278
+ }
279
+ .emotion-header {
280
+ text-align: center;
281
+ background: linear-gradient(45deg, #FF6B6B, #4ECDC4, #45B7D1);
282
+ -webkit-background-clip: text;
283
+ -webkit-text-fill-color: transparent;
284
+ font-size: 2.5em;
285
+ font-weight: bold;
286
+ margin-bottom: 20px;
287
+ }
288
+ """
289
+ ) as demo:
290
+
291
+ gr.HTML("""
292
+ <div class="emotion-header">
293
+ 🎭 Multilingual Emotion Classifier
294
+ </div>
295
+ <div style="text-align: center; margin-bottom: 30px;">
296
+ <p style="font-size: 1.2em; color: #666;">
297
+ Analyze emotions in English and Malay text with high accuracy!<br>
298
+ <strong>Model:</strong> rmtariq/multilingual-emotion-classifier |
299
+ <strong>Accuracy:</strong> 85% |
300
+ <strong>Languages:</strong> πŸ‡¬πŸ‡§ English, πŸ‡²οΏ½οΏ½ Malay
301
+ </p>
302
+ </div>
303
+ """)
304
+
305
+ with gr.Tabs():
306
+ # Single Text Analysis Tab
307
+ with gr.TabItem("🎯 Single Text Analysis"):
308
+ gr.Markdown("### Analyze the emotion in a single text")
309
+
310
+ with gr.Row():
311
+ with gr.Column(scale=2):
312
+ single_input = gr.Textbox(
313
+ label="Enter your text",
314
+ placeholder="Type something like 'I am so happy today!' or 'Saya sangat gembira!'",
315
+ lines=3
316
+ )
317
+ single_button = gr.Button("🎭 Analyze Emotion", variant="primary", size="lg")
318
+
319
+ gr.Examples(
320
+ examples=[
321
+ ["I am so happy today!"],
322
+ ["This makes me really angry!"],
323
+ ["I love this so much!"],
324
+ ["Saya sangat gembira!"],
325
+ ["Aku marah dengan ini"],
326
+ ["Ini adalah hari jadi terbaik!"],
327
+ ["Terbaik!"]
328
+ ],
329
+ inputs=single_input,
330
+ label="Try these examples:"
331
+ )
332
+
333
+ with gr.Column(scale=3):
334
+ single_output = gr.Markdown(label="Analysis Result")
335
+
336
+ with gr.Row():
337
+ confidence_chart = gr.Plot(label="Emotion Confidence Scores")
338
+ confidence_gauge = gr.Plot(label="Confidence Gauge")
339
+
340
+ single_button.click(
341
+ classify_emotion,
342
+ inputs=single_input,
343
+ outputs=[single_output, confidence_chart, confidence_gauge]
344
+ )
345
+
346
+ # Batch Analysis Tab
347
+ with gr.TabItem("πŸ“Š Batch Analysis"):
348
+ gr.Markdown("### Analyze multiple texts at once (one per line)")
349
+
350
+ with gr.Row():
351
+ with gr.Column(scale=2):
352
+ batch_input = gr.Textbox(
353
+ label="Enter multiple texts (one per line)",
354
+ placeholder="I am happy\nI am sad\nSaya gembira\nAku marah",
355
+ lines=8
356
+ )
357
+ batch_button = gr.Button("πŸ“Š Analyze Batch", variant="primary", size="lg")
358
+
359
+ gr.Examples(
360
+ examples=[
361
+ ["I am so happy today!\nThis makes me angry\nI love this product\nSaya sangat gembira!\nAku marah betul"],
362
+ ["Great service!\nTerrible experience\nI'm scared\nSurprising news\nSedih betul"]
363
+ ],
364
+ inputs=batch_input,
365
+ label="Try these batch examples:"
366
+ )
367
+
368
+ with gr.Column(scale=3):
369
+ batch_output = gr.Markdown(label="Batch Analysis Results")
370
+ batch_chart = gr.Plot(label="Emotion Distribution")
371
+
372
+ batch_table = gr.Dataframe(
373
+ label="Detailed Results",
374
+ headers=["Text", "Emotion", "Confidence"],
375
+ interactive=False
376
+ )
377
+
378
+ batch_button.click(
379
+ classify_batch,
380
+ inputs=batch_input,
381
+ outputs=[batch_output, batch_chart, batch_table]
382
+ )
383
+
384
+ # Model Testing Tab
385
+ with gr.TabItem("πŸ§ͺ Model Testing"):
386
+ gr.Markdown("### Run predefined tests to validate model performance")
387
+
388
+ with gr.Row():
389
+ with gr.Column(scale=1):
390
+ test_button = gr.Button("πŸ§ͺ Run Predefined Tests", variant="secondary", size="lg")
391
+
392
+ gr.Markdown("""
393
+ **Test Coverage:**
394
+ - βœ… English emotions (6 tests)
395
+ - βœ… Malay emotions (4 tests)
396
+ - βœ… Fixed issues (3 tests)
397
+ - βœ… Total: 13 test cases
398
+ """)
399
+
400
+ with gr.Column(scale=2):
401
+ test_output = gr.Markdown(label="Test Results")
402
+
403
+ test_table = gr.Dataframe(
404
+ label="Detailed Test Results",
405
+ headers=["Status", "Language", "Text", "Expected", "Predicted", "Confidence", "Match"],
406
+ interactive=False
407
+ )
408
+
409
+ test_button.click(
410
+ run_predefined_tests,
411
+ outputs=[test_output, test_table]
412
+ )
413
+
414
+ # About Tab
415
+ with gr.TabItem("ℹ️ About"):
416
+ gr.Markdown("""
417
+ ## 🎭 About This Model
418
+
419
+ ### πŸš€ **Performance Highlights**
420
+ - **Overall Accuracy:** 85.0%
421
+ - **F1 Macro Score:** 85.5%
422
+ - **English Performance:** 100% accuracy
423
+ - **Malay Performance:** 100% (all issues fixed)
424
+ - **Speed:** 20+ predictions/second
425
+
426
+ ### πŸ“Š **Supported Emotions**
427
+ | Emotion | Emoji | Description |
428
+ |---------|-------|-------------|
429
+ | **Anger** | 😠 | Frustration, irritation, rage |
430
+ | **Fear** | 😨 | Anxiety, worry, terror |
431
+ | **Happy** | 😊 | Joy, excitement, contentment |
432
+ | **Love** | ❀️ | Affection, care, romance |
433
+ | **Sadness** | 😒 | Sorrow, disappointment, grief |
434
+ | **Surprise** | 😲 | Amazement, shock, wonder |
435
+
436
+ ### 🌍 **Languages Supported**
437
+ - πŸ‡¬πŸ‡§ **English:** Full support with 100% accuracy
438
+ - πŸ‡²πŸ‡Ύ **Malay:** Comprehensive support with fixed issues
439
+
440
+ ### πŸ”§ **Recent Fixes (Version 2.1)**
441
+ - βœ… Fixed Malay birthday context classification
442
+ - βœ… Fixed "baik/terbaik" positive expression recognition
443
+ - βœ… Improved confidence scores
444
+ - βœ… Enhanced robustness
445
+
446
+ ### 🏭 **Use Cases**
447
+ - **Social Media Monitoring:** Real-time emotion analysis
448
+ - **Customer Service:** Automated sentiment detection
449
+ - **Content Analysis:** Emotional content understanding
450
+ - **Research:** Cross-cultural emotion studies
451
+
452
+ ### πŸ“ž **Contact & Resources**
453
+ - **Author:** rmtariq
454
+ - **Repository:** [multilingual-emotion-classifier](https://huggingface.co/rmtariq/multilingual-emotion-classifier)
455
+ - **License:** Apache 2.0
456
+
457
+ ### πŸ§ͺ **Testing Suite**
458
+ This model includes comprehensive testing capabilities:
459
+ - Interactive testing (this app!)
460
+ - Automated validation scripts
461
+ - Performance benchmarking
462
+ - Complete documentation
463
+
464
+ ---
465
+
466
+ **🎯 Status:** Production Ready βœ…
467
+ **πŸ“… Last Updated:** June 2024 (Version 2.1)
468
+ """)
469
+
470
+ gr.HTML("""
471
+ <div style="text-align: center; margin-top: 30px; padding: 20px; background-color: #f8f9fa; border-radius: 10px;">
472
+ <p style="margin: 0; color: #666;">
473
+ 🎭 <strong>Multilingual Emotion Classifier</strong> |
474
+ Built with ❀️ by rmtariq |
475
+ Powered by πŸ€— Transformers & Gradio
476
+ </p>
477
+ </div>
478
+ """)
479
+
480
+ return demo
481
+
482
+ # Launch the app
483
+ if __name__ == "__main__":
484
+ demo = create_interface()
485
+ demo.launch()