File size: 3,655 Bytes
6acab55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import io
import pandas as pd
import streamlit as st
import plotly.express as px
from utils.model_loader import predict_batch, model_is_available

st.markdown("## 📊 Analisis Batch")
st.caption("Unggah file CSV berisi ulasan produk untuk memproses sentimen secara massal.")

with st.container(border=True):
    uploaded = st.file_uploader(
        "Seret & letakkan file CSV di sini, atau klik untuk memilih file dari komputer",
        type=["csv"],
        help="Format: CSV · Maks: 20MB · Kolom teks harus ada",
    )
    st.caption("📄 Format: CSV · Maks: 20MB · Kolom teks (Butuh 1 kolom berisi teks ulasan)")
    st.caption("Belum ada file? [unduh contoh data](https://example.com) — atau gunakan `sample_data/contoh_ulasan.csv` di repo ini.")

if uploaded is not None:
    try:
        df = pd.read_csv(uploaded)
    except Exception as e:
        st.error(f"Gagal membaca CSV: {e}")
        st.stop()

    if df.empty:
        st.warning("File CSV kosong.")
        st.stop()

    st.write("")
    text_col = st.selectbox(
        "Pilih kolom yang berisi teks ulasan:",
        options=list(df.columns),
        index=0,
    )

    max_rows = st.slider("Jumlah baris yang diproses (batasi untuk demo cepat)", 1, len(df), min(len(df), 200))
    run = st.button("🚀 Jalankan Analisis Batch", type="primary")

    if run:
        subset = df.head(max_rows).copy()
        texts = subset[text_col].astype(str).tolist()

        progress_bar = st.progress(0.0, text="Memproses ulasan...")

        def _cb(frac):
            progress_bar.progress(frac, text=f"Memproses ulasan... {int(frac*100)}%")

        results = predict_batch(texts, progress_callback=_cb)
        progress_bar.empty()

        subset["Sentimen"] = [r[0] for r in results]
        subset["Confidence"] = [round(r[1] * 100, 2) for r in results]

        st.success(f"Selesai! {len(subset)} ulasan berhasil dianalisis.")

        st.markdown("#### Hasil Analisis")
        st.dataframe(subset, use_container_width=True, height=320)

        st.write("")
        col_pie, col_bar = st.columns(2)
        sent_counts = subset["Sentimen"].value_counts().reindex(["Positive", "Negative"]).fillna(0)

        with col_pie:
            fig_pie = px.pie(
                names=sent_counts.index, values=sent_counts.values,
                color=sent_counts.index,
                color_discrete_map={"Positive": "#2ecc71", "Negative": "#e74c3c"},
                title="Proporsi Sentimen",
                hole=0.35,
            )
            st.plotly_chart(fig_pie, use_container_width=True)

        with col_bar:
            fig_bar = px.bar(
                x=sent_counts.index, y=sent_counts.values,
                color=sent_counts.index,
                color_discrete_map={"Positive": "#2ecc71", "Negative": "#e74c3c"},
                labels={"x": "Sentimen", "y": "Jumlah Ulasan"},
                title="Distribusi Sentimen",
            )
            fig_bar.update_layout(showlegend=False)
            st.plotly_chart(fig_bar, use_container_width=True)

        csv_buffer = io.StringIO()
        subset.to_csv(csv_buffer, index=False)
        st.download_button(
            "⬇️ Unduh Hasil Analisis (CSV)",
            data=csv_buffer.getvalue(),
            file_name="hasil_analisis_sentimen.csv",
            mime="text/csv",
        )
else:
    st.info("Unggah file CSV untuk mulai menganalisis banyak ulasan sekaligus.")

if not model_is_available():
    st.caption(
        "⚠️ Model IndoBERT belum ditemukan — hasil batch di atas menggunakan mode demo "
        "(heuristik kata kunci). Lihat README.md untuk cara memasang model asli."
    )