File size: 8,892 Bytes
3bc0305
3dc2123
c13ab36
3dc2123
51ebb55
 
 
94adeb8
3dc2123
 
51ebb55
c13ab36
 
 
51ebb55
3dc2123
51ebb55
 
 
3dc2123
51ebb55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c13ab36
 
 
 
51ebb55
 
 
c13ab36
51ebb55
 
 
c13ab36
51ebb55
 
 
 
 
c13ab36
51ebb55
 
 
 
 
 
3dc2123
51ebb55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c13ab36
 
51ebb55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c13ab36
 
51ebb55
 
 
 
 
c13ab36
 
 
 
 
 
51ebb55
 
c13ab36
51ebb55
 
 
 
 
 
c13ab36
51ebb55
 
 
 
 
 
c13ab36
51ebb55
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
import gradio as gr
from transformers import pipeline
import os

# --- Model Loading ---
# Using the model ID you've been working with, which is fine-tuned on an English dataset (IMDB).
# It's crucial that this model is indeed fine-tuned for sentiment analysis in English.
MODEL_ID = "Light-Dav/sentiment-analysis-full-project"

try:
    # Attempt to load the pipeline. This needs to be outside the function for efficiency.
    # Using top_k=None to get all scores (equivalent to return_all_scores=True in older versions).
    # This also addresses the UserWarning about `return_all_scores` deprecation.
    sentiment_analyzer = pipeline("sentiment-analysis", model=MODEL_ID, top_k=None)
    model_loaded_successfully = True
except Exception as e:
    print(f"Error loading model: {e}")
    sentiment_analyzer = None
    model_loaded_successfully = False

# --- Custom CSS for a unique look ---
custom_css = """
body {
    background-color: #f0f2f5; /* Light grey background */
}
.gradio-container {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    border-radius: 15px;
    overflow: hidden;
    background-color: #ffffff; /* White card background */
}
h1, h2, h3 {
    color: #4CAF50; /* Green accents */
    text-align: center;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    animation: fadeIn 1s ease-in-out;
}
.gr-button.primary {
    background-color: #4CAF50 !important;
    color: white !important;
    border-radius: 8px;
    transition: background-color 0.3s ease;
}
.gr-button.primary:hover {
    background-color: #45a049 !important;
}
.gradio-output {
    border: 1px solid #e0e0e0;
    border-radius: 10px;
    padding: 15px;
    margin-top: 20px;
    background-color: #f9f9f9;
}
.sentiment-display {
    text-align: center;
    padding: 10px;
    border-radius: 8px;
    margin-top: 15px;
    font-size: 1.2em;
    font-weight: bold;
}
.sentiment-positive {
    background-color: #e6ffe6; /* Light green */
    color: #28a745; /* Darker green */
}
.sentiment-negative {
    background-color: #ffe6e6; /* Light red */
    color: #dc3545; /* Darker red */
}
.sentiment-neutral {
    background-color: #e6f7ff; /* Light blue */
    color: #007bff; /* Darker blue */
}
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}
"""

# --- Helper Function for Sentiment Interpretation ---
def interpret_sentiment(label, score):
    emoji = ""
    description = ""
    color_class = ""

    # IMPORTANT: Adjust 'LABEL_0', 'LABEL_1', 'LABEL_2' to your model's actual output labels
    # Check your model's config.json on Hugging Face Hub under 'id2label' or 'label2id'
    # Example: "id2label": {"0": "negative", "1": "neutral", "2": "positive"}
    if label.lower() == "positive" or label.lower() == "label_2": # Assuming LABEL_2 is positive
        emoji = "😊"
        description = "This text expresses a **highly positive** sentiment." if score > 0.9 else "This text expresses a **positive** sentiment."
        color_class = "sentiment-positive"
    elif label.lower() == "negative" or label.lower() == "label_0": # Assuming LABEL_0 is negative
        emoji = "😠"
        description = "This text expresses a **highly negative** sentiment." if score > 0.9 else "This text expresses a **negative** sentiment."
        color_class = "sentiment-negative"
    elif label.lower() == "neutral" or label.lower() == "label_1": # Assuming LABEL_1 is neutral
        emoji = "😐"
        description = "This text expresses a **neutral** sentiment."
        color_class = "sentiment-neutral"
    else:
        emoji = "❓"
        description = "Could not confidently determine sentiment. Unexpected label."
        color_class = ""
    
    return f"<div class='sentiment-display {color_class}'>{emoji} {label.upper()} ({score:.2f})</div>" + \
           f"<p>{description}</p>"

