JairoCesar commited on
Commit
e4f7e04
·
verified ·
1 Parent(s): 6f6776f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -116
app.py CHANGED
@@ -4,28 +4,38 @@ from docx import Document
4
  import tempfile
5
  import os
6
  import re
7
- import time
 
 
 
 
 
 
 
 
 
 
 
8
 
9
- # Configuración básica de Streamlit
10
  st.set_page_config(
11
- page_title="Interpretación Test de Rorschach",
12
  page_icon="🧠",
13
  )
14
 
15
- # Inicializar cliente - manteniendo simple pero con manejo de errores
16
- @st.cache_resource
17
- def get_inference_client():
18
- try:
19
- return InferenceClient("mistralai/Mistral-7B-Instruct-v0.2")
20
- except Exception as e:
21
- st.error(f"Error al inicializar el cliente de Hugging Face: {str(e)}")
22
- return None
23
-
24
- client = get_inference_client()
25
-
26
- # Function to format the prompt for Rorschach interpretation - MEJORADO
27
- def format_prompt(message, history):
28
- # Prompt mejorado pero manteniendo compatibilidad con formato original
29
  system_prompt = """Eres un experto en interpretación del Test de Rorschach.
30
  Analiza las respuestas del paciente a las láminas y proporciona una interpretación
31
  psicológica detallada basada en el método de Exner.
@@ -38,64 +48,65 @@ def format_prompt(message, history):
38
  - Funcionamiento cognitivo, afectivo e interpersonal
39
  """
40
 
41
- prompt = "<s>"
42
- # Añadir instrucciones de sistema al inicio solo si no hay historial previo
43
- if not history:
44
- prompt += f"[INST] {system_prompt} [/INST] Entendido, analizaré las respuestas profesionalmente. "
45
 
46
- # Añadir el historial de conversación manteniendo formato original
47
- for user_prompt, bot_response in history:
48
- prompt += f"[INST] {user_prompt} [/INST]"
49
- prompt += f" {bot_response} "
50
-
51
- # Añadir la consulta actual con formato específico para Rorschach
52
- prompt += f"[INST] Interpretación Rorschach: {message} [/INST]"
53
 
54
  return prompt
55
 
56
- # Function to generate response - OPTIMIZADA
57
- def generate(prompt, history, temperature=0.7, max_new_tokens=800, top_p=0.95, repetition_penalty=1.1):
58
  if not client:
 
59
  return "Error de conexión con el modelo. Por favor, inténtelo de nuevo más tarde."
60
 
61
  try:
62
- temperature = max(float(temperature), 1e-2)
63
- top_p = float(top_p)
64
 
65
- # Parámetros optimizados para interpretación psicológica
66
  generate_kwargs = dict(
67
- temperature=temperature,
68
- max_new_tokens=max_new_tokens,
69
- top_p=top_p,
70
- repetition_penalty=repetition_penalty,
71
  do_sample=True,
72
  seed=42,
73
  )
74
 
75
- formatted_prompt = format_prompt(prompt, history)
76
 
77
- # Mostrar indicador de progreso simple
78
- with st.spinner("Generando interpretación psicológica..."):
79
- # Stream de la respuesta
80
- stream = client.text_generation(formatted_prompt, **generate_kwargs, stream=True, details=True, return_full_text=False)
81
- output = ""
82
-
83
- for response in stream:
84
- output += response.token.text
85
-
86
- return output
 
 
 
 
 
 
 
 
 
87
 
88
  except Exception as e:
89
- st.error(f"Error en la generación: {str(e)}")
 
90
  return f"Lo siento, ocurrió un error durante la interpretación. Detalles: {str(e)}"
91
 
92
- # Manteniendo la función original para reemplazar variables en Word
93
  def replace_variables_word(doc, variables):
94
  for paragraph in doc.paragraphs:
95
  for key, value in variables.items():
96
  if f'<{key}>' in paragraph.text:
97
  paragraph.text = re.sub(f'<{key}>', value, paragraph.text)
