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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -170
app.py CHANGED
@@ -5,63 +5,55 @@ import tempfile
5
  import os
6
  import re
7
  import time
8
- from datetime import datetime
9
 
10
- # Configuraci贸n de Streamlit
11
  st.set_page_config(
12
  page_title="Interpretaci贸n Test de Rorschach",
13
  page_icon="馃",
14
- layout="wide"
15
  )
16
 
17
- # Inicializaci贸n del cliente - usando API Token de Hugging Face
18
- # Si tienes token, descomenta estas l铆neas y a帽ade tu token
19
- # import os
20
- # os.environ["HUGGINGFACE_TOKEN"] = "tu_token_aqu铆" # Mejor usar st.secrets en producci贸n
21
-
22
- # Inicializar cliente con manejo de errores
23
  @st.cache_resource
24
  def get_inference_client():
25
  try:
26
- return InferenceClient(
27
- model="mistralai/Mistral-7B-Instruct-v0.2",
28
- timeout=120 # Timeout m谩s largo para respuestas extensas
29
- )
30
  except Exception as e:
31
  st.error(f"Error al inicializar el cliente de Hugging Face: {str(e)}")
32
  return None
33
 
34
  client = get_inference_client()
35
 
36
- # Function to format the prompt for Rorschach interpretation with mejor contexto
37
  def format_prompt(message, history):
38
- # Sistema de instrucciones m谩s detallado para mejorar la interpretaci贸n
39
  system_prompt = """Eres un experto en interpretaci贸n del Test de Rorschach.
40
- Tu tarea es analizar las respuestas del paciente a las l谩minas y proporcionar una interpretaci贸n
41
- psicol贸gica detallada basada en el m茅todo de Exner y el enfoque psicodin谩mico.
42
-
43
- Para cada interpretaci贸n debes considerar:
44
- 1. Localizaci贸n de las respuestas (W, D, Dd)
45
- 2. Determinantes (forma, color, movimiento, sombreado)
46
- 3. Contenido (humano, animal, objeto, etc.)
47
- 4. Originalidad/popularidad de las respuestas
48
- 5. Indicadores de funcionamiento cognitivo, afectivo e interpersonal
49
 
50
- Tu interpretaci贸n debe ser profesional pero accesible, evitando jerga t茅cnica excesiva.
 
 
 
 
 
51
  """
52
 
53
- prompt = "<s>[INST] " + system_prompt + " [/INST] Entendido, analizar茅 las respuestas del Test de Rorschach profesionalmente.\n\n"
 
 
 
54
 
55
- # A帽adir el historial de conversaci贸n
56
  for user_prompt, bot_response in history:
57
- prompt += f"[INST] Respuestas a l谩minas: {user_prompt} [/INST]\n{bot_response}\n\n"
 
58
 
59
- # A帽adir la consulta actual
60
- prompt += f"[INST] Respuestas a l谩minas: {message} [/INST]"
61
 
62
  return prompt
63
 
64
- # Function to generate response with manejo de errores y feedback visual
65
  def generate(prompt, history, temperature=0.7, max_new_tokens=800, top_p=0.95, repetition_penalty=1.1):
66
  if not client:
67
  return "Error de conexi贸n con el modelo. Por favor, int茅ntelo de nuevo m谩s tarde."
