AIdeaText commited on
Commit
6f8aff2
·
verified ·
1 Parent(s): 603ce54

Create semantic_live_interface.py

Browse files
modules/semantic/semantic_live_interface.py CHANGED
@@ -1,197 +1,140 @@
1
- # modules/semantic/semantic_live_interface.py
2
- import streamlit as st
3
- from streamlit_float import *
4
- from streamlit_antd_components import *
5
- import pandas as pd
6
- import logging
7
-
8
- # Configuración del logger
9
- logger = logging.getLogger(__name__)
10
-
11
- # Importaciones locales
12
- from .semantic_process import (
13
- process_semantic_input,
14
- format_semantic_results
15
- )
16
-
17
- from ..utils.widget_utils import generate_unique_key
18
- from ..database.semantic_mongo_db import store_student_semantic_result
19
- from ..database.chat_mongo_db import store_chat_history, get_chat_history
20
-
21
- def display_semantic_live_interface(lang_code, nlp_models, semantic_t):
22
- """
23
- Interfaz para el análisis semántico en vivo con proporciones de columna ajustadas
24
- """
25
- try:
26
- # 1. Inicializar el estado de la sesión de manera más robusta
27
- if 'semantic_live_state' not in st.session_state:
28
- st.session_state.semantic_live_state = {
29
- 'analysis_count': 0,
30
- 'current_text': '',
31
- 'last_result': None,
32
- 'text_changed': False
33
- }
34
-
35
- # 2. Función para manejar cambios en el texto
36
- def on_text_change():
37
- current_text = st.session_state.semantic_live_text
38
- st.session_state.semantic_live_state['current_text'] = current_text
39
- st.session_state.semantic_live_state['text_changed'] = True
40
-
41
- # 3. Crear columnas con nueva proporción (1:3)
42
- input_col, result_col = st.columns([1, 3])
43
-
44
- # Columna izquierda: Entrada de texto
45
- with input_col:
46
- st.subheader(semantic_t.get('enter_text', 'Ingrese su texto'))
47
-
48
- # Área de texto con manejo de eventos
49
- text_input = st.text_area(
50
- semantic_t.get('text_input_label', 'Escriba o pegue su texto aquí'),
51
- height=500,
52
- key="semantic_live_text",
53
- value=st.session_state.semantic_live_state.get('current_text', ''),
54
- on_change=on_text_change,
55
- label_visibility="collapsed" # Oculta el label para mayor estabilidad
56
- )
57
-
58
- # Botón de análisis y procesamiento
59
- analyze_button = st.button(
60
- semantic_t.get('analyze_button', 'Analizar'),
61
- key="semantic_live_analyze",
62
- type="primary",
63
- icon="🔍",
64
- disabled=not text_input,
65
- use_container_width=True
66
- )
67
-
68
- if analyze_button and text_input:
69
- try:
70
- with st.spinner(semantic_t.get('processing', 'Procesando...')):
71
- analysis_result = process_semantic_input(
72
- text_input,
73
- lang_code,
74
- nlp_models,
75
- semantic_t
76
- )
77
-
78
- if analysis_result['success']:
79
- st.session_state.semantic_live_state['last_result'] = analysis_result
80
- st.session_state.semantic_live_state['analysis_count'] += 1
81
- st.session_state.semantic_live_state['text_changed'] = False
82
-
83
- store_student_semantic_result(
84
- st.session_state.username,
85
- text_input,
86
- analysis_result['analysis']
87
- )
88
- else:
89
- st.error(analysis_result.get('message', 'Error en el análisis'))
90
-
91
- except Exception as e:
92
- logger.error(f"Error en análisis: {str(e)}")
93
- st.error(semantic_t.get('error_processing', 'Error al procesar el texto'))
94
-
95
- # Columna derecha: Visualización de resultados
96
- with result_col:
97
- st.subheader(semantic_t.get('live_results', 'Resultados en vivo'))
98
-
99
- if 'last_result' in st.session_state.semantic_live_state and \
100
- st.session_state.semantic_live_state['last_result'] is not None:
101
-
102
- analysis = st.session_state.semantic_live_state['last_result']['analysis']
103
-
104
- if 'key_concepts' in analysis and analysis['key_concepts'] and \
105
- 'concept_graph' in analysis and analysis['concept_graph'] is not None:
106
-
107
- st.markdown("""
108
- <style>
109
- .unified-container {
110
- background-color: white;
111
- border-radius: 10px;
112
- overflow: hidden;
113
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
114
- width: 100%;
115
- margin-bottom: 1rem;
116
- }
117
- .concept-table {
118
- display: flex;
119
- flex-wrap: nowrap; /* Evita el wrap */
120
- gap: 6px; /* Reducido el gap */
121
- padding: 10px;
122
- background-color: #f8f9fa;
123
- overflow-x: auto; /* Permite scroll horizontal si es necesario */
124
- white-space: nowrap; /* Mantiene todo en una línea */
125
- }
126
- .concept-item {
127
- background-color: white;
128
- border-radius: 4px;
129
- padding: 4px 8px; /* Padding reducido */
130
- display: inline-flex; /* Cambiado a inline-flex */
131
- align-items: center;
132
- gap: 4px; /* Gap reducido */
133
- box-shadow: 0 1px 2px rgba(0,0,0,0.1);
134
- flex-shrink: 0; /* Evita que los items se encojan */
135
- }
136
- .concept-name {
137
- font-weight: 500;
138
- color: #1f2937;
139
- font-size: 0.8em; /* Tamaño de fuente reducido */
140
- }
141
- .concept-freq {
142
- color: #6b7280;
143
- font-size: 0.75em; /* Tamaño de fuente reducido */
144
- }
145
- .graph-section {
146
- padding: 20px;
147
- background-color: white;
148
- }
149
- </style>
150
- """, unsafe_allow_html=True)
151
-
152
- with st.container():
153
- # Conceptos en una sola línea
154
- concepts_html = """
155
- <div class="unified-container">
156
- <div class="concept-table">
157
- """
158
- concepts_html += ''.join(
159
- f'<div class="concept-item"><span class="concept-name">{concept}</span>'
160
- f'<span class="concept-freq">({freq:.2f})</span></div>'
161
- for concept, freq in analysis['key_concepts']
162
- )
163
- concepts_html += "</div></div>"
164
- st.markdown(concepts_html, unsafe_allow_html=True)
165
-
166
- # Grafo
167
- if 'concept_graph' in analysis and analysis['concept_graph'] is not None:
168
- st.image(
169
- analysis['concept_graph'],
170
- use_container_width=True
171
- )
172
-
173
- # Botones y controles
174
- button_col, spacer_col = st.columns([1,5])
175
- with button_col:
176
- st.download_button(
177
- label="📥 " + semantic_t.get('download_graph', "Download"),
178
- data=analysis['concept_graph'],
179
- file_name="semantic_live_graph.png",
180
- mime="image/png",
181
- use_container_width=True
182
- )
183
-
184
- with st.expander("📊 " + semantic_t.get('graph_help', "Graph Interpretation")):
185
- st.markdown("""
186
- - 🔀 Las flechas indican la dirección de la relación entre conceptos
187
- - 🎨 Los colores más intensos indican conceptos más centrales en el texto
188
- - ⭕ El tamaño de los nodos representa la frecuencia del concepto
189
- - ↔️ El grosor de las líneas indica la fuerza de la conexión
190
- """)
191
- else:
192
- st.info(semantic_t.get('no_graph', 'No hay datos para mostrar'))
193
-
194
- except Exception as e:
195
- logger.error(f"Error general en interfaz semántica en vivo: {str(e)}")
196
- st.error(semantic_t.get('general_error', "Se produjo un error. Por favor, intente de nuevo."))
197
-
 
