test2 / modules /ui.py
AIdeaText's picture
Update modules/ui.py
16dcc0e verified
raw
history blame
19.3 kB
#Importaciones generales
import streamlit as st
import re
import io
import base64
import matplotlib.pyplot as plt
import pandas as pd
from streamlit_player import st_player # Necesitarás instalar esta librería: pip install streamlit-player
from spacy import displacy
#Importaciones locales
#Importaciones locales de autenticación y base de datos
from .auth import authenticate_user, register_user, get_user_role
from .database import get_student_data, store_morphosyntax_result, store_semantic_result, store_chat_history
#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 login_register_page():
st.title("AIdeaText")
# Dividir la pantalla en dos columnas
left_column, right_column = st.columns([1, 3]) # 25% izquierda, 75% derecha
# Sección izquierda para login y registro
with left_column:
tab1, tab2 = st.tabs(["Iniciar Sesión", "Registrarse"])
with tab1:
login_form()
with tab2:
register_form()
# Sección derecha para videos de YouTube
with right_column:
st.header("Videos: pitch, demos, entrevistas, otros")
# Diccionario de videos de YouTube con títulos amigables
videos = {
"Intro AideaText": "https://www.youtube.com/watch?v=UA-md1VxaRc",
"Pitch que facilitó acceder a la segunda fase de IFE Explora del TEC de Monterrey": "https://www.youtube.com/watch?v=Fqi4Di_Rj_s",
"Entrevista con el doctor Guillermo Ruíz, EduMate Lima Perú" : "https://www.youtube.com/watch?v=_ch8cRja3oc",
"Demo versión desktop de AIdeaText": "https://www.youtube.com/watch?v=nP6eXbog-ZY"
}
# Selector de video
video_titles = list(videos.keys())
if video_titles:
selected_title = st.selectbox("Selecciona un video tutorial:", video_titles)
# Obtener la URL correspondiente al título seleccionado
if selected_title in videos:
selected_video = videos[selected_title]
# Reproductor de YouTube
try:
st_player(selected_video)
except Exception as e:
st.error(f"Error al cargar el video: {str(e)}")
else:
st.warning("El video seleccionado no está disponible.")
else:
st.warning("No hay videos disponibles para mostrar.")
# Información adicional
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 login_form():
username = st.text_input("Usuario")
password = st.text_input("Contraseña", type='password')
captcha_answer = st.text_input("Captcha: ¿Cuánto es 2 + 3?")
if st.button("Iniciar Sesión"):
if captcha_answer == "5":
if authenticate_user(username, password):
st.success(f"Bienvenido, {username}!")
st.session_state.logged_in = True
st.session_state.username = username
st.session_state.role = get_user_role(username)
st.experimental_rerun()
else:
st.error("Usuario o contraseña incorrectos")
else:
st.error("Captcha incorrecto")
##################################################################################################
def register_form():
new_username = st.text_input("Nuevo Usuario")
new_password = st.text_input("Nueva Contraseña", type='password')
carrera = st.text_input("Carrera")
captcha_answer = st.text_input("Captcha: ¿Cuánto es 3 + 4?")
if st.button("Registrarse"):
if captcha_answer == "7":
additional_info = {'carrera': carrera}
if register_user(new_username, new_password, additional_info):
st.success("Registro exitoso. Por favor, inicia sesión.")
else:
st.error("El usuario ya existe o ocurrió un error durante el registro")
else:
st.error("Captcha incorrecto")
##################################################################################################
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()
##################################################################################################
def display_student_progress(username, lang_code='es'):
student_data = get_student_data(username)
if student_data is None:
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}")
if student_data['entries_count'] > 0:
if 'word_count' in student_data and student_data['word_count']:
st.subheader("Total de palabras por categoría gramatical")
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=[POS_COLORS.get(cat, '#CCCCCC') for cat in 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()
buf = io.BytesIO()
fig.savefig(buf, format='png')
buf.seek(0)
st.image(buf, use_column_width=True)
else:
st.info("No hay datos de conteo de palabras disponibles.")
st.header("Diagramas de Arco")
with st.expander("Ver todos los Diagramas de Arco"):
for i, entry in enumerate(student_data['entries']):
if 'arc_diagrams' in entry and entry['arc_diagrams']:
st.subheader(f"Entrada {i+1} - {entry['timestamp']}")
st.write(entry['arc_diagrams'][0], unsafe_allow_html=True)
st.header("Diagramas de Red")
with st.expander("Ver todos los Diagramas de Red"):
for i, entry in enumerate(student_data['entries']):
if 'network_diagram' in entry and entry['network_diagram']:
st.subheader(f"Entrada {i+1} - {entry['timestamp']}")
try:
image_bytes = base64.b64decode(entry['network_diagram'])
st.image(image_bytes)
except Exception as e:
st.error(f"Error al mostrar el diagrama de red: {str(e)}")
else:
st.warning("No se encontraron entradas para este estudiante.")
st.info("Intenta realizar algunos análisis de texto primero.")
##################################################################################################
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"
},
'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"
},
'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"
}
}
t = translations[lang_code]
input_key = f"morphosyntax_input_{lang_code}"
# Inicializar la clave en session_state si no existe
if input_key not in st.session_state:
st.session_state[input_key] = ""
# Función para actualizar el estado del input
def update_input():
st.session_state[input_key] = st.session_state[f"text_area_{lang_code}"]
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=update_input
)
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("Análisis guardado correctamente.")
else:
st.error("Hubo un problema al guardar el análisis. Por favor, inténtelo de nuevo.")
else:
st.warning("Por favor, ingrese un texto para analizar.")
###############################################################################################################
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",
},
'en': {
'title': "AIdeaText - Semantic Analysis",
'file_uploader': "Upload text file",
'analyze_button': "Analyze text",
'semantic_relations': "Relevant Semantic Relations",
},
'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",
}
}
t = translations[lang_code]
st.header(t['title'])
uploaded_file = st.file_uploader(t['file_uploader'], type=['txt'])
if uploaded_file is not None:
text_content = uploaded_file.getvalue().decode('utf-8')
if st.button(t['analyze_button']):
relations_graph = perform_semantic_analysis(text_content, nlp_models[lang_code], lang_code)
with st.expander(t['semantic_relations'], expanded=True):
st.pyplot(relations_graph)
##################################################################################################
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",
},
'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",
},
'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",
}
}
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 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')
if st.button(t['analyze_button']):
graph1, graph2 = perform_discourse_analysis(text_content1, text_content2, nlp_models[lang_code], lang_code)
st.subheader(t['comparison'])
col1, col2 = st.columns(2)
with col1:
st.pyplot(graph1)
with col2:
st.pyplot(graph2)
##################################################################################################
def display_chatbot_interface(lang_code):
translations = {
'es': {
'title': "AIdeaText - Chatbot Multilingüe",
'input_placeholder': "Escribe tu mensaje aquí...",
'send_button': "Enviar",
'initial_message': "¡Hola! ¿En qué puedo ayudarte hoy?"
},
'en': {
'title': "AIdeaText - Multilingual Chatbot",
'input_placeholder': "Type your message here...",
'send_button': "Send",
'initial_message': "Hello! How can I assist you today?"
},
'fr': {
'title': "AIdeaText - Chatbot Multilingue",
'input_placeholder': "Écrivez votre message ici...",
'send_button': "Envoyer",
'initial_message': "Bonjour! Comment puis-je vous aider aujourd'hui?"
}
}
t = translations[lang_code]
st.header(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']}]
# Mostrar mensajes previos
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# Input del usuario
if prompt := st.chat_input(t['input_placeholder']):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
message_placeholder = st.empty()
full_response = ""
for response in get_chatbot_response(st.session_state.chatbot, prompt, lang_code):
full_response += response + " "
message_placeholder.markdown(full_response + "▌")
message_placeholder.markdown(full_response)
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)