noranisa commited on
Commit
082a160
Β·
verified Β·
1 Parent(s): e342c4a

Update services/sentiment.py

Browse files
Files changed (1) hide show
  1. services/sentiment.py +80 -64
services/sentiment.py CHANGED
@@ -1,102 +1,118 @@
1
- from transformers import pipeline
2
  import os
3
 
4
- # πŸ”₯ PATH MODEL (hasil fine-tuning)
5
  LOCAL_MODEL_PATH = "model/final_model"
6
 
7
- # πŸ”„ fallback model (pretrained)
8
  FALLBACK_MODEL = "w11wo/indonesian-roberta-base-sentiment-classifier"
9
 
10
 
11
- # πŸš€ INIT MODEL
12
  def load_model():
 
 
 
 
 
 
13
  try:
14
- # πŸ‘‰ cek apakah model fine-tuning ada
15
- if os.path.exists(LOCAL_MODEL_PATH):
16
- print("βœ… Load fine-tuned model")
17
- return pipeline("sentiment-analysis", model=LOCAL_MODEL_PATH)
18
-
19
- else:
20
- print("⚠️ Load fallback model (RoBERTa)")
21
- return pipeline("sentiment-analysis", model=FALLBACK_MODEL)
22
-
 
 
 
 
 
 
 
 
 
 
 
23
  except Exception as e:
24
- print("❌ Gagal load model:", e)
25
  return None
26
 
27
 
28
- # πŸ”₯ LOAD SEKALI SAJA (BIAR CEPAT)
29
  classifier = load_model()
30
 
31
 
32
- # 🧠 NORMALISASI LABEL
33
- def normalize_label(label):
34
  label = label.lower()
35
-
36
- # πŸ‘‰ untuk model huggingface (positive/negative)
37
- if "positive" in label:
38
  return "Positive"
39
- elif "negative" in label:
40
  return "Negative"
41
- elif "neutral" in label:
42
  return "Neutral"
 
43
 
44
- # πŸ‘‰ untuk model fine-tuned (LABEL_0,1,2)
45
- if label == "label_0":
46
- return "Negative"
47
- elif label == "label_1":
48
- return "Neutral"
49
- elif label == "label_2":
50
- return "Positive"
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  return "Neutral"
53
 
54
 
55
- # πŸ” PREDICT UTAMA
56
- def predict(texts):
57
- results = []
 
58
 
59
  if classifier is None:
60
- print("⚠️ Model tidak tersedia")
61
- return ["Neutral"] * len(texts)
62
 
63
  try:
64
- # πŸ”₯ batched prediction (lebih cepat)
65
  outputs = classifier(texts, batch_size=8, truncation=True)
66
-
67
- for o in outputs:
68
- label = normalize_label(o['label'])
69
- results.append(label)
70
-
71
  except Exception as e:
72
- print("❌ Error saat prediksi:", e)
73
- results = ["Neutral"] * len(texts)
74
-
75
- return results
76
-
77
-
78
- # πŸ”Ž PREDICT SINGLE (opsional)
79
- def predict_single(text):
 
 
 
 
 
 
80
  return predict([text])[0]
81
 
82
 
83
- # πŸ“Š PREDICT + SCORE (opsional untuk analisis lebih lanjut)
84
- def predict_with_score(texts):
85
- results = []
86
-
87
  if classifier is None:
88
- return [{"label": "Neutral", "score": 0}] * len(texts)
89
-
90
  try:
91
  outputs = classifier(texts, batch_size=8, truncation=True)
92
-
93
- for o in outputs:
94
- results.append({
95
- "label": normalize_label(o['label']),
96
- "score": round(o['score'], 4)
97
- })
98
-
99
  except Exception as e:
100
- print("❌ Error:", e)
101
-
102
- return results
 
 
1
  import os
2
 
3
+ # ── PATH MODEL FINE-TUNING ──
4
  LOCAL_MODEL_PATH = "model/final_model"
5
 
6
+ # ── FALLBACK: model pretrained HuggingFace ──
7
  FALLBACK_MODEL = "w11wo/indonesian-roberta-base-sentiment-classifier"
8
 
9
 
 
10
  def load_model():
11
+ """
12
+ Load pipeline sentimen. Urutan prioritas:
13
+ 1. Model fine-tuned lokal (jika ada)
14
+ 2. Model pretrained dari HuggingFace Hub
15
+ 3. None β†’ fallback ke rule-based
16
+ """
17
  try:
