-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
113 lines (90 loc) · 3.99 KB
/
app.py
File metadata and controls
113 lines (90 loc) · 3.99 KB
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
# app.py
"""Streamlit UI for SentiBot — delegates all analysis to analyzer.py."""
from __future__ import annotations
import csv
import io
from typing import Any
import pandas as pd
import streamlit as st
from analyzer import analyze_sentiment, load_csv, save_results
# ── helpers ───────────────────────────────────────────────────────────────────
def _label_color(label: str) -> str:
"""Map sentiment label to a Streamlit color name."""
return {"positive": "green", "negative": "red"}.get(label, "gray")
def _result_card(result: dict[str, Any]) -> None:
"""Render a color-coded sentiment result card."""
color = _label_color(result["label"])
confidence = result["confidence"]
st.markdown(
f'<div style="border-left:4px solid {color};padding-left:12px;">',
unsafe_allow_html=True,
)
col1, col2, col3 = st.columns(3)
col1.metric("Sentiment", result["label"].capitalize())
col2.metric("Confidence", f"{confidence:.0%}")
col3.metric("Tokens Used", result["tokens_used"])
st.progress(confidence)
st.markdown("</div>", unsafe_allow_html=True)
# ── tabs ──────────────────────────────────────────────────────────────────────
def render_text_tab() -> None:
"""Render the single-text analysis tab."""
text = st.text_area(
"Text to analyze",
placeholder="Type or paste text here…",
label_visibility="collapsed",
)
if st.button("Analyze"):
if not text or not text.strip():
st.warning("Please enter some text.")
return
try:
with st.spinner("Analyzing…"):
result = analyze_sentiment(text)
_result_card(result)
except Exception as exc: # noqa: BLE001
st.error(f"Error: {exc}")
def render_batch_tab() -> None:
"""Render the CSV batch analysis tab."""
uploaded_file = st.file_uploader("Upload a CSV file", type=["csv"])
if st.button("Analyze Batch", disabled=uploaded_file is None):
try:
content = uploaded_file.getvalue().decode("utf-8")
reader = csv.reader(io.StringIO(content))
next(reader, None) # skip header row
texts = [row[0] for row in reader if row]
if not texts:
st.warning("No data rows found in the CSV file.")
return
results: list[dict[str, Any]] = []
progress = st.progress(0.0)
for i, text in enumerate(texts):
results.append(analyze_sentiment(text))
progress.progress((i + 1) / len(texts))
df = pd.DataFrame(
results,
columns=["text", "label", "confidence", "tokens_used", "model"],
)
st.dataframe(df)
buf = io.StringIO()
writer = csv.DictWriter(
buf,
fieldnames=["text", "label", "confidence", "tokens_used", "model"],
)
writer.writeheader()
writer.writerows(results)
st.download_button(
label="Download Results CSV",
data=buf.getvalue().encode("utf-8"),
file_name="sentiment_results.csv",
mime="text/csv",
)
except Exception as exc: # noqa: BLE001
st.error(f"Error: {exc}")
# ── page ──────────────────────────────────────────────────────────────────────
st.set_page_config(page_title="SentiBot", layout="wide")
st.title("SentiBot")
tab_text, tab_batch = st.tabs(["Analyze Text", "Batch CSV"])
with tab_text:
render_text_tab()
with tab_batch:
render_batch_tab()