Hasitha16 commited on
Commit
a63b02b
ยท
verified ยท
1 Parent(s): ac5d8ef

Upload frontend.py

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