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