Sentiment Analysis
วิเคราะห์ความรู้สึกภาษาไทย และอื่นๆ etc. รองรับหลายโมเดล
import gradio as gr from transformers import pipeline import re from functools import lru_cache import logging from typing import List, Dict, Tuple import json # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Enhanced model list with descriptions MODEL_LIST = [ ("ZombitX64/MultiSent-E5-Pro", "🏆 MultiSent E5 Pro - แนะนำ (ความแม่นยำสูงสุด)"), ("ZombitX64/Thai-sentiment-e5", "🎯 Thai Sentiment E5 - เฉพาะภาษาไทย"), ("poom-sci/WangchanBERTa-finetuned-sentiment", "🔥 WangchanBERTa - โมเดลไทยยอดนิยม"), ("SandboxBhh/sentiment-thai-text-model", "✨ Sandbox Thai - เร็วและแม่นยำ"), ("ZombitX64/MultiSent-E5", "⚡ MultiSent E5 - รวดเร็ว"), ("Thaweewat/wangchanberta-hyperopt-sentiment-01", "🧠 WangchanBERTa Hyperopt"), ("cardiffnlp/twitter-xlm-roberta-base-sentiment", "🌐 XLM-RoBERTa - หลายภาษา"), ("phoner45/wangchan-sentiment-thai-text-model", "📱 Wangchan Mobile"), ("ZombitX64/Sentiment-01", "🔬 Sentiment v1"), ("ZombitX64/Sentiment-02", "🔬 Sentiment v2"), ("ZombitX64/Sentiment-03", "🔬 Sentiment v3"), ("ZombitX64/sentiment-103", "🔬 Sentiment 103"), ("ZombitX64/sentimentSumdata-v1", "🔬 sentimentSumdata-v1"), ("ZombitX64/wangchanberta-att-spm-uncased-sentiment", "wangchanberta-att-spm-uncased-sentiment"), ] # Cache for model loading @lru_cache(maxsize=3) def get_nlp(model_name: str): try: return pipeline("sentiment-analysis", model=model_name) except Exception as e: logger.error(f"Error loading model {model_name}: {e}") raise gr.Error(f"ไม่สามารถโหลดโมเดล {model_name} ได้: {str(e)}") # Model-specific label mappings MODEL_LABEL_MAPPINGS = { # wangchanberta-att-spm-uncased-sentiment - 3 classes ( negative, neutral, positive) "ZombitX64/wangchanberta-att-spm-uncased-sentiment": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # MultiSent E5 Pro - 4 classes (question, negative, neutral, positive) "ZombitX64/MultiSent-E5-Pro": { "LABEL_0": {"code": 0, "name": "question", "emoji": "🤔", "color": "#60a5fa", "bg": "rgba(96, 165, 250, 0.2)", "description": "คำถาม"}, "LABEL_1": {"code": 1, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_2": {"code": 2, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_3": {"code": 3, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # Thai Sentiment E5 - 3 classes (negative, neutral, positive) "ZombitX64/Thai-sentiment-e5": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # WangchanBERTa - usually neg/neu/pos "poom-sci/WangchanBERTa-finetuned-sentiment": { "neg": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "neu": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "pos": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # Sandbox Thai - 3 classes "SandboxBhh/sentiment-thai-text-model": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # MultiSent E5 - 3 classes "ZombitX64/MultiSent-E5": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # WangchanBERTa Hyperopt "Thaweewat/wangchanberta-hyperopt-sentiment-01": { "neg": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "neu": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "pos": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # Twitter XLM-RoBERTa - NEGATIVE/NEUTRAL/POSITIVE "cardiffnlp/twitter-xlm-roberta-base-sentiment": { "NEGATIVE": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "NEUTRAL": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "POSITIVE": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # Wangchan Mobile "phoner45/wangchan-sentiment-thai-text-model": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, # ZombitX64 Sentiment models - 3 classes "ZombitX64/Sentiment-01": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, "ZombitX64/Sentiment-02": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, "ZombitX64/Sentiment-03": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, "ZombitX64/sentiment-103": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, "ZombitX64/sentimentSumdata-v1": { "LABEL_0": {"code": 0, "name": "negative", "emoji": "😢", "color": "#f87171", "bg": "rgba(248, 113, 113, 0.2)", "description": "เชิงลบ"}, "LABEL_1": {"code": 1, "name": "neutral", "emoji": "😐", "color": "#facc15", "bg": "rgba(250, 204, 21, 0.2)", "description": "เป็นกลาง"}, "LABEL_2": {"code": 2, "name": "positive", "emoji": "😊", "color": "#34d399", "bg": "rgba(52, 211, 153, 0.2)", "description": "เชิงบวก"}, }, } def get_label_info(label: str, model_name: str) -> Dict: """Get label information for specific model with fallback for unknown labels""" model_mappings = MODEL_LABEL_MAPPINGS.get(model_name, {}) if label in model_mappings: return model_mappings[label] # Fallback for unknown labels return { "code": -1, "name": label.lower(), "emoji": "🔍", "color": "#64748b", "bg": "rgba(100, 116, 139, 0.2)", "description": f"ไม่ทราบ ({label})" } def split_sentences(text: str) -> List[str]: """Enhanced sentence splitting with better Thai support""" sentences = re.split(r'[.!?။\n]+', text) sentences = [s.strip() for s in sentences if s.strip() and len(s.strip()) > 2] return sentences def create_confidence_bar(score: float) -> str: """Create a modern confidence visualization""" percentage = int(score * 100) return f"""
โมเดล: {model_name.split('/')[-1]}
วิเคราะห์ความรู้สึกภาษาไทย และอื่นๆ etc. รองรับหลายโมเดล