DivYonko commited on
Commit ·
7da3a1d
1
Parent(s): c5feb54
Remove confidence trend chart and word cloud from Stats view
Browse files- frontend/streamlit_app.py +0 -94
- pages/stats.py +0 -91
frontend/streamlit_app.py
CHANGED
|
@@ -1372,37 +1372,6 @@ with col_t2:
|
|
| 1372 |
st.plotly_chart(fig_tpie, width='stretch', config={"displayModeBar": False})
|
| 1373 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 1374 |
|
| 1375 |
-
# ── Confidence trend ──────────────────────────────────────────
|
| 1376 |
-
if "confidence" in df.columns:
|
| 1377 |
-
st.divider()
|
| 1378 |
-
st.markdown('<div class="chart-wrap">', unsafe_allow_html=True)
|
| 1379 |
-
st.markdown('<div class="chart-title">Confidence Trend</div><div class="chart-sub">Model confidence per message in current window</div>', unsafe_allow_html=True)
|
| 1380 |
-
conf_df = df[["confidence"]].reset_index(drop=True)
|
| 1381 |
-
conf_df.index.name = "message_index"
|
| 1382 |
-
fig_line = go.Figure(go.Scatter(
|
| 1383 |
-
x=conf_df.index,
|
| 1384 |
-
y=conf_df["confidence"],
|
| 1385 |
-
mode="lines",
|
| 1386 |
-
line=dict(color="#7c3aed", width=2),
|
| 1387 |
-
fill="tozeroy",
|
| 1388 |
-
fillcolor="rgba(124,58,237,0.08)",
|
| 1389 |
-
hovertemplate="Msg %{x}: <b>%{y:.2f}</b><extra></extra>",
|
| 1390 |
-
))
|
| 1391 |
-
fig_line.update_layout(**plotly_layout(180))
|
| 1392 |
-
fig_line.update_yaxes(range=[0, 1])
|
| 1393 |
-
st.plotly_chart(fig_line, width='stretch', config={"displayModeBar": False})
|
| 1394 |
-
conf_hdr, conf_dl = st.columns([1, 1])
|
| 1395 |
-
with conf_hdr:
|
| 1396 |
-
show_conf_data = st.checkbox("View data", key="show_conf")
|
| 1397 |
-
with conf_dl:
|
| 1398 |
-
conf_export = conf_df.reset_index()
|
| 1399 |
-
conf_export.columns = ["message_index", "confidence"]
|
| 1400 |
-
csv_download(conf_export, "Download CSV", "confidence_trend.csv")
|
| 1401 |
-
if show_conf_data:
|
| 1402 |
-
st.dataframe(conf_export, width='stretch', hide_index=True)
|
| 1403 |
-
st.markdown('</div>', unsafe_allow_html=True)
|
| 1404 |
-
|
| 1405 |
-
|
| 1406 |
# ── SENTIMENT HEATMAP OVER TIME ───────────────────────────────
|
| 1407 |
st.divider()
|
| 1408 |
st.markdown(
|
|
@@ -1902,69 +1871,6 @@ else:
|
|
| 1902 |
unsafe_allow_html=True
|
| 1903 |
)
|
| 1904 |
|
| 1905 |
-
# ── WORD CLOUD ────────────────────────────────────────────────
|
| 1906 |
-
st.divider()
|
| 1907 |
-
st.markdown(
|
| 1908 |
-
'<div class="sec-hdr"><span class="sec-ttl">Word Cloud</span><span class="sec-pill">All Time</span></div>',
|
| 1909 |
-
unsafe_allow_html=True
|
| 1910 |
-
)
|
| 1911 |
-
|
| 1912 |
-
wc_col1, wc_col2, wc_col3 = st.columns([1, 1, 3])
|
| 1913 |
-
with wc_col1:
|
| 1914 |
-
wc_sentiment = st.selectbox("Filter sentiment", ["All", "Positive", "Neutral", "Negative"], key="wc_sent")
|
| 1915 |
-
with wc_col2:
|
| 1916 |
-
wc_topic = st.selectbox("Filter topic", ["All"] + TOPIC_LABELS, key="wc_topic")
|
| 1917 |
-
|
| 1918 |
-
_wc_json = json.dumps([{"text": m.get("text",""), "sentiment": m.get("sentiment","Neutral"), "topic": m.get("topic","General")} for m in all_data])
|
| 1919 |
-
word_freq = compute_word_freq(_wc_json, sentiment_filter=wc_sentiment, topic_filter=wc_topic)
|
| 1920 |
-
|
| 1921 |
-
if word_freq:
|
| 1922 |
-
try:
|
| 1923 |
-
from wordcloud import WordCloud
|
| 1924 |
-
import matplotlib.pyplot as plt
|
| 1925 |
-
import io
|
| 1926 |
-
|
| 1927 |
-
freq_dict = dict(word_freq)
|
| 1928 |
-
wc = WordCloud(
|
| 1929 |
-
width=900, height=320,
|
| 1930 |
-
background_color="white",
|
| 1931 |
-
colormap="cool",
|
| 1932 |
-
max_words=80,
|
| 1933 |
-
prefer_horizontal=0.85,
|
| 1934 |
-
collocations=False,
|
| 1935 |
-
).generate_from_frequencies(freq_dict)
|
| 1936 |
-
|
| 1937 |
-
st.markdown('<div class="chart-wrap">', unsafe_allow_html=True)
|
| 1938 |
-
st.image(wc.to_array(), width="stretch")
|
| 1939 |
-
st.markdown('</div>', unsafe_allow_html=True)
|
| 1940 |
-
|
| 1941 |
-
# Also show top 20 as a bar chart
|
| 1942 |
-
top20 = word_freq[:20]
|
| 1943 |
-
fig_wf = go.Figure(go.Bar(
|
| 1944 |
-
x=[w for w, _ in top20],
|
| 1945 |
-
y=[c for _, c in top20],
|
| 1946 |
-
marker_color="#7c3aed",
|
| 1947 |
-
marker_line_width=0,
|
| 1948 |
-
hovertemplate="<b>%{x}</b><br>%{y} times<extra></extra>",
|
| 1949 |
-
))
|
| 1950 |
-
layout_wf = plotly_layout(180)
|
| 1951 |
-
fig_wf.update_layout(**layout_wf)
|
| 1952 |
-
st.plotly_chart(fig_wf, width='stretch', config={"displayModeBar": False})
|
| 1953 |
-
|
| 1954 |
-
except ImportError:
|
| 1955 |
-
# Fallback: just show bar chart if wordcloud not available
|
| 1956 |
-
top20 = word_freq[:20]
|
| 1957 |
-
fig_wf = go.Figure(go.Bar(
|
| 1958 |
-
x=[w for w, _ in top20],
|
| 1959 |
-
y=[c for _, c in top20],
|
| 1960 |
-
marker_color="#7c3aed",
|
| 1961 |
-
marker_line_width=0,
|
| 1962 |
-
))
|
| 1963 |
-
fig_wf.update_layout(**plotly_layout(200))
|
| 1964 |
-
st.plotly_chart(fig_wf, width='stretch', config={"displayModeBar": False})
|
| 1965 |
-
else:
|
| 1966 |
-
st.info("Not enough text data yet.")
|
| 1967 |
-
|
| 1968 |
# ── MULTI-STREAM COMPARISON ───────────────────────────────────
|
| 1969 |
active_streams = [s for s in st.session_state.streams if r.llen(s["redis_key"]) > 0]
|
| 1970 |
|
|
|
|
| 1372 |
st.plotly_chart(fig_tpie, width='stretch', config={"displayModeBar": False})
|
| 1373 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 1374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1375 |
# ── SENTIMENT HEATMAP OVER TIME ───────────────────────────────
|
| 1376 |
st.divider()
|
| 1377 |
st.markdown(
|
|
|
|
| 1871 |
unsafe_allow_html=True
|
| 1872 |
)
|
| 1873 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1874 |
# ── MULTI-STREAM COMPARISON ───────────────────────────────────
|
| 1875 |
active_streams = [s for s in st.session_state.streams if r.llen(s["redis_key"]) > 0]
|
| 1876 |
|
pages/stats.py
CHANGED
|
@@ -326,36 +326,6 @@ with col_t2:
|
|
| 326 |
st.plotly_chart(fig_tpie, config={"displayModeBar": False})
|
| 327 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 328 |
|
| 329 |
-
# -- Confidence trend -----------------------------------------
|
| 330 |
-
if "confidence" in df.columns:
|
| 331 |
-
st.divider()
|
| 332 |
-
st.markdown('<div class="chart-wrap">', unsafe_allow_html=True)
|
| 333 |
-
st.markdown('<div class="chart-title">Confidence Trend</div><div class="chart-sub">Model confidence per message in current window</div>', unsafe_allow_html=True)
|
| 334 |
-
conf_df = df[["confidence"]].reset_index(drop=True)
|
| 335 |
-
conf_df.index.name = "message_index"
|
| 336 |
-
fig_line = go.Figure(go.Scatter(
|
| 337 |
-
x=conf_df.index,
|
| 338 |
-
y=conf_df["confidence"],
|
| 339 |
-
mode="lines",
|
| 340 |
-
line=dict(color="#7c3aed", width=2),
|
| 341 |
-
fill="tozeroy",
|
| 342 |
-
fillcolor="rgba(124,58,237,0.08)",
|
| 343 |
-
hovertemplate="Msg %{x}: <b>%{y:.2f}</b><extra></extra>",
|
| 344 |
-
))
|
| 345 |
-
fig_line.update_layout(**plotly_layout(180))
|
| 346 |
-
fig_line.update_yaxes(range=[0, 1])
|
| 347 |
-
st.plotly_chart(fig_line, config={"displayModeBar": False})
|
| 348 |
-
conf_hdr, conf_dl = st.columns([1, 1])
|
| 349 |
-
with conf_hdr:
|
| 350 |
-
show_conf_data = st.checkbox("View data", key="show_conf")
|
| 351 |
-
with conf_dl:
|
| 352 |
-
conf_export = conf_df.reset_index()
|
| 353 |
-
conf_export.columns = ["message_index", "confidence"]
|
| 354 |
-
csv_download(conf_export, "Download CSV", "confidence_trend.csv")
|
| 355 |
-
if show_conf_data:
|
| 356 |
-
st.dataframe(conf_export, hide_index=True)
|
| 357 |
-
st.markdown('</div>', unsafe_allow_html=True)
|
| 358 |
-
|
| 359 |
# -- SENTIMENT HEATMAP OVER TIME ------------------------------
|
| 360 |
st.divider()
|
| 361 |
st.markdown(
|
|
@@ -841,67 +811,6 @@ else:
|
|
| 841 |
unsafe_allow_html=True
|
| 842 |
)
|
| 843 |
|
| 844 |
-
# -- WORD CLOUD -----------------------------------------------
|
| 845 |
-
st.divider()
|
| 846 |
-
st.markdown(
|
| 847 |
-
'<div class="sec-hdr"><span class="sec-ttl">Word Cloud</span><span class="sec-pill">All Time</span></div>',
|
| 848 |
-
unsafe_allow_html=True
|
| 849 |
-
)
|
| 850 |
-
|
| 851 |
-
wc_col1, wc_col2, wc_col3 = st.columns([1, 1, 3])
|
| 852 |
-
with wc_col1:
|
| 853 |
-
wc_sentiment = st.selectbox("Filter sentiment", ["All", "Positive", "Neutral", "Negative"], key="wc_sent")
|
| 854 |
-
with wc_col2:
|
| 855 |
-
wc_topic = st.selectbox("Filter topic", ["All"] + TOPIC_LABELS, key="wc_topic")
|
| 856 |
-
|
| 857 |
-
_wc_json = json.dumps([{"text": m.get("text",""), "sentiment": m.get("sentiment","Neutral"), "topic": m.get("topic","General")} for m in all_data])
|
| 858 |
-
word_freq = compute_word_freq(_wc_json, sentiment_filter=wc_sentiment, topic_filter=wc_topic)
|
| 859 |
-
|
| 860 |
-
if word_freq:
|
| 861 |
-
try:
|
| 862 |
-
from wordcloud import WordCloud
|
| 863 |
-
import matplotlib.pyplot as plt
|
| 864 |
-
import io
|
| 865 |
-
|
| 866 |
-
freq_dict = dict(word_freq)
|
| 867 |
-
wc = WordCloud(
|
| 868 |
-
width=900, height=320,
|
| 869 |
-
background_color="white",
|
| 870 |
-
colormap="cool",
|
| 871 |
-
max_words=80,
|
| 872 |
-
prefer_horizontal=0.85,
|
| 873 |
-
collocations=False,
|
| 874 |
-
).generate_from_frequencies(freq_dict)
|
| 875 |
-
|
| 876 |
-
st.markdown('<div class="chart-wrap">', unsafe_allow_html=True)
|
| 877 |
-
st.image(wc.to_array())
|
| 878 |
-
st.markdown('</div>', unsafe_allow_html=True)
|
| 879 |
-
|
| 880 |
-
top20 = word_freq[:20]
|
| 881 |
-
fig_wf = go.Figure(go.Bar(
|
| 882 |
-
x=[w for w, _ in top20],
|
| 883 |
-
y=[c for _, c in top20],
|
| 884 |
-
marker_color="#7c3aed",
|
| 885 |
-
marker_line_width=0,
|
| 886 |
-
hovertemplate="<b>%{x}</b><br>%{y} times<extra></extra>",
|
| 887 |
-
))
|
| 888 |
-
layout_wf = plotly_layout(180)
|
| 889 |
-
fig_wf.update_layout(**layout_wf)
|
| 890 |
-
st.plotly_chart(fig_wf, config={"displayModeBar": False})
|
| 891 |
-
|
| 892 |
-
except ImportError:
|
| 893 |
-
top20 = word_freq[:20]
|
| 894 |
-
fig_wf = go.Figure(go.Bar(
|
| 895 |
-
x=[w for w, _ in top20],
|
| 896 |
-
y=[c for _, c in top20],
|
| 897 |
-
marker_color="#7c3aed",
|
| 898 |
-
marker_line_width=0,
|
| 899 |
-
))
|
| 900 |
-
fig_wf.update_layout(**plotly_layout(200))
|
| 901 |
-
st.plotly_chart(fig_wf, config={"displayModeBar": False})
|
| 902 |
-
else:
|
| 903 |
-
st.info("Not enough text data yet.")
|
| 904 |
-
|
| 905 |
# -- MULTI-STREAM COMPARISON ----------------------------------
|
| 906 |
active_streams = [s for s in st.session_state.streams if store_llen(s["redis_key"]) > 0]
|
| 907 |
|
|
|
|
| 326 |
st.plotly_chart(fig_tpie, config={"displayModeBar": False})
|
| 327 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 328 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
# -- SENTIMENT HEATMAP OVER TIME ------------------------------
|
| 330 |
st.divider()
|
| 331 |
st.markdown(
|
|
|
|
| 811 |
unsafe_allow_html=True
|
| 812 |
)
|
| 813 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 814 |
# -- MULTI-STREAM COMPARISON ----------------------------------
|
| 815 |
active_streams = [s for s in st.session_state.streams if store_llen(s["redis_key"]) > 0]
|
| 816 |
|