File size: 9,748 Bytes
7fb74eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# 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("""
    <style>
    .main-header {
        font-size: 3em;
        font-weight: bold;
        color: #4CAF50;
        text-align: center;
        margin-bottom: 30px;
        text-shadow: 2px 2px 4px #aaaaaa;
    }
    .stButton>button {
        background-color: #4CAF50;
        color: white;
        border-radius: 12px;
        padding: 10px 24px;
        font-size: 18px;
        border: none;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
    }
    .stButton>button:hover {
        background-color: #45a049;
        box-shadow: 0 6px 12px 0 rgba(0,0,0,0.3);
        transform: translateY(-2px);
    }
    .stTextInput>div>div>input {
        border-radius: 12px;
        border: 1px solid #ccc;
        padding: 10px;
        box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
    }
    .stFileUploader>div>div>button {
        background-color: #2196F3;
        color: white;
        border-radius: 12px;
        padding: 10px 24px;
        font-size: 18px;
        border: none;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
    }
    .stFileUploader>div>div>button:hover {
        background-color: #0b7dda;
        box-shadow: 0 6px 12px 0 rgba(0,0,0,0.3);
        transform: translateY(-2px);
    }
    .stAlert {
        border-radius: 12px;
    }
    mark {
        background-color: #FFEB3B; /* Yellow highlight */
        padding: 2px 5px;
        border-radius: 3px;
    }
    </style>
    """, unsafe_allow_html=True)


# --- Header ---
st.markdown("<h1 class='main-header'>Sentilyze ✨</h1>", 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("""
    <hr>
    <p style='text-align: center; color: grey;'>Sentilyze © 2023</p>
    """, unsafe_allow_html=True)