98
-
99
  for table in doc.tables:
100
  for row in table.rows:
101
  for cell in row.cells:
@@ -104,14 +115,15 @@ def replace_variables_word(doc, variables):
104
  if f'<{key}>' in paragraph.text:
105
  paragraph.text = re.sub(f'<{key}>', value, paragraph.text)
106
 
107
- # Manteniendo la función original para generar el documento Word
108
  def generate_word_document(interpretation):
109
  try:
110
  template_path = os.path.join('PLANTILLAS', 'PLANTILLA_INTERPRETACION.docx')
111
 
112
  # Verificar si existe la plantilla
113
  if not os.path.exists(template_path):
114
- st.warning(f"No se encontró la plantilla en {template_path}.")
 
115
  return None
116
 
117
  doc = Document(template_path)
@@ -121,82 +133,80 @@ def generate_word_document(interpretation):
121
 
122
  with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as tmp:
123
  doc.save(tmp.name)
 
124
  return tmp.name
125
 
126
  except Exception as e:
127
- st.error(f"Error al generar el documento: {str(e)}")
 
 
128
  return None
129
 
130
- # Streamlit interface - simplificada pero mejorada
131
  st.title("Interpretación del Test de Rorschach")
132
- st.markdown("""
133
- Esta aplicación genera interpretaciones preliminares del Test de Rorschach usando IA.
134
- """)
135
-
136
- # Sidebar con parámetros opcionales
137
- with st.sidebar:
138
- st.header("Configuración")
139
- temperature = st.slider("Creatividad", 0.1, 1.0, 0.7, 0.1,
140
- help="Valores más altos = respuestas más variadas")
141
- max_tokens = st.slider("Longitud", 200, 1000, 512, 50)
142
 
143
- # Chat history
144
- if 'history' not in st.session_state:
145
- st.session_state.history = []
146
 
147
- # User input - área de texto más cómoda
148
  entrada_usuario = st.text_area(
149
  "Ingrese respuestas del Test de Rorschach:",
150
  height=150,
151
  placeholder="Ejemplo: Lámina I: Veo un murciélago..."
152
  )
153
 
154
- # Botones en una fila
155
- col1, col2 = st.columns([1, 3])
156
-
157
- with col1:
158
- submit_button = st.button("Enviar", type="primary")
159
-
160
- if submit_button and entrada_usuario:
161
- # Generate response
162
- bot_response = generate(
163
- entrada_usuario,
164
- st.session_state.history,
165
- temperature=temperature,
166
- max_new_tokens=max_tokens
167
- )
168
-
169
- st.session_state.history.append((entrada_usuario, bot_response))
170
 
171
- # Generate Word document - usando la función original
172
- document_path = generate_word_document(bot_response)
173
-
174
- if document_path:
175
- # Proporcionar enlace de descarga
176
- with open(document_path, "rb") as file:
177
- file_data = file.read()
178
-
179
- st.download_button(
180
- label="Descargar Interpretación",
181
- data=file_data,
182
- file_name="Interpretacion_Rorschach.docx",
183
- mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
184
- )
185
-
186
- with col2:
187
- clear_button = st.button("Limpiar historial")
188
- if clear_button:
189
- st.session_state.history = []
190
- st.experimental_rerun()
191
-
192
- # Display conversation - similar al original pero con mejor formato
193
- st.subheader("Historial de interpretaciones")
194
-
195
- if not st.session_state.history:
196
- st.info("No hay interpretaciones previas.")
197
- else:
198
- chat_text = ""
199
- for user_msg, bot_msg in st.session_state.history:
200
- chat_text += f"Paciente: {user_msg}\n\nInterpretación: {bot_msg}\n\n---\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
- st.text_area("Respuestas e interpretaciones", value=chat_text, height=300, disabled=True)
 
 
4
  import tempfile
5
  import os
6
  import re
