AIdeaText commited on
Commit
0bacaa5
·
verified ·
1 Parent(s): 16f6b51

Update modules/discourse/discourse_interface.py

Browse files
Files changed (1) hide show
  1. modules/discourse/discourse_interface.py +127 -165
modules/discourse/discourse_interface.py CHANGED
@@ -5,6 +5,8 @@ import pandas as pd
5
  import matplotlib.pyplot as plt
6
  import plotly.graph_objects as go
7
  import logging
 
 
8
  from ..utils.widget_utils import generate_unique_key
9
  from .discourse_process import perform_discourse_analysis
10
  from ..database.chat_mongo_db import store_chat_history
@@ -133,186 +135,146 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
133
  def display_discourse_results(result, lang_code, discourse_t):
134
  """
135
  Muestra los resultados del análisis del discurso
 
 
 
 
 
136
  """
137
  if not result.get('success'):
138
  st.warning(discourse_t.get('no_results', 'No hay resultados disponibles'))
139
  return
140
 
141
- # Estilo CSS
142
  st.markdown("""
143
- <style>
144
- .concepts-container {
145
- display: flex;
146
- flex-wrap: nowrap;
147
- gap: 8px;
148
- padding: 12px;
149
- background-color: #f8f9fa;
150
- border-radius: 8px;
151
- overflow-x: auto;
152
- margin-bottom: 15px;
153
- white-space: nowrap;
154
- }
155
- .concept-item {
156
- background-color: white;
157
- border-radius: 4px;
158
- padding: 6px 10px;
159
- display: inline-flex;
160
- align-items: center;
161
- gap: 4px;
162
- box-shadow: 0 1px 2px rgba(0,0,0,0.1);
163
- flex-shrink: 0;
164
- }
165
- .concept-name {
166
- font-weight: 500;
167
- color: #1f2937;
168
- font-size: 0.85em;
169
- }
170
- .concept-freq {
171
- color: #6b7280;
172
- font-size: 0.75em;
173
- }
174
- .graph-container {
175
- background-color: white;
176
- padding: 15px;
177
- border-radius: 8px;
178
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
179
- margin-top: 10px;
180
- }
181
- </style>
182
  """, unsafe_allow_html=True)
183
 
 
184
  col1, col2 = st.columns(2)
185
-
186
  # Documento 1
187
  with col1:
188
- st.subheader(discourse_t.get('doc1_title', 'Documento 1'))
189
- st.markdown(discourse_t.get('key_concepts', 'Conceptos Clave'))
190
  if 'key_concepts1' in result:
191
- concepts_html = f"""
192
- <div class="concepts-container">
193
- {''.join([
194
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
195
- f'<span class="concept-freq">({freq:.2f})</span></div>'
196
- for concept, freq in result['key_concepts1']
197
- ])}
198
- </div>
199
- """
200
- st.markdown(concepts_html, unsafe_allow_html=True)
201
-
202
- # Verificar el tipo de graph1 de manera más robusta
203
- if 'graph1' in result:
204
- st.markdown('<div class="graph-container">', unsafe_allow_html=True)
205
-
206
- # Más información para depuración
207
- graph_type = type(result['graph1']).__name__
208
- graph_size = len(result['graph1']) if isinstance(result['graph1'], bytes) else "N/A"
209
- logger.info(f"Tipo de graph1: {graph_type}, Tamaño: {graph_size}")
210
-
211
- if isinstance(result['graph1'], bytes) and len(result['graph1']) > 0:
212
- # Es bytes válidos
213
- st.image(result['graph1'])
214
- elif isinstance(result['graph1'], plt.Figure):
215
- # Es una figura de matplotlib
216
- st.pyplot(result['graph1'])
217
- elif result['graph1'] is None:
218
- # Es None
219
- st.warning("Gráfico no disponible")
220
- else:
221
- # Otro tipo o bytes vacíos
222
- st.warning(f"Formato de gráfico no reconocido: {graph_type}")
223
-
224
- # Botones y controles
225
- button_col1, spacer_col1 = st.columns([1,4])
226
- with button_col1:
227
- if 'graph1_bytes' in result:
228
- st.download_button(
229
- label="📥 " + discourse_t.get('download_graph', "Download"),
230
- data=result['graph1_bytes'],
231
- file_name="discourse_graph1.png",
232
- mime="image/png",
233
- use_container_width=True
234
- )
235
-
236
- # Interpretación como texto normal sin expander
237
- st.markdown("**📊 Interpretación del grafo:**")
238
- st.markdown("""
239
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
240
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
241
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
242
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
243
- """)
244
-
245
- st.markdown('</div>', unsafe_allow_html=True)
246
- else:
247
- st.warning(discourse_t.get('graph_not_available', 'Gráfico no disponible'))
248
- else:
249
- st.warning(discourse_t.get('concepts_not_available', 'Conceptos no disponibles'))
250
 