@@ -82,82 +74,51 @@ def generate(prompt, history, temperature=0.7, max_new_tokens=800, top_p=0.95, r
82
 
83
  formatted_prompt = format_prompt(prompt, history)
84
 
85
- # Mostrar indicador de progreso
86
- progress_text = "Generando interpretaci贸n psicol贸gica..."
87
- my_bar = st.progress(0, text=progress_text)
88
-
89
- # Stream de la respuesta con feedback visual
90
- stream = client.text_generation(formatted_prompt, **generate_kwargs, stream=True, details=True, return_full_text=False)
91
- output = ""
92
-
93
- for i, response in enumerate(stream):
94
- output += response.token.text
95
- # Actualizar la barra de progreso simulando avance
96
- progress_percent = min(i/100, 1.0)
97
- my_bar.progress(progress_percent, text=progress_text)
98
- # Peque帽a pausa para mejorar UX
99
- time.sleep(0.01)
100
-
101
- # Completar la barra de progreso
102
- my_bar.progress(1.0, text="隆Interpretaci贸n completa!")
103
- time.sleep(0.5)
104
- my_bar.empty()
105
-
106
- return output
107
 
108
  except Exception as e:
109
  st.error(f"Error en la generaci贸n: {str(e)}")
110
  return f"Lo siento, ocurri贸 un error durante la interpretaci贸n. Detalles: {str(e)}"
111
 
112
- # Function to replace variables in a Word template con manejo mejorado
113
  def replace_variables_word(doc, variables):
114
  for paragraph in doc.paragraphs:
115
  for key, value in variables.items():
116
  if f'<{key}>' in paragraph.text:
117
- # Preservar el formato existente
118
- paragraph_format = paragraph.paragraph_format
119
- run_formats = [(run.text, run.bold, run.italic, run.font.size, run.font.name)
120
- for run in paragraph.runs]
121
 
122
- paragraph.text = paragraph.text.replace(f'<{key}>', value)
123
-
124
- # Restablecer formato despu茅s del reemplazo si es necesario
125
- paragraph.paragraph_format = paragraph_format
126
-
127
- # Procesar tablas
128
  for table in doc.tables:
129
  for row in table.rows:
130
  for cell in row.cells:
131
  for paragraph in cell.paragraphs:
132
  for key, value in variables.items():
133
  if f'<{key}>' in paragraph.text:
134
- paragraph.text = paragraph.text.replace(f'<{key}>', value)
135
 
136
- # Function to generate a Word document with interpretation
137
- def generate_word_document(interpretation, patient_name="", test_date=""):
138
  try:
139
  template_path = os.path.join('PLANTILLAS', 'PLANTILLA_INTERPRETACION.docx')
140
 
141
  # Verificar si existe la plantilla
142
  if not os.path.exists(template_path):
143
- st.warning(f"No se encontr贸 la plantilla en {template_path}. Usando documento en blanco.")
144
- doc = Document()
145
- doc.add_heading('Interpretaci贸n Test de Rorschach', 0)
146
- doc.add_paragraph(interpretation)
147
- else:
148
- doc = Document(template_path)
149
-
150
- # Preparar variables para la plantilla
151
- variables = {
152
- 'INTERPRETACION': interpretation,
153
- 'NOMBRE_PACIENTE': patient_name,
154
- 'FECHA_EVALUACION': test_date,
155
- 'FECHA_INFORME': datetime.now().strftime("%d/%m/%Y")
156
- }
157
 
158
- replace_variables_word(doc, variables)
 
 
 
159
 
160
- # Guardar el documento temporal
161
  with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as tmp:
162
  doc.save(tmp.name)
163
  return tmp.name
@@ -166,71 +127,38 @@ def generate_word_document(interpretation, patient_name="", test_date=""):
166
  st.error(f"Error al generar el documento: {str(e)}")
167
  return None
168
 
169
- # Interfaz de Streamlit mejorada
170
- st.title("馃 Interpretaci贸n del Test de Rorschach")
171
  st.markdown("""
172
- Esta aplicaci贸n utiliza inteligencia artificial para ayudar en la interpretaci贸n preliminar
173
- de respuestas al Test de Rorschach. **No sustituye el juicio cl铆nico profesional.**
174
  """)
175
 
176
- # Sidebar con opciones
177
  with st.sidebar:
178
  st.header("Configuraci贸n")
179
-
180
- # Par谩metros del paciente
181
- st.subheader("Datos del Paciente")
182
- patient_name = st.text_input("Nombre del paciente (opcional)")
183
- test_date = st.date_input("Fecha de evaluaci贸n", datetime.now()).strftime("%d/%m/%Y")
184
-
185
- # Par谩metros del modelo
186
- st.subheader("Par谩metros del Modelo")
187
- temperature = st.slider("Temperatura", 0.1, 1.0, 0.7, 0.1,
188
- help="Valores m谩s altos = respuestas m谩s creativas. Valores m谩s bajos = respuestas m谩s consistentes.")
189
- max_tokens = st.slider("Longitud m谩xima", 200, 1500, 800, 100,
190
- help="N煤mero m谩ximo de tokens en la respuesta")
191
 
192
  # Chat history
193
  if 'history' not in st.session_state:
194
  st.session_state.history = []
195
 
196
- # Explicaci贸n del uso
197
- with st.expander("鈩癸笍 C贸mo usar esta aplicaci贸n"):
198
- st.markdown("""
199
- 1. Escribe las respuestas del paciente a las l谩minas del Test de Rorschach en el campo de texto.
200
- 2. Incluye el n煤mero de l谩mina para cada respuesta, por ejemplo: "L谩mina I: Veo un murci茅lago".
201
- 3. Haz clic en "Generar Interpretaci贸n" para recibir el an谩lisis.
202
- 4. Puedes descargar la interpretaci贸n como documento Word.
203
-
204
- **Nota importante**: Esta herramienta est谩 dise帽ada para asistir en la interpretaci贸n preliminar.
205
- Siempre debe complementarse con el juicio cl铆nico de un profesional cualificado.
206
- """)
207
 
208
- # Uso de columnas para mejor distribuci贸n
209
- col1, col2 = st.columns([3, 2])
210
 
211
  with col1:
212
- # User input - 谩rea de texto m谩s grande para m煤ltiples respuestas
213
- entrada_usuario = st.text_area(
214
- "Ingrese las respuestas del paciente a las l谩minas:",
215
- height=200,
216
- placeholder="Ejemplo:\nL谩mina I: Veo un murci茅lago\nL谩mina II: Dos personas chocando las manos, hay sangre\n..."
217
- )
218
-
219
- # Botones de acci贸n
220
- col_btn1, col_btn2, _ = st.columns([1, 1, 2])
221
 
222
- with col_btn1:
223
- submit_button = st.button("Generar Interpretaci贸n", type="primary")
224
-
225
- with col_btn2:
226
- clear_button = st.button("Limpiar Historial")
227
- if clear_button:
228
- st.session_state.history = []
229
- st.experimental_rerun()
230
-
231
- # Generate response and create Word document
232
- if submit_button and entrada_usuario:
233
- with st.spinner("Analizando respuestas..."):
234
  bot_response = generate(
235
  entrada_usuario,
236
  st.session_state.history,
@@ -238,50 +166,37 @@ if submit_button and entrada_usuario:
238
  max_new_tokens=max_tokens
239
  )
240
 
241
- # A帽adir al historial
242
  st.session_state.history.append((entrada_usuario, bot_response))
243
 
244
- # Generar documento Word
245
- document_path = generate_word_document(
246
- bot_response,
247
- patient_name=patient_name,
248
- test_date=test_date
249
- )
250
 
251
  if document_path:
252
  # Proporcionar enlace de descarga
253
  with open(document_path, "rb") as file:
254
  file_data = file.read()
255
 
256
- # Nombre personalizado para el archivo
257
- file_name = f"Interpretacion_Rorschach_{datetime.now().strftime('%Y%m%d')}.docx"
258
- if patient_name:
259
- file_name = f"Rorschach_{patient_name.replace(' ', '_')}_{datetime.now().strftime('%Y%m%d')}.docx"
260
-
261
- with col2:
262
- st.download_button(
263
- label="馃搫 Descargar Interpretaci贸n (Word)",
264
- data=file_data,
265
- file_name=file_name,
266
- mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
267
- )
268
 
269
- # Display conversation en la segunda columna
270
  with col2:
271
- st.subheader("Historial de Interpretaciones")
 
 
 
 
 
 
 
 
 
 
 
 
 
272
 
273
- if not st.session_state.history:
274
- st.info("A煤n no hay interpretaciones generadas. Complete el formulario y haga clic en 'Generar Interpretaci贸n'.")
275
- else:
276
- # Mostrar la 煤ltima interpretaci贸n primero
277
- for i, (user_msg, bot_msg) in enumerate(reversed(st.session_state.history)):
278
- with st.expander(f"Interpretaci贸n {len(st.session_state.history) - i}", expanded=(i == 0)):
279
- st.markdown("**Respuestas del paciente:**")
280
- st.text(user_msg)
281
- st.markdown("**Interpretaci贸n psicol贸gica:**")
282
- st.markdown(bot_msg)
283
-
284
- # Pie de p谩gina
285
- st.markdown("---")
286
- st.markdown("馃搶 **Nota**: Esta aplicaci贸n usa el modelo Mistral-7B para generar interpretaciones preliminares.")
287
- st.markdown("鈿狅笍 Los resultados deben ser revisados por un profesional cualificado antes de usarse en contextos cl铆nicos.")
 
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.
 
 
 
 
 
 
 
32
 
33
+ Considera:
34
+ - Localizaci贸n de las respuestas
35
+ - Determinantes (forma, color, movimiento)
36
+ - Contenido de las respuestas
37
+ - Originalidad/popularidad
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."
 
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:
102
  for paragraph in cell.paragraphs:
103
  for key, value in variables.items():
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)
118
+
119
+ variables = {'INTERPRETACION': interpretation}
120
+ replace_variables_word(doc, variables)
121
 
 
122
  with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as tmp:
123
  doc.save(tmp.name)
124
  return tmp.name
 
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,
 
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)