AIdeaText commited on
Commit
344632c
verified
1 Parent(s): 9fec2f4

Update modules/morphosyntax/morphosyntax_interface.py

Browse files
modules/morphosyntax/morphosyntax_interface.py CHANGED
@@ -5,9 +5,12 @@ import re
5
  import logging
6
  from spacy import displacy
7
 
8
- # Importa tu pipeline de spacy, p. ej.:
9
  # nlp_models = {"es": spacy.load("es_core_news_sm")}
10
 
 
 
 
11
  from ..database.morphosyntax_iterative_mongo_db import (
12
  store_student_morphosyntax_base,
13
  store_student_morphosyntax_iteration,
@@ -17,54 +20,41 @@ logger = logging.getLogger(__name__)
17
 
18
  ###########################################################################
19
  def initialize_arc_analysis_state():
20
- """Inicializa el estado del an谩lisis de arcos y el cach茅 si no existen."""
21
- if 'arc_analysis_state' not in st.session_state:
22
- st.session_state.arc_analysis_state = {
23
- 'base_id': None, # ID del an谩lisis base
24
- 'original_text': '', # Texto original
25
- 'original_analysis': None, # Resultado an谩lisis original
26
- 'iteration_text': '', # Texto de iteraci贸n
27
- 'iteration_analysis': None,# Resultado an谩lisis iteraci贸n
28
- 'analysis_count': 0
29
- }
30
- logger.info("Estado de an谩lisis de arcos inicializado")
31
-
32
- # Inicializar cach茅 de an谩lisis
33
- if 'analysis_cache' not in st.session_state:
34
- st.session_state.analysis_cache = {}
35
- logger.info("Cach茅 de an谩lisis inicializado")
36
-
37
- ####################################################################
38
- def reset_morpho_state():
39
- """Resetea el estado del an谩lisis morfosint谩ctico en sesi贸n."""
40
- if 'arc_analysis_state' in st.session_state:
41
  st.session_state.arc_analysis_state = {
42
- 'base_id': None,
43
- 'original_text': '',
44
- 'original_analysis': None,
45
- 'iteration_text': '',
46
- 'iteration_analysis': None,
47
- 'analysis_count': 0
48
  }
 
49
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- def display_original_analysis(container, analysis, lang_code, morpho_t):
52
- """Muestra el an谩lisis original en el contenedor especificado."""
53
- with container:
54
- st.subheader("An谩lisis Original")
55
- display_morphosyntax_results(analysis, lang_code, morpho_t)
56
-
57
-
58
- def display_iteration_analysis(container, analysis, lang_code, morpho_t):
59
- """Muestra el an谩lisis de cambios en el contenedor especificado."""
60
- with container:
61
- st.subheader("An谩lisis de Cambios")
62
- display_morphosyntax_results(analysis, lang_code, morpho_t)
63
-
64
-
65
- def display_arc_diagram(doc, analysis):
66
- """Muestra un diagrama de arco sin t铆tulo."""
67
  try:
 
68
  for sent in doc.sents:
69
  svg_html = displacy.render(
70
  sent,
@@ -72,7 +62,7 @@ def display_arc_diagram(doc, analysis):
72
  options={
73
  "distance": 100,
74
  "arrow_spacing": 20,
75
- "word_spacing": 30
76
  }
77
  )
78
  # Ajustar tama帽o y posici贸n
@@ -87,250 +77,172 @@ def display_arc_diagram(doc, analysis):
87
  lambda m: f'<g transform="translate({m.group(1)},50)"',
88
  svg_html
89
  )
90
-
91
  # Envolver en contenedor con estilo
92
- svg_html = f'<div class="arc-diagram-container">{svg_html}</div>'
93
- st.write(svg_html, unsafe_allow_html=True)
94
-
95
  except Exception as e:
96
  logger.error(f"Error en display_arc_diagram: {str(e)}")
 
97
 
98
-
99
- def cache_analysis_results(key, result):
100
- """Almacena resultados de an谩lisis en cach茅."""
101
- if not hasattr(st.session_state, 'analysis_cache'):
102
- initialize_arc_analysis_state()
103
- st.session_state.analysis_cache[key] = result
104
- logger.info(f"Resultado almacenado en cach茅 con clave: {key}")
105
-
106
-
107
- def get_cached_analysis(key):
108
- """Recupera resultados de an谩lisis del cach茅."""
109
- if not hasattr(st.session_state, 'analysis_cache'):
110
- initialize_arc_analysis_state()
111
- return None
112
- return st.session_state.analysis_cache.get(key)
113
-
114
-
115
- def display_morphosyntax_interface(lang_code, nlp_models, morpho_t):
116
  """
117
- Interfaz principal para el an谩lisis morfosint谩ctico.
118
- Evita resets indebidos y conserva la pesta帽a activa.
119
  """
