# Importaciones generales import streamlit as st import re import io from io import BytesIO import base64 import matplotlib.pyplot as plt import plotly.graph_objects as go import pandas as pd import numpy as np import time from datetime import datetime from streamlit_player import st_player # Necesitarás instalar esta librería: pip install streamlit-player from spacy import displacy import logging import random ###################################################### # Configuración del logger logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) ###################################################### # Importaciones locales from ..email.email import send_email_notification ###################################################### # Importaciones locales de autenticación y base de datos from ..auth.auth import ( authenticate_user, register_user ) ###################################################### from ..database.database_oldFromV2 import ( get_student_data, store_application_request, store_morphosyntax_result, store_semantic_result, store_discourse_analysis_result, store_chat_history, create_admin_user, create_student_user, store_user_feedback, export_analysis_and_chat ) ###################################################### # Importaciones locales de uiadmin from ..admin.admin_ui import admin_page ###################################################### # Importaciones locales funciones de análisis from ..text_analysis.morpho_analysis import ( generate_arc_diagram, get_repeated_words_colors, highlight_repeated_words, POS_COLORS, POS_TRANSLATIONS, perform_advanced_morphosyntactic_analysis ) ###################################################### from ..text_analysis.semantic_analysis import ( #visualize_semantic_relations, perform_semantic_analysis, create_concept_graph, visualize_concept_graph ) ###################################################### from ..text_analysis.discourse_analysis import ( perform_discourse_analysis, display_discourse_analysis_results ) ###################################################### from ..chatbot.chatbot import ( initialize_chatbot, get_chatbot_response, process_chat_input, TEXT_TYPES ) ################################################################################################## def initialize_session_state(): if 'initialized' not in st.session_state: st.session_state.clear() st.session_state.initialized = True st.session_state.logged_in = False st.session_state.page = 'login' st.session_state.username = None st.session_state.role = None ################################################################################################## def main(): initialize_session_state() print(f"Página actual: {st.session_state.page}") print(f"Rol del usuario: {st.session_state.role}") if st.session_state.page == 'login': login_register_page() elif st.session_state.page == 'admin': print("Intentando mostrar página de admin") admin_page() elif st.session_state.page == 'user': user_page() else: print(f"Página no reconocida: {st.session_state.page}") print(f"Estado final de la sesión: {st.session_state}") ################################################################################################## def login_register_page(): st.title("AIdeaText") left_column, right_column = st.columns([1, 3]) with left_column: tab1, tab2 = st.tabs(["Iniciar Sesión", "Registrarse"]) with tab1: login_form() with tab2: register_form() with right_column: display_videos_and_info() ################################################################################################## def login_form(): username = st.text_input("Correo electrónico", key="login_username") password = st.text_input("Contraseña", type="password", key="login_password") if st.button("Iniciar Sesión", key="login_button"): success, role = authenticate_user(username, password) if success: st.session_state.logged_in = True st.session_state.username = username st.session_state.role = role st.session_state.page = 'admin' if role == 'Administrador' else 'user' print(f"Inicio de sesión exitoso. Usuario: {username}, Rol: {role}") print(f"Estado de sesión después de login: {st.session_state}") st.rerun() else: st.error("Credenciales incorrectas") ################################################################################################## def admin_page(): st.title("Panel de Administración") st.write(f"Bienvenida, {st.session_state.username}") st.header("Crear Nuevo Usuario Estudiante") new_username = st.text_input("Correo electrónico del nuevo usuario", key="admin_new_username") new_password = st.text_input("Contraseña", type="password", key="admin_new_password") if st.button("Crear Usuario", key="admin_create_user"): if create_student_user(new_username, new_password): st.success(f"Usuario estudiante {new_username} creado exitosamente") else: st.error("Error al crear el usuario estudiante") # Aquí puedes añadir más funcionalidades para el panel de administración ################################################################################################## def user_page(): # Asumimos que el idioma seleccionado está almacenado en st.session_state.lang_code # Si no está definido, usamos 'es' como valor predeterminado lang_code = st.session_state.get('lang_code', 'es') translations = { 'es': { 'welcome': "Bienvenido a AIdeaText", 'hello': "Hola", 'chat_title': "Chat de Análisis", 'results_title': "Resultados del Análisis", 'export_button': "Exportar Análisis Actual", 'no_analysis': "No hay análisis disponible. Utiliza el chat para realizar un análisis.", 'export_success': "Análisis y chat exportados correctamente.", 'export_error': "Hubo un problema al exportar el análisis y el chat.", 'nothing_to_export': "No hay análisis o chat para exportar." }, 'en': { 'welcome': "Welcome to AIdeaText", 'hello': "Hello", 'chat_title': "Analysis Chat", 'results_title': "Analysis Results", 'export_button': "Export Current Analysis", 'no_analysis': "No analysis available. Use the chat to perform an analysis.", 'export_success': "Analysis and chat exported successfully.", 'export_error': "There was a problem exporting the analysis and chat.", 'nothing_to_export': "No analysis or chat to export." }, 'fr': { 'welcome': "Bienvenue à AIdeaText", 'hello': "Bonjour", 'chat_title': "Chat d'Analyse", 'results_title': "Résultats de l'Analyse", 'export_button': "Exporter l'Analyse Actuelle", 'no_analysis': "Aucune analyse disponible. Utilisez le chat pour effectuer une analyse.", 'export_success': "Analyse et chat exportés avec succès.", 'export_error': "Un problème est survenu lors de l'exportation de l'analyse et du chat.", 'nothing_to_export': "Aucune analyse ou chat à exporter." } } t = translations[lang_code] st.title(t['welcome']) st.write(f"{t['hello']}, {st.session_state.username}") # Dividir la pantalla en dos columnas col1, col2 = st.columns(2) with col1: st.subheader(t['chat_title']) display_chatbot_interface(lang_code) with col2: st.subheader(t['results_title']) if 'current_analysis' in st.session_state and st.session_state.current_analysis is not None: display_analysis_results(st.session_state.current_analysis, lang_code) if st.button(t['export_button']): if export_analysis_and_chat(st.session_state.username, st.session_state.current_analysis, st.session_state.messages): st.success(t['export_success']) else: st.error(t['export_error']) else: st.info(t['no_analysis']) ################################################################################################## def display_analysis_results(analysis, lang_code): translations = { 'es': { 'morphosyntactic_title': "Análisis Morfosintáctico", 'semantic_title': "Análisis Semántico", 'discourse_title': "Análisis del Discurso", 'no_analysis': "No hay análisis disponible.", 'legend': "Leyenda: Categorías gramaticales", 'repeated_words': "Palabras repetidas", 'sentence_structure': "Estructura de oraciones", 'repeated_words': "Palabras repetidas", 'pos_analysis': "Análisis de categorías gramaticales", 'morphological_analysis': "Análisis morfológico", 'arc_diagram': "Análisis sintáctico: Diagrama de arco", 'sentence': "Oración", 'root': "Raíz", 'subjects': "Sujetos", 'objects': "Objetos", 'verbs': "Verbos", 'success_message': "Análisis guardado correctamente.", #categorias adicionales 'error_message': "Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.", #categorias adicionales 'warning_message': "Por favor, ingrese un texto para analizar.", #categorias adicionales 'initial_message': "Ingrese un texto y presione 'Analizar texto' para comenzar.", #categorias adicionales 'no_results': "No hay resultados disponibles. Por favor, realice un análisis primero.", #categorias adicionales 'word': "Palabra", #categorias adicionales 'count': "Cantidad", #categorias adicionales 'percentage': "Porcentaje", #categorias adicionales 'examples': "Ejemplos", #categorias adicionales 'lemma': "Lema", #categorias adicionales 'tag': "Etiqueta", #categorias adicionales 'dep': "Dependencia", #categorias adicionales 'morph': "Morfología", #categorias adicionales 'grammatical_category': "Categoría gramatical", #categorias adicionales 'dependency': "Dependencia", #categorias adicionales 'morphology': "Morfología", #categorias adicionales 'conceptual_relations': "Relaciones Conceptuales", 'identified_entities': "Entidades Identificadas", 'key_concepts': "Conceptos Clave", 'success_message': "Análisis semántico guardado correctamente.", 'error_message': "Hubo un problema al guardar el análisis semántico. Por favor, inténtelo de nuevo.", 'warning_message': "Por favor, ingrese un texto o cargue un archivo para analizar.", 'initial_message': "Ingrese un texto y presione 'Analizar texto' para comenzar.", 'no_results': "No hay resultados disponibles. Por favor, realice un análisis primero.", 'comparison': "Comparación de Relaciones Semánticas", 'success_message': "Análisis del discurso guardado correctamente.", 'error_message': "Hubo un problema al guardar el análisis del discurso. Por favor, inténtelo de nuevo.", 'warning_message': "Por favor, cargue ambos archivos para analizar.", 'initial_message': "Ingrese un texto y presione 'Analizar texto' para comenzar.", 'no_results': "No hay resultados disponibles. Por favor, realice un análisis primero.", 'key_concepts': "Conceptos Clave", 'graph_not_available': "El gráfico no está disponible.", 'concepts_not_available': "Los conceptos clave no están disponibles.", 'comparison_not_available': "La comparación no está disponible." }, 'en': { 'morphosyntactic_title': "Morphosyntactic Analysis", 'semantic_title': "Semantic Analysis", 'discourse_title': "Discourse Analysis", 'no_analysis': "No analysis available.", 'legend': "Legend: Grammatical categories", 'sentence_structure': "Sentence Structure", 'repeated_words': "Repeated words", 'pos_analysis': "Part of Speech Analysis", 'morphological_analysis': "Morphological Analysis", 'arc_diagram': "Syntactic analysis: Arc diagram", 'sentence': "Sentence", 'root': "Root", 'subjects': "Subjects", 'objects': "Objects", 'verbs': "Verbs", 'success_message': "Analysis saved successfully.", 'error_message': "There was a problem saving the analysis. Please try again.", 'warning_message': "Please enter a text to analyze.", 'initial_message': "Enter a text and press 'Analyze text' to start.", 'no_results': "No results available. Please perform an analysis first.", 'word': "Word", 'count': "Count", 'percentage': "Percentage", 'examples': "Examples", 'lemma': "Lemma", 'tag': "Tag", 'dep': "Dependency", 'morph': "Morphology", 'grammatical_category': "Grammatical category", 'dependency': "Dependency", 'morphology': "Morphology", 'conceptual_relations': "Conceptual Relations", 'identified_entities': "Identified Entities", 'key_concepts': "Key Concepts", 'success_message': "Semantic analysis saved successfully.", 'error_message': "There was a problem saving the semantic analysis. Please try again.", 'warning_message': "Please enter a text or upload a file to analyze.", 'initial_message': "Enter a text and press 'Analyze text' to start.", 'no_results': "No results available. Please perform an analysis first.", 'comparison': "Comparison of Semantic Relations", 'success_message': "Discourse analysis saved successfully.", 'error_message': "There was a problem saving the discourse analysis. Please try again.", 'warning_message': "Please upload both files to analyze.", 'initial_message': "Enter a text and press 'Analyze text' to start.", 'no_results': "No results available. Please perform an analysis first.", 'key_concepts': "Key Concepts", 'graph_not_available': "The graph is not available.", 'concepts_not_available': "Key concepts are not available.", 'comparison_not_available': "The comparison is not available." }, 'fr': { 'morphosyntactic_title': "Analyse Morphosyntaxique", 'semantic_title': "Analyse Sémantique", 'discourse_title': "Analyse du Discours", 'no_analysis': "Aucune analyse disponible.", 'legend': "Légende : Catégories grammaticales", 'sentence_structure': "Structure des phrases", 'repeated_words': "Mots répétés", 'pos_analysis': "Analyse des parties du discours", 'morphological_analysis': "Analyse morphologique", 'arc_diagram': "Analyse syntaxique : Diagramme en arc", 'sentence': "Phrase", 'root': "Racine", 'subjects': "Sujets", 'objects': "Objets", 'verbs': "Verbes", 'success_message': "Analyse enregistrée avec succès.", 'error_message': "Un problème est survenu lors de l'enregistrement de l'analyse. Veuillez réessayer.", 'warning_message': "Veuillez entrer un texte à analyser.", 'initial_message': "Entrez un texte et appuyez sur 'Analyser le texte' pour commencer.", 'no_results': "Aucun résultat disponible. Veuillez d'abord effectuer une analyse.", 'word': "Mot", 'count': "Nombre", 'percentage': "Pourcentage", 'examples': "Exemples", 'lemma': "Lemme", 'tag': "Étiquette", 'dep': "Dépendance", 'morph': "Morphologie", 'grammatical_category': "Catégorie grammaticale", 'dependency': "Dépendance", 'morphology': "Morphologie", 'conceptual_relations': "Relations Conceptuelles", 'identified_entities': "Entités Identifiées", 'key_concepts': "Concepts Clés", 'success_message': "Analyse sémantique enregistrée avec succès.", 'error_message': "Un problème est survenu lors de l'enregistrement de l'analyse sémantique. Veuillez réessayer.", 'warning_message': "Veuillez entrer un texte ou télécharger un fichier à analyser.", 'initial_message': "Entrez un texte et appuyez sur 'Analyser le texte' pour commencer.", 'no_results': "Aucun résultat disponible. Veuillez d'abord effectuer une analyse.", 'comparison': "Comparaison des Relations Sémantiques", 'success_message': "Analyse du discours enregistrée avec succès.", 'error_message': "Un problème est survenu lors de l'enregistrement de l'analyse du discours. Veuillez réessayer.", 'warning_message': "Veuillez télécharger les deux fichiers à analyser.", 'initial_message': "Entrez un texte et appuyez sur 'Analyser le texte' pour commencer.", 'no_results': "Aucun résultat disponible. Veuillez d'abord effectuer une analyse.", 'key_concepts': "Concepts Clés", 'graph_not_available': "Le graphique n'est pas disponible.", 'concepts_not_available': "Les concepts clés ne sont pas disponibles.", 'comparison_not_available': "La comparaison n'est pas disponible." } } t = translations[lang_code] if analysis is None: st.warning(t['no_analysis']) return if analysis['type'] == 'morphosyntactic': st.subheader(t['morphosyntactic_title']) display_morphosyntax_results(analysis['result'], lang_code, t) elif analysis['type'] == 'semantic': st.subheader(t['semantic_title']) display_semantic_results(analysis['result'], lang_code, t) elif analysis['type'] == 'discourse': st.subheader(t['discourse_title']) display_discourse_results(analysis['result'], lang_code, t) else: st.warning(t['no_analysis']) ################################################################################################## def display_videos_and_info(): st.header("Videos: pitch, demos, entrevistas, otros") videos = { "Presentación en PyCon Colombia, Medellín, 2024": "https://www.youtube.com/watch?v=Jn545-IKx5Q", "Presentación fundación Ser Maaestro": "https://www.youtube.com/watch?v=imc4TI1q164", "Pitch IFE Explora": "https://www.youtube.com/watch?v=Fqi4Di_Rj_s", "Entrevista Dr. Guillermo Ruíz": "https://www.youtube.com/watch?v=_ch8cRja3oc", "Demo versión desktop": "https://www.youtube.com/watch?v=nP6eXbog-ZY" } selected_title = st.selectbox("Selecciona un video tutorial:", list(videos.keys())) if selected_title in videos: try: st_player(videos[selected_title]) except Exception as e: st.error(f"Error al cargar el video: {str(e)}") st.markdown(""" ## Novedades de la versión actual - Nueva función de análisis semántico - Soporte para múltiples idiomas - Interfaz mejorada para una mejor experiencia de usuario """) ################################################################################################## def register_form(): st.header("Solicitar prueba de la aplicación") name = st.text_input("Nombre completo") email = st.text_input("Correo electrónico institucional") institution = st.text_input("Institución") role = st.selectbox("Rol", ["Estudiante", "Profesor", "Investigador", "Otro"]) reason = st.text_area("¿Por qué estás interesado en probar AIdeaText?") if st.button("Enviar solicitud"): logger.info(f"Attempting to submit application for {email}") logger.debug(f"Form data: name={name}, email={email}, institution={institution}, role={role}, reason={reason}") if not name or not email or not institution or not reason: logger.warning("Incomplete form submission") st.error("Por favor, completa todos los campos.") elif not is_institutional_email(email): logger.warning(f"Non-institutional email used: {email}") st.error("Por favor, utiliza un correo electrónico institucional.") else: logger.info(f"Attempting to store application for {email}") success = store_application_request(name, email, institution, role, reason) if success: st.success("Tu solicitud ha sido enviada. Te contactaremos pronto.") logger.info(f"Application request stored successfully for {email}") else: st.error("Hubo un problema al enviar tu solicitud. Por favor, intenta de nuevo más tarde.") logger.error(f"Failed to store application request for {email}") ################################################################################ def display_feedback_form(lang_code): logging.info(f"display_feedback_form called with lang_code: {lang_code}") translations = { 'es': { 'title': "Formulario de Retroalimentación", 'name': "Nombre", 'email': "Correo electrónico", 'feedback': "Tu retroalimentación", 'submit': "Enviar", 'success': "¡Gracias por tu retroalimentación!", 'error': "Hubo un problema al enviar el formulario. Por favor, intenta de nuevo." }, 'en': { 'title': "Feedback Form", 'name': "Name", 'email': "Email", 'feedback': "Your feedback", 'submit': "Submit", 'success': "Thank you for your feedback!", 'error': "There was a problem submitting the form. Please try again." }, 'fr': { 'title': "Formulaire de Rétroaction", 'name': "Nom", 'email': "Adresse e-mail", 'feedback': "Votre rétroaction", 'submit': "Envoyer", 'success': "Merci pour votre rétroaction !", 'error': "Un problème est survenu lors de l'envoi du formulaire. Veuillez réessayer." } } t = translations[lang_code] st.header(t['title']) name = st.text_input(t['name'], key=f"feedback_name_{lang_code}") email = st.text_input(t['email'], key=f"feedback_email_{lang_code}") feedback = st.text_area(t['feedback'], key=f"feedback_text_{lang_code}") if st.button(t['submit'], key=f"feedback_submit_{lang_code}"): if name and email and feedback: if store_user_feedback(st.session_state.username, name, email, feedback): st.success(t['success']) else: st.error(t['error']) else: st.warning("Por favor, completa todos los campos.") ################################################################################ def is_institutional_email(email): forbidden_domains = ['gmail.com', 'hotmail.com', 'yahoo.com', 'outlook.com'] return not any(domain in email.lower() for domain in forbidden_domains) ################################################################################ def display_student_progress(username, lang_code='es'): student_data = get_student_data(username) if student_data is None or len(student_data['entries']) == 0: st.warning("No se encontraron datos para este estudiante.") st.info("Intenta realizar algunos análisis de texto primero.") return st.title(f"Progreso de {username}") with st.expander("Resumen de Actividades y Progreso", expanded=True): # Resumen de actividades total_entries = len(student_data['entries']) st.write(f"Total de análisis realizados: {total_entries}") # Gráfico de tipos de análisis analysis_types = [entry['analysis_type'] for entry in student_data['entries']] analysis_counts = pd.Series(analysis_types).value_counts() fig, ax = plt.subplots() analysis_counts.plot(kind='bar', ax=ax) ax.set_title("Tipos de análisis realizados") ax.set_xlabel("Tipo de análisis") ax.set_ylabel("Cantidad") st.pyplot(fig) # Progreso a lo largo del tiempo dates = [datetime.fromisoformat(entry['timestamp']) for entry in student_data['entries']] analysis_counts = pd.Series(dates).value_counts().sort_index() fig, ax = plt.subplots() analysis_counts.plot(kind='line', ax=ax) ax.set_title("Análisis realizados a lo largo del tiempo") ax.set_xlabel("Fecha") ax.set_ylabel("Cantidad de análisis") st.pyplot(fig) ########################################################## with st.expander("Histórico de Análisis Morfosintácticos"): morphosyntax_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'morphosyntax'] for entry in morphosyntax_entries: st.subheader(f"Análisis del {entry['timestamp']}") if entry['arc_diagrams']: st.write(entry['arc_diagrams'][0], unsafe_allow_html=True) ########################################################## with st.expander("Histórico de Análisis Semánticos"): semantic_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'semantic'] for entry in semantic_entries: st.subheader(f"Análisis del {entry['timestamp']}") # Mostrar conceptos clave if 'key_concepts' in entry: st.write("Conceptos clave:") concepts_str = " | ".join([f"{concept} ({frequency:.2f})" for concept, frequency in entry['key_concepts']]) #st.write("Conceptos clave:") #st.write(concepts_str) st.markdown(f"