AIdeaText commited on
Commit
2f9e2e5
·
verified ·
1 Parent(s): 292a07f

Update modules/discourse/discourse_interface.py

Browse files
modules/discourse/discourse_interface.py CHANGED
@@ -10,16 +10,16 @@ from ..database.chat_mongo_db import store_chat_history
10
  from ..database.discourse_mongo_db import store_student_discourse_result
11
 
12
  logger = logging.getLogger(__name__)
13
- #############################################################################################
14
 
15
  def display_discourse_interface(lang_code, nlp_models, discourse_t):
16
  """
17
  Interfaz para el análisis del discurso
 
 
 
 
18
  """
19
  try:
20
- # Activar estado
21
- st.session_state.tab_states['discourse_active'] = True
22
-
23
  # 1. Inicializar estado si no existe
24
  if 'discourse_state' not in st.session_state:
25
  st.session_state.discourse_state = {
@@ -67,9 +67,11 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
67
  if analyze_button and uploaded_file1 and uploaded_file2:
68
  try:
69
  with st.spinner(discourse_t.get('processing', 'Procesando análisis...')):
 
70
  text1 = uploaded_file1.getvalue().decode('utf-8')
71
  text2 = uploaded_file2.getvalue().decode('utf-8')
72
 
 
73
  result = perform_discourse_analysis(
74
  text1,
75
  text2,
@@ -78,6 +80,7 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
78
  )
79
 
80
  if result['success']:
 
81
  st.session_state.discourse_result = result
82
  st.session_state.discourse_state['analysis_count'] += 1
83
  st.session_state.discourse_state['current_files'] = (
@@ -85,6 +88,7 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
85
  uploaded_file2.name
86
  )
87
 
 
88
  if store_student_discourse_result(
89
  st.session_state.username,
90
  text1,
@@ -92,6 +96,8 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
92
  result
93
  ):
94
  st.success(discourse_t.get('success_message', 'Análisis guardado correctamente'))
 
 
95
  display_discourse_results(result, lang_code, discourse_t)
96
  else:
97
  st.error(discourse_t.get('error_message', 'Error al guardar el análisis'))
@@ -99,7 +105,6 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
99
  st.error(discourse_t.get('analysis_error', 'Error en el análisis'))
100
 
101
  except Exception as e:
102
- st.session_state.tab_states['discourse_active'] = False
103
  logger.error(f"Error en análisis del discurso: {str(e)}")
104
  st.error(discourse_t.get('error_processing', f'Error procesando archivos: {str(e)}'))
105
 
@@ -117,69 +122,17 @@ def display_discourse_interface(lang_code, nlp_models, discourse_t):
117
  )
118
 
119
  except Exception as e:
120
- st.session_state.tab_states['discourse_active'] = False
121
- logger.error(f"Error general en interfaz discursiva: {str(e)}")
122
- st.error(discourse_t.get('general_error', "Se produjo un error. Por favor, intente de nuevo."))
123
-
124
- ##########################################################################################
125
 
126
  def display_discourse_results(result, lang_code, discourse_t):
127
  """
128
- Muestra los resultados del análisis del discurso con conceptos en formato horizontal
129
- y botones de control consistentes
130
  """
131
  if not result.get('success'):
132
  st.warning(discourse_t.get('no_results', 'No hay resultados disponibles'))
133
  return
134
 
135
- # Estilo CSS unificado
136
- st.markdown("""
137
- <style>
138
- .concepts-container {
139
- display: flex;
140
- flex-wrap: nowrap;
141
- gap: 8px;
142
- padding: 12px;
143
- background-color: #f8f9fa;
144
- border-radius: 8px 8px 0 0;
145
- overflow-x: auto;
146
- margin-bottom: 0;
147
- white-space: nowrap;
148
- }
149
- .concept-item {
150
- background-color: white;
151
- border-radius: 4px;
152
- padding: 6px 10px;
153
- display: inline-flex;
154
- align-items: center;
155
- gap: 4px;
156
- box-shadow: 0 1px 2px rgba(0,0,0,0.1);
157
- flex-shrink: 0;
158
- }
159
- .concept-name {
160
- font-weight: 500;
161
- color: #1f2937;
162
- font-size: 0.85em;
163
- }
164
- .concept-freq {
165
- color: #6b7280;
166
- font-size: 0.75em;
167
- }
168
- .graph-container {
169
- background-color: white;
170
- border-radius: 0 0 8px 8px;
171
- padding: 20px;
172
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
173
- margin-top: 0;
174
- }
175
- .controls-container {
176
- display: flex;
177
- gap: 10px;
178
- margin-top: 10px;
179
- }
180
- </style>
181
- """, unsafe_allow_html=True)
182
-
183
  col1, col2 = st.columns(2)
