analisisNews / app /analyzers /opinionfact.py
ahmadsayadi's picture
feat: add emotion, framing, fake-score, opinion-fact endpoints
599f4e5
Raw
History Blame Contribute Delete
2.07 kB
"""
Opinion vs Fact classifier.
Klasifikasi apakah artikel bersifat opini/editorial atau berita faktual.
"""
from typing import List, Dict
import re
OPINION_MARKERS = [
"menurut saya", "saya rasa", "seharusnya", "sebaiknya", "idealnya",
"opini", "editorial", "kolom", "perspektif", "pandangan",
"hemat saya", "saya pikir", "kita harus", "perlu diakui",
"jelas bahwa", "tidak bisa dipungkiri", "menariknya",
]
FACT_MARKERS = [
"berdasarkan data", "menurut", "kata", "ujar", "ungkap",
"dilaporkan", "tercatat", "statistik", "survei", "rilis",
"laporan", "konferensi pers", "siaran pers", "resmi",
"diumumkan", "ditetapkan", "diresmikan",
]
SUBJECTIVE_WORDS = [
"terbaik", "terburuk", "luar biasa", "mengecewakan", "menyedihkan",
"mengesankan", "fantastis", "mengerikan", "sempurna", "parah",
"indah", "jelek", "hebat", "bodoh", "cerdas",
]
def classify(text: str) -> Dict:
text_lower = text.lower()
opinion_hits = sum(1 for m in OPINION_MARKERS if m in text_lower)
fact_hits = sum(1 for m in FACT_MARKERS if m in text_lower)
subjective_hits = sum(1 for w in SUBJECTIVE_WORDS if w in text_lower)
opinion_score = opinion_hits * 3 + subjective_hits * 2
fact_score = fact_hits * 3
total = opinion_score + fact_score
if total == 0:
return {"classification": "unknown", "opinion_pct": 50, "fact_pct": 50, "confidence": 0}
opinion_pct = round((opinion_score / total) * 100)
fact_pct = 100 - opinion_pct
if opinion_pct > 60:
classification = "opinion"
elif fact_pct > 60:
classification = "fact"
else:
classification = "mixed"
confidence = round(abs(opinion_pct - 50) / 50, 2)
return {
"classification": classification,
"opinion_pct": opinion_pct,
"fact_pct": fact_pct,
"confidence": confidence,
}
def analyze_batch(items: List) -> List[Dict]:
results = []
for item in items:
result = classify(item.text)
results.append({"id": item.id, **result})
return results