7
+ import logging
8
+ import datetime
9
+
10
+ # Configurar logging para monitorear las llamadas al API
11
+ logging.basicConfig(
12
+ level=logging.INFO,
13
+ format='%(asctime)s - %(levelname)s - %(message)s',
14
+ handlers=[
15
+ logging.StreamHandler() # Log a stdout/stderr
16
+ ]
17
+ )
18
+ logger = logging.getLogger("rorschach_app")
19
 
20
+ # Configuración mínima de Streamlit
21
  st.set_page_config(
22
+ page_title="Interpretación Rorschach",
23
  page_icon="🧠",
24
  )
25
 
26
+ # Inicializar cliente - con log de verificación
27
+ client = None
28
+ try:
29
+ client = InferenceClient("mistralai/Mistral-7B-Instruct-v0.2")
30
+ logger.info("✅ Conexión con modelo Mistral-7B establecida correctamente")
31
+ except Exception as e:
32
+ error_msg = f"Error al inicializar cliente de Hugging Face: {str(e)}"
33
+ logger.error(error_msg)
34
+ st.error(error_msg)
35
+
36
+ # Function to format the prompt for Rorschach interpretation
37
+ def format_prompt(message):
38
+ # Prompt optimizado para interpretación Rorschach
 
39
  system_prompt = """Eres un experto en interpretación del Test de Rorschach.
40
  Analiza las respuestas del paciente a las láminas y proporciona una interpretación
41
  psicológica detallada basada en el método de Exner.
 
48
  - Funcionamiento cognitivo, afectivo e interpersonal
49
  """
50
 
51
+ prompt = f"<s>[INST] {system_prompt} [/INST] Entendido. [INST] Interpretación Rorschach: {message} [/INST]"
 
 
 
52
 
53
+ # Log del prompt para verificación
54
+ logger.info(f"Prompt generado con {len(prompt)} caracteres")
 
 
 
 
 
55
 
56
  return prompt
57
 
58
+ # Function to generate response - con logs detallados
59
+ def generate(prompt):
60
  if not client:
61
+ logger.error("❌ No hay cliente disponible para generar respuesta")
62
  return "Error de conexión con el modelo. Por favor, inténtelo de nuevo más tarde."
63
 
64
  try:
65
+ logger.info(f"🔄 Iniciando llamada al API de Hugging Face - {datetime.datetime.now()}")
 
66
 
67
+ # Parámetros fijos optimizados para interpretación psicológica
68
  generate_kwargs = dict(
69
+ temperature=0.7,
70
+ max_new_tokens=800,
71
+ top_p=0.95,
72
+ repetition_penalty=1.1,
73
  do_sample=True,
74
  seed=42,
75
  )
76
 
77
+ formatted_prompt = format_prompt(prompt)
78
 
79
+ # Monitoreo de tiempo de respuesta
80
+ start_time = datetime.datetime.now()
81
+
82
+ # Stream de la respuesta
83
+ stream = client.text_generation(formatted_prompt, **generate_kwargs, stream=True, details=True, return_full_text=False)
84
+ output = ""
85
+ token_count = 0
86
+
87
+ for response in stream:
88
+ output += response.token.text
89
+ token_count += 1
90
+
91
+ end_time = datetime.datetime.now()
92
+ duration = (end_time - start_time).total_seconds()
93
+
94
+ # Log detallado del resultado
95
+ logger.info(f"✅ Respuesta generada: {token_count} tokens en {duration:.2f} segundos")
96
+
97
+ return output
98
 
99
  except Exception as e:
100
+ error_msg = f"Error en la generación: {str(e)}"
101
+ logger.error(error_msg)
102
  return f"Lo siento, ocurrió un error durante la interpretación. Detalles: {str(e)}"
103
 
104
+ # Function to replace variables in a Word template - sin cambios
105
  def replace_variables_word(doc, variables):
106
  for paragraph in doc.paragraphs:
107
  for key, value in variables.items():
108
  if f'<{key}>' in paragraph.text:
