File size: 9,332 Bytes
3bc0305
3dc2123
c13ab36
3dc2123
9d5b24b
 
 
51ebb55
94adeb8
3dc2123
 
fbfc3a2
 
c13ab36
51ebb55
fbfc3a2
3dc2123
51ebb55
 
 
fbfc3a2
3dc2123
8a03f45
9d5b24b
51ebb55
 
8a03f45
 
51ebb55
 
8a03f45
 
51ebb55
8a03f45
 
 
51ebb55
 
8a03f45
51ebb55
 
 
 
 
8a03f45
 
 
51ebb55
8a03f45
51ebb55
 
8a03f45
51ebb55
 
8a03f45
 
51ebb55
8a03f45
 
 
51ebb55
 
 
 
8a03f45
 
 
51ebb55
 
 
8a03f45
 
51ebb55
 
8a03f45
 
51ebb55
 
8a03f45
 
51ebb55
 
 
 
 
9d5b24b
8a03f45
 
 
9d5b24b
 
 
 
51ebb55
 
 
 
 
 
 
 
8a03f45
51ebb55
 
 
8a03f45
51ebb55
 
 
8a03f45
51ebb55
 
 
 
 
c13ab36
51ebb55
9d5b24b
51ebb55
 
 
 
3dc2123
51ebb55
3dce035
 
 
 
 
 
51ebb55
 
3dce035
 
 
 
 
 
51ebb55
 
fbfc3a2
 
51ebb55
fbfc3a2
51ebb55
 
fbfc3a2
 
51ebb55
 
 
fbfc3a2
51ebb55
 
fbfc3a2
51ebb55
 
3dce035
 
51ebb55
3dce035
 
 
 
 
 
51ebb55
 
9d5b24b
 
fbfc3a2
8a03f45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fbfc3a2
 
8a03f45
 
 
 
 
 
 
 
 
 
 
3dce035
8a03f45
3dce035
8a03f45
 
 
 
fbfc3a2
3dce035
8a03f45
 
 
 
9d5b24b
3dce035
8a03f45
51ebb55
 
8a03f45
51ebb55
8a03f45
51ebb55
 
8a03f45
 
51ebb55
 
9d5b24b
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
217
218
219
220
221
222
223
224
225
226
227
228
import gradio as gr
from transformers import pipeline
import os

# Añade esto para verificar la versión de Gradio en tiempo de ejecución
print(f"Gradio version at runtime: {gr.__version__}")

# --- Model Loading ---
MODEL_ID = "Light-Dav/sentiment-analysis-full-project"

try:
    # Esto carga tu modelo pre-entrenado desde Hugging Face Hub
    # top_k=None asegura que se devuelvan las puntuaciones de todas las clases (positivo, negativo, neutral)
    sentiment_analyzer = pipeline("sentiment-analysis", model=MODEL_ID, top_k=None)
    model_loaded_successfully = True
    print("Sentiment analysis model loaded successfully.")
except Exception as e:
    print(f"Error loading model: {e}")
    sentiment_analyzer = None
    model_loaded_successfully = False
    print("Sentiment analysis model failed to load. Please check MODEL_ID and network connection.")