1
+ # modules/semantic/semantic_live_interface.py
2
+ import streamlit as st
3
+ import logging
4
+ from datetime import datetime, timezone
5
+
6
+ # Configuración del logger
7
+ logger = logging.getLogger(__name__)
8
+
9
+ # Importaciones locales
10
+ from .semantic_process import process_semantic_input
11
+ from ..database.semantic_mongo_live_db import store_student_semantic_live_result
12
+
13
+ def display_semantic_live_interface(lang_code, nlp_models, semantic_t):
14
+ """
15
+ Interfaz para el análisis semántico en vivo con texto directo
16
+ """
17
+ try:
18
+ # 1. Inicializar el estado de la sesión
19
+ if 'semantic_live_state' not in st.session_state:
20
+ st.session_state.semantic_live_state = {
21
+ 'analysis_count': 0,
22
+ 'current_text': '',
23
+ 'last_result': None,
24
+ 'text_changed': False
25
+ }
26
+
27
+ # 2. Función para manejar cambios en el texto
28
+ def on_text_change():
29
+ current_text = st.session_state.semantic_live_text
30
+ st.session_state.semantic_live_state['current_text'] = current_text
31
+ st.session_state.semantic_live_state['text_changed'] = True
32
+
33
+ # 3. Área de texto para entrada directa
34
+ st.subheader(semantic_t.get('enter_text', 'Ingrese su texto'))
35
+
36
+ text_input = st.text_area(
37
+ semantic_t.get('text_input_label', 'Escriba o pegue su texto aquí'),
38
+ height=300,
39
+ key="semantic_live_text",
40
+ value=st.session_state.semantic_live_state.get('current_text', ''),
41
+ on_change=on_text_change,
42
+ label_visibility="collapsed"
43
+ )
44
+
45
+ # 4. Botón de análisis
46
+ analyze_button = st.button(
47
+ semantic_t.get('analyze_button', 'Analizar'),
48
+ key="semantic_live_analyze",
49
+ type="primary",
50
+ disabled=not text_input,
51
+ use_container_width=True
52
+ )
53
+
54
+ # 5. Procesar análisis cuando se presiona el botón
55
+ if analyze_button and text_input:
56
+ with st.spinner(semantic_t.get('processing', 'Procesando...')):
57
+ try:
58
+ analysis_result = process_semantic_input(
59
+ text_input,
60
+ lang_code,
61
+ nlp_models,
62
+ semantic_t
63
+ )
64
+
65
+ if analysis_result['success']:
66
+ # Guardar resultado en sesión y base de datos
67
+ st.session_state.semantic_live_state['last_result'] = analysis_result
68
+ st.session_state.semantic_live_state['analysis_count'] += 1
69
+ st.session_state.semantic_live_state['text_changed'] = False
70
+
71
+ # Guardar en MongoDB (colección live)
72
+ store_result = store_student_semantic_live_result(
73
+ st.session_state.username,
74
+ text_input,
75
+ analysis_result['analysis'],
76
+ lang_code
77
+ )
78
+
79
+ if not store_result:
80
+ st.error(semantic_t.get('error_saving', 'Error al guardar el análisis'))
81
+ else:
82
+ st.success(semantic_t.get('analysis_saved', 'Análisis guardado correctamente'))
83
+ else:
84
+ st.error(analysis_result.get('message', 'Error en el análisis'))
85
+
86
+ except Exception as e:
87
+ logger.error(f"Error en análisis: {str(e)}")
88
+ st.error(semantic_t.get('error_processing', 'Error al procesar el texto'))
89
+
90
+ # 6. Mostrar resultados si existen
91
+ if 'last_result' in st.session_state.semantic_live_state and \
92
+ st.session_state.semantic_live_state['last_result'] is not None:
93
+
94
+ analysis = st.session_state.semantic_live_state['last_result']['analysis']
95
+
96
+ if 'key_concepts' in analysis and analysis['key_concepts'] and \
97
+ 'concept_graph' in analysis and analysis['concept_graph'] is not None:
98
+
99
+ # Mostrar conceptos clave
100
+ st.subheader(semantic_t.get('key_concepts', 'Conceptos Clave'))
101
+ concepts_html = """
102
+ <div style="display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px;">
103
+ """ + ''.join([
104
+ f'<div style="background-color: #f0f2f6; border-radius: 5px; padding: 6px 10px; display: inline-flex; align-items: center; gap: 6px;">'
105
+ f'<span style="font-weight: bold;">{concept}</span>'
106
+ f'<span style="color: #666; font-size: 0.9em;">({freq:.2f})</span></div>'
107
+ for concept, freq in analysis['key_concepts']
108
+ ]) + "</div>"
109
+ st.markdown(concepts_html, unsafe_allow_html=True)
110
+
111
+ # Mostrar gráfico
112
+ st.subheader(semantic_t.get('concept_network', 'Red de Conceptos'))
113
+ st.image(
114
+ analysis['concept_graph'],
115
+ use_container_width=True
116
+ )
117
+
118
+ # Botón para consultar con el asistente
119
+ if st.button("💬 Consultar con Asistente", key="semantic_live_chat_button"):
120
+ if 'last_result' not in st.session_state.semantic_live_state:
121
+ st.error("Primero complete el análisis semántico")
122
+ return
123
+
124
+ st.session_state.semantic_agent_data = {
125
+ 'text': st.session_state.semantic_live_state['current_text'],
126
+ 'metrics': st.session_state.semantic_live_state['last_result']['analysis'],
127
+ 'graph_data': st.session_state.semantic_live_state['last_result']['analysis'].get('concept_graph')
128
+ }
129
+ st.session_state.semantic_agent_active = True
130
+ st.rerun()
131
+
132
+ # Notificación si el agente está activo
133
+ if st.session_state.get('semantic_agent_active', False):
134
+ st.success(semantic_t.get('semantic_agent_ready_message', 'El agente virtual está listo. Abre el chat en la barra lateral.'))
135
+ else:
136
+ st.info(semantic_t.get('no_results', 'No hay resultados para mostrar'))
137
+
138
+ except Exception as e:
139
+ logger.error(f"Error general en interfaz semántica en vivo: {str(e)}")
140
+ st.error(semantic_t.get('general_error', "Se produjo un error. Por favor, intente de nuevo."))