Spaces:
Running
Running
Update frontend.py
Browse files- frontend.py +42 -27
frontend.py
CHANGED
@@ -22,6 +22,8 @@ if "dark_mode" not in st.session_state:
|
|
22 |
st.session_state.dark_mode = False
|
23 |
if "intelligence_mode" not in st.session_state:
|
24 |
st.session_state.intelligence_mode = True
|
|
|
|
|
25 |
|
26 |
# Apply Dark Mode Styling
|
27 |
if st.session_state.dark_mode:
|
@@ -48,13 +50,11 @@ with st.sidebar:
|
|
48 |
st.session_state.dark_mode = st.toggle("🌙 Dark Mode", value=st.session_state.dark_mode)
|
49 |
st.session_state.intelligence_mode = st.toggle("🧠 Intelligence Mode", value=st.session_state.intelligence_mode)
|
50 |
|
51 |
-
DEFAULT_DEMO_TOKEN = "my-secret-key"
|
52 |
api_token = st.text_input("🔐 API Token", value=DEFAULT_DEMO_TOKEN, type="password")
|
53 |
-
# 🟡 Insert this warning right after the token field
|
54 |
if not api_token or api_token.strip() == "my-secret-key":
|
55 |
st.warning("🧪 Running in demo mode — for full access, enter a valid API key.")
|
56 |
|
57 |
-
|
58 |
backend_url = st.text_input("🌐 Backend URL", value="http://localhost:8000")
|
59 |
|
60 |
sentiment_model = st.selectbox("📊 Sentiment Model", [
|
@@ -76,12 +76,10 @@ with st.sidebar:
|
|
76 |
use_aspects = st.checkbox("🔬 Enable Aspect Analysis")
|
77 |
use_smart_summary = st.checkbox("🧠 Smart Summary (Single)")
|
78 |
use_smart_summary_bulk = st.checkbox("🧠 Smart Summary for Bulk")
|
79 |
-
|
80 |
verbosity = st.radio("🗣️ Response Style", ["Brief", "Detailed"])
|
81 |
-
follow_up = st.text_input("🔁 Follow-up Question")
|
82 |
voice_lang = st.selectbox("🔈 Voice Language", ["en", "fr", "es", "de", "hi", "zh"])
|
83 |
|
84 |
-
#
|
85 |
def speak(text, lang='en'):
|
86 |
tts = gTTS(text, lang=lang)
|
87 |
mp3 = BytesIO()
|
@@ -105,16 +103,24 @@ with tab1:
|
|
105 |
analyze = st.button("🔍 Analyze", use_container_width=True, disabled=not api_token)
|
106 |
with col2:
|
107 |
if st.button("🎲 Example", use_container_width=True):
|
108 |
-
st.session_state.review =
|
|
|
|
|
|
|
|
|
109 |
st.rerun()
|
110 |
with col3:
|
111 |
if st.button("🧹 Clear", use_container_width=True):
|
112 |
st.session_state.review = ""
|
113 |
st.rerun()
|
114 |
|
|
|
|
|
|
|
|
|
115 |
if analyze and review:
|
116 |
-
if len(review.split()) <
|
117 |
-
st.warning("⚠️ Please enter at least
|
118 |
else:
|
119 |
with st.spinner("Analyzing..."):
|
120 |
try:
|
@@ -123,7 +129,7 @@ with tab1:
|
|
123 |
"model": sentiment_model,
|
124 |
"industry": industry,
|
125 |
"aspects": use_aspects,
|
126 |
-
"follow_up":
|
127 |
"product_category": product_category,
|
128 |
"verbosity": verbosity,
|
129 |
"intelligence": st.session_state.intelligence_mode
|
@@ -152,19 +158,34 @@ with tab1:
|
|
152 |
for a in data["aspects"]:
|
153 |
st.write(f"🔹 {a['aspect']}: {a['sentiment']} ({a['score']:.2%})")
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
else:
|
163 |
st.error(f"❌ API Error {res.status_code}: {res.json().get('detail', 'Unknown error')}")
|
164 |
-
|
165 |
except Exception as e:
|
166 |
st.error(f"🚫 Exception occurred: {e}")
|
167 |
-
|
168 |
# --- BULK CSV ---
|
169 |
with tab2:
|
170 |
st.title("📚 Bulk CSV Upload")
|
@@ -194,7 +215,6 @@ with tab2:
|
|
194 |
df[col] = ["Auto-detect"] * len(df)
|
195 |
df[col] = df[col].fillna("Auto-detect").astype(str)
|
196 |
|
197 |
-
# Replace "Auto-detect" with fallback
|
198 |
df["industry"] = df["industry"].apply(lambda x: "Generic" if x.lower() == "auto-detect" else x)
|
199 |
df["product_category"] = df["product_category"].apply(lambda x: "General" if x.lower() == "auto-detect" else x)
|
200 |
df["device"] = df["device"].apply(lambda x: "Web" if x.lower() == "auto-detect" else x)
|
@@ -211,21 +231,16 @@ with tab2:
|
|
211 |
"device": df["device"].tolist(),
|
212 |
"intelligence": st.session_state.intelligence_mode,
|
213 |
}
|
214 |
-
|
215 |
-
# ✅ Updated: Pass token as query param (NOT in headers)
|
216 |
res = requests.post(
|
217 |
-
f"{backend_url}/bulk/?token={api_token}",
|
218 |
json=payload
|
219 |
)
|
220 |
-
|
221 |
if res.status_code == 200:
|
222 |
results = pd.DataFrame(res.json()["results"])
|
223 |
st.dataframe(results)
|
224 |
-
|
225 |
-
if "sentiment" in results:
|
226 |
fig = px.pie(results, names="sentiment", title="Sentiment Distribution")
|
227 |
st.plotly_chart(fig)
|
228 |
-
|
229 |
st.download_button("⬇️ Download Results CSV", results.to_csv(index=False), "results.csv", mime="text/csv")
|
230 |
else:
|
231 |
st.error(f"❌ Bulk Error {res.status_code}: {res.json().get('detail', 'Unknown error')}")
|
|
|
22 |
st.session_state.dark_mode = False
|
23 |
if "intelligence_mode" not in st.session_state:
|
24 |
st.session_state.intelligence_mode = True
|
25 |
+
if "trigger_example_analysis" not in st.session_state:
|
26 |
+
st.session_state.trigger_example_analysis = False
|
27 |
|
28 |
# Apply Dark Mode Styling
|
29 |
if st.session_state.dark_mode:
|
|
|
50 |
st.session_state.dark_mode = st.toggle("🌙 Dark Mode", value=st.session_state.dark_mode)
|
51 |
st.session_state.intelligence_mode = st.toggle("🧠 Intelligence Mode", value=st.session_state.intelligence_mode)
|
52 |
|
53 |
+
DEFAULT_DEMO_TOKEN = "my-secret-key"
|
54 |
api_token = st.text_input("🔐 API Token", value=DEFAULT_DEMO_TOKEN, type="password")
|
|
|
55 |
if not api_token or api_token.strip() == "my-secret-key":
|
56 |
st.warning("🧪 Running in demo mode — for full access, enter a valid API key.")
|
57 |
|
|
|
58 |
backend_url = st.text_input("🌐 Backend URL", value="http://localhost:8000")
|
59 |
|
60 |
sentiment_model = st.selectbox("📊 Sentiment Model", [
|
|
|
76 |
use_aspects = st.checkbox("🔬 Enable Aspect Analysis")
|
77 |
use_smart_summary = st.checkbox("🧠 Smart Summary (Single)")
|
78 |
use_smart_summary_bulk = st.checkbox("🧠 Smart Summary for Bulk")
|
|
|
79 |
verbosity = st.radio("🗣️ Response Style", ["Brief", "Detailed"])
|
|
|
80 |
voice_lang = st.selectbox("🔈 Voice Language", ["en", "fr", "es", "de", "hi", "zh"])
|
81 |
|
82 |
+
# TTS
|
83 |
def speak(text, lang='en'):
|
84 |
tts = gTTS(text, lang=lang)
|
85 |
mp3 = BytesIO()
|
|
|
103 |
analyze = st.button("🔍 Analyze", use_container_width=True, disabled=not api_token)
|
104 |
with col2:
|
105 |
if st.button("🎲 Example", use_container_width=True):
|
106 |
+
st.session_state.review = (
|
107 |
+
"I love this phone! Super fast performance, great battery, and smooth UI. "
|
108 |
+
"Camera is awesome too, though the price is a bit high. Overall, very happy."
|
109 |
+
)
|
110 |
+
st.session_state.trigger_example_analysis = True
|
111 |
st.rerun()
|
112 |
with col3:
|
113 |
if st.button("🧹 Clear", use_container_width=True):
|
114 |
st.session_state.review = ""
|
115 |
st.rerun()
|
116 |
|
117 |
+
if st.session_state.trigger_example_analysis and st.session_state.review:
|
118 |
+
analyze = True
|
119 |
+
st.session_state.trigger_example_analysis = False
|
120 |
+
|
121 |
if analyze and review:
|
122 |
+
if len(review.split()) < 20:
|
123 |
+
st.warning("⚠️ Please enter at least 20 words.")
|
124 |
else:
|
125 |
with st.spinner("Analyzing..."):
|
126 |
try:
|
|
|
129 |
"model": sentiment_model,
|
130 |
"industry": industry,
|
131 |
"aspects": use_aspects,
|
132 |
+
"follow_up": None,
|
133 |
"product_category": product_category,
|
134 |
"verbosity": verbosity,
|
135 |
"intelligence": st.session_state.intelligence_mode
|
|
|
158 |
for a in data["aspects"]:
|
159 |
st.write(f"🔹 {a['aspect']}: {a['sentiment']} ({a['score']:.2%})")
|
160 |
|
161 |
+
# --- Follow-Up Section ---
|
162 |
+
st.markdown("### 🔁 Got questions?")
|
163 |
+
st.info("💬 You can ask a follow-up question based on this review summary.")
|
164 |
+
sample_questions = [
|
165 |
+
"What did the user like most?",
|
166 |
+
"Any complaints mentioned?",
|
167 |
+
"Is it positive overall?",
|
168 |
+
"What are the improvement areas?"
|
169 |
+
]
|
170 |
+
selected_q = st.selectbox("💡 Sample Questions", ["Type your own..."] + sample_questions)
|
171 |
+
custom_q = st.text_input("🔍 Ask a follow-up", value="" if selected_q == "Type your own..." else selected_q)
|
172 |
+
|
173 |
+
if custom_q:
|
174 |
+
with st.spinner("Thinking..."):
|
175 |
+
payload["follow_up"] = custom_q
|
176 |
+
res = requests.post(f"{backend_url}/analyze/", json=payload, headers=headers, params=params)
|
177 |
+
if res.status_code == 200:
|
178 |
+
follow = res.json().get("follow_up")
|
179 |
+
if follow:
|
180 |
+
st.subheader("🔁 Follow-Up Answer")
|
181 |
+
st.warning(follow)
|
182 |
+
else:
|
183 |
+
st.error(f"❌ Follow-up failed: {res.json().get('detail')}")
|
184 |
else:
|
185 |
st.error(f"❌ API Error {res.status_code}: {res.json().get('detail', 'Unknown error')}")
|
|
|
186 |
except Exception as e:
|
187 |
st.error(f"🚫 Exception occurred: {e}")
|
188 |
+
|
189 |
# --- BULK CSV ---
|
190 |
with tab2:
|
191 |
st.title("📚 Bulk CSV Upload")
|
|
|
215 |
df[col] = ["Auto-detect"] * len(df)
|
216 |
df[col] = df[col].fillna("Auto-detect").astype(str)
|
217 |
|
|
|
218 |
df["industry"] = df["industry"].apply(lambda x: "Generic" if x.lower() == "auto-detect" else x)
|
219 |
df["product_category"] = df["product_category"].apply(lambda x: "General" if x.lower() == "auto-detect" else x)
|
220 |
df["device"] = df["device"].apply(lambda x: "Web" if x.lower() == "auto-detect" else x)
|
|
|
231 |
"device": df["device"].tolist(),
|
232 |
"intelligence": st.session_state.intelligence_mode,
|
233 |
}
|
|
|
|
|
234 |
res = requests.post(
|
235 |
+
f"{backend_url}/bulk/?token={st.session_state.get('api_token', api_token)}",
|
236 |
json=payload
|
237 |
)
|
|
|
238 |
if res.status_code == 200:
|
239 |
results = pd.DataFrame(res.json()["results"])
|
240 |
st.dataframe(results)
|
241 |
+
if "sentiment" in results.columns:
|
|
|
242 |
fig = px.pie(results, names="sentiment", title="Sentiment Distribution")
|
243 |
st.plotly_chart(fig)
|
|
|
244 |
st.download_button("⬇️ Download Results CSV", results.to_csv(index=False), "results.csv", mime="text/csv")
|
245 |
else:
|
246 |
st.error(f"❌ Bulk Error {res.status_code}: {res.json().get('detail', 'Unknown error')}")
|