Ferdinann commited on
Commit
6e4bbc4
Β·
verified Β·
1 Parent(s): dcbebc4

Update sentiment_app.py

Browse files
Files changed (1) hide show
  1. sentiment_app.py +52 -29
sentiment_app.py CHANGED
@@ -5,9 +5,9 @@ import pandas as pd
5
  import matplotlib.pyplot as plt
6
  import seaborn as sns
7
  from datetime import datetime
8
- import collections
9
 
10
  # --- SETUP MODEL ---
 
11
  MODEL_NAME = "w11wo/indonesian-roberta-base-sentiment-classifier"
12
  device = 0 if torch.cuda.is_available() else -1
13
  sentiment_pipeline = pipeline("sentiment-analysis", model=MODEL_NAME, device=device)
@@ -15,7 +15,7 @@ sentiment_pipeline = pipeline("sentiment-analysis", model=MODEL_NAME, device=dev
15
  # --- DATABASE SEDERHANA (In-Memory) ---
16
  all_messages = []
17
 
18
- # Mapping Label untuk Tampilan UI
19
  label_map = {
20
  "POSITIVE": "Pujian/Apresiasi",
21
  "NEGATIVE": "Keluhan/Kritik",
@@ -26,13 +26,13 @@ def process_submission(text):
26
  if not text or text.strip() == "":
27
  return "⚠️ Mohon isi komentar Anda terlebih dahulu.", gr.update()
28
 
29
- # 1. Analisis Sentimen
30
  result = sentiment_pipeline(text)[0]
31
  label = result['label'].upper()
32
 
33
- # 2. Simpan ke Database Lokal
34
  new_entry = {
35
- "Waktu": datetime.now().strftime("%Y-%m-%d %H:%M"),
36
  "Pesan": text.strip(),
37
  "Sentimen": label
38
  }
@@ -44,13 +44,13 @@ def process_submission(text):
44
 
45
  def get_admin_dashboard(filter_val):
46
  if not all_messages:
47
- return None, pd.DataFrame(columns=["Pesan", "Sentimen", "Jumlah"]), "Belum ada data."
48
 
49
  df_all = pd.DataFrame(all_messages)
50
 
51
  # --- LOGIKA FILTER ---
52
  if filter_val != "SEMUA":
53
- # Balik mapping untuk filter data asli
54
  rev_map = {v: k for k, v in label_map.items()}
55
  target = rev_map.get(filter_val)
56
  df_filtered = df_all[df_all['Sentimen'] == target]
@@ -58,37 +58,44 @@ def get_admin_dashboard(filter_val):
58
  df_filtered = df_all
59
 
60
  if df_filtered.empty:
61
- return None, pd.DataFrame(columns=["Pesan", "Sentimen", "Jumlah"]), f"Tidak ada data untuk kategori: {filter_val}"
62
 
63
- # --- VISUALISASI TOTAL ---
64
  fig, ax = plt.subplots(figsize=(8, 5))
65
- color_map = {"POSITIVE": "#4CAF50", "NEGATIVE": "#F44336", "NEUTRAL": "#FFC107"}
66
  counts = df_all['Sentimen'].value_counts()
 
67
  counts.index = [label_map.get(i, i) for i in counts.index]
68
 
69
  sns.barplot(x=counts.index, y=counts.values, palette="viridis", ax=ax)
70
  ax.set_title("Proporsi Pesan Masuk (Total)", fontsize=12, fontweight='bold')
71
-
72
- # --- TABEL TOP 10 DENGAN KOLOM SENTIMEN ---
73
- top_df = df_filtered.groupby(['Pesan', 'Sentimen']).size().reset_index(name='Jumlah')
74
- top_df = top_df.sort_values(by='Jumlah', ascending=False).head(10)
75
- top_df['Sentimen'] = top_df['Sentimen'].map(label_map) # Percantik label di tabel
76
-
77
- return fig, top_df, f"Menampilkan {len(df_filtered)} pesan ({filter_val})"
 
78
 
79
  # --- INTERFACE GRADIO ---
80
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald"), title="PoskoLog Dashboard") as demo:
81
  gr.Markdown("# πŸ“¦ PoskoLog: Suara Pengungsi")
 
82
 
83
  with gr.Tabs():
84
- # TAB USER
85
  with gr.Tab("πŸ“ Sampaikan Pesan"):
86
  with gr.Column(variant="panel"):
87
- user_input = gr.Textbox(label="Komentar Anda", placeholder="Tulis masukan di sini...", lines=4)
 
 
 
 
 
88
  submit_btn = gr.Button("Kirim Pesan", variant="primary")
89
  user_feedback = gr.Markdown("")
90
 
91
- # TAB ADMIN
92
  with gr.Tab("πŸ“Š Dashboard Admin"):
93
  with gr.Row():
94
  sentiment_filter = gr.Dropdown(
@@ -96,20 +103,36 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald"), title="PoskoLog Dash
96
  value="SEMUA",
97
  label="Filter Sentimen"
98
  )
99
- refresh_btn = gr.Button("πŸ”„ Refresh & Filter", variant="secondary")
100
 
101
  with gr.Row():
102
- with gr.Column():
103
  plot_output = gr.Plot(label="Grafik Distribusi")
104
- with gr.Column():
105
- gr.Markdown("#### Pesan Berdasarkan Filter")
106
- table_output = gr.Dataframe(headers=["Pesan", "Sentimen", "Jumlah"], interactive=False)
 
 
 
 
 
107
 
108
- status_txt = gr.Markdown("")
109
 
110
- # Binding Events
111
- submit_btn.click(fn=process_submission, inputs=user_input, outputs=[user_feedback, user_input])
112
- refresh_btn.click(fn=get_admin_dashboard, inputs=sentiment_filter, outputs=[plot_output, table_output, status_txt])
 
 
 
 
 
 
 
 
 
 
 
113
 
114
  if __name__ == "__main__":
115
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
5
  import matplotlib.pyplot as plt
6
  import seaborn as sns
7
  from datetime import datetime
 
8
 
9
  # --- SETUP MODEL ---
10
+ # Menggunakan model RoBERTa Bahasa Indonesia untuk analisis sentimen
11
  MODEL_NAME = "w11wo/indonesian-roberta-base-sentiment-classifier"
12
  device = 0 if torch.cuda.is_available() else -1
13
  sentiment_pipeline = pipeline("sentiment-analysis", model=MODEL_NAME, device=device)
 
15
  # --- DATABASE SEDERHANA (In-Memory) ---
16
  all_messages = []
17
 
18
+ # Mapping Label untuk Tampilan UI agar lebih mudah dipahami manusia
19
  label_map = {
20
  "POSITIVE": "Pujian/Apresiasi",
21
  "NEGATIVE": "Keluhan/Kritik",
 
26
  if not text or text.strip() == "":
27
  return "⚠️ Mohon isi komentar Anda terlebih dahulu.", gr.update()
28
 
29
+ # 1. Analisis Sentimen menggunakan Pipeline Hugging Face
30
  result = sentiment_pipeline(text)[0]
31
  label = result['label'].upper()
32
 
33
+ # 2. Simpan ke Database Lokal dengan Timestamp
34
  new_entry = {
35
+ "Waktu": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
36
  "Pesan": text.strip(),
37
  "Sentimen": label
38
  }
 
44
 
45
  def get_admin_dashboard(filter_val):
46
  if not all_messages:
47
+ return None, pd.DataFrame(columns=["Waktu", "Pesan", "Sentimen"]), "Belum ada data."
48
 
49
  df_all = pd.DataFrame(all_messages)
50
 
51
  # --- LOGIKA FILTER ---
52
  if filter_val != "SEMUA":
53
+ # Balik mapping untuk mencari label asli (POSITIVE/NEGATIVE/NEUTRAL)
54
  rev_map = {v: k for k, v in label_map.items()}
55
  target = rev_map.get(filter_val)
56
  df_filtered = df_all[df_all['Sentimen'] == target]
 
58
  df_filtered = df_all
59
 
60
  if df_filtered.empty:
61
+ return None, pd.DataFrame(columns=["Waktu", "Pesan", "Sentimen"]), f"Tidak ada data untuk kategori: {filter_val}"
62
 
63
+ # --- VISUALISASI TOTAL (Pie Chart atau Bar Plot) ---
64
  fig, ax = plt.subplots(figsize=(8, 5))
 
65
  counts = df_all['Sentimen'].value_counts()
66
+ # Mengubah index angka/label asli ke label buatan kita (Pujian/Keluhan/dll)
67
  counts.index = [label_map.get(i, i) for i in counts.index]
68
 
69
  sns.barplot(x=counts.index, y=counts.values, palette="viridis", ax=ax)
70
  ax.set_title("Proporsi Pesan Masuk (Total)", fontsize=12, fontweight='bold')
71
+ ax.set_ylabel("Jumlah Pesan")
72
+
73
+ # --- TABEL DENGAN KOLOM WAKTU/TANGGAL ---
74
+ display_df = df_filtered[["Waktu", "Pesan", "Sentimen"]].copy()
75
+ display_df['Sentimen'] = display_df['Sentimen'].map(label_map) # Percantik label di tabel
76
+ display_df = display_df.sort_values(by="Waktu", ascending=False) # Urutkan: Terbaru di atas
77
+
78
+ return fig, display_df, f"Menampilkan {len(df_filtered)} pesan ({filter_val})"
79
 
80
  # --- INTERFACE GRADIO ---
81
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald"), title="PoskoLog Dashboard") as demo:
82
  gr.Markdown("# πŸ“¦ PoskoLog: Suara Pengungsi")
83
+ gr.Markdown("Sistem analisis sentimen otomatis untuk memprioritaskan laporan darurat pasca-bencana.")
84
 
85
  with gr.Tabs():
86
+ # --- TAB USER ---
87
  with gr.Tab("πŸ“ Sampaikan Pesan"):
88
  with gr.Column(variant="panel"):
89
+ gr.Markdown("### Laporkan kondisi atau berikan masukan Anda")
90
+ user_input = gr.Textbox(
91
+ label="Komentar Anda",
92
+ placeholder="Contoh: Bantuan air bersih belum sampai di tenda C...",
93
+ lines=4
94
+ )
95
  submit_btn = gr.Button("Kirim Pesan", variant="primary")
96
  user_feedback = gr.Markdown("")
97
 
98
+ # --- TAB ADMIN ---
99
  with gr.Tab("πŸ“Š Dashboard Admin"):
100
  with gr.Row():
101
  sentiment_filter = gr.Dropdown(
 
103
  value="SEMUA",
104
  label="Filter Sentimen"
105
  )
106
+ refresh_btn = gr.Button("πŸ”„ Refresh & Filter Data", variant="secondary")
107
 
108
  with gr.Row():
109
+ with gr.Column(scale=1):
110
  plot_output = gr.Plot(label="Grafik Distribusi")
111
+ with gr.Column(scale=2):
112
+ gr.Markdown("#### Daftar Laporan Masuk")
113
+ # Tabel diperbarui dengan kolom Waktu
114
+ table_output = gr.Dataframe(
115
+ headers=["Waktu", "Pesan", "Sentimen"],
116
+ interactive=False,
117
+ wrap=True
118
+ )
119
 
120
+ status_txt = gr.Markdown("Klik 'Refresh' untuk memuat data terbaru.")
121
 
122
+ # --- BINDING EVENTS ---
123
+ # Saat klik kirim: proses teks, beri feedback, dan kosongkan textbox
124
+ submit_btn.click(
125
+ fn=process_submission,
126
+ inputs=user_input,
127
+ outputs=[user_feedback, user_input]
128
+ )
129
+
130
+ # Saat klik refresh: update grafik dan tabel berdasarkan filter
131
+ refresh_btn.click(
132
+ fn=get_admin_dashboard,
133
+ inputs=sentiment_filter,
134
+ outputs=[plot_output, table_output, status_txt]
135
+ )
136
 
137
  if __name__ == "__main__":
138
  demo.launch(server_name="0.0.0.0", server_port=7860)