18
+ # import di dalam fungsi agar tidak crash saat torch tidak tersedia
19
+ import torch
20
+ from transformers import pipeline
21
+
22
+ model_path = LOCAL_MODEL_PATH if os.path.exists(LOCAL_MODEL_PATH) else FALLBACK_MODEL
23
+ label = "fine-tuned" if os.path.exists(LOCAL_MODEL_PATH) else "fallback RoBERTa"
24
+
25
+ clf = pipeline(
26
+ "sentiment-analysis",
27
+ model=model_path,
28
+ device=-1, # CPU-only (HF Spaces free tier)
29
+ truncation=True,
30
+ max_length=512,
31
+ )
32
+ print(f"βœ… Model loaded: {label}")
33
+ return clf
34
+
35
+ except ImportError:
36
+ print("⚠️ PyTorch tidak tersedia β€” menggunakan rule-based fallback")
37
+ return None
38
  except Exception as e:
39
+ print(f"❌ Gagal load model: {e}")
40
  return None
41
 
42
 
43
+ # Load sekali saat startup
44
  classifier = load_model()
45
 
46
 
47
+ # ── NORMALISASI LABEL ──
48
+ def normalize_label(label: str) -> str:
49
  label = label.lower()
50
+ if "positive" in label or label == "label_2":
 
 
51
  return "Positive"
52
+ if "negative" in label or label == "label_0":
53
  return "Negative"
54
+ if "neutral" in label or label == "label_1":
55
  return "Neutral"
56
+ return "Neutral"
57
 
 
 
 
 
 
 
 
58
 
59
+ # ── RULE-BASED FALLBACK ──
60
+ POS_KW = ["bagus","baik","senang","suka","mantap","keren","hebat","oke","setuju",
61
+ "benar","bagus","sukses","berhasil","love","good","great","nice","best",
62
+ "amazing","excellent","wonderful","happy","glad"]
63
+ NEG_KW = ["buruk","jelek","benci","kecewa","gagal","salah","rugi","marah","bohong",
64
+ "hoax","fitnah","jahat","tidak setuju","parah","malu","takut",
65
+ "bad","worst","terrible","hate","fail","wrong","poor","awful"]
66
+
67
+ def rule_based(text: str) -> str:
68
+ lower = text.lower()
69
+ pos = sum(1 for k in POS_KW if k in lower)
70
+ neg = sum(1 for k in NEG_KW if k in lower)
71
+ if pos > neg:
72
+ return "Positive"
73
+ if neg > pos:
74
+ return "Negative"
75
  return "Neutral"
76
 
77
 
78
+ # ── PREDIKSI UTAMA ──
79
+ def predict(texts: list) -> list:
80
+ if not texts:
81
+ return []
82
 
83
  if classifier is None:
84
+ print("⚠️ Classifier tidak tersedia β†’ rule-based")
85
+ return [rule_based(t) for t in texts]
86
 
87
  try:
 
88
  outputs = classifier(texts, batch_size=8, truncation=True)
89
+ return [normalize_label(o["label"]) for o in outputs]
 
 
 
 
90
  except Exception as e:
91
+ print(f"❌ Error saat prediksi batch: {e}")
92
+ # per-item fallback
93
+ results = []
94
+ for t in texts:
95
+ try:
96
+ out = classifier(t[:512], truncation=True)
97
+ results.append(normalize_label(out[0]["label"]))
98
+ except Exception:
99
+ results.append(rule_based(t))
100
+ return results
101
+
102
+
103
+ # ── PREDICT SINGLE ──
104
+ def predict_single(text: str) -> str:
105
  return predict([text])[0]
106
 
107
 
108
+ # ── PREDICT WITH SCORE ──
109
+ def predict_with_score(texts: list) -> list:
 
 
110
  if classifier is None:
111
+ return [{"label": rule_based(t), "score": 0.0} for t in texts]
 
112
  try:
113
  outputs = classifier(texts, batch_size=8, truncation=True)
114
+ return [{"label": normalize_label(o["label"]), "score": round(o["score"], 4)}
115
+ for o in outputs]
 
 
 
 
 
116
  except Exception as e:
117
+ print(f"❌ Error predict_with_score: {e}")
118
+ return [{"label": rule_based(t), "score": 0.0} for t in texts]