Hasitha16 commited on
Commit
4c20abe
ยท
verified ยท
1 Parent(s): 939ac52

Update frontend.py

Browse files
Files changed (1) hide show
  1. frontend.py +202 -26
frontend.py CHANGED
@@ -1,45 +1,221 @@
1
  import streamlit as st
2
  import requests
 
3
  from gtts import gTTS
4
  import base64
5
  from io import BytesIO
 
 
 
6
 
7
  st.set_page_config(page_title="NeuroPulse AI", page_icon="๐Ÿง ", layout="wide")
8
 
 
 
 
 
 
 
9
  if "review" not in st.session_state:
10
  st.session_state.review = ""
11
  if "dark_mode" not in st.session_state:
12
  st.session_state.dark_mode = False
 
 
13
 
 
14
  if st.session_state.dark_mode:
15
- st.markdown("""<style>body { background-color: #111; color: white; }</style>""", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
 
17
  with st.sidebar:
18
- st.title("โš™๏ธ Settings")
19
  st.session_state.dark_mode = st.toggle("๐ŸŒ™ Dark Mode", value=st.session_state.dark_mode)
20
- api_key = st.text_input("๐Ÿ” API Key", type="password")
 
 
21
  backend_url = st.text_input("๐ŸŒ Backend URL", value="http://localhost:8000")
22
 
23
- st.title("๐Ÿง  NeuroPulse AI โ€“ Multimodal Review Analyzer")
24
- review = st.text_area("๐Ÿ“ Enter Review", value=st.session_state.review, height=150)
25
-
26
- if st.button("๐Ÿ” Analyze", use_container_width=True):
27
- if not api_key:
28
- st.error("โš ๏ธ Please enter API key.")
29
- elif len(review.split()) < 10:
30
- st.warning("๐Ÿ“ Minimum 10 words required.")
31
- else:
32
- with st.spinner("Processing..."):
33
- try:
34
- payload = {"text": review}
35
- headers = {"x-api-key": api_key}
36
- res = requests.post(f"{backend_url}/analyze/", json=payload, headers=headers)
37
- if res.status_code == 200:
38
- data = res.json()
39
- st.success("โœ… Analysis Successful")
40
- st.info(f"๐Ÿ“Œ Summary: {data['summary']}")
41
- st.metric("๐Ÿ“Š Sentiment", data["sentiment"]["label"])
42
- else:
43
- st.error(f"โŒ API Error: {res.status_code} - {res.text}")
44
- except Exception as e:
45
- st.error(f"๐Ÿšซ Exception: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import requests
3
+ import pandas as pd
4
  from gtts import gTTS
5
  import base64
6
  from io import BytesIO
7
+ from PIL import Image
8
+ import os
9
+ import plotly.express as px
10
 
11
  st.set_page_config(page_title="NeuroPulse AI", page_icon="๐Ÿง ", layout="wide")
12
 
13
+ # Load logo
14
+ logo_path = os.path.join("app", "static", "logo.png")
15
+ if os.path.exists(logo_path):
16
+ st.image(logo_path, width=160)
17
+
18
+ # Session State
19
  if "review" not in st.session_state:
20
  st.session_state.review = ""
21
  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:
28
+ st.markdown("""
29
+ <style>
30
+ html, body, [class*="st-"] {
31
+ background-color: #1e1e1e;
32
+ color: #f5f5f5;
33
+ }
34
+ .stTextInput > div > div > input, .stTextArea > div > textarea {
35
+ background-color: #2b2b2b;
36
+ color: white;
37
+ }
38
+ .stButton > button {
39
+ background-color: #333;
40
+ color: white;
41
+ }
42
+ .stDownloadButton > button {
43
+ background-color: #444;
44
+ color: white;
45
+ }
46
+ .stSelectbox, .stCheckbox, .stRadio, .stFileUploader {
47
+ background-color: #2b2b2b;
48
+ color: white;
49
+ }
50
+ </style>
51
+ """, unsafe_allow_html=True)
52
 
53
+ # Sidebar controls
54
  with st.sidebar:
55
+ st.header("โš™๏ธ Global Settings")
56
  st.session_state.dark_mode = st.toggle("๐ŸŒ™ Dark Mode", value=st.session_state.dark_mode)
57
+ st.session_state.intelligence_mode = st.toggle("๐Ÿง  Intelligence Mode", value=st.session_state.intelligence_mode)
58
+
59
+ api_token = st.text_input("๐Ÿ” API Token", type="password")
60
  backend_url = st.text_input("๐ŸŒ Backend URL", value="http://localhost:8000")
61
 
62
+ sentiment_model = st.selectbox("๐Ÿ“Š Sentiment Model", [
63
+ "distilbert-base-uncased-finetuned-sst-2-english",
64
+ "nlptown/bert-base-multilingual-uncased-sentiment"
65
+ ])
66
+
67
+ industry = st.selectbox("๐Ÿญ Industry", [
68
+ "Auto-detect", "Generic", "E-commerce", "Healthcare", "Education", "Travel", "Banking", "Insurance", "Gaming", "Food Delivery", "Real Estate", "Fitness", "Entertainment"
69
+ ])
70
+
71
+ product_category = st.selectbox("๐Ÿงฉ Product Category", [
72
+ "Auto-detect", "General", "Mobile Devices", "Laptops", "Healthcare Devices", "Banking App", "Travel Service", "Educational Tool", "Insurance Portal", "Streaming App", "Wearables", "Home Appliances", "Food Apps"
73
+ ])
74
+
75
+ device_type = st.selectbox("๐Ÿ’ป Device", [
76
+ "Auto-detect", "Web", "Android", "iOS", "Desktop", "Smartwatch", "Kiosk"
77
+ ])
78
+
79
+ use_aspects = st.checkbox("๐Ÿ”ฌ Enable Aspect Analysis")
80
+ use_smart_summary = st.checkbox("๐Ÿง  Smart Summary (Single)")
81
+ use_smart_summary_bulk = st.checkbox("๐Ÿง  Smart Summary for Bulk")
82
+
83
+ verbosity = st.radio("๐Ÿ—ฃ๏ธ Response Style", ["Brief", "Detailed"])
84
+ follow_up = st.text_input("๐Ÿ” Follow-up Question")
85
+ voice_lang = st.selectbox("๐Ÿ”ˆ Voice Language", ["en", "fr", "es", "de", "hi", "zh"])
86
+
87
+ # Text-to-Speech Helper
88
+ def speak(text, lang='en'):
89
+ tts = gTTS(text, lang=lang)
90
+ mp3 = BytesIO()
91
+ tts.write_to_fp(mp3)
92
+ b64 = base64.b64encode(mp3.getvalue()).decode()
93
+ st.markdown(f'<audio controls><source src="data:audio/mp3;base64,{b64}" type="audio/mp3"></audio>', unsafe_allow_html=True)
94
+ mp3.seek(0)
95
+ return mp3
96
+
97
+ # Tabs
98
+ tab1, tab2 = st.tabs(["๐Ÿง  Single Review", "๐Ÿ“š Bulk CSV"])
99
+
100
+ # --- SINGLE ---
101
+ with tab1:
102
+ st.title("๐Ÿง  NeuroPulse AI โ€“ Multimodal Review Analyzer")
103
+ st.markdown("<div style='font-size:16px;color:#aaa;'>Minimum 50โ€“100 words recommended.</div>", unsafe_allow_html=True)
104
+
105
+ review = st.text_area("๐Ÿ“ Enter Review", value=st.session_state.review, height=180)
106
+
107
+ col1, col2, col3 = st.columns(3)
108
+ with col1:
109
+ analyze = st.button("๐Ÿ” Analyze", use_container_width=True, disabled=not api_token)
110
+ with col2:
111
+ if st.button("๐ŸŽฒ Example", use_container_width=True):
112
+ st.session_state.review = "App was smooth, but the transaction failed twice on Android during checkout."
113
+ st.rerun()
114
+ with col3:
115
+ if st.button("๐Ÿงน Clear", use_container_width=True):
116
+ st.session_state.review = ""
117
+ st.rerun()
118
+
119
+ if analyze and review:
120
+ if len(review.split()) < 50:
121
+ st.warning("โš ๏ธ Please enter at least 50 words.")
122
+ else:
123
+ with st.spinner("Analyzing..."):
124
+ try:
125
+ payload = {
126
+ "text": review,
127
+ "model": sentiment_model,
128
+ "industry": industry,
129
+ "aspects": use_aspects,
130
+ "follow_up": follow_up,
131
+ "product_category": product_category,
132
+ "device": device_type,
133
+ "verbosity": verbosity,
134
+ "intelligence": st.session_state.intelligence_mode
135
+ }
136
+ headers = {"x-api-key": api_token}
137
+ params = {"smart": "1"} if use_smart_summary else {}
138
+ res = requests.post(f"{backend_url}/analyze/", json=payload, headers=headers, params=params)
139
+
140
+ if res.status_code == 200:
141
+ data = res.json()
142
+ st.success("โœ… Analysis Complete")
143
+ st.subheader("๐Ÿ“Œ Summary")
144
+ st.info(data["summary"])
145
+ st.caption(f"๐Ÿง  Summary Type: {'Smart' if use_smart_summary else 'Standard'}")
146
+ st.markdown(f"**Context:** {industry} | {product_category} | {device_type}")
147
+ st.subheader("๐Ÿ”Š Audio")
148
+ audio = speak(data["summary"], lang=voice_lang)
149
+ st.download_button("โฌ‡๏ธ Download Summary Audio", audio.read(), "summary.mp3", mime="audio/mp3")
150
+ st.metric("๐Ÿ“Š Sentiment", data["sentiment"]["label"], delta=f"{data['sentiment']['score']:.2%}")
151
+ st.info(f"๐Ÿ’ข Emotion: {data['emotion']}")
152
+ if data.get("aspects"):
153
+ st.subheader("๐Ÿ” Aspects")
154
+ for a in data["aspects"]:
155
+ st.write(f"๐Ÿ”น {a['aspect']}: {a['sentiment']} ({a['score']:.2%})")
156
+ if data.get("follow_up"):
157
+ st.subheader("๐Ÿง  Follow-Up Response")
158
+ st.warning(data["follow_up"])
159
+ if data.get("explanation"):
160
+ st.subheader("๐Ÿงฎ Explain This")
161
+ st.markdown(data["explanation"])
162
+ else:
163
+ st.error(f"โŒ API Error {res.status_code}: {res.json().get('detail', 'Unknown error')}")
164
+ except Exception as e:
165
+ st.error(f"๐Ÿšซ Exception occurred: {e}")
166
+
167
+ # --- BULK ---
168
+ with tab2:
169
+ st.title("๐Ÿ“š Bulk CSV Upload")
170
+ st.markdown("""
171
+ Upload a CSV with the following columns:<br>
172
+ <code>review</code> (required), <code>industry</code>, <code>product_category</code>, <code>device</code> (optional)
173
+ """, unsafe_allow_html=True)
174
+
175
+ with st.expander("๐Ÿ“„ Sample CSV"):
176
+ with open("sample_reviews.csv", "rb") as f:
177
+ st.download_button("โฌ‡๏ธ Download sample CSV", f, file_name="sample_reviews.csv")
178
+
179
+ uploaded_file = st.file_uploader("๐Ÿ“ Upload your CSV", type="csv")
180
+
181
+ if uploaded_file and api_token:
182
+ try:
183
+ df = pd.read_csv(uploaded_file)
184
+ if "review" not in df.columns:
185
+ st.error("CSV must contain a `review` column.")
186
+ else:
187
+ st.success(f"โœ… Loaded {len(df)} reviews")
188
+ for col in ["industry", "product_category", "device"]:
189
+ if col not in df.columns:
190
+ df[col] = [industry if industry != "Auto-detect" else "Generic"] * len(df)
191
+ df[col] = df[col].fillna("").astype(str)
192
+
193
+ if st.button("๐Ÿ“Š Analyze Bulk Reviews", use_container_width=True):
194
+ with st.spinner("Processing..."):
195
+ try:
196
+ payload = {
197
+ "reviews": df["review"].tolist(),
198
+ "model": sentiment_model,
199
+ "aspects": use_aspects,
200
+ "industry": df["industry"].tolist(),
201
+ "product_category": df["product_category"].tolist(),
202
+ "device": df["device"].tolist(),
203
+ "intelligence": st.session_state.intelligence_mode
204
+ }
205
+ headers = {"x-api-key": api_token}
206
+ params = {"smart": "1"} if use_smart_summary_bulk else {}
207
+ res = requests.post(f"{backend_url}/bulk/", json=payload, headers=headers, params=params)
208
+
209
+ if res.status_code == 200:
210
+ results = pd.DataFrame(res.json()["results"])
211
+ st.dataframe(results)
212
+ if "sentiment" in results:
213
+ fig = px.pie(results, names="sentiment", title="Sentiment Distribution")
214
+ st.plotly_chart(fig)
215
+ st.download_button("โฌ‡๏ธ Download Results CSV", results.to_csv(index=False), "results.csv", mime="text/csv")
216
+ else:
217
+ st.error(f"โŒ Bulk Error {res.status_code}: {res.json().get('detail', 'Unknown error')}")
218
+ except Exception as e:
219
+ st.error(f"๐Ÿšจ Processing Error: {e}")
220
+ except Exception as e:
221
+ st.error(f"โŒ File Read Error: {e}")