AIdeaText commited on
Commit
a694ee8
·
verified ·
1 Parent(s): b9f76a5

Upload 2 files

Browse files
modules/semantic/semantic_interface.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #modules/semantic/semantic_interface.py
2
+ import streamlit as st
3
+ from streamlit_float import *
4
+ from streamlit_antd_components import *
5
+ from streamlit.components.v1 import html
6
+ import spacy_streamlit
7
+ import io
8
+ from io import BytesIO
9
+ import base64
10
+ import matplotlib.pyplot as plt
11
+ import pandas as pd
12
+ import re
13
+ import logging
14
+
15
+ # Configuración del logger
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # Importaciones locales
19
+ from .semantic_process import (
20
+ process_semantic_input,
21
+ format_semantic_results
22
+ )
23
+
24
+ from ..utils.widget_utils import generate_unique_key
25
+ from ..database.semantic_mongo_db import store_student_semantic_result
26
+ from ..database.chat_mongo_db import store_chat_history, get_chat_history
27
+
28
+ # from ..database.semantic_export import export_user_interactions
29
+
30
+
31
+ ###############################
32
+
33
+ # En semantic_interface.py
34
+ def display_semantic_interface(lang_code, nlp_models, semantic_t):
35
+ try:
36
+ # 1. Inicializar el estado de la sesión
37
+ if 'semantic_state' not in st.session_state:
38
+ st.session_state.semantic_state = {
39
+ 'analysis_count': 0,
40
+ 'last_analysis': None,
41
+ 'current_file': None,
42
+ 'pending_analysis': False # Nuevo flag para controlar el análisis pendiente
43
+ }
44
+
45
+ # 2. Área de carga de archivo con mensaje informativo
46
+ st.info(semantic_t.get('initial_instruction',
47
+ 'Para comenzar un nuevo análisis semántico, cargue un archivo de texto (.txt)'))
48
+
49
+ uploaded_file = st.file_uploader(
50
+ semantic_t.get('semantic_file_uploader', 'Upload a text file for semantic analysis'),
51
+ type=['txt'],
52
+ key=f"semantic_file_uploader_{st.session_state.semantic_state['analysis_count']}"
53
+ )
54
+
55
+ # 2.1 Verificar si hay un archivo cargado y un análisis pendiente
56
+ if uploaded_file is not None and st.session_state.semantic_state.get('pending_analysis', False):
57
+ try:
58
+ with st.spinner(semantic_t.get('processing', 'Processing...')):
59
+ # Realizar análisis
60
+ text_content = uploaded_file.getvalue().decode('utf-8')
61
+
62
+ analysis_result = process_semantic_input(
63
+ text_content,
64
+ lang_code,
65
+ nlp_models,
66
+ semantic_t
67
+ )
68
+
69
+ if analysis_result['success']:
70
+ # Guardar resultado
71
+ st.session_state.semantic_result = analysis_result
72
+ st.session_state.semantic_state['analysis_count'] += 1
73
+ st.session_state.semantic_state['current_file'] = uploaded_file.name
74
+
75
+ # Guardar en base de datos
76
+ storage_success = store_student_semantic_result(
77
+ st.session_state.username,
78
+ text_content,
79
+ analysis_result['analysis']
80
+ )
81
+
82
+ if storage_success:
83
+ st.success(
84
+ semantic_t.get('analysis_complete',
85
+ 'Análisis completado y guardado. Para realizar un nuevo análisis, cargue otro archivo.')
86
+ )
87
+ else:
88
+ st.error(semantic_t.get('error_message', 'Error saving analysis'))
89
+ else:
90
+ st.error(analysis_result['message'])
91
+
92
+ # Restablecer el flag de análisis pendiente
93
+ st.session_state.semantic_state['pending_analysis'] = False
94
+
95
+ except Exception as e:
96
+ logger.error(f"Error en análisis semántico: {str(e)}")
97
+ st.error(semantic_t.get('error_processing', f'Error processing text: {str(e)}'))
98
+ # Restablecer el flag de análisis pendiente en caso de error
99
+ st.session_state.semantic_state['pending_analysis'] = False
100
+
101
+ # 3. Columnas para los botones y mensajes
102
+ col1, col2 = st.columns([1,4])
103
+
104
+ # 4. Botón de análisis
105
+ with col1:
106
+ analyze_button = st.button(
107
+ semantic_t.get('semantic_analyze_button', 'Analyze'),
108
+ key=f"semantic_analyze_button_{st.session_state.semantic_state['analysis_count']}",
109
+ type="primary",
110
+ icon="🔍",
111
+ disabled=uploaded_file is None,
112
+ use_container_width=True
113
+ )
114
+
115
+ # 5. Procesar análisis
116
+ if analyze_button and uploaded_file is not None:
117
+ # En lugar de realizar el análisis inmediatamente, establecer el flag
118
+ st.session_state.semantic_state['pending_analysis'] = True
119
+ # Forzar la recarga de la aplicación
120
+ st.rerun()
121
+
122
+ # 6. Mostrar resultados previos o mensaje inicial
123
+ elif 'semantic_result' in st.session_state and st.session_state.semantic_result is not None:
124
+ # Mostrar mensaje sobre el análisis actual
125
+ st.info(
126
+ semantic_t.get('current_analysis_message',
127
+ 'Mostrando análisis del archivo: {}. Para realizar un nuevo análisis, cargue otro archivo.'
128
+ ).format(st.session_state.semantic_state["current_file"])
129
+ )
130
+
131
+ display_semantic_results(
132
+ st.session_state.semantic_result,
133
+ lang_code,
134
+ semantic_t
135
+ )
136
+ else:
137
+ st.info(semantic_t.get('upload_prompt', 'Cargue un archivo para comenzar el análisis'))
138
+
139
+ except Exception as e:
140
+ logger.error(f"Error general en interfaz semántica: {str(e)}")
141
+ st.error(semantic_t.get('general_error', "Se produjo un error. Por favor, intente de nuevo."))
142
+
143
+
144
+ #######################################
145
+ def display_semantic_results(semantic_result, lang_code, semantic_t):
146
+ """
147
+ Muestra los resultados del análisis semántico de conceptos clave.
148
+ """
149
+ if semantic_result is None or not semantic_result['success']:
150
+ st.warning(semantic_t.get('no_results', 'No results available'))
151
+ return
152
+
153
+ analysis = semantic_result['analysis']
154
+
155
+ # Mostrar conceptos clave en formato horizontal
156
+ st.subheader(semantic_t.get('key_concepts', 'Key Concepts'))
157
+ if 'key_concepts' in analysis and analysis['key_concepts']:
158
+ # Crear tabla de conceptos
159
+ df = pd.DataFrame(
160
+ analysis['key_concepts'],
161
+ columns=[
162
+ semantic_t.get('concept', 'Concept'),
163
+ semantic_t.get('frequency', 'Frequency')
164
+ ]
165
+ )
166
+
167
+ # Convertir DataFrame a formato horizontal
168
+ st.write(
169
+ """
170
+ <style>
171
+ .concept-table {
172
+ display: flex;
173
+ flex-wrap: wrap;
174
+ gap: 10px;
175
+ margin-bottom: 20px;
176
+ }
177
+ .concept-item {
178
+ background-color: #f0f2f6;
179
+ border-radius: 5px;
180
+ padding: 8px 12px;
181
+ display: flex;
182
+ align-items: center;
183
+ gap: 8px;
184
+ }
185
+ .concept-name {
186
+ font-weight: bold;
187
+ }
188
+ .concept-freq {
189
+ color: #666;
190
+ font-size: 0.9em;
191
+ }
192
+ </style>
193
+ <div class="concept-table">
194
+ """ +
195
+ ''.join([
196
+ f'<div class="concept-item"><span class="concept-name">{concept}</span>'
197
+ f'<span class="concept-freq">({freq:.2f})</span></div>'
198
+ for concept, freq in df.values
199
+ ]) +
200
+ "</div>",
201
+ unsafe_allow_html=True
202
+ )
203
+ else:
204
+ st.info(semantic_t.get('no_concepts', 'No key concepts found'))
205
+
206
+ # Gráfico de conceptos
207
+ # st.subheader(semantic_t.get('concept_graph', 'Concepts Graph'))
208
+ #Colocar aquí el bloque de código
209
+ if 'concept_graph' in analysis and analysis['concept_graph'] is not None:
210
+ try:
211
+ # Container para el grafo con estilos mejorados
212
+ st.markdown(
213
+ """
214
+ <style>
215
+ .graph-container {
216
+ background-color: white;
217
+ border-radius: 10px;
218
+ padding: 20px;
219
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
220
+ margin: 10px 0;
221
+ }
222
+ .button-container {
223
+ display: flex;
224
+ gap: 10px;
225
+ margin: 10px 0;
226
+ }
227
+ </style>
228
+ """,
229
+ unsafe_allow_html=True
230
+ )
231
+ #Colocar aquí el bloque de código
232
+
233
+ with st.container():
234
+ st.markdown('<div class="graph-container">', unsafe_allow_html=True)
235
+
236
+ # Mostrar grafo
237
+ graph_bytes = analysis['concept_graph']
238
+ graph_base64 = base64.b64encode(graph_bytes).decode()
239
+ st.markdown(
240
+ f'<img src="data:image/png;base64,{graph_base64}" alt="Concept Graph" style="width:100%;"/>',
241
+ unsafe_allow_html=True
242
+ )
243
+
244
+ # Leyenda del grafo
245
+ #st.caption(semantic_t.get(
246
+ # 'graph_description',
247
+ # 'Visualización de relaciones entre conceptos clave identificados en el texto.'
248
+ #))
249
+
250
+ st.markdown('</div>', unsafe_allow_html=True)
251
+
252
+ # Expandible con la interpretación
253
+ with st.expander("📊 " + semantic_t.get('semantic_graph_interpretation', "Interpretación del gráfico semántico")):
254
+ st.markdown(f"""
255
+ - 🔀 {semantic_t.get('semantic_arrow_meaning', 'Las flechas indican la dirección de la relación entre conceptos')}
256
+ - 🎨 {semantic_t.get('semantic_color_meaning', 'Los colores más intensos indican conceptos más centrales en el texto')}
257
+ - ⭕ {semantic_t.get('semantic_size_meaning', 'El tamaño de los nodos representa la frecuencia del concepto')}
258
+ - ↔️ {semantic_t.get('semantic_thickness_meaning', 'El grosor de las líneas indica la fuerza de la conexión')}
259
+ """)
260
+
261
+ # Contenedor para botones
262
+ col1, col2 = st.columns([1,4])
263
+ with col1:
264
+ st.download_button(
265
+ label="📥 " + semantic_t.get('download_semantic_network_graph', "Descargar gráfico de red semántica"),
266
+ data=graph_bytes,
267
+ file_name="semantic_graph.png",
268
+ mime="image/png",
269
+ use_container_width=True
270
+ )
271
+
272
+ except Exception as e:
273
+ logger.error(f"Error displaying graph: {str(e)}")
274
+ st.error(semantic_t.get('graph_error', 'Error displaying the graph'))
275
+ else:
276
+ st.info(semantic_t.get('no_graph', 'No concept graph available'))
modules/semantic/semantic_process.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # modules/semantic/semantic_process.py
2
+ import streamlit as st
3
+ import matplotlib.pyplot as plt
4
+ import io
5
+ import base64
6
+ import logging
7
+
8
+ from ..text_analysis.semantic_analysis import (
9
+ perform_semantic_analysis,
10
+ identify_key_concepts,
11
+ create_concept_graph,
12
+ visualize_concept_graph
13
+ )
14
+ from ..database.semantic_mongo_db import store_student_semantic_result
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ def process_semantic_input(text, lang_code, nlp_models, t):
19
+ """
20
+ Procesa el texto ingresado para realizar el análisis semántico.
21
+ """
22
+ try:
23
+ logger.info(f"Iniciando análisis semántico para texto de {len(text)} caracteres")
24
+
25
+ # Realizar el análisis semántico
26
+ nlp = nlp_models[lang_code]
27
+ analysis_result = perform_semantic_analysis(text, nlp, lang_code)
28
+
29
+ if not analysis_result['success']:
30
+ return {
31
+ 'success': False,
32
+ 'message': analysis_result['error'],
33
+ 'analysis': None
34
+ }
35
+
36
+ logger.info("Análisis semántico completado. Guardando resultados...")
37
+
38
+ # Intentar guardar en la base de datos
39
+ try:
40
+ store_result = store_student_semantic_result(
41
+ st.session_state.username,
42
+ text,
43
+ analysis_result
44
+ )
45
+ if not store_result:
46
+ logger.warning("No se pudo guardar el análisis en la base de datos")
47
+ except Exception as db_error:
48
+ logger.error(f"Error al guardar en base de datos: {str(db_error)}")
49
+
50
+ # Devolver el resultado incluso si falla el guardado
51
+ return {
52
+ 'success': True,
53
+ 'message': t.get('success_message', 'Analysis completed successfully'),
54
+ 'analysis': {
55
+ 'key_concepts': analysis_result['key_concepts'],
56
+ 'concept_graph': analysis_result['concept_graph']
57
+ }
58
+ }
59
+
60
+ except Exception as e:
61
+ logger.error(f"Error en process_semantic_input: {str(e)}")
62
+ return {
63
+ 'success': False,
64
+ 'message': str(e),
65
+ 'analysis': None
66
+ }
67
+
68
+ def format_semantic_results(analysis_result, t):
69
+ """
70
+ Formatea los resultados del análisis para su visualización.
71
+ """
72
+ try:
73
+ if not analysis_result['success']:
74
+ return {
75
+ 'formatted_text': analysis_result['message'],
76
+ 'visualizations': None
77
+ }
78
+
79
+ formatted_sections = []
80
+ analysis = analysis_result['analysis']
81
+
82
+ # Formatear conceptos clave
83
+ if 'key_concepts' in analysis:
84
+ concepts_section = [f"### {t.get('key_concepts', 'Key Concepts')}"]
85
+ concepts_section.extend([
86
+ f"- {concept}: {frequency:.2f}"
87
+ for concept, frequency in analysis['key_concepts']
88
+ ])
89
+ formatted_sections.append('\n'.join(concepts_section))
90
+
91
+ return {
92
+ 'formatted_text': '\n\n'.join(formatted_sections),
93
+ 'visualizations': {
94
+ 'concept_graph': analysis.get('concept_graph')
95
+ }
96
+ }
97
+
98
+ except Exception as e:
99
+ logger.error(f"Error en format_semantic_results: {str(e)}")
100
+ return {
101
+ 'formatted_text': str(e),
102
+ 'visualizations': None
103
+ }
104
+
105
+ __all__ = [
106
+ 'process_semantic_input',
107
+ 'format_semantic_results'
108
+ ]