analisisNews / app /analyzers /emotion.py
ahmadsayadi's picture
feat: add emotion, framing, fake-score, opinion-fact endpoints
599f4e5
Raw
History Blame Contribute Delete
2.21 kB
"""
Emotion detection granular.
Deteksi emosi: anger, fear, joy, sadness, surprise, disgust, trust, anticipation.
"""
from typing import List, Dict
import re
# Lexicon emosi Bahasa Indonesia (extensible)
EMOTION_LEXICON: Dict[str, List[str]] = {
"anger": ["marah", "murka", "geram", "berang", "emosi", "kesal", "jengkel", "protes", "demo", "kecam", "tolak", "rusuh", "amuk"],
"fear": ["takut", "khawatir", "cemas", "panik", "ancaman", "bahaya", "waspada", "darurat", "teror", "ngeri", "was-was", "resah"],
"joy": ["senang", "gembira", "bahagia", "sukses", "juara", "menang", "prestasi", "bangga", "puas", "optimis", "harapan", "selebrasi"],
"sadness": ["sedih", "duka", "meninggal", "tewas", "korban", "tragis", "pilu", "menderita", "kehilangan", "bela sungkawa", "nestapa"],
"surprise": ["kejutan", "mendadak", "tiba-tiba", "mengejutkan", "tak terduga", "heboh", "viral", "gempar", "terungkap", "ternyata"],
"disgust": ["jijik", "muak", "korupsi", "skandal", "busuk", "curang", "manipulasi", "penipuan", "menjijikkan", "tercela"],
"trust": ["percaya", "yakin", "aman", "terpercaya", "jaminan", "komitmen", "konsisten", "transparan", "akuntabel", "integritas"],
"anticipation": ["harap", "rencana", "siap", "target", "proyeksi", "prediksi", "antisipasi", "agenda", "akan", "berencana"],
}
def detect_emotions(text: str) -> Dict[str, float]:
text_lower = text.lower()
tokens = re.findall(r'\b\w+\b', text_lower)
token_set = set(tokens)
total_tokens = max(len(tokens), 1)
scores = {}
for emotion, keywords in EMOTION_LEXICON.items():
hits = sum(1 for kw in keywords if kw in text_lower or kw in token_set)
scores[emotion] = round(hits / total_tokens * 10, 3) # normalized
return scores
def analyze_batch(items: List) -> List[Dict]:
results = []
for item in items:
scores = detect_emotions(item.text)
dominant = max(scores, key=scores.get) if any(v > 0 for v in scores.values()) else "neutral"
results.append({
"id": item.id,
"emotions": scores,
"dominant_emotion": dominant,
"dominant_score": scores.get(dominant, 0),
})
return results