120
- try:
121
- # CSS para layout estable
122
- st.markdown("""
123
- <style>
124
- .stTextArea textarea {
125
- font-size: 1rem;
126
- line-height: 1.5;
127
- min-height: 100px !important;
128
- height: 100px !important;
129
- }
130
- .arc-diagram-container {
131
- width: 100%;
132
- padding: 0.5rem;
133
- margin: 0.5rem 0;
134
- }
135
- .divider {
136
- height: 3px;
137
- border: none;
138
- background-color: #333;
139
- margin: 2rem 0;
140
- }
141
- </style>
142
- """, unsafe_allow_html=True)
143
-
144
- # Inicializar estados de an谩lisis si no existen
145
- initialize_arc_analysis_state()
146
-
147
- # ------------------------------------------------------------------
148
- # Si tuvieras un control de tabs global, puedes comentarlo:
149
- #
150
- # st.session_state.tab_states['morpho_active'] = True
151
- # st.session_state.selected_tab = 1
152
- # ------------------------------------------------------------------
153
-
154
- # Crear subtabs
155
- subtabs = st.tabs([
156
- "An谩lisis de Diagramas de Arco",
157
- "An谩lisis de Categor铆as",
158
- "An谩lisis Morfol贸gico"
159
- ])
160
-
161
- # -------------------- Subtab 0: Diagramas de Arco --------------------
162
- with subtabs[0]:
163
- # Bot贸n de reset
164
- col1, col2, col3 = st.columns([2, 1, 2])
165
- with col1:
166
- if st.button("Nuevo An谩lisis", type="secondary", use_container_width=True):
167
- reset_morpho_state()
168
- # Forzar el rec谩lculo limpio
169
- st.rerun()
170
-
171
- # Container principal para an谩lisis base
172
- analysis_container = st.container()
173
- with analysis_container:
174
- # Entrada de texto original
175
- text_input_key = f"original_text_{st.session_state.arc_analysis_state['analysis_count']}"
176
- text_input = st.text_area(
177
- "Texto original",
178
- value=st.session_state.arc_analysis_state.get('original_text', ''),
179
- key=text_input_key,
180
- height=100
181
- )
182
-
183
- # Bot贸n de an谩lisis
184
- col1, col2, col3 = st.columns([2, 1, 2])
185
- with col1:
186
- analyze_button = st.button(
187
- "Analizar Texto",
188
- type="primary",
189
- use_container_width=True
190
  )
