AIdeaText commited on
Commit
21973a9
·
verified ·
1 Parent(s): 4cd6fca

Create ui.py

Browse files
Files changed (1) hide show
  1. modules/ui/ui.py +814 -0
modules/ui/ui.py ADDED
@@ -0,0 +1,814 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Importaciones generales
2
+ import streamlit as st
3
+ import re
4
+ import io
5
+ from io import BytesIO
6
+ import base64
7
+ import matplotlib.pyplot as plt
8
+ import pandas as pd
9
+ import time
10
+ from datetime import datetime
11
+ from streamlit_player import st_player # Necesitarás instalar esta librería: pip install streamlit-player
12
+ from spacy import displacy
13
+ import logging
14
+
15
+ ######################################################
16
+ # Configuración del logger
17
+ logging.basicConfig(level=logging.INFO)
18
+ logger = logging.getLogger(__name__)
19
+
20
+ ######################################################
21
+ # Importaciones locales
22
+ from ..email.email import send_email_notification
23
+
24
+ ######################################################
25
+ # Importaciones locales de autenticación y base de datos
26
+ from ..auth.auth import (
27
+ authenticate_user,
28
+ register_user
29
+ )
30
+
31
+ ######################################################
32
+ from ..database.database import (
33
+ get_student_data,
34
+ store_application_request,
35
+ store_morphosyntax_result,
36
+ store_semantic_result,
37
+ store_discourse_analysis_result,
38
+ store_chat_history,
39
+ create_admin_user,
40
+ create_student_user
41
+ )
42
+
43
+ ######################################################
44
+ # Importaciones locales de uiadmin
45
+ from ..admin.admin_ui import admin_page
46
+
47
+ ######################################################
48
+ # Importaciones locales funciones de análisis
49
+ from ..text_analysis.morpho_analysis import (
50
+ generate_arc_diagram,
51
+ get_repeated_words_colors,
52
+ highlight_repeated_words,
53
+ POS_COLORS,
54
+ POS_TRANSLATIONS,
55
+ perform_advanced_morphosyntactic_analysis
56
+ )
57
+
58
+ ######################################################
59
+ from ..text_analysis.semantic_analysis import (
60
+ visualize_semantic_relations,
61
+ perform_semantic_analysis
62
+ )
63
+
64
+ ######################################################
65
+ from ..text_analysis.discourse_analysis import (
66
+ compare_semantic_analysis,
67
+ perform_discourse_analysis
68
+ )
69
+
70
+ ######################################################
71
+ from ..chatbot.chatbot import (
72
+ initialize_chatbot,
73
+ get_chatbot_response
74
+ )
75
+
76
+ ##################################################################################################
77
+ def initialize_session_state():
78
+ if 'initialized' not in st.session_state:
79
+ st.session_state.clear()
80
+ st.session_state.initialized = True
81
+ st.session_state.logged_in = False
82
+ st.session_state.page = 'login'
83
+ st.session_state.username = None
84
+ st.session_state.role = None
85
+
86
+ ##################################################################################################
87
+ def main():
88
+ initialize_session_state()
89
+
90
+ print(f"Página actual: {st.session_state.page}")
91
+ print(f"Rol del usuario: {st.session_state.role}")
92
+
93
+ if st.session_state.page == 'login':
94
+ login_register_page()
95
+ elif st.session_state.page == 'admin':
96
+ print("Intentando mostrar página de admin")
97
+ admin_page()
98
+ elif st.session_state.page == 'user':
99
+ user_page()
100
+ else:
101
+ print(f"Página no reconocida: {st.session_state.page}")
102
+
103
+ print(f"Estado final de la sesión: {st.session_state}")
104
+
105
+ ##################################################################################################
106
+ def login_register_page():
107
+ st.title("AIdeaText")
108
+
109
+ left_column, right_column = st.columns([1, 3])
110
+
111
+ with left_column:
112
+ tab1, tab2 = st.tabs(["Iniciar Sesión", "Registrarse"])
113
+
114
+ with tab1:
115
+ login_form()
116
+
117
+ with tab2:
118
+ register_form()
119
+
120
+ with right_column:
121
+ display_videos_and_info()
122
+
123
+ ##################################################################################################
124
+
125
+ def login_form():
126
+ username = st.text_input("Correo electrónico", key="login_username")
127
+ password = st.text_input("Contraseña", type="password", key="login_password")
128
+
129
+ if st.button("Iniciar Sesión", key="login_button"):
130
+ success, role = authenticate_user(username, password)
131
+ if success:
132
+ st.session_state.logged_in = True
133
+ st.session_state.username = username
134
+ st.session_state.role = role
135
+ st.session_state.page = 'admin' if role == 'Administrador' else 'user'
136
+ print(f"Inicio de sesión exitoso. Usuario: {username}, Rol: {role}")
137
+ print(f"Estado de sesión después de login: {st.session_state}")
138
+ st.rerun()
139
+ else:
140
+ st.error("Credenciales incorrectas")
141
+
142
+ ##################################################################################################
143
+ def admin_page():
144
+ st.title("Panel de Administración")
145
+ st.write(f"Bienvenido, {st.session_state.username}")
146
+
147
+ st.header("Crear Nuevo Usuario Estudiante")
148
+ new_username = st.text_input("Correo electrónico del nuevo usuario", key="admin_new_username")
149
+ new_password = st.text_input("Contraseña", type="password", key="admin_new_password")
150
+ if st.button("Crear Usuario", key="admin_create_user"):
151
+ if create_student_user(new_username, new_password):
152
+ st.success(f"Usuario estudiante {new_username} creado exitosamente")
153
+ else:
154
+ st.error("Error al crear el usuario estudiante")
155
+
156
+ # Aquí puedes añadir más funcionalidades para el panel de administración
157
+
158
+ ##################################################################################################
159
+ def user_page():
160
+ st.title("Bienvenido a AIdeaText")
161
+ st.write(f"Hola, {st.session_state.username}")
162
+
163
+ # Aquí puedes añadir las funcionalidades para el usuario estudiante
164
+ # Por ejemplo:
165
+ tabs = st.tabs(["Análisis Morfosintáctico", "Análisis Semántico", "Análisis del Discurso", "Chat", "Mi Progreso"])
166
+
167
+ with tabs[0]:
168
+ display_morphosyntax_analysis_interface(nlp_models, 'es') # Asumiendo que 'es' es el idioma por defecto
169
+ with tabs[1]:
170
+ display_semantic_analysis_interface(nlp_models, 'es')
171
+ with tabs[2]:
172
+ display_discourse_analysis_interface(nlp_models, 'es')
173
+ with tabs[3]:
174
+ display_chatbot_interface('es')
175
+ with tabs[4]:
176
+ display_student_progress(st.session_state.username, 'es')
177
+
178
+ ##################################################################################################
179
+ def display_videos_and_info():
180
+ st.header("Videos: pitch, demos, entrevistas, otros")
181
+
182
+ videos = {
183
+ "Intro AideaText": "https://www.youtube.com/watch?v=UA-md1VxaRc",
184
+ "Presentación fundación Ser Maaestro": "https://www.youtube.com/watch?v=imc4TI1q164",
185
+ "Pitch IFE Explora": "https://www.youtube.com/watch?v=Fqi4Di_Rj_s",
186
+ "Entrevista Dr. Guillermo Ruíz": "https://www.youtube.com/watch?v=_ch8cRja3oc",
187
+ "Demo versión desktop": "https://www.youtube.com/watch?v=nP6eXbog-ZY"
188
+ }
189
+
190
+ selected_title = st.selectbox("Selecciona un video tutorial:", list(videos.keys()))
191
+
192
+ if selected_title in videos:
193
+ try:
194
+ st_player(videos[selected_title])
195
+ except Exception as e:
196
+ st.error(f"Error al cargar el video: {str(e)}")
197
+
198
+ st.markdown("""
199
+ ## Novedades de la versión actual
200
+ - Nueva función de análisis semántico
201
+ - Soporte para múltiples idiomas
202
+ - Interfaz mejorada para una mejor experiencia de usuario
203
+ """)
204
+
205
+ ##################################################################################################
206
+ def register_form():
207
+ st.header("Solicitar prueba de la aplicación")
208
+
209
+ name = st.text_input("Nombre completo")
210
+ email = st.text_input("Correo electrónico institucional")
211
+ institution = st.text_input("Institución")
212
+ role = st.selectbox("Rol", ["Estudiante", "Profesor", "Investigador", "Otro"])
213
+ reason = st.text_area("¿Por qué estás interesado en probar AIdeaText?")
214
+
215
+ if st.button("Enviar solicitud"):
216
+ logger.info(f"Attempting to submit application for {email}")
217
+ logger.debug(f"Form data: name={name}, email={email}, institution={institution}, role={role}, reason={reason}")
218
+
219
+ if not name or not email or not institution or not reason:
220
+ logger.warning("Incomplete form submission")
221
+ st.error("Por favor, completa todos los campos.")
222
+ elif not is_institutional_email(email):
223
+ logger.warning(f"Non-institutional email used: {email}")
224
+ st.error("Por favor, utiliza un correo electrónico institucional.")
225
+ else:
226
+ logger.info(f"Attempting to store application for {email}")
227
+ success = store_application_request(name, email, institution, role, reason)
228
+ if success:
229
+ st.success("Tu solicitud ha sido enviada. Te contactaremos pronto.")
230
+ logger.info(f"Application request stored successfully for {email}")
231
+ else:
232
+ st.error("Hubo un problema al enviar tu solicitud. Por favor, intenta de nuevo más tarde.")
233
+ logger.error(f"Failed to store application request for {email}")
234
+
235
+
236
+ ################################################################################
237
+ def is_institutional_email(email):
238
+ forbidden_domains = ['gmail.com', 'hotmail.com', 'yahoo.com', 'outlook.com']
239
+ return not any(domain in email.lower() for domain in forbidden_domains)
240
+ ################################################################################
241
+
242
+ def display_student_progress(username, lang_code='es'):
243
+ student_data = get_student_data(username)
244
+
245
+ if student_data is None or len(student_data['entries']) == 0:
246
+ st.warning("No se encontraron datos para este estudiante.")
247
+ st.info("Intenta realizar algunos análisis de texto primero.")
248
+ return
249
+
250
+ st.title(f"Progreso de {username}")
251
+
252
+ with st.expander("Resumen de Actividades y Progreso", expanded=True):
253
+ # Resumen de actividades
254
+ total_entries = len(student_data['entries'])
255
+ st.write(f"Total de análisis realizados: {total_entries}")
256
+
257
+ # Gráfico de tipos de análisis
258
+ analysis_types = [entry['analysis_type'] for entry in student_data['entries']]
259
+ analysis_counts = pd.Series(analysis_types).value_counts()
260
+
261
+ fig, ax = plt.subplots()
262
+ analysis_counts.plot(kind='bar', ax=ax)
263
+ ax.set_title("Tipos de análisis realizados")
264
+ ax.set_xlabel("Tipo de análisis")
265
+ ax.set_ylabel("Cantidad")
266
+ st.pyplot(fig)
267
+
268
+ # Progreso a lo largo del tiempo
269
+ dates = [datetime.fromisoformat(entry['timestamp']) for entry in student_data['entries']]
270
+ analysis_counts = pd.Series(dates).value_counts().sort_index()
271
+
272
+ fig, ax = plt.subplots()
273
+ analysis_counts.plot(kind='line', ax=ax)
274
+ ax.set_title("Análisis realizados a lo largo del tiempo")
275
+ ax.set_xlabel("Fecha")
276
+ ax.set_ylabel("Cantidad de análisis")
277
+ st.pyplot(fig)
278
+
279
+ ##########################################################
280
+ with st.expander("Histórico de Análisis Morfosintácticos"):
281
+ morphosyntax_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'morphosyntax']
282
+ for entry in morphosyntax_entries:
283
+ st.subheader(f"Análisis del {entry['timestamp']}")
284
+ if entry['arc_diagrams']:
285
+ st.write(entry['arc_diagrams'][0], unsafe_allow_html=True)
286
+
287
+
288
+ ##########################################################
289
+ with st.expander("Histórico de Análisis Semánticos"):
290
+ semantic_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'semantic']
291
+ st.write(f"Número total de entradas semánticas: {len(semantic_entries)}")
292
+ for entry in semantic_entries:
293
+ st.subheader(f"Análisis del {entry['timestamp']}")
294
+ st.write(f"Archivo analizado: {entry.get('filename', 'Nombre no disponible')}")
295
+ st.write(f"Claves disponibles en esta entrada: {', '.join(entry.keys())}")
296
+
297
+ # Verificar si 'relations_graph' está en entry antes de intentar acceder
298
+ if 'network_diagram' in entry:
299
+ try:
300
+ logger.info(f"Longitud de la imagen recuperada: {len(entry['network_diagram'])}")
301
+ st.image(f"data:image/png;base64,{entry['network_diagram']}")
302
+ except Exception as e:
303
+ st.error(f"No se pudo mostrar la imagen: {str(e)}")
304
+ st.write("Datos de la imagen (para depuración):")
305
+ st.write(entry['network_diagram'][:100] + "...")
306
+ else:
307
+ logger.warning(f"No se encontró 'relations_graph' en la entrada: {entry.keys()}")
308
+ st.write("No se encontró el gráfico para este análisis.")
309
+
310
+ ##########################################################
311
+ with st.expander("Histórico de Análisis Discursivos"):
312
+ discourse_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'discourse']
313
+ for entry in discourse_entries:
314
+ st.subheader(f"Análisis del {entry['timestamp']}")
315
+ st.write(f"Archivo patrón: {entry.get('filename1', 'Nombre no disponible')}")
316
+ st.write(f"Archivo comparado: {entry.get('filename2', 'Nombre no disponible')}")
317
+
318
+ try:
319
+ # Intentar obtener y combinar las dos imágenes
320
+ if 'graph1' in entry and 'graph2' in entry:
321
+ img1 = Image.open(BytesIO(base64.b64decode(entry['graph1'])))
322
+ img2 = Image.open(BytesIO(base64.b64decode(entry['graph2'])))
323
+
324
+ # Crear una nueva imagen combinada
325
+ total_width = img1.width + img2.width
326
+ max_height = max(img1.height, img2.height)
327
+ combined_img = Image.new('RGB', (total_width, max_height))
328
+
329
+ # Pegar las dos imágenes lado a lado
330
+ combined_img.paste(img1, (0, 0))
331
+ combined_img.paste(img2, (img1.width, 0))
332
+
333
+ # Convertir la imagen combinada a bytes
334
+ buffered = BytesIO()
335
+ combined_img.save(buffered, format="PNG")
336
+ img_str = base64.b64encode(buffered.getvalue()).decode()
337
+
338
+ # Mostrar la imagen combinada
339
+ st.image(f"data:image/png;base64,{img_str}")
340
+ elif 'combined_graph' in entry:
341
+ # Si ya existe una imagen combinada, mostrarla directamente
342
+ img_bytes = base64.b64decode(entry['combined_graph'])
343
+ st.image(img_bytes)
344
+ else:
345
+ st.write("No se encontraron gráficos para este análisis.")
346
+ except Exception as e:
347
+ st.error(f"No se pudieron mostrar los gráficos: {str(e)}")
348
+ st.write("Datos de los gráficos (para depuración):")
349
+ if 'graph1' in entry:
350
+ st.write("Graph 1:", entry['graph1'][:100] + "...")
351
+ if 'graph2' in entry:
352
+ st.write("Graph 2:", entry['graph2'][:100] + "...")
353
+ if 'combined_graph' in entry:
354
+ st.write("Combined Graph:", entry['combined_graph'][:100] + "...")
355
+
356
+
357
+ ##########################################################
358
+ with st.expander("Histórico de Conversaciones con el ChatBot"):
359
+ if 'chat_history' in student_data:
360
+ for i, chat in enumerate(student_data['chat_history']):
361
+ st.subheader(f"Conversación {i+1} - {chat['timestamp']}")
362
+ for message in chat['messages']:
363
+ if message['role'] == 'user':
364
+ st.write("Usuario: " + message['content'])
365
+ else:
366
+ st.write("Asistente: " + message['content'])
367
+ st.write("---")
368
+ else:
369
+ st.write("No se encontraron conversaciones con el ChatBot.")
370
+
371
+ # Añadir logs para depuración
372
+ if st.checkbox("Mostrar datos de depuración"):
373
+ st.write("Datos del estudiante (para depuración):")
374
+ st.json(student_data)
375
+
376
+ ##################################################################################################
377
+ def display_morphosyntax_analysis_interface(nlp_models, lang_code):
378
+ translations = {
379
+ 'es': {
380
+ 'title': "AIdeaText - Análisis morfológico y sintáctico",
381
+ 'input_label': "Ingrese un texto para analizar (máximo 5,000 palabras",
382
+ 'input_placeholder': "Esta funcionalidad le ayudará con dos competencias:\n"
383
+ "[1] \"Escribe diversos tipos de textos en su lengua materna\"\n"
384
+ "[2] \"Lee diversos tipos de textos escritos en su lengua materna\"\n\n"
385
+ "Ingrese su texto aquí para analizar...",
386
+ 'analyze_button': "Analizar texto",
387
+ 'repeated_words': "Palabras repetidas",
388
+ 'legend': "Leyenda: Categorías gramaticales",
389
+ 'arc_diagram': "Análisis sintáctico: Diagrama de arco",
390
+ 'sentence': "Oración",
391
+ 'success_message': "Análisis guardado correctamente.",
392
+ 'error_message': "Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.",
393
+ 'warning_message': "Por favor, ingrese un texto para analizar.",
394
+ 'pos_analysis': "Análisis de categorías gramaticales",
395
+ 'morphological_analysis': "Análisis morfológico",
396
+ 'sentence_structure': "Estructura de oraciones",
397
+ 'word': "Palabra",
398
+ 'count': "Cantidad",
399
+ 'percentage': "Porcentaje",
400
+ 'examples': "Ejemplos",
401
+ 'lemma': "Lema",
402
+ 'tag': "Etiqueta",
403
+ 'dep': "Dependencia",
404
+ 'morph': "Morfología",
405
+ 'root': "Raíz",
406
+ 'subjects': "Sujetos",
407
+ 'objects': "Objetos",
408
+ 'verbs': "Verbos"
409
+ },
410
+ 'en': {
411
+ 'title': "AIdeaText - Morphological and Syntactic Analysis",
412
+ 'input_label': "Enter a text to analyze (max 5,000 words):",
413
+ 'input_placeholder': "This functionality will help you with two competencies:\n"
414
+ "[1] \"Write various types of texts in your native language\"\n"
415
+ "[2] \"Read various types of written texts in your native language\"\n\n"
416
+ "Enter your text here to analyze...",
417
+ 'analyze_button': "Analyze text",
418
+ 'repeated_words': "Repeated words",
419
+ 'legend': "Legend: Grammatical categories",
420
+ 'arc_diagram': "Syntactic analysis: Arc diagram",
421
+ 'sentence': "Sentence",
422
+ 'success_message': "Analysis saved successfully.",
423
+ 'error_message': "There was a problem saving the analysis. Please try again.",
424
+ 'warning_message': "Please enter a text to analyze.",
425
+ 'pos_analysis': "Part of Speech Analysis",
426
+ 'morphological_analysis': "Morphological Analysis",
427
+ 'sentence_structure': "Sentence Structure",
428
+ 'word': "Word",
429
+ 'count': "Count",
430
+ 'percentage': "Percentage",
431
+ 'examples': "Examples",
432
+ 'lemma': "Lemma",
433
+ 'tag': "Tag",
434
+ 'dep': "Dependency",
435
+ 'morph': "Morphology",
436
+ 'root': "Root",
437
+ 'subjects': "Subjects",
438
+ 'objects': "Objects",
439
+ 'verbs': "Verbs"
440
+ },
441
+ 'fr': {
442
+ 'title': "AIdeaText - Analyse morphologique et syntaxique",
443
+ 'input_label': "Entrez un texte à analyser (max 5 000 mots) :",
444
+ 'input_placeholder': "Cette fonctionnalité vous aidera avec deux compétences :\n"
445
+ "[1] \"Écrire divers types de textes dans votre langue maternelle\"\n"
446
+ "[2] \"Lire divers types de textes écrits dans votre langue maternelle\"\n\n"
447
+ "Entrez votre texte ici pour l'analyser...",
448
+ 'analyze_button': "Analyser le texte",
449
+ 'repeated_words': "Mots répétés",
450
+ 'legend': "Légende : Catégories grammaticales",
451
+ 'arc_diagram': "Analyse syntaxique : Diagramme en arc",
452
+ 'sentence': "Phrase",
453
+ 'success_message': "Analyse enregistrée avec succès.",
454
+ 'error_message': "Un problème est survenu lors de l'enregistrement de l'analyse. Veuillez réessayer.",
455
+ 'warning_message': "Veuillez entrer un texte à analyser.",
456
+ 'pos_analysis': "Analyse des parties du discours",
457
+ 'morphological_analysis': "Analyse morphologique",
458
+ 'sentence_structure': "Structure des phrases",
459
+ 'word': "Mot",
460
+ 'count': "Nombre",
461
+ 'percentage': "Pourcentage",
462
+ 'examples': "Exemples",
463
+ 'lemma': "Lemme",
464
+ 'tag': "Étiquette",
465
+ 'dep': "Dépendance",
466
+ 'morph': "Morphologie",
467
+ 'root': "Racine",
468
+ 'subjects': "Sujets",
469
+ 'objects': "Objets",
470
+ 'verbs': "Verbes"
471
+ }
472
+ }
473
+
474
+ t = translations[lang_code]
475
+
476
+ input_key = f"morphosyntax_input_{lang_code}"
477
+
478
+ if input_key not in st.session_state:
479
+ st.session_state[input_key] = ""
480
+
481
+ sentence_input = st.text_area(
482
+ t['input_label'],
483
+ height=150,
484
+ placeholder=t['input_placeholder'],
485
+ value=st.session_state[input_key],
486
+ key=f"text_area_{lang_code}",
487
+ on_change=lambda: setattr(st.session_state, input_key, st.session_state[f"text_area_{lang_code}"])
488
+ )
489
+
490
+ if st.button(t['analyze_button'], key=f"analyze_button_{lang_code}"):
491
+ current_input = st.session_state[input_key]
492
+ if current_input:
493
+ doc = nlp_models[lang_code](current_input)
494
+
495
+ # Análisis morfosintáctico avanzado
496
+ advanced_analysis = perform_advanced_morphosyntactic_analysis(current_input, nlp_models[lang_code])
497
+
498
+ # Mostrar leyenda (código existente)
499
+ st.markdown(f"##### {t['legend']}")
500
+ legend_html = "<div style='display: flex; flex-wrap: wrap;'>"
501
+ for pos, color in POS_COLORS.items():
502
+ if pos in POS_TRANSLATIONS[lang_code]:
503
+ legend_html += f"<div style='margin-right: 10px;'><span style='background-color: {color}; padding: 2px 5px;'>{POS_TRANSLATIONS[lang_code][pos]}</span></div>"
504
+ legend_html += "</div>"
505
+ st.markdown(legend_html, unsafe_allow_html=True)
506
+
507
+ # Mostrar análisis de palabras repetidas (código existente)
508
+ word_colors = get_repeated_words_colors(doc)
509
+ with st.expander(t['repeated_words'], expanded=True):
510
+ highlighted_text = highlight_repeated_words(doc, word_colors)
511
+ st.markdown(highlighted_text, unsafe_allow_html=True)
512
+
513
+ # Mostrar estructura de oraciones
514
+ with st.expander(t['sentence_structure'], expanded=True):
515
+ for i, sent_analysis in enumerate(advanced_analysis['sentence_structure']):
516
+ sentence_str = (
517
+ f"**{t['sentence']} {i+1}** "
518
+ f"{t['root']}: {sent_analysis['root']} ({sent_analysis['root_pos']}) -- "
519
+ f"{t['subjects']}: {', '.join(sent_analysis['subjects'])} -- "
520
+ f"{t['objects']}: {', '.join(sent_analysis['objects'])} -- "
521
+ f"{t['verbs']}: {', '.join(sent_analysis['verbs'])}"
522
+ )
523
+ st.markdown(sentence_str)
524
+
525
+ # Mostrar análisis de categorías gramaticales # Mostrar análisis morfológico
526
+ col1, col2 =st.columns(2)
527
+ with col1:
528
+ with st.expander(t['pos_analysis'], expanded=True):
529
+ pos_df = pd.DataFrame(advanced_analysis['pos_analysis'])
530
+ st.dataframe(pos_df)
531
+ with col2:
532
+ with st.expander(t['morphological_analysis'], expanded=True):
533
+ morph_df = pd.DataFrame(advanced_analysis['morphological_analysis'])
534
+ st.dataframe(morph_df)
535
+
536
+ # Mostrar diagramas de arco (código existente)
537
+ with st.expander(t['arc_diagram'], expanded=True):
538
+ sentences = list(doc.sents)
539
+ arc_diagrams = []
540
+ for i, sent in enumerate(sentences):
541
+ st.subheader(f"{t['sentence']} {i+1}")
542
+ html = displacy.render(sent, style="dep", options={"distance": 100})
543
+ html = html.replace('height="375"', 'height="200"')
544
+ html = re.sub(r'<svg[^>]*>', lambda m: m.group(0).replace('height="450"', 'height="300"'), html)
545
+ html = re.sub(r'<g [^>]*transform="translate\((\d+),(\d+)\)"', lambda m: f'<g transform="translate({m.group(1)},50)"', html)
546
+ st.write(html, unsafe_allow_html=True)
547
+ arc_diagrams.append(html)
548
+
549
+ # Guardar resultados
550
+ if store_morphosyntax_result(
551
+ st.session_state.username,
552
+ current_input,
553
+ word_colors,
554
+ advanced_analysis['arc_diagram'],
555
+ advanced_analysis['pos_analysis'],
556
+ advanced_analysis['morphological_analysis'],
557
+ advanced_analysis['sentence_structure']
558
+
559
+ ):
560
+ st.success(t['success_message'])
561
+ else:
562
+ st.error(t['error_message'])
563
+ else:
564
+ st.warning(t['warning_message'])
565
+
566
+ ###############################################################################################################
567
+ def display_semantic_analysis_interface(nlp_models, lang_code):
568
+ translations = {
569
+ 'es': {
570
+ 'title': "AIdeaText - Análisis semántico",
571
+ 'text_input_label': "Ingrese un texto para analizar (máx. 5,000 palabras):",
572
+ 'text_input_placeholder': "El objetivo de esta aplicación es que mejore sus habilidades de redacción...",
573
+ 'file_uploader': "O cargue un archivo de texto",
574
+ 'analyze_button': "Analizar texto",
575
+ 'semantic_relations': "Relaciones Semánticas Relevantes",
576
+ 'identified_entities': "Entidades Identificadas",
577
+ 'key_concepts': "Conceptos Clave",
578
+ 'success_message': "Análisis semántico guardado correctamente.",
579
+ 'error_message': "Hubo un problema al guardar el análisis semántico. Por favor, inténtelo de nuevo.",
580
+ 'warning_message': "Por favor, ingrese un texto o cargue un archivo para analizar."
581
+ },
582
+ 'en': {
583
+ 'title': "AIdeaText - Semantic Analysis",
584
+ 'text_input_label': "Enter a text to analyze (max. 5,000 words):",
585
+ 'text_input_placeholder': "The goal of this application is to improve your writing skills...",
586
+ 'file_uploader': "Or upload a text file",
587
+ 'analyze_button': "Analyze text",
588
+ 'semantic_relations': "Relevant Semantic Relations",
589
+ 'identified_entities': "Identified Entities",
590
+ 'key_concepts': "Key Concepts",
591
+ 'success_message': "Semantic analysis saved successfully.",
592
+ 'error_message': "There was a problem saving the semantic analysis. Please try again.",
593
+ 'warning_message': "Please enter a text or upload a file to analyze."
594
+ },
595
+ 'fr': {
596
+ 'title': "AIdeaText - Analyse sémantique",
597
+ 'text_input_label': "Entrez un texte à analyser (max. 5 000 mots) :",
598
+ 'text_input_placeholder': "L'objectif de cette application est d'améliorer vos compétences en rédaction...",
599
+ 'file_uploader': "Ou téléchargez un fichier texte",
600
+ 'analyze_button': "Analyser le texte",
601
+ 'semantic_relations': "Relations Sémantiques Pertinentes",
602
+ 'identified_entities': "Entités Identifiées",
603
+ 'key_concepts': "Concepts Clés",
604
+ 'success_message': "Analyse sémantique enregistrée avec succès.",
605
+ 'error_message': "Un problème est survenu lors de l'enregistrement de l'analyse sémantique. Veuillez réessayer.",
606
+ 'warning_message': "Veuillez entrer un texte ou télécharger un fichier à analyser."
607
+ }
608
+ }
609
+
610
+ t = translations[lang_code]
611
+
612
+ st.header(t['title'])
613
+
614
+ # Opción para introducir texto
615
+ text_input = st.text_area(
616
+ t['text_input_label'],
617
+ height=150,
618
+ placeholder=t['text_input_placeholder'],
619
+ )
620
+
621
+ # Opción para cargar archivo
622
+ uploaded_file = st.file_uploader(t['file_uploader'], type=['txt'])
623
+
624
+ if st.button(t['analyze_button']):
625
+ if text_input or uploaded_file is not None:
626
+ if uploaded_file:
627
+ text_content = uploaded_file.getvalue().decode('utf-8')
628
+ else:
629
+ text_content = text_input
630
+
631
+ # Realizar el análisis
632
+ analysis_result = perform_semantic_analysis(text_content, nlp_models[lang_code], lang_code)
633
+
634
+ # Mostrar conceptos clave
635
+ with st.expander(t['key_concepts'], expanded=True):
636
+ key_concepts_text = " ".join([f"[[{concept}]]" for concept, _ in analysis_result['key_concepts']])
637
+ st.markdown(key_concepts_text)
638
+
639
+ # Mostrar entidades identificadas
640
+ with st.expander(t['identified_entities'], expanded=True):
641
+ entities_text = ""
642
+ for entity in analysis_result['entities']:
643
+ entities_text += f"[[{entity['text']} ({entity['label']}) - Contexto: {entity['context']}]] "
644
+ st.markdown(entities_text)
645
+
646
+ # Mostrar el gráfico de relaciones semánticas
647
+ with st.expander(t['semantic_relations'], expanded=True):
648
+ st.pyplot(analysis_result['relations_graph'])
649
+
650
+ # Guardar el resultado del análisis
651
+ if store_semantic_result(st.session_state.username, text_content, analysis_result):
652
+ st.success(t['success_message'])
653
+ else:
654
+ st.error(t['error_message'])
655
+ else:
656
+ st.warning(t['warning_message'])
657
+
658
+ ##################################################################################################
659
+ def display_discourse_analysis_interface(nlp_models, lang_code):
660
+ translations = {
661
+ 'es': {
662
+ 'title': "AIdeaText - Análisis del discurso",
663
+ 'file_uploader1': "Cargar archivo de texto 1 (Patrón)",
664
+ 'file_uploader2': "Cargar archivo de texto 2 (Comparación)",
665
+ 'analyze_button': "Analizar textos",
666
+ 'comparison': "Comparación de Relaciones Semánticas",
667
+ 'success_message': "Análisis del discurso guardado correctamente.",
668
+ 'error_message': "Hubo un problema al guardar el análisis del discurso. Por favor, inténtelo de nuevo.",
669
+ 'warning_message': "Por favor, cargue ambos archivos para analizar."
670
+ },
671
+ 'en': {
672
+ 'title': "AIdeaText - Discourse Analysis",
673
+ 'file_uploader1': "Upload text file 1 (Pattern)",
674
+ 'file_uploader2': "Upload text file 2 (Comparison)",
675
+ 'analyze_button': "Analyze texts",
676
+ 'comparison': "Comparison of Semantic Relations",
677
+ 'success_message': "Discourse analysis saved successfully.",
678
+ 'error_message': "There was a problem saving the discourse analysis. Please try again.",
679
+ 'warning_message': "Please upload both files to analyze."
680
+ },
681
+ 'fr': {
682
+ 'title': "AIdeaText - Analyse du discours",
683
+ 'file_uploader1': "Télécharger le fichier texte 1 (Modèle)",
684
+ 'file_uploader2': "Télécharger le fichier texte 2 (Comparaison)",
685
+ 'analyze_button': "Analyser les textes",
686
+ 'comparison': "Comparaison des Relations Sémantiques",
687
+ 'success_message': "Analyse du discours enregistrée avec succès.",
688
+ 'error_message': "Un problème est survenu lors de l'enregistrement de l'analyse du discours. Veuillez réessayer.",
689
+ 'warning_message': "Veuillez télécharger les deux fichiers à analyser."
690
+ }
691
+ }
692
+
693
+ t = translations[lang_code]
694
+ st.header(t['title'])
695
+
696
+ col1, col2 = st.columns(2)
697
+
698
+ with col1:
699
+ uploaded_file1 = st.file_uploader(t['file_uploader1'], type=['txt'])
700
+
701
+ with col2:
702
+ uploaded_file2 = st.file_uploader(t['file_uploader2'], type=['txt'])
703
+
704
+ if st.button(t['analyze_button']):
705
+ if uploaded_file1 is not None and uploaded_file2 is not None:
706
+ text_content1 = uploaded_file1.getvalue().decode('utf-8')
707
+ text_content2 = uploaded_file2.getvalue().decode('utf-8')
708
+
709
+ # Realizar el análisis
710
+ graph1, graph2 = perform_discourse_analysis(text_content1, text_content2, nlp_models[lang_code], lang_code)
711
+
712
+ # Mostrar los gráficos de comparación
713
+ st.subheader(t['comparison'])
714
+ col1, col2 = st.columns(2)
715
+ with col1:
716
+ st.pyplot(graph1)
717
+ with col2:
718
+ st.pyplot(graph2)
719
+
720
+ # Guardar el resultado del análisis
721
+ #if store_discourse_analysis_result(st.session_state.username, text_content1 + "\n\n" + text_content2, graph1, graph2):
722
+ if store_discourse_analysis_result(st.session_state.username, text_content1, text_content2, graph1, graph2):
723
+ st.success(t['success_message'])
724
+ else:
725
+ st.error(t['error_message'])
726
+ else:
727
+ st.warning(t['warning_message'])
728
+
729
+ ##################################################################################################
730
+ #def display_saved_discourse_analysis(analysis_data):
731
+ # img_bytes = base64.b64decode(analysis_data['combined_graph'])
732
+ # img = plt.imread(io.BytesIO(img_bytes), format='png')
733
+
734
+ # st.image(img, use_column_width=True)
735
+ # st.write("Texto del documento patrón:")
736
+ # st.write(analysis_data['text1'])
737
+ # st.write("Texto del documento comparado:")
738
+ # st.write(analysis_data['text2'])
739
+
740
+ ##################################################################################################
741
+ def display_chatbot_interface(lang_code):
742
+ translations = {
743
+ 'es': {
744
+ 'title': "Expertos en Vacaciones",
745
+ 'input_placeholder': "Escribe tu mensaje aquí...",
746
+ 'initial_message': "¡Hola! ¿Cómo podemos ayudarte?"
747
+ },
748
+ 'en': {
749
+ 'title': "Vacation Experts",
750
+ 'input_placeholder': "Type your message here...",
751
+ 'initial_message': "Hi! How can we help you?"
752
+ },
753
+ 'fr': {
754
+ 'title': "Experts en Vacances",
755
+ 'input_placeholder': "Écrivez votre message ici...",
756
+ 'initial_message': "Bonjour! Comment pouvons-nous vous aider?"
757
+ }
758
+ }
759
+ t = translations[lang_code]
760
+ st.title(t['title'])
761
+
762
+ if 'chatbot' not in st.session_state:
763
+ st.session_state.chatbot = initialize_chatbot()
764
+ if 'messages' not in st.session_state:
765
+ st.session_state.messages = [{"role": "assistant", "content": t['initial_message']}]
766
+
767
+ # Contenedor principal para el chat
768
+ chat_container = st.container()
769
+
770
+ # Mostrar mensajes existentes
771
+ with chat_container:
772
+ for message in st.session_state.messages:
773
+ with st.chat_message(message["role"]):
774
+ st.markdown(message["content"])
775
+
776
+ # Área de entrada del usuario
777
+ user_input = st.chat_input(t['input_placeholder'])
778
+
779
+ if user_input:
780
+ # Agregar mensaje del usuario
781
+ st.session_state.messages.append({"role": "user", "content": user_input})
782
+
783
+ # Mostrar mensaje del usuario
784
+ with chat_container:
785
+ with st.chat_message("user"):
786
+ st.markdown(user_input)
787
+
788
+ # Generar respuesta del chatbot
789
+ with chat_container:
790
+ with st.chat_message("assistant"):
791
+ message_placeholder = st.empty()
792
+ full_response = ""
793
+ for chunk in get_chatbot_response(st.session_state.chatbot, user_input, lang_code):
794
+ full_response += chunk
795
+ message_placeholder.markdown(full_response + "▌")
796
+ message_placeholder.markdown(full_response)
797
+
798
+ # Agregar respuesta del asistente a los mensajes
799
+ st.session_state.messages.append({"role": "assistant", "content": full_response})
800
+
801
+ # Guardar la conversación en la base de datos
802
+ try:
803
+ store_chat_history(st.session_state.username, st.session_state.messages)
804
+ st.success("Conversación guardada exitosamente")
805
+ except Exception as e:
806
+ st.error(f"Error al guardar la conversación: {str(e)}")
807
+ logger.error(f"Error al guardar el historial de chat para {st.session_state.username}: {str(e)}")
808
+
809
+ # Scroll al final del chat
810
+ st.markdown('<script>window.scrollTo(0,document.body.scrollHeight);</script>', unsafe_allow_html=True)
811
+
812
+ ######################################################
813
+ if __name__ == "__main__":
814
+ main()