# --- Custom CSS for a dark look inspired by the website ---
# Este CSS define todo el aspecto visual sin depender de un tema de Gradio
custom_css = """
body {
    background-color: #121212; /* Dark background */
    color: #f8f8f2; /* Light text */
}
.gradio-container {
    box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    overflow: hidden;
    background-color: #1e1e1e; /* Darker card background */
    padding: 20px;
    margin-bottom: 20px;
}
h1, h2, h3 {
    color: #80cbc4; /* Teal/Cyan accents */
    text-align: center;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    animation: fadeIn 1s ease-in-out;
}
.gr-button.primary {
    background-color: #80cbc4 !important;
    color: #1e1e1e !important;
    border-radius: 6px;
    transition: background-color 0.3s ease;
    padding: 10px 20px;
}
.gr-button.primary:hover {
    background-color: #26a69a !important;
}
.gradio-output {
    border: 1px solid #424242;
    border-radius: 8px;
    padding: 15px;
    margin-top: 15px;
    background-color: #212121;
    color: #f8f8f2;
}
.sentiment-display {
    text-align: center;
    padding: 10px;
    border-radius: 6px;
    margin-top: 10px;
    font-size: 1.1em;
    font-weight: bold;
}
.sentiment-positive {
    background-color: #388e3c; /* Darker green */
    color: #e8f5e9; /* Light green */
}
.sentiment-negative {
    background-color: #d32f2f; /* Darker red */
    color: #ffebee; /* Light red */
}
.sentiment-neutral {
    background-color: #1976d2; /* Darker blue */
    color: #e3f2fd; /* Light blue */
}
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}
/* Estilos para las etiquetas de los componentes de entrada */
gr-textbox > label {
    color: #80cbc4;
}
/* Asegúrate de que las etiquetas de salida también tengan color */
.gradio-output .label {
    color: #80cbc4; /* Color de acento para las etiquetas de salida */
}
"""

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

    if label.lower() == "positive" or label.lower() == "label_2":
        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":
        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":
        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:
        # Devuelve 3 valores: HTML, dict, string
        return ( 
            "<div class='sentiment-display'>⚠️ Model Not Loaded ⚠️</div><p>Please contact the administrator. The sentiment analysis model failed to load.</p>",
            {}, # Diccionario vacío para Confidence Scores
            "Model loading failed." # String de error para Raw Output
        )

    if not text.strip():
        # Devuelve 3 valores: HTML, dict, string
        return ( 
            "<div class='sentiment-display'>✍️ Please enter some text! ✍️</div><p>Start typing to analyze its sentiment.</p>",
            {}, # Diccionario vacío para Confidence Scores
            "" # String vacío para Raw Output
        )

    try:
        # Asegúrate de que la salida del pipeline es una lista de listas, y toma la primera.
        results = sentiment_analyzer(text)[0] 

        # Ordenar los resultados por puntuación de confianza de mayor a menor
        results_sorted = sorted(results, key=lambda x: x['score'], reverse=True)

        # Tomar el primer elemento (el de mayor confianza)
        top_sentiment = results_sorted[0] 
        label = top_sentiment['label']
        score = top_sentiment['score']

        # Crear un diccionario de puntuaciones de confianza para la salida de la etiqueta
        confidence_scores_output = {item['label']: item['score'] for item in results}

        # Generar el HTML para mostrar el sentimiento general
        overall_sentiment_display = interpret_sentiment(label, score)

        # ¡CAMBIO CLAVE AQUÍ! Ahora devuelve una tupla con 3 valores separados
        return (overall_sentiment_display, confidence_scores_output, str(results))
    except Exception as e:
        # En caso de cualquier error durante el análisis, devuelve 3 valores de error
        return ( 
            f"<div class='sentiment-display'>❌ Error ❌</div><p>An error occurred during analysis: {e}</p>",
            {}, # Diccionario vacío para Confidence Scores
            f"Error: {e}" # String de error para Raw Output
        )

# --- Gradio Interface ---
# Al establecer theme=None, Gradio no aplicará ningún tema predefinido.
# Todo el estilo visual vendrá de nuestro `custom_css`.
with gr.Blocks(css=custom_css, theme=None) as demo: 
    gr.Markdown("<h1 style='color: #80cbc4; text-align: center;'>🌌 Sentiment Analyzer 🌌</h1>")
    gr.Markdown("<p style='color: #f8f8f2; text-align: center;'>Uncover the emotional tone of your English text instantly.</p>")

    with gr.Column(elem_classes="gradio-container"):
        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")

        gr.Markdown("<hr style='border-top: 1px solid #424242;'>")
        gr.Markdown("<h3 style='color: #80cbc4; text-align: center;'>Try some examples:</h3>")
        
        # IMPORTANTE: Desactivamos cache_examples para evitar el FileNotFoundError
        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,
            # Asegúrate de que estos 3 outputs coinciden con los 3 valores que devuelve analyze_sentiment
            outputs=[gr.HTML(label="Overall Sentiment"), gr.Label(num_top_classes=3, label="Confidence Scores"), gr.JSON(label="Raw Model Output", visible=False)],
            cache_examples=False # ESTE ES EL CAMBIO CLAVE PARA ELIMINAR EL FileNotFoundError
        )

        gr.Markdown("<hr style='border-top: 1px solid #424242;'>")
        gr.Markdown("<h2 style='color: #80cbc4;'>📊 Analysis Results</h2>")
        
        # Estas variables de salida deben coincidir en tipo y orden con lo que devuelve analyze_sentiment
        overall_sentiment_output = gr.HTML(label="Overall Sentiment")
        confidence_scores_output = gr.Label(num_top_classes=3, label="Confidence Scores")
        raw_output = gr.JSON(label="Raw Model Output", visible=False)

    # --- Event Listeners ---
    # Los outputs aquí también deben coincidir con los 3 valores que devuelve analyze_sentiment
    analyze_btn.click(
        fn=analyze_sentiment,
        inputs=text_input,
        outputs=[overall_sentiment_output, confidence_scores_output, raw_output]
    )
    text_input.change(
        fn=analyze_sentiment,
        inputs=text_input,
        outputs=[overall_sentiment_output, confidence_scores_output, raw_output],
        # live=True # Puedes descomentar si quieres actualizaciones en vivo (consume más recursos)
    )

# Launch the Gradio application
demo.launch()