191
-
192
- # Procesar texto original
193
- if analyze_button and text_input.strip():
194
- try:
195
- # Realizar an谩lisis base (SpaCy)
196
- doc = nlp_models[lang_code](text_input)
197
- analysis = perform_advanced_morphosyntactic_analysis(
198
- text_input,
199
- nlp_models[lang_code]
200
- )
201
-
202
- # Guardar an谩lisis base en BD y obtener ID
203
- base_id = store_student_morphosyntax_base(
204
- st.session_state.username,
205
- text_input,
206
- analysis['arc_diagrams']
207
- )
208
-
209
- if base_id:
210
- # Actualizar el estado en session_state
211
- st.session_state.arc_analysis_state.update({
212
- 'base_id': base_id,
213
- 'original_text': text_input,
214
- 'original_analysis': analysis, # guardamos el dict
215
- 'analysis_count': st.session_state.arc_analysis_state['analysis_count'] + 1
216
- })
217
-
218
- # Mostrar diagrama base
219
- display_arc_diagram(doc, analysis)
220
-
221
- # L铆nea divisora
222
- st.markdown('<hr class="divider">', unsafe_allow_html=True)
223
-
224
- # 脕rea de iteraci贸n: usar un formulario
225
- with st.form("iteration_form"):
226
- # Separamos la key para la iteraci贸n para que no se sobreescriba
227
- iteration_text_key = f"iteration_text_{st.session_state.arc_analysis_state['analysis_count']}"
228
-
229
- # Mostrar el texto de iteraci贸n que tengamos en session_state
230
- iteration_text = st.text_area(
231
- "Texto de iteraci贸n",
232
- value=st.session_state.arc_analysis_state.get('iteration_text', text_input),
233
- key=iteration_text_key,
234
- height=100
235
- )
236
-
237
- # Bot贸n de submit en el formulario
238
- col1, col2, col3 = st.columns([2,1,2])
239
- with col1:
240
- submitted = st.form_submit_button(
241
- "Analizar Cambios",
242
- type="primary",
243
- use_container_width=True
244
- )
245
-
246
- # Procesar iteraci贸n
247
- if submitted and iteration_text.strip():
248
- try:
249
- doc_iter = nlp_models[lang_code](iteration_text)
250
- analysis_iter = perform_advanced_morphosyntactic_analysis(
251
- iteration_text,
252
- nlp_models[lang_code]
253
- )
254
-
255
- # Guardar iteraci贸n
256
- iteration_id = store_student_morphosyntax_iteration(
257
- st.session_state.username,
258
- base_id,
259
- text_input, # Texto original
260
- iteration_text, # Texto de iteraci贸n
261
- analysis_iter['arc_diagrams']
262
- )
263
-
264
- if iteration_id:
265
- # Actualizar el estado de iteraci贸n en session_state
266
- st.session_state.arc_analysis_state.update({
267
- 'iteration_text': iteration_text,
268
- 'iteration_analysis': analysis_iter
269
- })
270
- # Mostrar diagrama de iteraci贸n
271
- display_arc_diagram(doc_iter, analysis_iter)
272
-
273
- except Exception as e:
274
- st.error("Error procesando iteraci贸n")
275
- logger.error(f"Error en iteraci贸n: {str(e)}")
276
-
277
- except Exception as e:
278
- st.error("Error procesando an谩lisis base")
279
- logger.error(f"Error base: {str(e)}")
280
-
281
- # -------------------- Subtab 1: An谩lisis de Categor铆as ----------------
282
- with subtabs[1]:
283
- st.info("An谩lisis de Categor铆as en desarrollo...")
284
-
285
- # -------------------- Subtab 2: An谩lisis Morfol贸gico ------------------
286
- with subtabs[2]:
287
- st.info("An谩lisis Morfol贸gico en desarrollo...")
288
-
289
- except Exception as e:
290
- st.error("Error en la interfaz de morfosintaxis")
291
- logger.error(f"Error general en la interfaz: {str(e)}")
292
-
293
-
294
- def display_morphosyntax_results(result, lang_code, morpho_t):
295
- """
296
- Muestra solo el diagrama de arco.
297
- Args:
298
- result: Diccionario con el documento procesado y su an谩lisis
299
- lang_code: C贸digo del idioma
300
- morpho_t: Diccionario de traducciones (opcional)
301
- """
302
- if result is None:
303
- return
304
- try:
305
- doc = result['doc']
306
- sentences = list(doc.sents)
307
- for i, sent in enumerate(sentences):
308
- try:
309
- st.subheader(f"{morpho_t.get('sentence', 'Sentence')} {i+1}")
310
- svg_html = displacy.render(
311
- sent,
312
- style="dep",
313
- options={
314
- "distance": 100,
315
- "arrow_spacing": 20,
316
- "word_spacing": 30
317
- }
318
- )
319
- svg_html = svg_html.replace('height="375"', 'height="200"')
320
- svg_html = re.sub(
321
- r'<svg[^>]*>',
322
- lambda m: m.group(0).replace('height="450"', 'height="300"'),
323
- svg_html
324
- )
325
- svg_html = re.sub(
326
- r'<g [^>]*transform="translate\((\d+),(\d+)\)"',
327
- lambda m: f'<g transform="translate({m.group(1)},50)"',
328
- svg_html
329
- )
330
- svg_html = f'<div class="arc-diagram-container">{svg_html}</div>'
331
- st.write(svg_html, unsafe_allow_html=True)
332
- except Exception as exc:
333
- logger.error(f"Error mostrando diagrama de la oraci贸n {i}: {str(exc)}")
334
- continue
335
- except Exception as e:
336
- logger.error(f"Error en display_morphosyntax_results: {str(e)}")
 
5
  import logging
6
  from spacy import displacy
7
 
8
+ # Importa tu pipeline de spacy, por ejemplo:
9
  # nlp_models = {"es": spacy.load("es_core_news_sm")}
10
 
