# frontend/app.py
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sys
import os
# Add the parent directory of 'backend' to the Python path
# This allows importing 'backend' as a package
# os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) points to 'sentilyze/'
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
# Import functions directly from the 'backend' package
# The __init__.py in backend handles the individual imports
from backend import analyze_sentiment, process_csv_for_dashboard, detect_sarcasm_and_highlight
# --- Streamlit App Configuration ---
st.set_page_config(
page_title="Sentilyze - Sentiment & Sarcasm Analyzer",
page_icon="✨",
layout="wide",
initial_sidebar_state="expanded"
)
# --- Custom CSS for better aesthetics ---
st.markdown("""
""", unsafe_allow_html=True)
# --- Header ---
st.markdown("
Sentilyze ✨
", unsafe_allow_html=True)
st.write("Analyze sentiment, detect sarcasm, and visualize insights from your text data.")
# --- Navigation (using Streamlit's sidebar for sections) ---
st.sidebar.title("Navigation")
page = st.sidebar.radio("Go to", ["Single Text Analysis", "CSV File Analysis", "About"])
# --- Single Text Analysis Section ---
if page == "Single Text Analysis":
st.header("Analyze Single Text")
user_input = st.text_area("Enter text here:", "This product is absolutely fantastic!", height=150)
col1, col2 = st.columns(2)
with col1:
if st.button("Analyze Sentiment"):
if user_input:
sentiment_result = analyze_sentiment(user_input)
st.success(f"**Sentiment:** {sentiment_result['class'].capitalize()}")
st.info(f"**Polarity Score:** {sentiment_result['polarity']:.2f} (closer to 1 is positive, -1 is negative)")
else:
st.warning("Please enter some text to analyze sentiment.")
with col2:
if st.button("Detect Sarcasm"):
if user_input:
sarcasm_result = detect_sarcasm_and_highlight(user_input)
st.success(f"**Sarcasm Probability:** {sarcasm_result['sarcasm_percent']:.2f}%")
# FIX: Changed 'predicted_sentiment_label' to 'predicted_sarcasm_label'
st.info(f"**Predicted Sarcasm (Model's view):** {sarcasm_result['predicted_sarcasm_label'].capitalize()}")
st.markdown(f"**Highlighted Text:** {sarcasm_result['highlighted_sentence']}", unsafe_allow_html=True)
if "note" in sarcasm_result:
st.caption(f"Note: {sarcasm_result['note']}")
else:
st.warning("Please enter some text to detect sarcasm.")
# --- CSV File Analysis Section ---
elif page == "CSV File Analysis":
st.header("Analyze CSV File")
st.write("Upload a CSV file containing text data for sentiment analysis and dashboard visualization.")
uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
if uploaded_file is not None:
# Save the uploaded file temporarily to process it with pandas
# In a real app, consider more robust temporary file handling or direct BytesIO
temp_filepath = os.path.join("data", uploaded_file.name)
with open(temp_filepath, "wb") as f:
f.write(uploaded_file.getbuffer())
df = process_csv_for_dashboard(temp_filepath)
if not df.empty:
st.success("CSV file uploaded and processed successfully!")
st.subheader("Raw Data Preview:")
st.dataframe(df.head())
# Allow user to select the text column
text_columns = [col for col in df.columns if df[col].dtype == 'object'] # Assuming text is object/string type
if not text_columns:
st.error("No text columns found in the CSV. Please ensure your CSV has columns with review text.")
else:
selected_text_column = st.selectbox(
"Select the column containing text/reviews for analysis:",
text_columns
)
if st.button(f"Perform Sentiment Analysis on '{selected_text_column}'"):
with st.spinner("Analyzing sentiment... This might take a while for large files."):
# Apply sentiment analysis to the selected column
df['Sentiment'] = df[selected_text_column].astype(str).apply(lambda x: analyze_sentiment(x)['class'])
df['Polarity'] = df[selected_text_column].astype(str).apply(lambda x: analyze_sentiment(x)['polarity'])
st.subheader("Sentiment Analysis Results:")
st.dataframe(df[[selected_text_column, 'Sentiment', 'Polarity']].head())
st.subheader("Sentiment Distribution:")
sentiment_counts = df['Sentiment'].value_counts()
st.bar_chart(sentiment_counts)
# Interactive Dashboard Elements
st.subheader("Interactive Dashboard")
# Pie chart for sentiment distribution
fig1, ax1 = plt.subplots()
sentiment_counts.plot.pie(autopct='%1.1f%%', startangle=90, ax=ax1,
colors=['#4CAF50', '#FFC107', '#F44336']) # Positive, Neutral, Negative
ax1.set_ylabel('') # Hide the default 'Sentiment' label
ax1.set_title('Overall Sentiment Distribution')
st.pyplot(fig1)
# Histogram of Polarity Scores
fig2, ax2 = plt.subplots()
sns.histplot(df['Polarity'], bins=20, kde=True, ax=ax2, color='#2196F3')
ax2.set_title('Distribution of Polarity Scores')
ax2.set_xlabel('Polarity Score')
ax2.set_ylabel('Frequency')
st.pyplot(fig2)
# Display data by sentiment type
st.subheader("View Data by Sentiment Type")
sentiment_filter = st.selectbox(
"Filter by Sentiment:",
["All", "positive", "neutral", "negative"]
)
if sentiment_filter == "All":
st.dataframe(df[[selected_text_column, 'Sentiment', 'Polarity']])
else:
filtered_df = df[df['Sentiment'] == sentiment_filter]
st.dataframe(filtered_df[[selected_text_column, 'Sentiment', 'Polarity']])
else:
st.error("Could not process the CSV file. Please check its format.")
# Clean up the temporary file
if os.path.exists(temp_filepath):
os.remove(temp_filepath)
# --- About Section ---
elif page == "About":
st.header("About Sentilyze")
st.write("""
Sentilyze is a web application designed to help you understand the sentiment and nuances
of text data. It offers:
- **Single Text Analysis:** Quickly determine the sentiment (positive, neutral, negative)
and potential sarcasm of individual pieces of text.
- **CSV File Analysis:** Upload your own datasets (e.g., customer reviews, social media comments)
and get an interactive dashboard showing sentiment distribution and polarity.
- **Sarcasm Detection:** A feature to estimate the sarcasm percentage in a sentence,
with basic highlighting (note: advanced sarcasm highlighting is a complex NLP task).
**Technologies Used:**
- **Backend:** Python, `pandas`, `TextBlob`, `transformers` (Hugging Face)
- **Frontend:** Streamlit
- **Deployment:** Docker, GitHub, (potential platforms like Streamlit Community Cloud, Heroku, Render)
**Developed by:** [Your Name/Team Name Here]
""")
st.markdown("[GitHub Repository (Coming Soon!)](#)", unsafe_allow_html=True)
# --- Footer ---
st.markdown("""
Sentilyze © 2023
""", unsafe_allow_html=True)