251
  # Documento 2
252
  with col2:
253
- st.subheader(discourse_t.get('doc2_title', 'Documento 2'))
254
- st.markdown(discourse_t.get('key_concepts', 'Conceptos Clave'))
255
  if 'key_concepts2' in result:
256
- concepts_html = f"""
257
- <div class="concepts-container">
258
- {''.join([
259
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
260
- f'<span class="concept-freq">({freq:.2f})</span></div>'
261
- for concept, freq in result['key_concepts2']
262
- ])}
263
- </div>
264
- """
265
- st.markdown(concepts_html, unsafe_allow_html=True)
266
-
267
- # Verificar el tipo de graph1 de manera más robusta
268
- if 'graph1' in result:
269
- st.markdown('<div class="graph-container">', unsafe_allow_html=True)
270
-
271
- # Más información para depuración
272
- graph_type = type(result['graph2']).__name__
273
- graph_size = len(result['graph2']) if isinstance(result['graph2'], bytes) else "N/A"
274
- logger.info(f"Tipo de graph2: {graph_type}, Tamaño: {graph_size}")
275
-
276
- if isinstance(result['graph2'], bytes) and len(result['graph2']) > 0:
277
- # Es bytes válidos
278
- st.image(result['graph2'])
279
- elif isinstance(result['graph2'], plt.Figure):
280
- # Es una figura de matplotlib
281
- st.pyplot(result['graph2'])
282
- elif result['graph2'] is None:
283
- # Es None
284
- st.warning("Gráfico no disponible")
285
- else:
286
- # Otro tipo o bytes vacíos
287
- st.warning(f"Formato de gráfico no reconocido: {graph_type}")
288
-
289
- # Botones y controles
290
- button_col2, spacer_col2 = st.columns([1,4])
291
- with button_col2:
292
- if 'graph2_bytes' in result:
293
- st.download_button(
294
- label="📥 " + discourse_t.get('download_graph', "Download"),
295
- data=result['graph2_bytes'],
296
- file_name="discourse_graph2.png",
297
- mime="image/png",
298
- use_container_width=True
299
- )
300
 
301
- # Interpretación como texto normal sin expander
302
- st.markdown("**📊 Interpretación del grafo:**")
303
- st.markdown("""
304
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
305
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
306
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
307
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
308
- """)
309
-
310
- st.markdown('</div>', unsafe_allow_html=True)
311
- else:
312
- st.warning(discourse_t.get('graph_not_available', 'Gráfico no disponible'))
313
- else:
314
- st.warning(discourse_t.get('concepts_not_available', 'Conceptos no disponibles'))
 
 
 
315
 
