test2 / modules /ui.py
AIdeaText's picture
Update modules/ui.py
78cd30d verified
raw
history blame
No virus
27.2 kB
#Importaciones generales
import streamlit as st
import re
import io
import base64
import matplotlib.pyplot as plt
import pandas as pd
import time
from streamlit_player import st_player # Necesitarás instalar esta librería: pip install streamlit-player
from spacy import displacy
import login
# Configuración del logger
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
#Importaciones locales
#Importaciones locales de autenticación y base de datos
from .auth import authenticate_user, register_user
from .database import (
get_student_data,
store_morphosyntax_result,
store_semantic_result,
store_discourse_analysis_result,
store_chat_history,
create_admin_user,
create_student_user
)
#Importaciones locales de uiadmin
from .admin_ui import admin_page
#Importaciones locales funciones de análisis
from .morpho_analysis import generate_arc_diagram, get_repeated_words_colors, highlight_repeated_words, POS_COLORS, POS_TRANSLATIONS
from .semantic_analysis import visualize_semantic_relations, perform_semantic_analysis
from .discourse_analysis import compare_semantic_analysis, perform_discourse_analysis
from .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"Bienvenido, {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():
st.title("Bienvenido a AIdeaText")
st.write(f"Hola, {st.session_state.username}")
# Aquí puedes añadir las funcionalidades para el usuario estudiante
# Por ejemplo:
tabs = st.tabs(["Análisis Morfosintáctico", "Análisis Semántico", "Análisis del Discurso", "Chat", "Mi Progreso"])
with tabs[0]:
display_morphosyntax_analysis_interface(nlp_models, 'es') # Asumiendo que 'es' es el idioma por defecto
with tabs[1]:
display_semantic_analysis_interface(nlp_models, 'es')
with tabs[2]:
display_discourse_analysis_interface(nlp_models, 'es')
with tabs[3]:
display_chatbot_interface('es')
with tabs[4]:
display_student_progress(st.session_state.username, 'es')
##################################################################################################
def display_videos_and_info():
st.header("Videos: pitch, demos, entrevistas, otros")
videos = {
"Intro AideaText": "https://www.youtube.com/watch?v=UA-md1VxaRc",
"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():
##
##
pass
##################################################################################################
def display_chat_interface():
st.markdown("### Chat con AIdeaText")
if 'chat_history' not in st.session_state:
st.session_state.chat_history = []
for i, (role, text) in enumerate(st.session_state.chat_history):
if role == "user":
st.text_area(f"Tú:", value=text, height=50, key=f"user_message_{i}", disabled=True)
else:
st.text_area(f"AIdeaText:", value=text, height=50, key=f"bot_message_{i}", disabled=True)
user_input = st.text_input("Escribe tu mensaje aquí:")
if st.button("Enviar"):
if user_input:
st.session_state.chat_history.append(("user", user_input))
response = get_chatbot_response(user_input)
st.session_state.chat_history.append(("bot", response))
st.experimental_rerun()
################################################################################
# Funciones para Cosmos DB MongoDB API (análisis de texto)
def display_student_progress(username, lang_code='es'):
logger.info(f"Intentando mostrar progreso para el usuario: {username}")
student_data = get_student_data(username)
if student_data is None:
logger.warning(f"No se pudieron recuperar datos para el usuario: {username}")
st.warning("No se encontraron datos para este estudiante.")
st.info("Intenta realizar algunos análisis de texto primero.")
return
logger.info(f"Datos recuperados para {username}: {student_data}")
st.title(f"Progreso de {username}")
if student_data['entries_count'] == 0:
st.warning("No se encontraron entradas para este estudiante.")
st.info("Intenta realizar algunos análisis de texto primero.")
return
# Mostrar el conteo de palabras
if student_data['word_count']:
with st.expander("Total de palabras por categoría gramatical", expanded=False):
df = pd.DataFrame(list(student_data['word_count'].items()), columns=['category', 'count'])
df['label'] = df.apply(lambda x: f"{POS_TRANSLATIONS[lang_code].get(x['category'], x['category'])}", axis=1)
df = df.sort_values('count', ascending=False)
fig, ax = plt.subplots(figsize=(12, 6))
bars = ax.bar(df['label'], df['count'], color=df['category'])
ax.set_xlabel('Categoría Gramatical')
ax.set_ylabel('Cantidad de Palabras')
ax.set_title('Total de palabras por categoría gramatical')
plt.xticks(rotation=45, ha='right')
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height, f'{height}', ha='center', va='bottom')
plt.tight_layout()
st.pyplot(fig)
# Mostrar análisis morfosintáctico
morphosyntax_entries = [entry for entry in student_data['entries'] if entry['analysis_type'] == 'morphosyntax']
if morphosyntax_entries:
with st.expander("Análisis Morfosintáctico - Diagramas de Arco", expanded=False):
for i, entry in enumerate(morphosyntax_entries):
st.subheader(f"Análisis {i+1} - {entry['timestamp']}")
st.write(entry['text'])
for j, diagram in enumerate(entry.get('arc_diagrams', [])):
st.subheader(f"Diagrama de Arco {j+1}")
st.write(diagram, unsafe_allow_html=True)
# Mostrar análisis semántico
if student_data['semantic_analyses']:
with st.expander("Análisis Semántico - Diagramas de Red", expanded=False):
for i, entry in enumerate(student_data['semantic_analyses']):
st.subheader(f"Análisis Semántico {i+1} - {entry['timestamp']}")
st.write(entry['text'])
if 'network_diagram' in entry:
image_bytes = base64.b64decode(entry['network_diagram'])
st.image(image_bytes)
# Mostrar análisis del discurso
if student_data['discourse_analyses']:
with st.expander("Análisis del Discurso - Comparación de Grafos", expanded=False):
for i, entry in enumerate(student_data['discourse_analyses']):
st.subheader(f"Análisis del Discurso {i+1} - {entry['timestamp']}")
st.write("Texto del documento patrón:")
st.write(entry.get('text1', 'No disponible'))
st.write("Texto del documento comparado:")
st.write(entry.get('text2', 'No disponible'))
if 'graph1' in entry:
st.image(base64.b64decode(entry['graph1']))
if 'graph2' in entry:
st.image(base64.b64decode(entry['graph2']))
# Mostrar conversaciones del chat
if student_data['chat_history']:
with st.expander("Historial de Conversaciones del Chat", expanded=False):
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.warning("No se encontraron entradas para este estudiante.")
st.info("Intenta realizar algunos análisis de texto primero.")
# Añadir logs para 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áx. 5,000 palabras):",
'input_placeholder': "El objetivo de esta aplicación es que mejore sus habilidades de redacción...",
'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."
},
'en': {
'title': "AIdeaText - Morphological and Syntactic Analysis",
'input_label': "Enter a text to analyze (max 5,000 words):",
'input_placeholder': "The goal of this app is for you to improve your writing skills...",
'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."
},
'fr': {
'title': "AIdeaText - Analyse morphologique et syntaxique",
'input_label': "Entrez un texte à analyser (max 5 000 mots) :",
'input_placeholder': "Le but de cette application est d'améliorer vos compétences en rédaction...",
'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."
}
}
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)
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)
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)
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)
if store_morphosyntax_result(
st.session_state.username,
current_input,
word_colors,
arc_diagrams,
):
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",
'file_uploader': "Cargar archivo de texto",
'analyze_button': "Analizar texto",
'semantic_relations': "Relaciones Semánticas Relevantes",
'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, cargue un archivo para analizar."
},
'en': {
'title': "AIdeaText - Semantic Analysis",
'file_uploader': "Upload text file",
'analyze_button': "Analyze text",
'semantic_relations': "Relevant Semantic Relations",
'success_message': "Semantic analysis saved successfully.",
'error_message': "There was a problem saving the semantic analysis. Please try again.",
'warning_message': "Please upload a file to analyze."
},
'fr': {
'title': "AIdeaText - Analyse sémantique",
'file_uploader': "Télécharger le fichier texte",
'analyze_button': "Analyser le texte",
'semantic_relations': "Relations Sémantiques Pertinentes",
'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 télécharger un fichier à analyser."
}
}
t = translations[lang_code]
st.header(t['title'])
# Opción para cargar archivo
uploaded_file = st.file_uploader(t['file_uploader'], type=['txt'])
if st.button(t['analyze_button']):
if uploaded_file is not None:
text_content = uploaded_file.getvalue().decode('utf-8')
# Realizar el análisis
relations_graph = perform_semantic_analysis(text_content, nlp_models[lang_code], lang_code)
# Mostrar el gráfico de relaciones semánticas
with st.expander(t['semantic_relations'], expanded=True):
st.pyplot(relations_graph)
# Guardar el resultado del análisis
if store_semantic_result(st.session_state.username, text_content, relations_graph):
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
graph1, graph2 = 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(graph1)
with col2:
st.pyplot(graph2)
# Guardar el resultado del análisis
#if store_discourse_analysis_result(st.session_state.username, text_content1 + "\n\n" + text_content2, graph1, graph2):
if store_discourse_analysis_result(st.session_state.username, text_content1, text_content2, graph1, 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
store_chat_history(st.session_state.username, st.session_state.messages)
# Scroll al final del chat
st.markdown('<script>window.scrollTo(0,document.body.scrollHeight);</script>', unsafe_allow_html=True)
######################################################
if __name__ == "__main__":
main()