109
  paragraph.text = re.sub(f'<{key}>', value, paragraph.text)
 
110
  for table in doc.tables:
111
  for row in table.rows:
112
  for cell in row.cells:
 
115
  if f'<{key}>' in paragraph.text:
116
  paragraph.text = re.sub(f'<{key}>', value, paragraph.text)
117
 
118
+ # Function to generate a Word document with interpretation - sin cambios
119
  def generate_word_document(interpretation):
120
  try:
121
  template_path = os.path.join('PLANTILLAS', 'PLANTILLA_INTERPRETACION.docx')
122
 
123
  # Verificar si existe la plantilla
124
  if not os.path.exists(template_path):
125
+ logger.warning(f"⚠️ No se encontró la plantilla en {template_path}")
126
+ st.warning(f"No se encontró la plantilla en {template_path}")
127
  return None
128
 
129
  doc = Document(template_path)
 
133
 
134
  with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as tmp:
135
  doc.save(tmp.name)
136
+ logger.info(f"✅ Documento Word generado correctamente: {tmp.name}")
137
  return tmp.name
138
 
139
  except Exception as e:
140
+ error_msg = f"Error al generar el documento: {str(e)}"
141
+ logger.error(error_msg)
142
+ st.error(error_msg)
143
  return None
144
 
145
+ # Streamlit interface - simplificada al máximo
146
  st.title("Interpretación del Test de Rorschach")
 
 
 
 
 
 
 
 
 
 
147
 
148
+ # Log de inicio de sesión
149
+ logger.info("🚀 Aplicación iniciada")
 
150
 
151
+ # User input - simplificado
152
  entrada_usuario = st.text_area(
153
  "Ingrese respuestas del Test de Rorschach:",
154
  height=150,
155
  placeholder="Ejemplo: Lámina I: Veo un murciélago..."
156
  )
157
 
158
+ # UI simplificada con un solo botón
159
+ if st.button("Enviar", type="primary"):
160
+ if not entrada_usuario:
161
+ st.warning("Por favor ingrese texto para interpretar")
162
+ else:
163
+ logger.info(f"🔄 Procesando entrada de {len(entrada_usuario)} caracteres")
 
 
 
 
 
 
 
 
 
 
164
 
165
+ # UI feedback
166
+ with st.spinner("Generando interpretación..."):
167
+ # Generate response
168
+ bot_response = generate(entrada_usuario)
169
+
170
+ # UI para mostrar la respuesta
171
+ st.subheader("Interpretación")
172
+ st.write(bot_response)
173
+
174
+ # Generate Word document
175
+ document_path = generate_word_document(bot_response)
176
+
177
+ if document_path:
178
+ # Proporcionar enlace de descarga
179
+ with open(document_path, "rb") as file:
180
+ file_data = file.read()
181
+
182
+ st.download_button(
183
+ label="Descargar Interpretación",
184
+ data=file_data,
185
+ file_name="Interpretacion_Rorschach.docx",
186
+ mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
187
+ )
188
+ logger.info("📄 Botón de descarga mostrado al usuario")
189
+ else:
190
+ logger.error("No se pudo generar el documento Word")
191
+
192
+ # Mostrar logs en la interfaz (para depuración)
193
+ if st.checkbox("Mostrar logs", value=False):
194
+ class StreamlitLogHandler(logging.Handler):
195
+ def emit(self, record):
196
+ log_entry = self.format(record)
197
+ st.code(log_entry)
198
+
199
+ # Mostrar los últimos 10 logs del sistema
200
+ st.subheader("Logs del sistema")
201
+ log_output = st.empty()
202
+
203
+ # Agregar handler temporal para mostrar logs
204
+ stream_handler = StreamlitLogHandler()
205
+ stream_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
206
+ logger.addHandler(stream_handler)
207
+
208
+ # Generar log de prueba
209
+ logger.info("📊 Visualización de logs activada")
210
 
211
+ # Eliminar handler temporal
212
+ logger.removeHandler(stream_handler)