184
 
185
  # Documento 1
@@ -187,42 +140,12 @@ def display_discourse_results(result, lang_code, discourse_t):
187
  with st.expander(discourse_t.get('doc1_title', 'Documento 1'), expanded=True):
188
  st.subheader(discourse_t.get('key_concepts', 'Conceptos Clave'))
189
  if 'key_concepts1' in result:
190
- concepts_html = f"""
191
- <div class="concepts-container">
192
- {''.join([
193
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
194
- f'<span class="concept-freq">({freq:.2f})</span></div>'
195
- for concept, freq in result['key_concepts1']
196
- ])}
197
- </div>
198
- """
199
- st.markdown(concepts_html, unsafe_allow_html=True)
200
 
201
  if 'graph1' in result:
202
- with st.container():
203
- st.markdown('<div class="graph-container">', unsafe_allow_html=True)
204
- st.pyplot(result['graph1'])
205
-
206
- # Añadir botones de control para el grafo 1
207
- button_col1, spacer_col1 = st.columns([1,4])
208
- with button_col1:
209
- st.download_button(
210
- label="📥 " + discourse_t.get('download_graph', "Download"),
211
- data=result['graph1_bytes'] if 'graph1_bytes' in result else None,
212
- file_name="discourse_graph1.png",
213
- mime="image/png",
214
- use_container_width=True
215
- )
216
-
217
- with st.expander("📊 " + discourse_t.get('graph_help', "Graph Interpretation")):
218
- st.markdown("""
219
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
220
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
221
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
222
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
223
- """)
224
-
225
- st.markdown('</div>', unsafe_allow_html=True)
226
  else:
227
  st.warning(discourse_t.get('graph_not_available', 'Gráfico no disponible'))
228
  else:
@@ -233,42 +156,12 @@ def display_discourse_results(result, lang_code, discourse_t):
233
  with st.expander(discourse_t.get('doc2_title', 'Documento 2'), expanded=True):
234
  st.subheader(discourse_t.get('key_concepts', 'Conceptos Clave'))
235
  if 'key_concepts2' in result:
236
- concepts_html = f"""
237
- <div class="concepts-container">
238
- {''.join([
239
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
240
- f'<span class="concept-freq">({freq:.2f})</span></div>'
241
- for concept, freq in result['key_concepts2']
242
- ])}
243
- </div>
244
- """
245
- st.markdown(concepts_html, unsafe_allow_html=True)
246
 
247
  if 'graph2' in result:
248
- with st.container():
249
- st.markdown('<div class="graph-container">', unsafe_allow_html=True)
250
- st.pyplot(result['graph2'])
251
-
252
- # Añadir botones de control para el grafo 2
253
- button_col2, spacer_col2 = st.columns([1,4])
254
- with button_col2:
255
- st.download_button(
256
- label="📥 " + discourse_t.get('download_graph', "Download"),
257
- data=result['graph2_bytes'] if 'graph2_bytes' in result else None,
258
- file_name="discourse_graph2.png",
259
- mime="image/png",
260
- use_container_width=True
261
- )
262
-
263
- with st.expander("📊 " + discourse_t.get('graph_help', "Graph Interpretation")):
264
- st.markdown("""
265
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
266
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
267
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
268
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
269
- """)
270
-
271
- st.markdown('</div>', unsafe_allow_html=True)
272
  else:
273
  st.warning(discourse_t.get('graph_not_available', 'Gráfico no disponible'))
274
  else:
@@ -276,4 +169,4 @@ def display_discourse_results(result, lang_code, discourse_t):
276
 
277
  # Nota informativa sobre la comparación
278
  st.info(discourse_t.get('comparison_note',
279
- 'La funcionalidad de comparación detallada estará disponible en una próxima actualización.'))
 
10
  from ..database.discourse_mongo_db import store_student_discourse_result
11
 
12
  logger = logging.getLogger(__name__)
 
13
 
