JonusNattapong commited on
Commit
d5704f3
·
verified ·
1 Parent(s): e8fd6ae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -154
app.py CHANGED
@@ -14,7 +14,6 @@ logger = logging.getLogger(__name__)
14
  MODEL_LIST = [
15
  ("ZombitX64/MultiSent-E5-Pro", "🏆 MultiSent E5 Pro - แนะนำ (ความแม่นยำสูงสุด)"),
16
  ("ZombitX64/Thai-sentiment-e5", "🎯 Thai Sentiment E5 - เฉพาะภาษาไทย"),
17
- ("ZombitX64/wangchanberta-att-spm-uncased-sentiment", "ZombitX64/wangchanberta-att-spm-uncased-sentiment"),
18
  ("poom-sci/WangchanBERTa-finetuned-sentiment", "🔥 WangchanBERTa - โมเดลไทยยอดนิยม"),
19
  ("SandboxBhh/sentiment-thai-text-model", "✨ Sandbox Thai - เร็วและแม่นยำ"),
20
  ("ZombitX64/MultiSent-E5", "⚡ MultiSent E5 - รวดเร็ว"),
@@ -26,8 +25,7 @@ MODEL_LIST = [
26
  ("ZombitX64/Sentiment-03", "🔬 Sentiment v3"),
27
  ("ZombitX64/sentiment-103", "🔬 Sentiment 103"),
28
  ("nlptown/bert-base-multilingual-uncased-sentiment", "🌍 BERT Multilingual"),
29
- ("ZombitX64/sentimentv2","🔍 sentimentv2"),
30
- ("ZombitX64/sentimentSumdata-v1","sentimentSumDatav1")
31
  ]
32
 
33
  # Cache for model loading
@@ -39,94 +37,31 @@ def get_nlp(model_name: str):
39
  logger.error(f"Error loading model {model_name}: {e}")
40
  raise gr.Error(f"ไม่สามารถโหลดโมเดล {model_name} ได้: {str(e)}")
41
 
42
- # Comprehensive label mapping system that covers multiple model formats
43
- COMPREHENSIVE_LABEL_MAPPINGS = {
44
- # Standard format labels (LABEL_X)
45
- "LABEL_0": {"sentiment": "negative", "intensity": "normal", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
46
- "LABEL_1": {"sentiment": "neutral", "intensity": "normal", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"},
47
- "LABEL_2": {"sentiment": "positive", "intensity": "normal", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
48
- "LABEL_3": {"sentiment": "very_positive", "intensity": "high", "emoji": "🤩", "color": "#22c55e", "bg": "rgba(34, 197, 94, 0.2)", "description": "เชิงบวกมาก"},
49
- "LABEL_4": {"sentiment": "question", "intensity": "normal", "emoji": "🤔", "color": "#60a5fa", "bg": "rgba(96, 165, 250, 0.2)", "description": "คำถาม"},
50
 
51
- # Numeric format labels (0, 1, 2, etc.)
52
- "0": {"sentiment": "negative", "intensity": "normal", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
53
- "1": {"sentiment": "neutral", "intensity": "normal", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"},
54
- "2": {"sentiment": "positive", "intensity": "normal", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
55
- "3": {"sentiment": "very_positive", "intensity": "high", "emoji": "🤩", "color": "#22c55e", "bg": "rgba(34, 197, 94, 0.2)", "description": "เชิงบวกมาก"},
56
- "4": {"sentiment": "question", "intensity": "normal", "emoji": "🤔", "color": "#60a5fa", "bg": "rgba(96, 165, 250, 0.2)", "description": "คำถาม"},
57
 
58
- # Extended range for models with more classes
59
- "5": {"sentiment": "very_negative", "intensity": "high", "emoji": "😡", "color": "#ef4444", "bg": "rgba(239, 68, 68, 0.2)", "description": "เชิงลบมาก"},
60
- "LABEL_5": {"sentiment": "very_negative", "intensity": "high", "emoji": "😡", "color": "#ef4444", "bg": "rgba(239, 68, 68, 0.2)", "description": "เชิงลบมาก"},
61
-
62
- # Text-based labels (common in some models)
63
- "NEGATIVE": {"sentiment": "negative", "intensity": "normal", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
64
- "NEUTRAL": {"sentiment": "neutral", "intensity": "normal", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"},
65
- "POSITIVE": {"sentiment": "positive", "intensity": "normal", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
66
- "VERY_NEGATIVE": {"sentiment": "very_negative", "intensity": "high", "emoji": "😡", "color": "#ef4444", "bg": "rgba(239, 68, 68, 0.2)", "description": "เชิงลบมาก"},
67
- "VERY_POSITIVE": {"sentiment": "very_positive", "intensity": "high", "emoji": "🤩", "color": "#22c55e", "bg": "rgba(34, 197, 94, 0.2)", "description": "เชิงบวกมาก"},
68
- "QUESTION": {"sentiment": "question", "intensity": "normal", "emoji": "🤔", "color": "#60a5fa", "bg": "rgba(96, 165, 250, 0.2)", "description": "คำถาม"},
69
-
70
- # Lowercase variants
71
- "negative": {"sentiment": "negative", "intensity": "normal", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
72
- "neutral": {"sentiment": "neutral", "intensity": "normal", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"},
73
- "positive": {"sentiment": "positive", "intensity": "normal", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
74
- "very_negative": {"sentiment": "very_negative", "intensity": "high", "emoji": "😡", "color": "#ef4444", "bg": "rgba(239, 68, 68, 0.2)", "description": "เชิงลบมาก"},
75
- "very_positive": {"sentiment": "very_positive", "intensity": "high", "emoji": "🤩", "color": "#22c55e", "bg": "rgba(34, 197, 94, 0.2)", "description": "เชิงบวกมาก"},
76
- "question": {"sentiment": "question", "intensity": "normal", "emoji": "🤔", "color": "#60a5fa", "bg": "rgba(96, 165, 250, 0.2)", "description": "คำถาม"},
77
- }
78
-
79
- # Sentiment categories for counting and summary
80
- SENTIMENT_CATEGORIES = {
81
- "very_negative": {"name": "เชิงลบมาก", "emoji": "😡", "color": "#ef4444", "order": 1},
82
- "negative": {"name": "เชิงลบ", "emoji": "😢", "color": "#f87171", "order": 2},
83
- "neutral": {"name": "เป็นกลาง", "emoji": "😐", "color": "#facc15", "order": 3},
84
- "positive": {"name": "เชิงบวก", "emoji": "😊", "color": "#34d399", "order": 4},
85
- "very_positive": {"name": "เชิงบวกมาก", "emoji": "🤩", "color": "#22c55e", "order": 5},
86
- "question": {"name": "คำถาม", "emoji": "🤔", "color": "#60a5fa", "order": 6},
87
- "unknown": {"name": "ไม่ทราบ", "emoji": "🔍", "color": "#64748b", "order": 7}
88
  }
89
 
90
  def get_label_info(label: str) -> Dict:
91
- """
92
- Enhanced label information extraction with fallback handling
93
- Supports multiple label formats from different models
94
- """
95
- # Convert to string and clean
96
- label_str = str(label).strip()
97
-
98
- # Try exact match first
99
- if label_str in COMPREHENSIVE_LABEL_MAPPINGS:
100
- return COMPREHENSIVE_LABEL_MAPPINGS[label_str]
101
-
102
- # Try case-insensitive match
103
- label_upper = label_str.upper()
104
- label_lower = label_str.lower()
105
-
106
- for key, value in COMPREHENSIVE_LABEL_MAPPINGS.items():
107
- if key.upper() == label_upper or key.lower() == label_lower:
108
- return value
109
-
110
- # Try pattern matching for complex labels
111
- if re.match(r'^LABEL_\d+$', label_str, re.IGNORECASE):
112
- # Extract number from LABEL_X format
113
- try:
114
- num = int(re.findall(r'\d+', label_str)[0])
115
- if str(num) in COMPREHENSIVE_LABEL_MAPPINGS:
116
- return COMPREHENSIVE_LABEL_MAPPINGS[str(num)]
117
- except (IndexError, ValueError):
118
- pass
119
-
120
- # Fallback for unknown labels
121
- logger.warning(f"Unknown label: {label}")
122
- return {
123
- "sentiment": "unknown",
124
- "intensity": "normal",
125
  "emoji": "🔍",
126
  "color": "#64748b",
127
  "bg": "rgba(100, 116, 139, 0.2)",
128
- "description": f"ไม่ทราบ ({label})"
129
- }
130
 
131
  def split_sentences(text: str) -> List[str]:
132
  """Enhanced sentence splitting with better Thai support"""
@@ -147,7 +82,7 @@ def create_confidence_bar(score: float) -> str:
147
  """
148
 
149
  def analyze_text(text: str, model_name: str) -> str:
150
- """Enhanced text analysis with comprehensive multi-model support"""
151
  if not text or not text.strip():
152
  return """
153
  <div style="padding: 20px; background: rgba(248, 113, 113, 0.2); border-radius: 12px; border-left: 4px solid #f87171;">
@@ -193,11 +128,9 @@ def analyze_text(text: str, model_name: str) -> str:
193
  </div>
194
  """]
195
 
196
- # Initialize sentiment counting system
197
- sentiment_counts = {category: 0 for category in SENTIMENT_CATEGORIES.keys()}
198
  total_confidence = 0
199
  sentence_results = []
200
- unique_labels_found = set()
201
 
202
  # Analyze each sentence
203
  for i, sentence in enumerate(sentences, 1):
@@ -206,17 +139,13 @@ def analyze_text(text: str, model_name: str) -> str:
206
  label = result['label']
207
  score = result['score']
208
 
209
- # Track unique labels for debugging
210
- unique_labels_found.add(label)
211
-
212
  label_info = get_label_info(label)
213
- sentiment_type = label_info["sentiment"]
214
 
215
- # Count sentiment
216
- if sentiment_type in sentiment_counts:
217
- sentiment_counts[sentiment_type] += 1
218
  else:
219
- sentiment_counts["unknown"] += 1
220
 
221
  total_confidence += score
222
 
@@ -225,8 +154,7 @@ def analyze_text(text: str, model_name: str) -> str:
225
  'sentence': sentence,
226
  'label_info': label_info,
227
  'score': score,
228
- 'index': i,
229
- 'raw_label': label
230
  })
231
 
232
  except Exception as e:
@@ -269,9 +197,6 @@ def analyze_text(text: str, model_name: str) -> str:
269
  <span style="background: {label_info['color']}; color: #f8fafc; padding: 4px 12px; border-radius: 20px; font-size: 12px; font-weight: 600; text-transform: uppercase;">
270
  {label_info['description']}
271
  </span>
272
- <span style="color: #64748b; font-size: 12px; background: #1e293b; padding: 2px 8px; border-radius: 10px;">
273
- {result['raw_label']}
274
- </span>
275
  <span style="color: #94a3b8; font-size: 14px;">ประโยคที่ {result['index']}</span>
276
  </div>
277
  <p style="color: #f8fafc; margin: 0 0 12px 0; font-size: 16px; line-height: 1.5;">
@@ -288,34 +213,26 @@ def analyze_text(text: str, model_name: str) -> str:
288
  total_sentences = len(sentences)
289
  avg_confidence = total_confidence / total_sentences if total_sentences > 0 else 0
290
 
291
- # Create chart data for summary (only show categories with counts > 0 or important ones)
292
  chart_items = []
293
- sorted_categories = sorted(
294
- [(k, v, sentiment_counts[k]) for k, v in SENTIMENT_CATEGORIES.items()],
295
- key=lambda x: x[1]["order"]
296
- )
297
 
298
- for sentiment_key, sentiment_info, count in sorted_categories:
299
- if count == 0 and sentiment_key == "unknown":
300
- continue # Skip unknown if no unknown sentiments
301
-
302
- percentage = (count / total_sentences) * 100 if total_sentences > 0 else 0
303
-
304
- chart_items.append(f"""
305
- <div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: rgba(59, 130, 246, 0.1); border-radius: 8px;">
306
- <span style="font-size: 24px;">{sentiment_info['emoji']}</span>
307
- <div style="flex: 1;">
308
- <div style="font-weight: 600; color: #f8fafc;">{sentiment_info['name']}</div>
309
- <div style="color: #94a3b8; font-size: 14px;">{count} ประโยค ({percentage:.1f}%)</div>
310
- </div>
311
- <div style="width: 60px; height: 6px; background: #334155; border-radius: 3px; overflow: hidden;">
312
- <div style="width: {percentage}%; height: 100%; background: {sentiment_info['color']}; transition: all 0.3s ease;"></div>
313
  </div>
314
- </div>
315
- """)
316
-
317
- # Debug information showing found labels
318
- debug_labels = ", ".join(sorted(unique_labels_found))
319
 
320
  html_parts.append(f"""
321
  <div style="padding: 24px; background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);">
@@ -335,14 +252,9 @@ def analyze_text(text: str, model_name: str) -> str:
335
  </div>
336
  </div>
337
 
338
- <div style="display: grid; gap: 8px; margin-bottom: 16px;">
339
  {"".join(chart_items)}
340
  </div>
341
-
342
- <div style="background: #1e293b; padding: 12px; border-radius: 8px; border-left: 4px solid #60a5fa;">
343
- <div style="color: #60a5fa; font-size: 12px; font-weight: 600; margin-bottom: 4px;">🔍 Labels ที่พบในโมเดลนี้:</div>
344
- <div style="color: #94a3b8; font-size: 12px; font-family: monospace;">{debug_labels}</div>
345
- </div>
346
  </div>
347
  """)
348
 
@@ -483,8 +395,8 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Base()) as demo:
483
  with gr.Row():
484
  gr.HTML("""
485
  <div class='main-uxui-header'>
486
- <h1>Thai Sentiment Analysis (Multi-Model)</h1>
487
- <p>วิเคราะห์ความรู้สึกภาษาไทย/อังกฤษ รองรับหลายโมเดล | Enhanced Multi-Label Support</p>
488
  </div>
489
  """)
490
  with gr.Row():
@@ -512,10 +424,8 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Base()) as demo:
512
  ["เศร้ามากเลยวันนี้ งานเยอะเกินไป"],
513
  ["อาหารอร่อยดี แต่บริการช้ามาก"],
514
  ["คุณคิดอย่างไรกับเศรษฐกิจไทย?"],
515
- ["I love this product! It's amazing and perfect!"],
516
- ["This is the worst experience I've ever had. Absolutely terrible!"],
517
- ["The weather is okay today, nothing special."],
518
- ["What do you think about this new technology?"]
519
  ],
520
  inputs=input_box,
521
  label="ตัวอย่างข้อความ",
@@ -524,25 +434,13 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Base()) as demo:
524
  gr.HTML("""
525
  <div class='main-uxui-legend'>
526
  <div class='main-uxui-section-title'>
527
- <span>🗂️</span> คำอธิบายผลลัพธ์ (รองรับ Label หลายรูปแบบ)
528
  </div>
529
  <div class='legend-row'>
530
- <div class='legend-item'><strong>😡 เชิงลบมาก</strong><br><small>Very Negative<br>Labels: 5, LABEL_5, VERY_NEGATIVE</small></div>
531
- <div class='legend-item'><strong>😢 เชิงลบ</strong><br><small>Negative<br>Labels: 0, LABEL_0, NEGATIVE</small></div>
532
- <div class='legend-item'><strong>😐 เป็นกลาง</strong><br><small>Neutral<br>Labels: 1, LABEL_1, NEUTRAL</small></div>
533
- <div class='legend-item'><strong>😊 เชิงบวก</strong><br><small>Positive<br>Labels: 2, LABEL_2, POSITIVE</small></div>
534
- <div class='legend-item'><strong>🤩 เชิงบวกมาก</strong><br><small>Very Positive<br>Labels: 3, LABEL_3, VERY_POSITIVE</small></div>
535
- <div class='legend-item'><strong>🤔 คำถาม</strong><br><small>Question<br>Labels: 4, LABEL_4, QUESTION</small></div>
536
- </div>
537
- <div style="margin-top: 16px; padding: 12px; background: rgba(96, 165, 250, 0.1); border-radius: 8px; border-left: 4px solid #60a5fa;">
538
- <div style="color: #60a5fa; font-weight: 600; margin-bottom: 8px;">✨ คุณสมบัติใหม่:</div>
539
- <ul style="color: #94a3b8; font-size: 14px; margin: 0; padding-left: 20px;">
540
- <li>รองรับ Label หลายรูปแบบ (LABEL_X, ตัวเลข, ข้อความ)</li>
541
- <li>แสดง Label ดิบที่โมเดลส่งออกมา</li>
542
- <li>ระบบ Fallback สำหรับ Label ที่ไม่รู้จัก</li>
543
- <li>Debug information แสดง Label ที่พบ</li>
544
- <li>การนับและสรุปผลที่แม่นยำขึ้น</li>
545
- </ul>
546
  </div>
547
  </div>
548
  """)
 
14
  MODEL_LIST = [
15
  ("ZombitX64/MultiSent-E5-Pro", "🏆 MultiSent E5 Pro - แนะนำ (ความแม่นยำสูงสุด)"),
16
  ("ZombitX64/Thai-sentiment-e5", "🎯 Thai Sentiment E5 - เฉพาะภาษาไทย"),
 
17
  ("poom-sci/WangchanBERTa-finetuned-sentiment", "🔥 WangchanBERTa - โมเดลไทยยอดนิยม"),
18
  ("SandboxBhh/sentiment-thai-text-model", "✨ Sandbox Thai - เร็วและแม่นยำ"),
19
  ("ZombitX64/MultiSent-E5", "⚡ MultiSent E5 - รวดเร็ว"),
 
25
  ("ZombitX64/Sentiment-03", "🔬 Sentiment v3"),
26
  ("ZombitX64/sentiment-103", "🔬 Sentiment 103"),
27
  ("nlptown/bert-base-multilingual-uncased-sentiment", "🌍 BERT Multilingual"),
28
+ ("ZombitX64/sentimentv2","🔍 sentimentv2")
 
29
  ]
30
 
31
  # Cache for model loading
 
37
  logger.error(f"Error loading model {model_name}: {e}")
38
  raise gr.Error(f"ไม่สามารถโหลดโมเดล {model_name} ได้: {str(e)}")
39
 
40
+ # Enhanced label mapping with modern styling for dark blue theme
41
+ LABEL_MAPPINGS = {
42
+ "LABEL_0": {"code": 0, "name": "question", "emoji": "🤔", "color": "#60a5fa", "bg": "rgba(96, 165, 250, 0.2)", "description": "คำถาม"},
43
+ "LABEL_1": {"code": 1, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
44
+ "LABEL_2": {"code": 2, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"},
45
+ "LABEL_3": {"code": 3, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
 
 
46
 
47
+ "POSITIVE": {"code": 3, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
48
+ "NEGATIVE": {"code": 1, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
49
+ "NEUTRAL": {"code": 2, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"},
 
 
 
50
 
51
+ "0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"},
52
+ "1": {"code": 1, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
 
55
  def get_label_info(label: str) -> Dict:
56
+ """Get label information with fallback for unknown labels"""
57
+ return LABEL_MAPPINGS.get(label, {
58
+ "code": -1,
59
+ "name": label.lower(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  "emoji": "🔍",
61
  "color": "#64748b",
62
  "bg": "rgba(100, 116, 139, 0.2)",
63
+ "description": "ไม่ทราบ"
64
+ })
65
 
66
  def split_sentences(text: str) -> List[str]:
67
  """Enhanced sentence splitting with better Thai support"""
 
82
  """
83
 
84
  def analyze_text(text: str, model_name: str) -> str:
85
+ """Enhanced text analysis with modern HTML formatting"""
86
  if not text or not text.strip():
87
  return """
88
  <div style="padding: 20px; background: rgba(248, 113, 113, 0.2); border-radius: 12px; border-left: 4px solid #f87171;">
 
128
  </div>
129
  """]
130
 
131
+ sentiment_counts = {"positive": 0, "negative": 0, "neutral": 0, "question": 0, "other": 0}
 
132
  total_confidence = 0
133
  sentence_results = []
 
134
 
135
  # Analyze each sentence
136
  for i, sentence in enumerate(sentences, 1):
 
139
  label = result['label']
140
  score = result['score']
141
 
 
 
 
142
  label_info = get_label_info(label)
143
+ label_name = label_info["name"]
144
 
145
+ if label_name in sentiment_counts:
146
+ sentiment_counts[label_name] += 1
 
147
  else:
148
+ sentiment_counts["other"] += 1
149
 
150
  total_confidence += score
151
 
 
154
  'sentence': sentence,
155
  'label_info': label_info,
156
  'score': score,
157
+ 'index': i
 
158
  })
159
 
160
  except Exception as e:
 
197
  <span style="background: {label_info['color']}; color: #f8fafc; padding: 4px 12px; border-radius: 20px; font-size: 12px; font-weight: 600; text-transform: uppercase;">
198
  {label_info['description']}
199
  </span>
 
 
 
200
  <span style="color: #94a3b8; font-size: 14px;">ประโยคที่ {result['index']}</span>
201
  </div>
202
  <p style="color: #f8fafc; margin: 0 0 12px 0; font-size: 16px; line-height: 1.5;">
 
213
  total_sentences = len(sentences)
214
  avg_confidence = total_confidence / total_sentences if total_sentences > 0 else 0
215
 
216
+ # Create chart data for summary
217
  chart_items = []
218
+ colors = {"positive": "#34d399", "negative": "#f87171", "neutral": "#facc15", "question": "#60a5fa", "other": "#64748b"}
219
+ emojis = {"positive": "😊", "negative": "😢", "neutral": "😐", "question": "🤔", "other": "🔍"}
 
 
220
 
221
+ for sentiment, count in sentiment_counts.items():
222
+ if count > 0:
223
+ percentage = (count / total_sentences) * 100
224
+ chart_items.append(f"""
225
+ <div style="display: flex; align-items: center; gap: 12px; padding: 12px; background: rgba(59, 130, 246, 0.1); border-radius: 8px;">
226
+ <span style="font-size: 24px;">{emojis.get(sentiment, '🔍')}</span>
227
+ <div style="flex: 1;">
228
+ <div style="font-weight: 600; color: #f8fafc; text-transform: capitalize;">{sentiment}</div>
229
+ <div style="color: #94a3b8; font-size: 14px;">{count} ประโยค ({percentage:.1f}%)</div>
230
+ </div>
231
+ <div style="width: 60px; height: 6px; background: #334155; border-radius: 3px; overflow: hidden;">
232
+ <div style="width: {percentage}%; height: 100%; background: {colors.get(sentiment, '#64748b')}; transition: all 0.3s ease;"></div>
233
+ </div>
 
 
234
  </div>
235
+ """)
 
 
 
 
236
 
237
  html_parts.append(f"""
238
  <div style="padding: 24px; background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);">
 
252
  </div>
253
  </div>
254
 
255
+ <div style="display: grid; gap: 8px;">
256
  {"".join(chart_items)}
257
  </div>
 
 
 
 
 
258
  </div>
259
  """)
260
 
 
395
  with gr.Row():
396
  gr.HTML("""
397
  <div class='main-uxui-header'>
398
+ <h1>Thai Sentiment Analysis (SpaceThai-e5)</h1>
399
+ <p>วิเคราะห์ความรู้สึกภาษาไทย/อังกฤษ รองรับหลายโมเดล | Modern UX/UI</p>
400
  </div>
401
  """)
402
  with gr.Row():
 
424
  ["เศร้ามากเลยวันนี้ งานเยอะเกินไป"],
425
  ["อาหารอร่อยดี แต่บริการช้ามาก"],
426
  ["คุณคิดอย่างไรกับเศรษฐกิจไทย?"],
427
+ ["I love this product! It's amazing."],
428
+ ["This is the worst experience I've ever had."]
 
 
429
  ],
430
  inputs=input_box,
431
  label="ตัวอย่างข้อความ",
 
434
  gr.HTML("""
435
  <div class='main-uxui-legend'>
436
  <div class='main-uxui-section-title'>
437
+ <span>🗂️</span> คำอธิบายผลลัพธ์
438
  </div>
439
  <div class='legend-row'>
440
+ <div class='legend-item'><strong>😊 เชิงบวก</strong><br><small>Positive</small></div>
441
+ <div class='legend-item'><strong>😢 เชิงลบ</strong><br><small>Negative</small></div>
442
+ <div class='legend-item'><strong>😐 เป็นกลาง</strong><br><small>Neutral</small></div>
443
+ <div class='legend-item'><strong>🤔 คำถาม</strong><br><small>Question</small></div>
 
 
 
 
 
 
 
 
 
 
 
 
444
  </div>
445
  </div>
446
  """)