316
- # Nota informativa sobre la comparación
317
- st.info(discourse_t.get('comparison_note',
318
- 'La funcionalidad de comparación detallada estará disponible en una próxima actualización.'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import matplotlib.pyplot as plt
6
  import plotly.graph_objects as go
7
  import logging
8
+ import io # <-- Añade esta importación
9
+
10
  from ..utils.widget_utils import generate_unique_key
11
  from .discourse_process import perform_discourse_analysis
12
  from ..database.chat_mongo_db import store_chat_history
 
135
  def display_discourse_results(result, lang_code, discourse_t):
136
  """
137
  Muestra los resultados del análisis del discurso
138
+ Versión actualizada con:
139
+ - Un solo expander para interpretación
140
+ - Botón de descarga combinado
141
+ - Sin mensaje de "próxima actualización"
142
+ - Estilo consistente con semantic_interface
143
  """
144
  if not result.get('success'):
145
  st.warning(discourse_t.get('no_results', 'No hay resultados disponibles'))
146
  return
147
 
148
+ # Estilo CSS unificado
149
  st.markdown("""
150
+ <style>
151
+ .concept-table {
152
+ display: flex;
153
+ flex-wrap: wrap;
154
+ gap: 10px;
155
+ margin-bottom: 20px;
156
+ }
157
+ .concept-item {
158
+ background-color: #f0f2f6;
159
+ border-radius: 5px;
160
+ padding: 8px 12px;
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 8px;
164
+ }
165
+ .concept-name {
166
+ font-weight: bold;
167
+ }
168
+ .concept-freq {
169
+ color: #666;
170
+ font-size: 0.9em;
171
+ }
172
+ .download-btn-container {
173
+ display: flex;
174
+ justify-content: center;
175
+ margin-top: 15px;
176
+ }
177
+ </style>
 
 
 
 
 
 
 
 
 
 
 
178
  """, unsafe_allow_html=True)
179
 
180
+ # Mostrar conceptos clave para ambos documentos
181
  col1, col2 = st.columns(2)
182
+
183
  # Documento 1
184
  with col1:
185
+ st.subheader(discourse_t.get('compare_doc1_title', 'Documento 1'))
 
186
  if 'key_concepts1' in result:
187
+ df1 = pd.DataFrame(
188
+ result['key_concepts1'],
189
+ columns=[discourse_t.get('concept', 'Concepto'), discourse_t.get('frequency', 'Frecuencia')]
190
+ )
191
+ st.write(
192
+ '<div class="concept-table">' +
193
+ ''.join([
194
+ f'<div class="concept-item"><span class="concept-name">{concept}</span>'
195
+ f'<span class="concept-freq">({freq:.2f})</span></div>'
196
+ for concept, freq in df1.values
197
+ ]) + "</div>",
198
+ unsafe_allow_html=True
199
+ )
200
+
201
+ if 'graph1' in result and result['graph1']:
202
+ st.image(result['graph1'], use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
  # Documento 2
205
  with col2:
206
+ st.subheader(discourse_t.get('compare_doc2_title', 'Documento 2'))
 
207
  if 'key_concepts2' in result:
208
+ df2 = pd.DataFrame(
209
+ result['key_concepts2'],
210
+ columns=[discourse_t.get('concept', 'Concepto'), discourse_t.get('frequency', 'Frecuencia')]
211
+ )
212
+ st.write(
213
+ '<div class="concept-table">' +
214
+ ''.join([
215
+ f'<div class="concept-item"><span class="concept-name">{concept}</span>'
216
+ f'<span class="concept-freq">({freq:.2f})</span></div>'
217
+ for concept, freq in df2.values
218
+ ]) + "</div>",
219
+ unsafe_allow_html=True
220
+ )
221
+
222
+ if 'graph2' in result and result['graph2']:
223
+ st.image(result['graph2'], use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
+ # Sección unificada de interpretación (como semantic_interface)
226
+ st.markdown("""
227
+ <style>
228
+ div[data-testid="stExpander"] div[role="button"] p {
229
+ text-align: center;
230
+ font-weight: bold;
231
+ }
232
+ </style>
233
+ """, unsafe_allow_html=True)
234
+
235
+ with st.expander("📊 " + discourse_t.get('semantic_graph_interpretation', "Interpretación de los gráficos")):
236
+ st.markdown(f"""
237
+ - 🔀 {discourse_t.get('compare_arrow_meaning', 'Las flechas indican la dirección de la relación entre conceptos')}
238
+ - 🎨 {discourse_t.get('compare_color_meaning', 'Los colores más intensos indican conceptos más centrales en el texto')}
239
+ - ⭕ {discourse_t.get('compare_size_meaning', 'El tamaño de los nodos representa la frecuencia del concepto')}
240
+ - ↔️ {discourse_t.get('compare_thickness_meaning', 'El grosor de las líneas indica la fuerza de la conexión')}
241
+ """)
242
 
243
+ # Botón de descarga combinado (para ambas imágenes)
244
+ if 'graph1' in result and 'graph2' in result and result['graph1'] and result['graph2']:
245
+ # Crear figura combinada
246
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 10))
247
+
248
+ # Mostrar primer gráfico
249
+ if isinstance(result['graph1'], bytes):
250
+ img1 = plt.imread(io.BytesIO(result['graph1']))
251
+ ax1.imshow(img1)
252
+ ax1.axis('off')
253
+ ax1.set_title(discourse_t.get('compare_doc1_title', 'Documento 1'))
254
+
255
+ # Mostrar segundo gráfico
256
+ if isinstance(result['graph2'], bytes):
257
+ img2 = plt.imread(io.BytesIO(result['graph2']))
258
+ ax2.imshow(img2)
259
+ ax2.axis('off')
260
+ ax2.set_title(discourse_t.get('compare_doc2_title', 'Documento 2'))
261
+
262
+ plt.tight_layout()
263
+
264
+ # Convertir a bytes
265
+ buf = io.BytesIO()
266
+ plt.savefig(buf, format='png', dpi=150, bbox_inches='tight')
267
+ buf.seek(0)
268
+
269
+ # Botón de descarga
270
+ st.markdown('<div class="download-btn-container">', unsafe_allow_html=True)
271
+ st.download_button(
272
+ label="📥 " + discourse_t.get('download_both_graphs', "Descargar ambos gráficos"),
273
+ data=buf,
274
+ file_name="comparison_graphs.png",
275
+ mime="image/png",
276
+ use_container_width=True
277
+ )
278
+ st.markdown('</div>', unsafe_allow_html=True)
279
+
280
+ plt.close()