11
+ # Supongamos que estas funciones existen en tus otros m贸dulos:
12
+ from ..morphosyntax.morphosyntax_process import perform_advanced_morphosyntactic_analysis
13
+
14
  from ..database.morphosyntax_iterative_mongo_db import (
15
  store_student_morphosyntax_base,
16
  store_student_morphosyntax_iteration,
 
20
 
21
  ###########################################################################
22
  def initialize_arc_analysis_state():
23
+ """
24
+ Inicializa el estado de an谩lisis de arcos (base e iteraciones) si no existe.
25
+ """
26
+ if "arc_analysis_state" not in st.session_state:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  st.session_state.arc_analysis_state = {
28
+ "base_id": None, # ObjectId del documento base
29
+ "base_text": "", # Texto inicial
30
+ "base_diagram": None, # HTML del diagrama base
31
+ "iteration_text": "", # Texto de iteraci贸n
32
+ "iteration_diagram": None, # HTML del diagrama de iteraci贸n
 
33
  }
34
+ logger.info("Estado de an谩lisis de arcos inicializado.")
35
 
36
+ ###########################################################################
37
+ def reset_arc_analysis_state():
38
+ """
39
+ Resetea completamente el estado de an谩lisis de arcos.
40
+ """
41
+ st.session_state.arc_analysis_state = {
42
+ "base_id": None,
43
+ "base_text": "",
44
+ "base_diagram": None,
45
+ "iteration_text": "",
46
+ "iteration_diagram": None,
47
+ }
48
 
49
+ ###########################################################################
50
+ def display_arc_diagram(doc):
51
+ """
52
+ Genera y retorna el HTML del diagrama de arco para un `Doc` de spaCy.
53
+ No imprime directamente en pantalla; regresa el HTML para que se
54
+ renderice con `st.write(..., unsafe_allow_html=True)`.
55
+ """
 
 
 
 
 
 
 
 
 
56
  try:
57
+ diagram_html = ""
58
  for sent in doc.sents:
59
  svg_html = displacy.render(
60
  sent,
 
62
  options={
63
  "distance": 100,
64
  "arrow_spacing": 20,
65
+ "word_spacing": 30,
66
  }
67
  )
68
  # Ajustar tama帽o y posici贸n
 
77
  lambda m: f'<g transform="translate({m.group(1)},50)"',
78
  svg_html
79
  )
 
80
  # Envolver en contenedor con estilo
81
+ diagram_html += f'<div class="arc-diagram-container">{svg_html}</div>'
82
+ return diagram_html
 
83
  except Exception as e:
84
  logger.error(f"Error en display_arc_diagram: {str(e)}")
85
+ return "<p style='color:red;'>Error generando diagrama</p>"
86
 
87
+ ###########################################################################
88
+ def display_morphosyntax_interface(lang_code, nlp_models):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  """
90
+ Interfaz principal para la visualizaci贸n de diagramas de arco
91
+ (Texto Base vs Iteraciones).
92
  """
93
+ # CSS para layout estable
94
+ st.markdown("""
95
+ <style>
96
+ .stTextArea textarea {
97
+ font-size: 1rem;
98
+ line-height: 1.5;
99
+ min-height: 100px !important;
100
+ height: 100px !important;
101
+ }
102
+ .arc-diagram-container {
103
+ width: 100%;
104
+ padding: 0.5rem;
105
+ margin: 0.5rem 0;
106
+ }
107
+ .divider {
108
+ height: 3px;
109
+ border: none;
110
+ background-color: #333;
111
+ margin: 2rem 0;
112
+ }
113
+ </style>
114
+ """, unsafe_allow_html=True)
115
+
116
+ # Inicializar el estado si no existe
117
+ initialize_arc_analysis_state()
118
+ arc_state = st.session_state.arc_analysis_state # Para abreviar
119
+
120
+ # Creamos pesta帽as: "Texto Base" y "Iteraciones"
121
+ tabs = st.tabs(["Texto Base", "Iteraciones"])
122
+
123
+ # ------------------- PESTA脩A 1: Texto Base --------------------------
124
+ with tabs[0]:
125
+ st.subheader("An谩lisis de Texto Base")
126
+
127
+ # Bot贸n para resetear todo
128
+ if st.button("Nuevo An谩lisis", key="btn_reset_base"):
129
+ reset_arc_analysis_state()
130
+ st.experimental_rerun()
131
+
132
+ # Input para texto base
133
+ arc_state["base_text"] = st.text_area(
134
+ "Ingrese su texto inicial",
135
+ value=arc_state["base_text"],
136
+ key="base_text_input",
137
+ height=120
138
+ )
139
+
140
+ # Bot贸n de an谩lisis base
141
+ if st.button("Analizar Texto Base", key="btn_analyze_base"):
142
+ if not arc_state["base_text"].strip():
143
+ st.warning("Ingrese un texto para analizar.")
144
+ else:
145
+ try:
146
+ # Procesar con spaCy
147
+ doc = nlp_models[lang_code](arc_state["base_text"])
148
+ # Generar HTML del arco
149
+ base_arc_html = display_arc_diagram(doc)
150
+ arc_state["base_diagram"] = base_arc_html
151
+
152
+ # Guardar en BD usando tu an谩lisis avanzado
153
+ analysis = perform_advanced_morphosyntactic_analysis(
154
+ arc_state["base_text"],
155
+ nlp_models[lang_code]
 
 
 
 
 
 
 
156
  )
