Hasitha16 commited on
Commit
0e76a85
Β·
verified Β·
1 Parent(s): 52adbed

Update frontend.py

Browse files
Files changed (1) hide show
  1. frontend.py +150 -98
frontend.py CHANGED
@@ -9,23 +9,49 @@ import os
9
 
10
  st.set_page_config(page_title="NeuroPulse AI", page_icon="🧠", layout="wide")
11
 
12
- # Optional logo
13
  logo_path = os.path.join("app", "static", "logo.png")
14
  if os.path.exists(logo_path):
15
  st.image(logo_path, width=160)
16
 
17
- # Session state
18
- if "page" not in st.session_state:
19
- st.session_state.page = "Home"
20
  if "review" not in st.session_state:
21
  st.session_state.review = ""
 
 
22
 
23
- # Navigation
24
  with st.sidebar:
25
- st.title("🧭 Navigation")
26
- st.session_state.page = st.radio("Go to", ["Home", "Single Review", "Bulk CSV"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
- # Text-to-speech
29
  def speak(text, lang='en'):
30
  tts = gTTS(text, lang=lang)
31
  mp3 = BytesIO()
@@ -35,103 +61,129 @@ def speak(text, lang='en'):
35
  mp3.seek(0)
36
  return mp3
37
 
38
- # Page: Home
39
- if st.session_state.page == "Home":
 
 
 
 
40
  st.markdown("""
41
- <div style='text-align: center;'>
42
- <h1 style='font-size: 48px;'>🧠 NeuroPulse AI</h1>
43
- <p style='font-size: 20px;'>Smarter feedback analyzer using GenAI for Summarization, Sentiment, Emotion, Aspects, and GPT Q&A</p>
44
- <a href='https://huggingface.co/spaces/your-space-name' target='_blank' style='text-decoration: none;'>
45
- <button style='padding: 12px 30px; font-size: 18px; border-radius: 8px; background: linear-gradient(90deg, #6366f1, #4f46e5); color: white; border: none;'>πŸš€ Try App</button>
46
- </a>
47
- </div>
48
  """, unsafe_allow_html=True)
49
 
50
- # Page: Single Review
51
- elif st.session_state.page == "Single Review":
52
- st.title("🧠 Analyze Single Review")
53
-
54
- with st.expander("βš™οΈ Settings"):
55
- sentiment_model = st.selectbox("Sentiment Model", [
56
- "distilbert-base-uncased-finetuned-sst-2-english",
57
- "nlptown/bert-base-multilingual-uncased-sentiment"])
58
- industry = st.selectbox("Industry", ["Generic", "E-commerce", "Healthcare"])
59
- product_category = st.text_input("Product Category", "General")
60
- device = st.text_input("Device", "Web")
61
- use_aspects = st.checkbox("Enable Aspect Analysis")
62
- use_smart = st.checkbox("Use Smart Summary")
63
- follow_up = st.text_input("Follow-up Question")
64
- voice_lang = st.selectbox("Voice Language", ["en", "fr", "es"])
65
- backend_url = st.text_input("Backend URL", "http://0.0.0.0:8000")
66
- api_token = st.text_input("API Token", type="password")
67
-
68
- st.session_state.review = st.text_area("πŸ“ Enter your review", value=st.session_state.review, height=160)
69
-
70
- if st.button("πŸ” Analyze") and st.session_state.review:
71
- with st.spinner("Analyzing..."):
72
- payload = {
73
- "text": st.session_state.review,
74
- "model": sentiment_model,
75
- "industry": industry,
76
- "aspects": use_aspects,
77
- "follow_up": follow_up,
78
- "product_category": product_category,
79
- "device": device
80
- }
81
- headers = {"X-API-Key": api_token}
82
- params = {"smart": "1"} if use_smart else {}
83
- res = requests.post(f"{backend_url}/analyze/", json=payload, headers=headers, params=params)
84
- if res.status_code == 200:
85
- out = res.json()
86
- st.success("βœ… Done")
87
- st.markdown(f"### πŸ“Œ Summary\n{out['summary']}")
88
- st.caption(f"Smart Summary: {use_smart}")
89
- audio = speak(out["summary"], lang=voice_lang)
90
- st.download_button("⬇️ Download Audio", audio.read(), "summary.mp3")
91
- st.metric("πŸ“Š Sentiment", out['sentiment']['label'], f"{out['sentiment']['score']:.2%}")
92
- st.info(f"πŸ’’ Emotion: {out['emotion']}")
93
- if out.get("aspects"):
94
- st.markdown("### πŸ” Aspects")
95
- for asp in out["aspects"]:
96
- st.write(f"- {asp['aspect']}: {asp['sentiment']} ({asp['score']:.2%})")
97
- if out.get("follow_up"):
98
- st.warning(f"🧠 GPT: {out['follow_up']}")
99
- else:
100
- st.error(f"❌ Error: {res.status_code}")
101
-
102
- # Page: Bulk CSV
103
- elif st.session_state.page == "Bulk CSV":
104
- st.title("πŸ“š Analyze CSV in Bulk")
105
- uploaded_file = st.file_uploader("Upload CSV with `review` column", type="csv")
106
- if uploaded_file:
107
- df = pd.read_csv(uploaded_file)
108
- if "review" not in df.columns:
109
- st.error("CSV must have a 'review' column")
110
  else:
111
- st.success(f"βœ… {len(df)} reviews loaded")
112
- df.fillna("", inplace=True)
113
- if st.button("πŸ“Š Run Bulk Analysis"):
114
- with st.spinner("Running..."):
115
  payload = {
116
- "reviews": df["review"].tolist(),
117
  "model": sentiment_model,
118
- "industry": df["industry"].tolist() if "industry" in df else ["Generic"]*len(df),
119
- "product_category": df["product_category"].tolist() if "product_category" in df else [""]*len(df),
120
- "device": df["device"].tolist() if "device" in df else [""]*len(df),
121
- "aspects": use_aspects
 
122
  }
123
  headers = {"X-API-Key": api_token}
124
- params = {"smart": "1"} if use_smart else {}
125
- res = requests.post(f"{backend_url}/bulk/", json=payload, headers=headers, params=params)
126
  if res.status_code == 200:
127
- results = pd.DataFrame(res.json()["results"])
128
- st.dataframe(results)
129
- st.download_button("⬇️ Download CSV", results.to_csv(index=False), "results.csv")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  else:
131
- st.error(f"❌ Failed: {res.status_code}")
132
- with st.expander("πŸ“„ Sample CSV"):
133
- st.markdown("""
134
- Download sample CSV [here](https://huggingface.co/datasets/hasi-labs/sample-neuropulse-csv/raw/main/sample.csv)
135
-
136
- Required column: `review` (Optional: `industry`, `product_category`, `device`)
137
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  st.set_page_config(page_title="NeuroPulse AI", page_icon="🧠", layout="wide")
11
 
 
12
  logo_path = os.path.join("app", "static", "logo.png")
13
  if os.path.exists(logo_path):
14
  st.image(logo_path, width=160)
15
 
16
+ # Session state defaults
 
 
17
  if "review" not in st.session_state:
18
  st.session_state.review = ""
19
+ if "dark_mode" not in st.session_state:
20
+ st.session_state.dark_mode = False
21
 
22
+ # Shared Sidebar Controls
23
  with st.sidebar:
24
+ st.header("βš™οΈ Global Settings")
25
+ st.session_state.dark_mode = st.toggle("πŸŒ™ Dark Mode", value=st.session_state.dark_mode)
26
+
27
+ api_token = st.text_input("πŸ” API Token", type="password")
28
+ backend_url = st.text_input("πŸ–₯️ Backend URL", value="http://0.0.0.0:8000")
29
+
30
+ sentiment_model = st.selectbox("πŸ“Š Sentiment Model", [
31
+ "distilbert-base-uncased-finetuned-sst-2-english",
32
+ "nlptown/bert-base-multilingual-uncased-sentiment"
33
+ ])
34
+
35
+ industry = st.selectbox("🏭 Industry Context", [
36
+ "Auto-detect", "Generic", "E-commerce", "Healthcare", "Education", "Travel", "Banking", "Insurance", "Gaming", "Food Delivery", "Real Estate", "Fitness", "Entertainment"
37
+ ])
38
+
39
+ product_category = st.selectbox("🧩 Product Category", [
40
+ "Auto-detect", "General", "Mobile Devices", "Laptops", "Healthcare Devices", "Banking App", "Travel Service", "Educational Tool", "Insurance Portal", "Streaming App", "Wearables", "Home Appliances", "Food Apps"
41
+ ])
42
+
43
+ device_type = st.selectbox("πŸ’» Device Type", [
44
+ "Auto-detect", "Web", "Android", "iOS", "Desktop", "Smartwatch", "Kiosk"
45
+ ])
46
+
47
+ use_aspects = st.checkbox("πŸ”¬ Enable Aspect Analysis")
48
+ use_smart_summary = st.checkbox("🧠 Use Smart Summary (Single)")
49
+ use_smart_summary_bulk = st.checkbox("🧠 Smart Summary for Bulk")
50
+ follow_up = st.text_input("πŸ” Follow-up Question")
51
+ voice_lang = st.selectbox("πŸ”ˆ Voice Language", ["en", "fr", "es", "de", "hi", "zh"])
52
+
53
+ # Text-to-Speech Helper
54
 
 
55
  def speak(text, lang='en'):
56
  tts = gTTS(text, lang=lang)
57
  mp3 = BytesIO()
 
61
  mp3.seek(0)
62
  return mp3
63
 
64
+ # Tabs for modes
65
+ tab1, tab2 = st.tabs(["🧠 Single Review", "πŸ“š Bulk CSV"])
66
+
67
+ # --- SINGLE REVIEW MODE ---
68
+ with tab1:
69
+ st.title("🧠 NeuroPulse AI – Multimodal Review Analyzer")
70
  st.markdown("""
71
+ <div style='font-size:16px;color:#555;'>Minimum 50–100 words recommended for optimal insights.</div>
 
 
 
 
 
 
72
  """, unsafe_allow_html=True)
73
 
74
+ review = st.text_area("πŸ“ Enter a Review", value=st.session_state.review, height=180)
75
+
76
+ col1, col2, col3 = st.columns(3)
77
+ with col1:
78
+ analyze = st.button("πŸ” Analyze", use_container_width=True, disabled=not api_token)
79
+ with col2:
80
+ if st.button("🎲 Example", use_container_width=True):
81
+ st.session_state.review = "App was smooth, but the transaction failed twice on Android during checkout."
82
+ st.rerun()
83
+ with col3:
84
+ if st.button("🧹 Clear", use_container_width=True):
85
+ st.session_state.review = ""
86
+ st.rerun()
87
+
88
+ if analyze and review:
89
+ if len(review.split()) < 50:
90
+ st.error("⚠️ Please enter at least 50 words for meaningful analysis.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  else:
92
+ with st.spinner("Analyzing..."):
93
+ try:
 
 
94
  payload = {
95
+ "text": review,
96
  "model": sentiment_model,
97
+ "industry": industry,
98
+ "aspects": use_aspects,
99
+ "follow_up": follow_up,
100
+ "product_category": product_category,
101
+ "device": device_type
102
  }
103
  headers = {"X-API-Key": api_token}
104
+ params = {"smart": "1"} if use_smart_summary else {}
105
+ res = requests.post(f"{backend_url}/analyze/", json=payload, headers=headers, params=params)
106
  if res.status_code == 200:
107
+ data = res.json()
108
+ st.success("βœ… Analysis Complete")
109
+ st.subheader("πŸ“Œ Summary")
110
+ st.info(data["summary"])
111
+ st.caption(f"🧠 Summary Type: {'Smart Summary' if use_smart_summary else 'Standard Model'}")
112
+ st.markdown(f"**Context:** {industry} | {product_category} | {device_type}")
113
+ st.subheader("πŸ”Š Audio")
114
+ audio = speak(data["summary"], lang=voice_lang)
115
+ st.download_button("⬇️ Download Summary Audio", audio.read(), "summary.mp3", mime="audio/mp3")
116
+ st.metric("πŸ“Š Sentiment", data["sentiment"]["label"], delta=f"{data['sentiment']['score']:.2%}")
117
+ st.info(f"πŸ’’ Emotion: {data['emotion']}")
118
+ if data.get("aspects"):
119
+ st.subheader("πŸ” Aspects")
120
+ for a in data["aspects"]:
121
+ st.write(f"πŸ”Ή {a['aspect']}: {a['sentiment']} ({a['score']:.2%})")
122
+ if data.get("follow_up"):
123
+ st.subheader("🧠 Follow-Up Response")
124
+ st.warning(data["follow_up"])
125
  else:
126
+ st.error(f"❌ API Error: {res.status_code}")
127
+ except Exception as e:
128
+ st.error(f"🚫 {e}")
129
+
130
+ # --- BULK REVIEW MODE ---
131
+ with tab2:
132
+ st.title("πŸ“š Bulk CSV Upload")
133
+ st.markdown("""
134
+ <div style='font-size:16px;'>Upload a CSV with the following columns:<br>
135
+ <code>review</code> <span style='color:#aaa;'>(required)</span>,
136
+ <code>industry</code>, <code>product_category</code>, <code>device</code> <span style='color:#aaa;'>(optional)</span></div>
137
+ """, unsafe_allow_html=True)
138
+
139
+ sample_df = pd.DataFrame({
140
+ "review": ["This app helps me manage my medical appointments smoothly.", "The mobile battery drains fast when using the banking app.", "Streaming service loads slowly on Smart TV."],
141
+ "industry": ["Healthcare", "Banking", "Entertainment"],
142
+ "product_category": ["Healthcare Devices", "Banking App", "Streaming App"],
143
+ "device": ["Android", "iOS", "Smartwatch"]
144
+ })
145
+ sample_csv = sample_df.to_csv(index=False).encode("utf-8")
146
+ with st.expander("πŸ“Ž Sample CSV"):
147
+ st.download_button("⬇️ Download sample CSV", sample_csv, "sample_reviews.csv", mime="text/csv")
148
+
149
+ uploaded_file = st.file_uploader("πŸ“ Upload your CSV", type="csv")
150
+
151
+ if uploaded_file and api_token:
152
+ try:
153
+ df = pd.read_csv(uploaded_file)
154
+ if "review" not in df.columns:
155
+ st.error("CSV must contain a `review` column.")
156
+ else:
157
+ st.success(f"βœ… Loaded {len(df)} reviews")
158
+
159
+ for col in ["industry", "product_category", "device"]:
160
+ if col not in df.columns:
161
+ df[col] = [industry if industry != "Auto-detect" else "Generic"] * len(df)
162
+ df[col] = df[col].fillna("").astype(str)
163
+
164
+ if st.button("πŸ“Š Analyze Bulk Reviews", use_container_width=True):
165
+ with st.spinner("Processing CSV..."):
166
+ try:
167
+ payload = {
168
+ "reviews": df["review"].tolist(),
169
+ "model": sentiment_model,
170
+ "aspects": use_aspects,
171
+ "industry": df["industry"].tolist(),
172
+ "product_category": df["product_category"].tolist(),
173
+ "device": df["device"].tolist()
174
+ }
175
+ headers = {"X-API-Key": api_token}
176
+ params = {"smart": "1"} if use_smart_summary_bulk else {}
177
+
178
+ res = requests.post(f"{backend_url}/bulk/", json=payload, headers=headers, params=params)
179
+ if res.status_code == 200:
180
+ results = pd.DataFrame(res.json()["results"])
181
+ results["summary_type"] = "Smart" if use_smart_summary_bulk else "Standard"
182
+ st.dataframe(results)
183
+ st.download_button("⬇️ Download Results CSV", results.to_csv(index=False), "bulk_results.csv", mime="text/csv")
184
+ else:
185
+ st.error(f"❌ Bulk Analysis Failed: {res.status_code}")
186
+ except Exception as e:
187
+ st.error(f"πŸ’₯ Error: {e}")
188
+ except Exception as e:
189
+ st.error(f"❌ File Error: {e}")