import streamlit as st import requests import pandas as pd from gtts import gTTS import base64 from io import BytesIO import os import plotly.express as px st.set_page_config(page_title="NeuroPulse AI", page_icon="๐Ÿง ", layout="wide") if os.path.exists("logo.png"): st.image("logo.png", width=180) # Session state setup defaults = { "review": "", "dark_mode": False, "intelligence_mode": True, "trigger_example_analysis": False, "last_response": None, "followup_answer": None } for k, v in defaults.items(): if k not in st.session_state: st.session_state[k] = v # Dark mode styling if st.session_state.dark_mode: st.markdown(""" """, unsafe_allow_html=True) # Sidebar settings with st.sidebar: st.header("โš™๏ธ Global Settings") st.session_state.dark_mode = st.toggle("๐ŸŒ™ Dark Mode", value=st.session_state.dark_mode) st.session_state.intelligence_mode = st.toggle("๐Ÿง  Intelligence Mode", value=st.session_state.intelligence_mode) api_token = st.text_input("๐Ÿ” API Token", value="my-secret-key", type="password") if not api_token or api_token.strip() == "my-secret-key": st.warning("๐Ÿงช Running in demo mode โ€” for full access, enter a valid API key.") backend_url = st.text_input("๐ŸŒ Backend URL", value="http://localhost:8000") sentiment_model = st.selectbox("๐Ÿ“Š Sentiment Model", [ "Auto-detect", "distilbert-base-uncased-finetuned-sst-2-english", "nlptown/bert-base-multilingual-uncased-sentiment" ]) industry = st.selectbox("๐Ÿญ Industry", ["Auto-detect", "Generic", "E-commerce", "Healthcare", "Education"]) product_category = st.selectbox("๐Ÿงฉ Product Category", ["Auto-detect", "General", "Mobile Devices", "Laptops"]) use_aspects = st.checkbox("๐Ÿ”ฌ Enable Aspect Analysis") use_explain_bulk = st.checkbox("๐Ÿง  Generate Explanations (Bulk)") verbosity = st.radio("๐Ÿ—ฃ๏ธ Response Style", ["Brief", "Detailed"]) voice_lang = st.selectbox("๐Ÿ”ˆ Voice Language", ["en", "fr", "es", "de", "hi", "zh"]) # TTS def speak(text, lang='en'): tts = gTTS(text, lang=lang) mp3 = BytesIO() tts.write_to_fp(mp3) b64 = base64.b64encode(mp3.getvalue()).decode() st.markdown(f'', unsafe_allow_html=True) mp3.seek(0) return mp3 tab1, tab2 = st.tabs(["๐Ÿง  Single Review", "๐Ÿ“š Bulk CSV"]) # ==== SINGLE REVIEW ==== with tab1: st.title("๐Ÿง  NeuroPulse AI โ€“ Multimodal Review Analyzer") st.markdown("
Minimum 20โ€“50 words recommended.
", unsafe_allow_html=True) review = st.text_area("๐Ÿ“ Enter Review", value=st.session_state.review, height=180) st.session_state.review = review col1, col2, col3 = st.columns(3) with col1: analyze = st.button("๐Ÿ” Analyze") with col2: if st.button("๐ŸŽฒ Example"): st.session_state.review = ( "I love this phone! Super fast performance, great battery, and smooth UI. " "Camera is awesome too, though the price is a bit high. Overall, very happy." ) st.session_state.trigger_example_analysis = True st.rerun() with col3: if st.button("๐Ÿงน Clear"): for key in ["review", "last_response", "followup_answer"]: st.session_state[key] = "" st.rerun() if (analyze or st.session_state.trigger_example_analysis) and st.session_state.review: st.session_state.trigger_example_analysis = False st.session_state.followup_answer = None with st.spinner("Analyzing..."): try: model = None if sentiment_model == "Auto-detect" else sentiment_model payload = { "text": st.session_state.review, "model": model or "distilbert-base-uncased-finetuned-sst-2-english", "industry": industry, "product_category": product_category, "verbosity": verbosity, "aspects": use_aspects, "intelligence": st.session_state.intelligence_mode } headers = {"x-api-key": api_token} res = requests.post(f"{backend_url}/analyze/", json=payload, headers=headers) if res.status_code == 200: st.session_state.last_response = res.json() else: st.error(f"API error: {res.status_code} - {res.json().get('detail')}") except Exception as e: st.error(f"๐Ÿšซ Exception: {e}") data = st.session_state.last_response if data: st.subheader("๐Ÿ“Œ Summary") st.info(data["summary"]) st.caption("๐Ÿง  Summary Model: facebook/bart-large-cnn | " + verbosity + " response") st.markdown(f"**Context:** `{data['industry']}` | `{data['product_category']}` | `Web`") st.metric("๐Ÿ“Š Sentiment", data["sentiment"]["label"], delta=f"{data['sentiment']['score']:.2%}") st.info(f"๐Ÿ’ข Emotion: {data['emotion']}") st.subheader("๐Ÿ”Š Audio") audio = speak(data["summary"], lang=voice_lang) st.download_button("โฌ‡๏ธ Download Summary Audio", audio.read(), "summary.mp3") st.markdown("### ๐Ÿ” Got questions?") sample_questions = ["What did the user like most?", "Any complaints mentioned?", "Is it positive overall?"] selected_q = st.selectbox("๐Ÿ’ก Sample Questions", ["Type your own..."] + sample_questions) custom_q = selected_q if selected_q != "Type your own..." else st.text_input("๐Ÿ” Ask a follow-up") if custom_q: with st.spinner("Thinking..."): try: follow_payload = { "text": st.session_state.review, "question": custom_q, "verbosity": verbosity } headers = {"x-api-key": api_token} res = requests.post(f"{backend_url}/followup/", json=follow_payload, headers=headers) if res.status_code == 200: st.session_state.followup_answer = res.json().get("answer") else: st.error(f"โŒ Follow-up failed: {res.json().get('detail')}") except Exception as e: st.error(f"โš ๏ธ Follow-up error: {e}") if st.session_state.followup_answer: st.subheader("๐Ÿ” Follow-Up Answer") st.success(st.session_state.followup_answer) # ==== BULK CSV ==== with tab2: st.title("๐Ÿ“š Bulk CSV Upload") st.markdown(""" Upload a CSV with columns:
review, industry, product_category, device, follow_up (optional) """, unsafe_allow_html=True) with st.expander("๐Ÿ“„ Sample CSV"): with open("sample_reviews.csv", "rb") as f: st.download_button("โฌ‡๏ธ Download sample CSV", f, file_name="sample_reviews.csv") uploaded_file = st.file_uploader("๐Ÿ“ Upload your CSV", type="csv") if uploaded_file: if not api_token: st.error("๐Ÿ” Please enter your API token in the sidebar.") else: try: df = pd.read_csv(uploaded_file) if "review" not in df.columns: st.error("CSV must contain a `review` column.") else: for col in ["industry", "product_category", "device", "follow_up"]: if col not in df.columns: df[col] = ["Auto-detect"] * len(df) df[col] = df[col].fillna("Auto-detect").astype(str) df["industry"] = df["industry"].apply(lambda x: "Generic" if x.lower() == "auto-detect" else x) df["product_category"] = df["product_category"].apply(lambda x: "General" if x.lower() == "auto-detect" else x) df["device"] = df["device"].apply(lambda x: "Web" if x.lower() == "auto-detect" else x) if st.button("๐Ÿ“Š Analyze Bulk Reviews", use_container_width=True): with st.spinner("Processing..."): try: payload = { "reviews": df["review"].tolist(), "model": None if sentiment_model == "Auto-detect" else sentiment_model, "industry": df["industry"].tolist(), "product_category": df["product_category"].tolist(), "device": df["device"].tolist(), "follow_up": df["follow_up"].tolist(), "explain": use_explain_bulk, "aspects": use_aspects, "intelligence": st.session_state.intelligence_mode } res = requests.post(f"{backend_url}/bulk/?token={api_token}", json=payload) if res.status_code == 200: results = pd.DataFrame(res.json()["results"]) st.dataframe(results) if "sentiment" in results.columns: fig = px.pie(results, names="sentiment", title="Sentiment Distribution") st.plotly_chart(fig) st.download_button("โฌ‡๏ธ Download Results CSV", results.to_csv(index=False), "results.csv", mime="text/csv") else: st.error(f"โŒ Bulk Error {res.status_code}: {res.json().get('detail')}") except Exception as e: st.error(f"๐Ÿšจ Bulk Processing Error: {e}") except Exception as e: st.error(f"โŒ File Read Error: {e}")