Spaces:
Running
Running
# modules/morphosyntax/morphosyntax_interface.py | |
import streamlit as st | |
import re | |
import logging | |
from spacy import displacy | |
# Importa tu pipeline de spacy, por ejemplo: | |
# nlp_models = {"es": spacy.load("es_core_news_sm")} | |
# Supongamos que estas funciones existen en tus otros m贸dulos: | |
from ..morphosyntax.morphosyntax_process import perform_advanced_morphosyntactic_analysis | |
from ..database.morphosyntax_iterative_mongo_db import ( | |
store_student_morphosyntax_base, | |
store_student_morphosyntax_iteration, | |
) | |
logger = logging.getLogger(__name__) | |
########################################################################### | |
def initialize_arc_analysis_state(): | |
""" | |
Inicializa el estado de an谩lisis de arcos (base e iteraciones) si no existe. | |
""" | |
if "arc_analysis_state" not in st.session_state: | |
st.session_state.arc_analysis_state = { | |
"base_id": None, # ObjectId del documento base | |
"base_text": "", # Texto inicial | |
"base_diagram": None, # HTML del diagrama base | |
"iteration_text": "", # Texto de iteraci贸n | |
"iteration_diagram": None, # HTML del diagrama de iteraci贸n | |
} | |
logger.info("Estado de an谩lisis de arcos inicializado.") | |
########################################################################### | |
def reset_arc_analysis_state(): | |
""" | |
Resetea completamente el estado de an谩lisis de arcos. | |
""" | |
st.session_state.arc_analysis_state = { | |
"base_id": None, | |
"base_text": "", | |
"base_diagram": None, | |
"iteration_text": "", | |
"iteration_diagram": None, | |
} | |
########################################################################### | |
def display_arc_diagram(doc): | |
""" | |
Genera y retorna el HTML del diagrama de arco para un `Doc` de spaCy. | |
No imprime directamente en pantalla; regresa el HTML para que se | |
renderice con `st.write(..., unsafe_allow_html=True)`. | |
""" | |
try: | |
diagram_html = "" | |
for sent in doc.sents: | |
svg_html = displacy.render( | |
sent, | |
style="dep", | |
options={ | |
"distance": 100, | |
"arrow_spacing": 20, | |
"word_spacing": 30, | |
} | |
) | |
# Ajustar tama帽o y posici贸n | |
svg_html = svg_html.replace('height="375"', 'height="200"') | |
svg_html = re.sub( | |
r'<svg[^>]*>', | |
lambda m: m.group(0).replace('height="450"', 'height="300"'), | |
svg_html | |
) | |
svg_html = re.sub( | |
r'<g [^>]*transform="translate\((\d+),(\d+)\)"', | |
lambda m: f'<g transform="translate({m.group(1)},50)"', | |
svg_html | |
) | |
# Envolver en contenedor con estilo | |
diagram_html += f'<div class="arc-diagram-container">{svg_html}</div>' | |
return diagram_html | |
except Exception as e: | |
logger.error(f"Error en display_arc_diagram: {str(e)}") | |
return "<p style='color:red;'>Error generando diagrama</p>" | |
########################################################################### | |
def display_morphosyntax_interface(lang_code, nlp_models): | |
""" | |
Interfaz principal para la visualizaci贸n de diagramas de arco | |
(Texto Base vs Iteraciones). | |
""" | |
# CSS para layout estable | |
st.markdown(""" | |
<style> | |
.stTextArea textarea { | |
font-size: 1rem; | |
line-height: 1.5; | |
min-height: 100px !important; | |
height: 100px !important; | |
} | |
.arc-diagram-container { | |
width: 100%; | |
padding: 0.5rem; | |
margin: 0.5rem 0; | |
} | |
.divider { | |
height: 3px; | |
border: none; | |
background-color: #333; | |
margin: 2rem 0; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Inicializar el estado si no existe | |
initialize_arc_analysis_state() | |
arc_state = st.session_state.arc_analysis_state # Para abreviar | |
# Creamos pesta帽as: "Texto Base" y "Iteraciones" | |
tabs = st.tabs(["Texto Base", "Iteraciones"]) | |
# ------------------- PESTA脩A 1: Texto Base -------------------------- | |
with tabs[0]: | |
st.subheader("An谩lisis de Texto Base") | |
# Bot贸n para resetear todo | |
if st.button("Nuevo An谩lisis", key="btn_reset_base"): | |
reset_arc_analysis_state() | |
st.experimental_rerun() | |
# Input para texto base | |
arc_state["base_text"] = st.text_area( | |
"Ingrese su texto inicial", | |
value=arc_state["base_text"], | |
key="base_text_input", | |
height=120 | |
) | |
# Bot贸n de an谩lisis base | |
if st.button("Analizar Texto Base", key="btn_analyze_base"): | |
if not arc_state["base_text"].strip(): | |
st.warning("Ingrese un texto para analizar.") | |
else: | |
try: | |
# Procesar con spaCy | |
doc = nlp_models[lang_code](arc_state["base_text"]) | |
# Generar HTML del arco | |
base_arc_html = display_arc_diagram(doc) | |
arc_state["base_diagram"] = base_arc_html | |
# Guardar en BD usando tu an谩lisis avanzado | |
analysis = perform_advanced_morphosyntactic_analysis( | |
arc_state["base_text"], | |
nlp_models[lang_code] | |
) | |
base_id = store_student_morphosyntax_base( | |
username=st.session_state.username, | |
text=arc_state["base_text"], | |
arc_diagrams=analysis["arc_diagrams"] | |
) | |
if base_id: | |
arc_state["base_id"] = base_id | |
st.success(f"An谩lisis base guardado con ID: {base_id}") | |
except Exception as e: | |
st.error("Error procesando texto base") | |
logger.error(f"Error en an谩lisis base: {str(e)}") | |
# Mostrar el arco base, si existe | |
if arc_state["base_diagram"]: | |
st.markdown("<hr class='divider'>", unsafe_allow_html=True) | |
st.markdown("#### Diagrama de Arco (Texto Base)") | |
st.write(arc_state["base_diagram"], unsafe_allow_html=True) | |
# ------------------- PESTA脩A 2: Iteraciones ------------------------- | |
with tabs[1]: | |
st.subheader("An谩lisis de Cambios / Iteraciones") | |
# Si no se ha analizado nada en la primera pesta帽a | |
if not arc_state["base_id"]: | |
st.info("Primero analiza un texto base en la pesta帽a anterior.") | |
return | |
# Mostrar el texto base como referencia, en modo solo lectura | |
st.text_area( | |
"Texto Base (solo lectura)", | |
value=arc_state["base_text"], | |
key="base_text_ref", | |
height=80, | |
disabled=True | |
) | |
# Texto de iteraci贸n | |
arc_state["iteration_text"] = st.text_area( | |
"Texto de Iteraci贸n", | |
value=arc_state["iteration_text"], | |
key="iteration_text_input", | |
height=120 | |
) | |
# Bot贸n para analizar iteraci贸n | |
if st.button("Analizar Cambios", key="btn_analyze_iteration"): | |
if not arc_state["iteration_text"].strip(): | |
st.warning("Ingrese texto de iteraci贸n.") | |
else: | |
try: | |
# Procesar con spaCy | |
doc_iter = nlp_models[lang_code](arc_state["iteration_text"]) | |
iteration_arc_html = display_arc_diagram(doc_iter) | |
arc_state["iteration_diagram"] = iteration_arc_html | |
# Guardar en BD | |
iteration_analysis = perform_advanced_morphosyntactic_analysis( | |
arc_state["iteration_text"], | |
nlp_models[lang_code] | |
) | |
iteration_id = store_student_morphosyntax_iteration( | |
username=st.session_state.username, | |
base_id=arc_state["base_id"], | |
original_text=arc_state["base_text"], | |
iteration_text=arc_state["iteration_text"], | |
arc_diagrams=iteration_analysis["arc_diagrams"] | |
) | |
if iteration_id: | |
st.success(f"Iteraci贸n guardada con ID: {iteration_id}") | |
except Exception as e: | |
st.error("Error procesando iteraci贸n") | |
logger.error(f"Error en iteraci贸n: {str(e)}") | |
# Mostrar el arco de iteraci贸n, si existe | |
if arc_state["iteration_diagram"]: | |
st.markdown("<hr class='divider'>", unsafe_allow_html=True) | |
st.markdown("#### Diagrama de Arco (Iteraci贸n)") | |
st.write(arc_state["iteration_diagram"], unsafe_allow_html=True) | |
# Mostrar comparaci贸n (opcional) | |
if arc_state["base_diagram"] and arc_state["iteration_diagram"]: | |
st.markdown("<hr class='divider'>", unsafe_allow_html=True) | |
st.markdown("### Comparaci贸n de Diagrama Base vs. Iteraci贸n") | |
col_base, col_iter = st.columns(2) | |
with col_base: | |
st.markdown("**Diagrama Base**") | |
st.write(arc_state["base_diagram"], unsafe_allow_html=True) | |
with col_iter: | |
st.markdown("**Diagrama Iterado**") | |
st.write(arc_state["iteration_diagram"], unsafe_allow_html=True) | |