157
+ base_id = store_student_morphosyntax_base(
158
+ username=st.session_state.username,
159
+ text=arc_state["base_text"],
160
+ arc_diagrams=analysis["arc_diagrams"]
161
+ )
162
+ if base_id:
163
+ arc_state["base_id"] = base_id
164
+ st.success(f"An谩lisis base guardado con ID: {base_id}")
165
+
166
+ except Exception as e:
167
+ st.error("Error procesando texto base")
168
+ logger.error(f"Error en an谩lisis base: {str(e)}")
169
+
170
+ # Mostrar el arco base, si existe
171
+ if arc_state["base_diagram"]:
172
+ st.markdown("<hr class='divider'>", unsafe_allow_html=True)
173
+ st.markdown("#### Diagrama de Arco (Texto Base)")
174
+ st.write(arc_state["base_diagram"], unsafe_allow_html=True)
175
+
176
+ # ------------------- PESTA脩A 2: Iteraciones -------------------------
177
+ with tabs[1]:
178
+ st.subheader("An谩lisis de Cambios / Iteraciones")
179
+
180
+ # Si no se ha analizado nada en la primera pesta帽a
181
+ if not arc_state["base_id"]:
182
+ st.info("Primero analiza un texto base en la pesta帽a anterior.")
183
+ return
184
+
185
+ # Mostrar el texto base como referencia, en modo solo lectura
186
+ st.text_area(
187
+ "Texto Base (solo lectura)",
188
+ value=arc_state["base_text"],
189
+ key="base_text_ref",
190
+ height=80,
191
+ disabled=True
192
+ )
193
+
194
+ # Texto de iteraci贸n
195
+ arc_state["iteration_text"] = st.text_area(
196
+ "Texto de Iteraci贸n",
197
+ value=arc_state["iteration_text"],
198
+ key="iteration_text_input",
199
+ height=120
200
+ )
201
+
202
+ # Bot贸n para analizar iteraci贸n
203
+ if st.button("Analizar Cambios", key="btn_analyze_iteration"):
204
+ if not arc_state["iteration_text"].strip():
205
+ st.warning("Ingrese texto de iteraci贸n.")
206
+ else:
207
+ try:
208
+ # Procesar con spaCy
209
+ doc_iter = nlp_models[lang_code](arc_state["iteration_text"])
210
+ iteration_arc_html = display_arc_diagram(doc_iter)
211
+ arc_state["iteration_diagram"] = iteration_arc_html
212
+
213
+ # Guardar en BD
214
+ iteration_analysis = perform_advanced_morphosyntactic_analysis(
215
+ arc_state["iteration_text"],
216
+ nlp_models[lang_code]
217
+ )
218
+ iteration_id = store_student_morphosyntax_iteration(
219
+ username=st.session_state.username,
220
+ base_id=arc_state["base_id"],
221
+ original_text=arc_state["base_text"],
222
+ iteration_text=arc_state["iteration_text"],
223
+ arc_diagrams=iteration_analysis["arc_diagrams"]
224
+ )
225
+ if iteration_id:
226
+ st.success(f"Iteraci贸n guardada con ID: {iteration_id}")
227
+
228
+ except Exception as e:
229
+ st.error("Error procesando iteraci贸n")
230
+ logger.error(f"Error en iteraci贸n: {str(e)}")
231
+
232
+ # Mostrar el arco de iteraci贸n, si existe
233
+ if arc_state["iteration_diagram"]:
234
+ st.markdown("<hr class='divider'>", unsafe_allow_html=True)
235
+ st.markdown("#### Diagrama de Arco (Iteraci贸n)")
236
+ st.write(arc_state["iteration_diagram"], unsafe_allow_html=True)
237
+
238
+ # Mostrar comparaci贸n (opcional)
239
+ if arc_state["base_diagram"] and arc_state["iteration_diagram"]:
240
+ st.markdown("<hr class='divider'>", unsafe_allow_html=True)
241
+ st.markdown("### Comparaci贸n de Diagrama Base vs. Iteraci贸n")
242
+ col_base, col_iter = st.columns(2)
243
+ with col_base:
244
+ st.markdown("**Diagrama Base**")
245
+ st.write(arc_state["base_diagram"], unsafe_allow_html=True)
246
+ with col_iter:
247
+ st.markdown("**Diagrama Iterado**")
248
+ st.write(arc_state["iteration_diagram"], unsafe_allow_html=True)