14
  def display_discourse_interface(lang_code, nlp_models, discourse_t):
15
  """
16
  Interfaz para el análisis del discurso
17
+ Args:
18
+ lang_code: Código del idioma actual
19
+ nlp_models: Modelos de spaCy cargados
20
+ discourse_t: Diccionario de traducciones
21
  """
22
  try:
 
 
 
23
  # 1. Inicializar estado si no existe
24
  if 'discourse_state' not in st.session_state:
25
  st.session_state.discourse_state = {
 
67
  if analyze_button and uploaded_file1 and uploaded_file2:
68
  try:
69
  with st.spinner(discourse_t.get('processing', 'Procesando análisis...')):
70
+ # Leer contenido de archivos
71
  text1 = uploaded_file1.getvalue().decode('utf-8')
72
  text2 = uploaded_file2.getvalue().decode('utf-8')
73
 
74
+ # Realizar análisis
75
  result = perform_discourse_analysis(
76
  text1,
77
  text2,
 
80
  )
81
 
82
  if result['success']:
83
+ # Guardar estado
84
  st.session_state.discourse_result = result
85
  st.session_state.discourse_state['analysis_count'] += 1
86
  st.session_state.discourse_state['current_files'] = (
 
88
  uploaded_file2.name
89
  )
90
 
91
+ # Guardar en base de datos
92
  if store_student_discourse_result(
93
  st.session_state.username,
94
  text1,
 
96
  result
97
  ):
98
  st.success(discourse_t.get('success_message', 'Análisis guardado correctamente'))
99
+
100
+ # Mostrar resultados
101
  display_discourse_results(result, lang_code, discourse_t)
102
  else:
103
  st.error(discourse_t.get('error_message', 'Error al guardar el análisis'))
 
105
  st.error(discourse_t.get('analysis_error', 'Error en el análisis'))
106
 
107
  except Exception as e:
 
108
  logger.error(f"Error en análisis del discurso: {str(e)}")
109
  st.error(discourse_t.get('error_processing', f'Error procesando archivos: {str(e)}'))
110
 
 
122
  )
123
 
124
  except Exception as e:
125
+ logger.error(f"Error general en interfaz del discurso: {str(e)}")
126
+ st.error(discourse_t.get('general_error', 'Se produjo un error. Por favor, intente de nuevo.'))
 
 
 
127
 
128
  def display_discourse_results(result, lang_code, discourse_t):
129
  """
130
+ Muestra los resultados del análisis del discurso
 
131
  """
132
  if not result.get('success'):
133
  st.warning(discourse_t.get('no_results', 'No hay resultados disponibles'))
134
  return
135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  col1, col2 = st.columns(2)
137
 
138
  # Documento 1
 
140
  with st.expander(discourse_t.get('doc1_title', 'Documento 1'), expanded=True):
141
  st.subheader(discourse_t.get('key_concepts', 'Conceptos Clave'))
142
  if 'key_concepts1' in result:
143
+ df1 = pd.DataFrame(result['key_concepts1'], columns=['Concepto', 'Frecuencia'])
144
+ df1['Frecuencia'] = df1['Frecuencia'].round(2)
145
+ st.table(df1)
 
 
 
 
 
 
 
146
 
147
  if 'graph1' in result:
148
+ st.pyplot(result['graph1'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  else:
150
  st.warning(discourse_t.get('graph_not_available', 'Gráfico no disponible'))
151
  else:
 
156
  with st.expander(discourse_t.get('doc2_title', 'Documento 2'), expanded=True):
157
  st.subheader(discourse_t.get('key_concepts', 'Conceptos Clave'))
158
  if 'key_concepts2' in result:
159
+ df2 = pd.DataFrame(result['key_concepts2'], columns=['Concepto', 'Frecuencia'])
160
+ df2['Frecuencia'] = df2['Frecuencia'].round(2)
161
+ st.table(df2)
 
 
 
 
 
 
 
162
 
163
  if 'graph2' in result:
164
+ st.pyplot(result['graph2'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  else:
166
  st.warning(discourse_t.get('graph_not_available', 'Gráfico no disponible'))
167
  else:
 
169
 
170
  # Nota informativa sobre la comparación
171
  st.info(discourse_t.get('comparison_note',
172
+ 'La funcionalidad de comparación detallada estará disponible en una próxima actualización.'))