Download sentiment_app.py from Ferdinann/PoskoLog: direct link, hf CLI and curl.
- Browser
- Download file 5.42 kB
-
https://huggingface.co/spaces/Ferdinann/PoskoLog/resolve/main/sentiment_app.py
- Command line
-
hf download hf://spaces/Ferdinann/PoskoLog/sentiment_app.py
-
curl -L -o sentiment_app.py https://huggingface.co/spaces/Ferdinann/PoskoLog/resolve/main/sentiment_app.py
5.42 kB
| 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) |