test2 / modules /ui /ui.py
AIdeaText's picture
Update modules/ui/ui.py
2a7bb3e verified
raw
history blame
49.3 kB
# Importaciones generales
import streamlit as st
import re
import io
from io import BytesIO
import base64
import matplotlib.pyplot as plt
import pandas as pd
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
######################################################
# 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 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
)
######################################################
# 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 (
compare_semantic_analysis,
perform_discourse_analysis
)
######################################################
from ..chatbot.chatbot import (
initialize_chatbot,
get_chatbot_response
)
##################################################################################################
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",
'tabs': ["Análisis Morfosintáctico", "Análisis Semántico", "Análisis del Discurso", "Chat", "Mi Progreso", "Formulario de Retroalimentación"]
},
'en': {
'welcome': "Welcome to AIdeaText",
'hello': "Hello",
'tabs': ["Morphosyntactic Analysis", "Semantic Analysis", "Discourse Analysis", "Chat", "My Progress", "Feedback Form"]
},
'fr': {
'welcome': "Bienvenue à AIdeaText",
'hello': "Bonjour",
'tabs': ["Analyse Morphosyntaxique", "Analyse Sémantique", "Analyse du Discours", "Chat", "Mon Progrès", "Formulaire de Rétroaction"]
}
}
t = translations[lang_code]
st.title(t['welcome'])
st.write(f"{t['hello']}, {st.session_state.username}")
tabs = st.tabs(t['tabs'])
with tabs[0]:
display_morphosyntax_analysis_interface(nlp_models, lang_code)
with tabs[1]:
display_semantic_analysis_interface(nlp_models, lang_code)
with tabs[2]:
display_discourse_analysis_interface(nlp_models, lang_code)
with tabs[3]:
display_chatbot_interface(lang_code)
with tabs[4]:
display_student_progress(st.session_state.username, lang_code)
with tabs[5]:
display_feedback_form(lang_code)
##################################################################################################
def display_videos_and_info():
st.header("Videos: pitch, demos, entrevistas, otros")
videos = {
"Intro AideaText": "https://www.youtube.com/watch?v=UA-md1VxaRc",
"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'])
email = st.text_input(t['email'])
feedback = st.text_area(t['feedback'])
if st.button(t['submit']):
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']
st.write(f"Número total de entradas semánticas: {len(semantic_entries)}")
for entry in semantic_entries:
st.subheader(f"Análisis del {entry['timestamp']}")
st.write(f"Archivo analizado: {entry.get('filename', 'Nombre no disponible')}")
st.write(f"Claves disponibles en esta entrada: {', '.join(entry.keys())}")
# Verificar si 'relations_graph' está en entry antes de intentar acceder
if 'network_diagram' in entry:
try:
logger.info(f"Longitud de la imagen recuperada: {len(entry['network_diagram'])}")
st.image(f"data:image/png;base64,{entry['network_diagram']}")
except Exception as e:
st.error(f"No se pudo mostrar la imagen: {str(e)}")
st.write("Datos de la imagen (para depuración):")
st.write(entry['network_diagram'][:100] + "...")
else:
logger.warning(f"No se encontró 'relations_graph' en la entrada: {entry.keys()}")
st.write("No se encontró el gráfico para este análisis.")
##########################################################
with st.expander("Histórico de Análisis Discursivos"):
discourse_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'discourse']
for entry in discourse_entries:
st.subheader(f"Análisis del {entry['timestamp']}")
st.write(f"Archivo patrón: {entry.get('filename1', 'Nombre no disponible')}")
st.write(f"Archivo comparado: {entry.get('filename2', 'Nombre no disponible')}")
try:
# Intentar obtener y combinar las dos imágenes
if 'graph1' in entry and 'graph2' in entry:
img1 = Image.open(BytesIO(base64.b64decode(entry['graph1'])))
img2 = Image.open(BytesIO(base64.b64decode(entry['graph2'])))
# Crear una nueva imagen combinada
total_width = img1.width + img2.width
max_height = max(img1.height, img2.height)
combined_img = Image.new('RGB', (total_width, max_height))
# Pegar las dos imágenes lado a lado
combined_img.paste(img1, (0, 0))
combined_img.paste(img2, (img1.width, 0))
# Convertir la imagen combinada a bytes
buffered = BytesIO()
combined_img.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue()).decode()
# Mostrar la imagen combinada
st.image(f"data:image/png;base64,{img_str}")
elif 'combined_graph' in entry:
# Si ya existe una imagen combinada, mostrarla directamente
img_bytes = base64.b64decode(entry['combined_graph'])
st.image(img_bytes)
else:
st.write("No se encontraron gráficos para este análisis.")
except Exception as e:
st.error(f"No se pudieron mostrar los gráficos: {str(e)}")
st.write("Datos de los gráficos (para depuración):")
if 'graph1' in entry:
st.write("Graph 1:", entry['graph1'][:100] + "...")
if 'graph2' in entry:
st.write("Graph 2:", entry['graph2'][:100] + "...")
if 'combined_graph' in entry:
st.write("Combined Graph:", entry['combined_graph'][:100] + "...")
##########################################################
with st.expander("Histórico de Conversaciones con el ChatBot"):
if 'chat_history' in student_data:
for i, chat in enumerate(student_data['chat_history']):
st.subheader(f"Conversación {i+1} - {chat['timestamp']}")
for message in chat['messages']:
if message['role'] == 'user':
st.write("Usuario: " + message['content'])
else:
st.write("Asistente: " + message['content'])
st.write("---")
else:
st.write("No se encontraron conversaciones con el ChatBot.")
# Añadir logs para depuración
if st.checkbox("Mostrar datos de depuración"):
st.write("Datos del estudiante (para depuración):")
st.json(student_data)
##################################################################################################
def display_morphosyntax_analysis_interface(nlp_models, lang_code):
translations = {
'es': {
'title': "AIdeaText - Análisis morfológico y sintáctico",
'input_label': "Ingrese un texto para analizar (máximo 5,000 palabras",
'input_placeholder': "Esta funcionalidad le ayudará con dos competencias:\n"
"[1] \"Escribe diversos tipos de textos en su lengua materna\"\n"
"[2] \"Lee diversos tipos de textos escritos en su lengua materna\"\n\n"
"Ingrese su texto aquí para analizar...",
'analyze_button': "Analizar texto",
'repeated_words': "Palabras repetidas",
'legend': "Leyenda: Categorías gramaticales",
'arc_diagram': "Análisis sintáctico: Diagrama de arco",
'sentence': "Oración",
'success_message': "Análisis guardado correctamente.",
'error_message': "Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.",
'warning_message': "Por favor, ingrese un texto para analizar.",
'pos_analysis': "Análisis de categorías gramaticales",
'morphological_analysis': "Análisis morfológico",
'sentence_structure': "Estructura de oraciones",
'word': "Palabra",
'count': "Cantidad",
'percentage': "Porcentaje",
'examples': "Ejemplos",
'lemma': "Lema",
'tag': "Etiqueta",
'dep': "Dependencia",
'morph': "Morfología",
'root': "Raíz",
'subjects': "Sujetos",
'objects': "Objetos",
'verbs': "Verbos",
'grammatical_category': "Categoría gramatical",
'dependency': "Dependencia",
'morphology': "Morfología"
},
'en': {
'title': "AIdeaText - Morphological and Syntactic Analysis",
'input_label': "Enter a text to analyze (max 5,000 words):",
'input_placeholder': "This functionality will help you with two competencies:\n"
"[1] \"Write various types of texts in your native language\"\n"
"[2] \"Read various types of written texts in your native language\"\n\n"
"Enter your text here to analyze...",
'analyze_button': "Analyze text",
'repeated_words': "Repeated words",
'legend': "Legend: Grammatical categories",
'arc_diagram': "Syntactic analysis: Arc diagram",
'sentence': "Sentence",
'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.",
'pos_analysis': "Part of Speech Analysis",
'morphological_analysis': "Morphological Analysis",
'sentence_structure': "Sentence Structure",
'word': "Word",
'count': "Count",
'percentage': "Percentage",
'examples': "Examples",
'lemma': "Lemma",
'tag': "Tag",
'dep': "Dependency",
'morph': "Morphology",
'root': "Root",
'subjects': "Subjects",
'objects': "Objects",
'verbs': "Verbs",
'grammatical_category': "Grammatical category",
'dependency': "Dependency",
'morphology': "Morphology"
},
'fr': {
'title': "AIdeaText - Analyse morphologique et syntaxique",
'input_label': "Entrez un texte à analyser (max 5 000 mots) :",
'input_placeholder': "Cette fonctionnalité vous aidera avec deux compétences :\n"
"[1] \"Écrire divers types de textes dans votre langue maternelle\"\n"
"[2] \"Lire divers types de textes écrits dans votre langue maternelle\"\n\n"
"Entrez votre texte ici pour l'analyser...",
'analyze_button': "Analyser le texte",
'repeated_words': "Mots répétés",
'legend': "Légende : Catégories grammaticales",
'arc_diagram': "Analyse syntaxique : Diagramme en arc",
'sentence': "Phrase",
'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.",
'pos_analysis': "Analyse des parties du discours",
'morphological_analysis': "Analyse morphologique",
'sentence_structure': "Structure des phrases",
'word': "Mot",
'count': "Nombre",
'percentage': "Pourcentage",
'examples': "Exemples",
'lemma': "Lemme",
'tag': "Étiquette",
'dep': "Dépendance",
'morph': "Morphologie",
'root': "Racine",
'subjects': "Sujets",
'objects': "Objets",
'verbs': "Verbes",
'grammatical_category': "Catégorie grammaticale",
'dependency': "Dépendance",
'morphology': "Morphologie"
}
}
t = translations[lang_code]
input_key = f"morphosyntax_input_{lang_code}"
if input_key not in st.session_state:
st.session_state[input_key] = ""
sentence_input = st.text_area(
t['input_label'],
height=150,
placeholder=t['input_placeholder'],
value=st.session_state[input_key],
key=f"text_area_{lang_code}",
on_change=lambda: setattr(st.session_state, input_key, st.session_state[f"text_area_{lang_code}"])
)
if st.button(t['analyze_button'], key=f"analyze_button_{lang_code}"):
current_input = st.session_state[input_key]
if current_input:
doc = nlp_models[lang_code](current_input)
# Análisis morfosintáctico avanzado
advanced_analysis = perform_advanced_morphosyntactic_analysis(current_input, nlp_models[lang_code])
# Mostrar leyenda (código existente)
st.markdown(f"##### {t['legend']}")
legend_html = "<div style='display: flex; flex-wrap: wrap;'>"
for pos, color in POS_COLORS.items():
if pos in POS_TRANSLATIONS[lang_code]:
legend_html += f"<div style='margin-right: 10px;'><span style='background-color: {color}; padding: 2px 5px;'>{POS_TRANSLATIONS[lang_code][pos]}</span></div>"
legend_html += "</div>"
st.markdown(legend_html, unsafe_allow_html=True)
# Mostrar análisis de palabras repetidas (código existente)
word_colors = get_repeated_words_colors(doc)
with st.expander(t['repeated_words'], expanded=True):
highlighted_text = highlight_repeated_words(doc, word_colors)
st.markdown(highlighted_text, unsafe_allow_html=True)
# Mostrar estructura de oraciones
with st.expander(t['sentence_structure'], expanded=True):
for i, sent_analysis in enumerate(advanced_analysis['sentence_structure']):
sentence_str = (
f"**{t['sentence']} {i+1}** "
f"{t['root']}: {sent_analysis['root']} ({sent_analysis['root_pos']}) -- "
f"{t['subjects']}: {', '.join(sent_analysis['subjects'])} -- "
f"{t['objects']}: {', '.join(sent_analysis['objects'])} -- "
f"{t['verbs']}: {', '.join(sent_analysis['verbs'])}"
)
st.markdown(sentence_str)
# Mostrar análisis de categorías gramaticales # Mostrar análisis morfológico
# Mostrar análisis de categorías gramaticales # Mostrar análisis morfológico
col1, col2 = st.columns(2)
with col1:
with st.expander(t['pos_analysis'], expanded=True):
pos_df = pd.DataFrame(advanced_analysis['pos_analysis'])
# Traducir las etiquetas POS a sus nombres en el idioma seleccionado
pos_df['pos'] = pos_df['pos'].map(lambda x: POS_TRANSLATIONS[lang_code].get(x, x))
# Renombrar las columnas para mayor claridad
pos_df = pos_df.rename(columns={
'pos': t['grammatical_category'],
'count': t['count'],
'percentage': t['percentage'],
'examples': t['examples']
})
# Mostrar el dataframe
st.dataframe(pos_df)
with col2:
with st.expander(t['morphological_analysis'], expanded=True):
morph_df = pd.DataFrame(advanced_analysis['morphological_analysis'])
# Definir el mapeo de columnas
column_mapping = {
'text': t['word'],
'lemma': t['lemma'],
'pos': t['grammatical_category'],
'dep': t['dependency'],
'morph': t['morphology']
}
# Renombrar las columnas existentes
morph_df = morph_df.rename(columns={col: new_name for col, new_name in column_mapping.items() if col in morph_df.columns})
# Traducir las categorías gramaticales
morph_df[t['grammatical_category']] = morph_df[t['grammatical_category']].map(lambda x: POS_TRANSLATIONS[lang_code].get(x, x))
# Traducir las dependencias
dep_translations = {
'es': {
'ROOT': 'RAÍZ', 'nsubj': 'sujeto nominal', 'obj': 'objeto', 'iobj': 'objeto indirecto',
'csubj': 'sujeto clausal', 'ccomp': 'complemento clausal', 'xcomp': 'complemento clausal abierto',
'obl': 'oblicuo', 'vocative': 'vocativo', 'expl': 'expletivo', 'dislocated': 'dislocado',
'advcl': 'cláusula adverbial', 'advmod': 'modificador adverbial', 'discourse': 'discurso',
'aux': 'auxiliar', 'cop': 'cópula', 'mark': 'marcador', 'nmod': 'modificador nominal',
'appos': 'aposición', 'nummod': 'modificador numeral', 'acl': 'cláusula adjetiva',
'amod': 'modificador adjetival', 'det': 'determinante', 'clf': 'clasificador',
'case': 'caso', 'conj': 'conjunción', 'cc': 'coordinante', 'fixed': 'fijo',
'flat': 'plano', 'compound': 'compuesto', 'list': 'lista', 'parataxis': 'parataxis',
'orphan': 'huérfano', 'goeswith': 'va con', 'reparandum': 'reparación', 'punct': 'puntuación'
},
'en': {
'ROOT': 'ROOT', 'nsubj': 'nominal subject', 'obj': 'object',
'iobj': 'indirect object', 'csubj': 'clausal subject', 'ccomp': 'clausal complement', 'xcomp': 'open clausal complement',
'obl': 'oblique', 'vocative': 'vocative', 'expl': 'expletive', 'dislocated': 'dislocated', 'advcl': 'adverbial clause modifier',
'advmod': 'adverbial modifier', 'discourse': 'discourse element', 'aux': 'auxiliary', 'cop': 'copula', 'mark': 'marker',
'nmod': 'nominal modifier', 'appos': 'appositional modifier', 'nummod': 'numeric modifier', 'acl': 'clausal modifier of noun',
'amod': 'adjectival modifier', 'det': 'determiner', 'clf': 'classifier', 'case': 'case marking',
'conj': 'conjunct', 'cc': 'coordinating conjunction', 'fixed': 'fixed multiword expression',
'flat': 'flat multiword expression', 'compound': 'compound', 'list': 'list', 'parataxis': 'parataxis', 'orphan': 'orphan',
'goeswith': 'goes with', 'reparandum': 'reparandum', 'punct': 'punctuation'
},
'fr': {
'ROOT': 'RACINE', 'nsubj': 'sujet nominal', 'obj': 'objet', 'iobj': 'objet indirect',
'csubj': 'sujet phrastique', 'ccomp': 'complément phrastique', 'xcomp': 'complément phrastique ouvert', 'obl': 'oblique',
'vocative': 'vocatif', 'expl': 'explétif', 'dislocated': 'disloqué', 'advcl': 'clause adverbiale', 'advmod': 'modifieur adverbial',
'discourse': 'élément de discours', 'aux': 'auxiliaire', 'cop': 'copule', 'mark': 'marqueur', 'nmod': 'modifieur nominal',
'appos': 'apposition', 'nummod': 'modifieur numéral', 'acl': 'clause relative', 'amod': 'modifieur adjectival', 'det': 'déterminant',
'clf': 'classificateur', 'case': 'marqueur de cas', 'conj': 'conjonction', 'cc': 'coordination', 'fixed': 'expression figée',
'flat': 'construction plate', 'compound': 'composé', 'list': 'liste', 'parataxis': 'parataxe', 'orphan': 'orphelin',
'goeswith': 'va avec', 'reparandum': 'réparation', 'punct': 'ponctuation'
}
}
morph_df[t['dependency']] = morph_df[t['dependency']].map(lambda x: dep_translations[lang_code].get(x, x))
# Traducir la morfología
def translate_morph(morph_string, lang_code):
morph_translations = {
'es': {
'Gender': 'Género', 'Number': 'Número', 'Case': 'Caso', 'Definite': 'Definido',
'PronType': 'Tipo de Pronombre', 'Person': 'Persona', 'Mood': 'Modo',
'Tense': 'Tiempo', 'VerbForm': 'Forma Verbal', 'Voice': 'Voz',
'Fem': 'Femenino', 'Masc': 'Masculino', 'Sing': 'Singular', 'Plur': 'Plural',
'Ind': 'Indicativo', 'Sub': 'Subjuntivo', 'Imp': 'Imperativo', 'Inf': 'Infinitivo',
'Part': 'Participio', 'Ger': 'Gerundio', 'Pres': 'Presente', 'Past': 'Pasado',
'Fut': 'Futuro', 'Perf': 'Perfecto', 'Imp': 'Imperfecto'
},
'en': {
'Gender': 'Gender', 'Number': 'Number', 'Case': 'Case', 'Definite': 'Definite', 'PronType': 'Pronoun Type', 'Person': 'Person',
'Mood': 'Mood', 'Tense': 'Tense', 'VerbForm': 'Verb Form', 'Voice': 'Voice',
'Fem': 'Feminine', 'Masc': 'Masculine', 'Sing': 'Singular', 'Plur': 'Plural', 'Ind': 'Indicative',
'Sub': 'Subjunctive', 'Imp': 'Imperative', 'Inf': 'Infinitive', 'Part': 'Participle',
'Ger': 'Gerund', 'Pres': 'Present', 'Past': 'Past', 'Fut': 'Future', 'Perf': 'Perfect', 'Imp': 'Imperfect'
},
'fr': {
'Gender': 'Genre', 'Number': 'Nombre', 'Case': 'Cas', 'Definite': 'Défini', 'PronType': 'Type de Pronom',
'Person': 'Personne', 'Mood': 'Mode', 'Tense': 'Temps', 'VerbForm': 'Forme Verbale', 'Voice': 'Voix',
'Fem': 'Féminin', 'Masc': 'Masculin', 'Sing': 'Singulier', 'Plur': 'Pluriel', 'Ind': 'Indicatif',
'Sub': 'Subjonctif', 'Imp': 'Impératif', 'Inf': 'Infinitif', 'Part': 'Participe',
'Ger': 'Gérondif', 'Pres': 'Présent', 'Past': 'Passé', 'Fut': 'Futur', 'Perf': 'Parfait', 'Imp': 'Imparfait'
}
}
for key, value in morph_translations[lang_code].items():
morph_string = morph_string.replace(key, value)
return morph_string
morph_df[t['morphology']] = morph_df[t['morphology']].apply(lambda x: translate_morph(x, lang_code))
# Seleccionar y ordenar las columnas a mostrar
columns_to_display = [t['word'], t['lemma'], t['grammatical_category'], t['dependency'], t['morphology']]
columns_to_display = [col for col in columns_to_display if col in morph_df.columns]
# Mostrar el DataFrame
st.dataframe(morph_df[columns_to_display])
# Mostrar diagramas de arco (código existente)
with st.expander(t['arc_diagram'], expanded=True):
sentences = list(doc.sents)
arc_diagrams = []
for i, sent in enumerate(sentences):
st.subheader(f"{t['sentence']} {i+1}")
html = displacy.render(sent, style="dep", options={"distance": 100})
html = html.replace('height="375"', 'height="200"')
html = re.sub(r'<svg[^>]*>', lambda m: m.group(0).replace('height="450"', 'height="300"'), html)
html = re.sub(r'<g [^>]*transform="translate\((\d+),(\d+)\)"', lambda m: f'<g transform="translate({m.group(1)},50)"', html)
st.write(html, unsafe_allow_html=True)
arc_diagrams.append(html)
# Guardar resultados
if store_morphosyntax_result(
st.session_state.username,
current_input,
word_colors,
advanced_analysis['arc_diagram'],
advanced_analysis['pos_analysis'],
advanced_analysis['morphological_analysis'],
advanced_analysis['sentence_structure']
):
st.success(t['success_message'])
else:
st.error(t['error_message'])
else:
st.warning(t['warning_message'])
###############################################################################################################
def display_semantic_analysis_interface(nlp_models, lang_code):
translations = {
'es': {
'title': "AIdeaText - Análisis semántico",
'text_input_label': "Ingrese un texto para analizar (máx. 5,000 palabras):",
'text_input_placeholder': "El objetivo de esta aplicación es que mejore sus habilidades de redacción...",
'file_uploader': "O cargue un archivo de texto",
'analyze_button': "Analizar texto",
'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."
},
'en': {
'title': "AIdeaText - Semantic Analysis",
'text_input_label': "Enter a text to analyze (max. 5,000 words):",
'text_input_placeholder': "The goal of this application is to improve your writing skills...",
'file_uploader': "Or upload a text file",
'analyze_button': "Analyze text",
'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."
},
'fr': {
'title': "AIdeaText - Analyse sémantique",
'text_input_label': "Entrez un texte à analyser (max. 5 000 mots) :",
'text_input_placeholder': "L'objectif de cette application est d'améliorer vos compétences en rédaction...",
'file_uploader': "Ou téléchargez un fichier texte",
'analyze_button': "Analyser le texte",
'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."
}
}
t = translations[lang_code]
st.header(t['title'])
# Opción para introducir texto
text_input = st.text_area(
t['text_input_label'],
height=150,
placeholder=t['text_input_placeholder'],
)
# Opción para cargar archivo
uploaded_file = st.file_uploader(t['file_uploader'], type=['txt'])
if st.button(t['analyze_button']):
if text_input or uploaded_file is not None:
if uploaded_file:
text_content = uploaded_file.getvalue().decode('utf-8')
else:
text_content = text_input
# Realizar el análisis
analysis_result = perform_semantic_analysis(text_content, nlp_models[lang_code], lang_code)
# Mostrar conceptos clave
with st.expander(t['key_concepts'], expanded=True):
for concept, frequency in analysis_result['key_concepts']:
st.write(f"{concept}: {frequency:.2f}")
# Mostrar el gráfico de relaciones conceptuales
with st.expander(t['conceptual_relations'], expanded=True):
st.pyplot(analysis_result['relations_graph'])
# Guardar el resultado del análisis
if store_semantic_result(st.session_state.username, text_content, analysis_result):
st.success(t['success_message'])
else:
st.error(t['error_message'])
else:
st.warning(t['warning_message'])
##################################################################################################
def display_discourse_analysis_interface(nlp_models, lang_code):
translations = {
'es': {
'title': "AIdeaText - Análisis del discurso",
'file_uploader1': "Cargar archivo de texto 1 (Patrón)",
'file_uploader2': "Cargar archivo de texto 2 (Comparación)",
'analyze_button': "Analizar textos",
'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."
},
'en': {
'title': "AIdeaText - Discourse Analysis",
'file_uploader1': "Upload text file 1 (Pattern)",
'file_uploader2': "Upload text file 2 (Comparison)",
'analyze_button': "Analyze texts",
'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."
},
'fr': {
'title': "AIdeaText - Analyse du discours",
'file_uploader1': "Télécharger le fichier texte 1 (Modèle)",
'file_uploader2': "Télécharger le fichier texte 2 (Comparaison)",
'analyze_button': "Analyser les textes",
'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."
}
}
t = translations[lang_code]
st.header(t['title'])
col1, col2 = st.columns(2)
with col1:
uploaded_file1 = st.file_uploader(t['file_uploader1'], type=['txt'])
with col2:
uploaded_file2 = st.file_uploader(t['file_uploader2'], type=['txt'])
if st.button(t['analyze_button']):
if uploaded_file1 is not None and uploaded_file2 is not None:
text_content1 = uploaded_file1.getvalue().decode('utf-8')
text_content2 = uploaded_file2.getvalue().decode('utf-8')
# Realizar el análisis
analysis_result = perform_discourse_analysis(text_content1, text_content2, nlp_models[lang_code], lang_code)
# Mostrar los gráficos de comparación
st.subheader(t['comparison'])
col1, col2 = st.columns(2)
with col1:
st.pyplot(analysis_result['graph1'])
with col2:
st.pyplot(analysis_result['graph2'])
# Mostrar conceptos clave
st.subheader("Conceptos Clave - Documento 1")
for concept, frequency in analysis_result['key_concepts1']:
st.write(f"{concept}: {frequency:.2f}")
st.subheader("Conceptos Clave - Documento 2")
for concept, frequency in analysis_result['key_concepts2']:
st.write(f"{concept}: {frequency:.2f}")
# Guardar el resultado del análisis
if store_discourse_analysis_result(st.session_state.username, text_content1, text_content2, analysis_result['graph1'], analysis_result['graph2']):
st.success(t['success_message'])
else:
st.error(t['error_message'])
else:
st.warning(t['warning_message'])
##################################################################################################
#def display_saved_discourse_analysis(analysis_data):
# img_bytes = base64.b64decode(analysis_data['combined_graph'])
# img = plt.imread(io.BytesIO(img_bytes), format='png')
# st.image(img, use_column_width=True)
# st.write("Texto del documento patrón:")
# st.write(analysis_data['text1'])
# st.write("Texto del documento comparado:")
# st.write(analysis_data['text2'])
##################################################################################################
def display_chatbot_interface(lang_code):
translations = {
'es': {
'title': "Expertos en Vacaciones",
'input_placeholder': "Escribe tu mensaje aquí...",
'initial_message': "¡Hola! ¿Cómo podemos ayudarte?"
},
'en': {
'title': "Vacation Experts",
'input_placeholder': "Type your message here...",
'initial_message': "Hi! How can we help you?"
},
'fr': {
'title': "Experts en Vacances",
'input_placeholder': "Écrivez votre message ici...",
'initial_message': "Bonjour! Comment pouvons-nous vous aider?"
}
}
t = translations[lang_code]
st.title(t['title'])
if 'chatbot' not in st.session_state:
st.session_state.chatbot = initialize_chatbot()
if 'messages' not in st.session_state:
st.session_state.messages = [{"role": "assistant", "content": t['initial_message']}]
# Contenedor principal para el chat
chat_container = st.container()
# Mostrar mensajes existentes
with chat_container:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# Área de entrada del usuario
user_input = st.chat_input(t['input_placeholder'])
if user_input:
# Agregar mensaje del usuario
st.session_state.messages.append({"role": "user", "content": user_input})
# Mostrar mensaje del usuario
with chat_container:
with st.chat_message("user"):
st.markdown(user_input)
# Generar respuesta del chatbot
with chat_container:
with st.chat_message("assistant"):
message_placeholder = st.empty()
full_response = ""
for chunk in get_chatbot_response(st.session_state.chatbot, user_input, lang_code):
full_response += chunk
message_placeholder.markdown(full_response + "▌")
message_placeholder.markdown(full_response)
# Agregar respuesta del asistente a los mensajes
st.session_state.messages.append({"role": "assistant", "content": full_response})
# Guardar la conversación en la base de datos
try:
store_chat_history(st.session_state.username, st.session_state.messages)
st.success("Conversación guardada exitosamente")
except Exception as e:
st.error(f"Error al guardar la conversación: {str(e)}")
logger.error(f"Error al guardar el historial de chat para {st.session_state.username}: {str(e)}")
# Scroll al final del chat
st.markdown('<script>window.scrollTo(0,document.body.scrollHeight);</script>', unsafe_allow_html=True)
######################################################
if __name__ == "__main__":
main()