devenirfantasma commited on
Commit
c22d0f6
·
verified ·
1 Parent(s): 64c53f8

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -0
app.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MVP: Comparador de Modelos de Análisis de Sentimiento
3
+
4
+ Aplicación Gradio que compara dos modelos de análisis de sentimiento en español:
5
+ - pysentimiento/robertuito-sentiment-analysis (entrenado en Twitter)
6
+ - finiteautomata/beto-sentiment-analysis (BETO clásico)
7
+
8
+ Arquitectura:
9
+ - Carga eficiente: modelos cargados una sola vez al inicio
10
+ - Procesamiento paralelo: ambos modelos ejecutados simultáneamente
11
+ - Interfaz simple: texto de entrada + resultados lado a lado
12
+
13
+ Autor: Desarrollado para IFTS - Procesamiento de Lenguaje Natural
14
+ Fecha: 2025
15
+ """
16
+
17
+ import gradio as gr
18
+ from transformers import pipeline
19
+ import time
20
+ from typing import Dict, Tuple
21
+
22
+ # Modelos a comparar
23
+ MODELOS = {
24
+ "RoBERTuito": "pysentimiento/robertuito-sentiment-analysis",
25
+ "BETO": "finiteautomata/beto-sentiment-analysis",
26
+ }
27
+
28
+ # Mapeo de etiquetas a español
29
+ ETIQUETAS_ES = {"POS": "Positivo", "NEG": "Negativo", "NEU": "Neutral"}
30
+
31
+
32
+ class ComparadorSentimientos:
33
+ """Clase para manejar la comparación de modelos de sentimiento."""
34
+
35
+ def __init__(self):
36
+ self.modelos = {}
37
+ self._cargar_modelos()
38
+
39
+ def _cargar_modelos(self):
40
+ """Carga ambos modelos una sola vez al inicio."""
41
+ print("🚀 Cargando modelos de análisis de sentimiento...")
42
+
43
+ for nombre, modelo_path in MODELOS.items():
44
+ print(f" 📥 Cargando {nombre}: {modelo_path}")
45
+ try:
46
+ self.modelos[nombre] = pipeline(
47
+ "sentiment-analysis", model=modelo_path, return_all_scores=False
48
+ )
49
+ print(f" ✅ {nombre} cargado exitosamente")
50
+ except Exception as e:
51
+ print(f" ❌ Error cargando {nombre}: {str(e)}")
52
+ self.modelos[nombre] = None
53
+
54
+ print("🎉 Modelos cargados!\n")
55
+
56
+ def analizar_texto(self, texto: str) -> Dict[str, Dict[str, float]]:
57
+ """
58
+ Analiza el sentimiento usando ambos modelos.
59
+
60
+ Args:
61
+ texto: Texto a analizar
62
+
63
+ Returns:
64
+ Diccionario con resultados de ambos modelos
65
+ """
66
+ if not texto.strip():
67
+ return {
68
+ "error": "Por favor ingresa un texto válido",
69
+ "RoBERTuito": {"Error": 1.0},
70
+ "BETO": {"Error": 1.0},
71
+ }
72
+
73
+ resultados = {}
74
+
75
+ for nombre_modelo, modelo in self.modelos.items():
76
+ if modelo is None:
77
+ resultados[nombre_modelo] = {"Error": 1.0}
78
+ continue
79
+
80
+ try:
81
+ inicio = time.time()
82
+ resultado = modelo(texto)[0]
83
+ tiempo = time.time() - inicio
84
+
85
+ # Convertir etiqueta a español
86
+ etiqueta_original = resultado["label"]
87
+ etiqueta_es = ETIQUETAS_ES.get(etiqueta_original, etiqueta_original)
88
+
89
+ resultados[nombre_modelo] = {
90
+ etiqueta_es: round(resultado["score"], 4),
91
+ "_tiempo": round(tiempo, 3),
92
+ "_confianza": round(resultado["score"], 4),
93
+ }
94
+
95
+ except Exception as e:
96
+ resultados[nombre_modelo] = {"Error": 1.0, "_error": str(e)}
97
+
98
+ return resultados
99
+
100
+
101
+ # Inicializar comparador global
102
+ comparador = ComparadorSentimientos()
103
+
104
+
105
+ def analizar_sentimiento(texto: str) -> Tuple[str, str]:
106
+ """
107
+ Función principal para la interfaz Gradio.
108
+
109
+ Args:
110
+ texto: Texto ingresado por el usuario
111
+
112
+ Returns:
113
+ Tupla con resultados formateados para ambos modelos
114
+ """
115
+ resultados = comparador.analizar_texto(texto)
116
+
117
+ # Formatear resultados para mostrar en Gradio
118
+ robertuito_text = ""
119
+ beto_text = ""
120
+
121
+ if "error" in resultados:
122
+ robertuito_text = f"❌ {resultados['error']}"
123
+ beto_text = f"❌ {resultados['error']}"
124
+ else:
125
+ # RoBERTuito
126
+ robertuito = resultados.get("RoBERTuito", {"Error": 1.0})
127
+ if "Error" in robertuito:
128
+ robertuito_text = "❌ Error en RoBERTuito"
129
+ else:
130
+ etiqueta = list(robertuito.keys())[0]
131
+ confianza = robertuito[etiqueta]
132
+ tiempo = robertuito.get("_tiempo", 0)
133
+ robertuito_text = f"🎯 {etiqueta}: {confianza:.1%} ({tiempo:.2f}s)"
134
+
135
+ # BETO
136
+ beto = resultados.get("BETO", {"Error": 1.0})
137
+ if "Error" in beto:
138
+ beto_text = "❌ Error en BETO"
139
+ else:
140
+ etiqueta = list(beto.keys())[0]
141
+ confianza = beto[etiqueta]
142
+ tiempo = beto.get("_tiempo", 0)
143
+ beto_text = f"🎯 {etiqueta}: {confianza:.1%} ({tiempo:.2f}s)"
144
+
145
+ return robertuito_text, beto_text
146
+
147
+
148
+ # Ejemplos representativos en español argentino
149
+ EJEMPLOS = [
150
+ ["La verdad, este lugar está bárbaro. Muy recomendable."],
151
+ ["Qué buena onda la atención, volvería sin dudarlo."],
152
+ ["Me encantó la comida, aunque la música estaba muy fuerte."],
153
+ ["Una porquería de servicio, nunca más vuelvo."],
154
+ ["Qué garrón, tardaron una banda en traer el pedido."],
155
+ ["Re copado todo, la rompieron con el ambiente."],
156
+ ["Zafa, pero nada especial el lugar."],
157
+ ["Está piola el lugar, volvería."],
158
+ ]
159
+
160
+ # Crear interfaz Gradio
161
+ with gr.Blocks(
162
+ title="Comparador de Modelos de Sentimiento",
163
+ theme=gr.themes.Soft(),
164
+ css="""
165
+ .gradio-container {
166
+ max-width: 900px;
167
+ margin: auto;
168
+ }
169
+ .title {
170
+ text-align: center;
171
+ color: #2563eb;
172
+ font-size: 2.5em;
173
+ margin-bottom: 1em;
174
+ }
175
+ .subtitle {
176
+ text-align: center;
177
+ color: #64748b;
178
+ font-size: 1.1em;
179
+ margin-bottom: 2em;
180
+ }
181
+ """,
182
+ ) as demo:
183
+ # Header
184
+ gr.HTML("""
185
+ <div class="title">🆚 Comparador de Modelos de Sentimiento</div>
186
+ <div class="subtitle">
187
+ Compara RoBERTuito vs BETO en análisis de sentimiento para español<br>
188
+ <strong>RoBERTuito:</strong> Especializado en lenguaje coloquial y redes sociales<br>
189
+ <strong>BETO:</strong> Modelo clásico entrenado en Wikipedia
190
+ </div>
191
+ """)
192
+
193
+ # Input
194
+ with gr.Row():
195
+ with gr.Column(scale=2):
196
+ texto_input = gr.Textbox(
197
+ label="📝 Texto para analizar",
198
+ placeholder="Ingresa aquí el texto que quieres analizar...",
199
+ lines=4,
200
+ show_copy_button=True,
201
+ )
202
+
203
+ # Botón de análisis
204
+ analizar_btn = gr.Button("🔍 Analizar Sentimiento", variant="primary", size="lg")
205
+
206
+ # Resultados
207
+ with gr.Row():
208
+ with gr.Column():
209
+ gr.HTML(
210
+ "<h3 style='text-align: center; color: #059669;'>🤖 RoBERTuito</h3>"
211
+ )
212
+ robertuito_output = gr.Textbox(
213
+ label="Resultado RoBERTuito", interactive=False, lines=2
214
+ )
215
+
216
+ with gr.Column():
217
+ gr.HTML("<h3 style='text-align: center; color: #dc2626;'>📚 BETO</h3>")
218
+ beto_output = gr.Textbox(label="Resultado BETO", interactive=False, lines=2)
219
+
220
+ # Ejemplos
221
+ gr.Examples(
222
+ examples=EJEMPLOS,
223
+ inputs=texto_input,
224
+ label="💡 Ejemplos en español argentino (clickea para probar)",
225
+ examples_per_page=4,
226
+ )
227
+
228
+ # Información técnica
229
+ with gr.Accordion("ℹ️ Información técnica", open=False):
230
+ gr.Markdown("""
231
+ **Modelos utilizados:**
232
+ - **RoBERTuito**: `pysentimiento/robertuito-sentiment-analysis`
233
+ - Entrenado en tweets en español
234
+ - Especializado en lenguaje coloquial
235
+ - Mejor para redes sociales y lenguaje informal
236
+
237
+ - **BETO**: `finiteautomata/beto-sentiment-analysis`
238
+ - Basado en BERT entrenado en Wikipedia
239
+ - Más formal y generalista
240
+ - Bueno para textos formales y periodísticos
241
+
242
+ **Arquitectura:**
243
+ - Modelos cargados una sola vez al inicio
244
+ - Procesamiento paralelo para mejor rendimiento
245
+ - Resultados mostrados con confianza y tiempo de respuesta
246
+ """)
247
+
248
+ # Conectar eventos
249
+ analizar_btn.click(
250
+ fn=analizar_sentimiento,
251
+ inputs=[texto_input],
252
+ outputs=[robertuito_output, beto_output],
253
+ )
254
+
255
+ # También analizar cuando cambia el texto
256
+ texto_input.change(
257
+ fn=analizar_sentimiento,
258
+ inputs=[texto_input],
259
+ outputs=[robertuito_output, beto_output],
260
+ )
261
+
262
+ # Punto de entrada
263
+ if __name__ == "__main__":
264
+ print("🚀 Iniciando aplicación de comparación de modelos...")
265
+ demo.launch(
266
+ server_name="0.0.0.0", # Para Hugging Face Spaces
267
+ server_port=7860,
268
+ show_api=False,
269
+ )