# --- Sentiment Analysis Function ---
def analyze_sentiment(text):
    if not model_loaded_successfully:
        return {
            "Overall Sentiment": "<div class='sentiment-display'>⚠️ Model Not Loaded ⚠️</div><p>Please contact the administrator. The sentiment analysis model failed to load.</p>",
            "Confidence Scores": {},
            "Raw Output": "Model loading failed."
        }

    if not text.strip():
        return {
            "Overall Sentiment": "<div class='sentiment-display'>✍️ Please enter some text! ✍️</div><p>Start typing to analyze its sentiment.</p>",
            "Confidence Scores": {},
            "Raw Output": ""
        }

    try:
        # The pipeline returns a list of lists of dictionaries if top_k=None
        # e.g., [[{'label': 'LABEL_0', 'score': 0.9}, {'label': 'LABEL_1', 'score': 0.05}, ...]]
        results = sentiment_analyzer(text)[0] # Get the first (and only) list of results

        # Sort results by score in descending order
        results_sorted = sorted(results, key=lambda x: x['score'], reverse=True)

        # Get the top sentiment
        top_sentiment = results_sorted[0]
        label = top_sentiment['label']
        score = top_sentiment['score']

        # Format for Gradio Label component (Dictionary {label: score})
        # This is for the 'Confidence Scores' output
        confidence_scores_output = {item['label']: item['score'] for item in results}

        # Interpret sentiment for the 'Overall Sentiment' output
        overall_sentiment_display = interpret_sentiment(label, score)

        return {
            "Overall Sentiment": overall_sentiment_display,
            "Confidence Scores": confidence_scores_output,
            "Raw Output": str(results)
        }
    except Exception as e:
        return {
            "Overall Sentiment": f"<div class='sentiment-display'>❌ Error ❌</div><p>An error occurred during analysis: {e}</p>",
            "Confidence Scores": {},
            "Raw Output": f"Error: {e}"
        }

# --- Gradio Interface ---
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: # Using gr.Blocks for more layout control
    gr.Markdown("# ✨ Sentiment Spark ✨")
    gr.Markdown("---")
    gr.Markdown("### Uncover the emotional tone of your English text instantly!")

    with gr.Row(): # Horizontal layout for input and outputs
        with gr.Column(scale=2):
            text_input = gr.Textbox(
                lines=7,
                placeholder="Type your English text here...",
                label="Your Text",
                interactive=True,
                value="This movie was absolutely brilliant! A masterpiece of storytelling and emotion."
            )
            analyze_btn = gr.Button("Analyze Sentiment", variant="primary") # The main action button

            gr.Markdown("---")
            gr.Markdown("### Try some examples:")
            gr.Examples(
                examples=[
                    ["This product exceeded my expectations, truly amazing!"],
                    ["I found the customer service to be quite disappointing and slow."],
                    ["The weather forecast predicts light rain for tomorrow morning."],
                    ["What a fantastic experience! Highly recommend it."],
                    ["I'm so frustrated with this slow internet connection."],
                    ["The meeting concluded without any major decisions."]
                ],
                inputs=text_input,
                fn=analyze_sentiment, # <-- CORRECTED: Function to run for examples
                outputs=[overall_sentiment_output, confidence_scores_output, raw_output], # <-- CORRECTED: Outputs for examples
                cache_examples=True # Caching examples for faster loading
            )

        with gr.Column(scale=3):
            gr.Markdown("## πŸ“ˆ Analysis Results πŸ“‰")
            # Using gr.HTML for "Overall Sentiment" to allow custom CSS and rich content
            overall_sentiment_output = gr.HTML(label="Overall Sentiment")
            # Using gr.Label for "Confidence Scores" as it's designed for classification outputs
            confidence_scores_output = gr.Label(num_top_classes=3, label="Confidence Scores")
            # Using gr.JSON for raw output, useful for debugging, but hidden by default
            raw_output = gr.JSON(label="Raw Model Output", visible=False)

    # --- Event Listeners ---
    # Trigger analysis when text input changes (optional, can be resource intensive if live=True)
    text_input.change(
        fn=analyze_sentiment,
        inputs=text_input,
        outputs=[overall_sentiment_output, confidence_scores_output, raw_output],
        # live=True # Uncomment for live updates as user types (can be resource intensive)
    )
    # Trigger analysis when the button is clicked
    analyze_btn.click(
        fn=analyze_sentiment,
        inputs=text_input,
        outputs=[overall_sentiment_output, confidence_scores_output, raw_output]
    )

# Launch the Gradio application
demo.launch()