Basicomanchas / app.py
JairoCesar's picture
Update app.py
bde368b verified
raw
history blame
11.6 kB
import streamlit as st
from huggingface_hub import InferenceClient
from docx import Document
import tempfile
import os
import re
import time
from datetime import datetime
# Configuraci贸n de Streamlit
st.set_page_config(
page_title="Interpretaci贸n Test de Rorschach",
page_icon="馃",
layout="wide"
)
# Inicializaci贸n del cliente - usando API Token de Hugging Face
# Si tienes token, descomenta estas l铆neas y a帽ade tu token
# import os
# os.environ["HUGGINGFACE_TOKEN"] = "tu_token_aqu铆" # Mejor usar st.secrets en producci贸n
# Inicializar cliente con manejo de errores
@st.cache_resource
def get_inference_client():
try:
return InferenceClient(
model="mistralai/Mistral-7B-Instruct-v0.2",
timeout=120 # Timeout m谩s largo para respuestas extensas
)
except Exception as e:
st.error(f"Error al inicializar el cliente de Hugging Face: {str(e)}")
return None
client = get_inference_client()
# Function to format the prompt for Rorschach interpretation with mejor contexto
def format_prompt(message, history):
# Sistema de instrucciones m谩s detallado para mejorar la interpretaci贸n
system_prompt = """Eres un experto en interpretaci贸n del Test de Rorschach.
Tu tarea es analizar las respuestas del paciente a las l谩minas y proporcionar una interpretaci贸n
psicol贸gica detallada basada en el m茅todo de Exner y el enfoque psicodin谩mico.
Para cada interpretaci贸n debes considerar:
1. Localizaci贸n de las respuestas (W, D, Dd)
2. Determinantes (forma, color, movimiento, sombreado)
3. Contenido (humano, animal, objeto, etc.)
4. Originalidad/popularidad de las respuestas
5. Indicadores de funcionamiento cognitivo, afectivo e interpersonal
Tu interpretaci贸n debe ser profesional pero accesible, evitando jerga t茅cnica excesiva.
"""
prompt = "<s>[INST] " + system_prompt + " [/INST] Entendido, analizar茅 las respuestas del Test de Rorschach profesionalmente.\n\n"
# A帽adir el historial de conversaci贸n
for user_prompt, bot_response in history:
prompt += f"[INST] Respuestas a l谩minas: {user_prompt} [/INST]\n{bot_response}\n\n"
# A帽adir la consulta actual
prompt += f"[INST] Respuestas a l谩minas: {message} [/INST]"
return prompt
# Function to generate response with manejo de errores y feedback visual
def generate(prompt, history, temperature=0.7, max_new_tokens=800, top_p=0.95, repetition_penalty=1.1):
if not client:
return "Error de conexi贸n con el modelo. Por favor, int茅ntelo de nuevo m谩s tarde."
try:
temperature = max(float(temperature), 1e-2)
top_p = float(top_p)
# Par谩metros optimizados para interpretaci贸n psicol贸gica
generate_kwargs = dict(
temperature=temperature,
max_new_tokens=max_new_tokens,
top_p=top_p,
repetition_penalty=repetition_penalty,
do_sample=True,
seed=42,
)
formatted_prompt = format_prompt(prompt, history)
# Mostrar indicador de progreso
progress_text = "Generando interpretaci贸n psicol贸gica..."
my_bar = st.progress(0, text=progress_text)
# Stream de la respuesta con feedback visual
stream = client.text_generation(formatted_prompt, **generate_kwargs, stream=True, details=True, return_full_text=False)
output = ""
for i, response in enumerate(stream):
output += response.token.text
# Actualizar la barra de progreso simulando avance
progress_percent = min(i/100, 1.0)
my_bar.progress(progress_percent, text=progress_text)
# Peque帽a pausa para mejorar UX
time.sleep(0.01)
# Completar la barra de progreso
my_bar.progress(1.0, text="隆Interpretaci贸n completa!")
time.sleep(0.5)
my_bar.empty()
return output
except Exception as e:
st.error(f"Error en la generaci贸n: {str(e)}")
return f"Lo siento, ocurri贸 un error durante la interpretaci贸n. Detalles: {str(e)}"
# Function to replace variables in a Word template con manejo mejorado
def replace_variables_word(doc, variables):
for paragraph in doc.paragraphs:
for key, value in variables.items():
if f'<{key}>' in paragraph.text:
# Preservar el formato existente
paragraph_format = paragraph.paragraph_format
run_formats = [(run.text, run.bold, run.italic, run.font.size, run.font.name)
for run in paragraph.runs]
paragraph.text = paragraph.text.replace(f'<{key}>', value)
# Restablecer formato despu茅s del reemplazo si es necesario
paragraph.paragraph_format = paragraph_format
# Procesar tablas
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for paragraph in cell.paragraphs:
for key, value in variables.items():
if f'<{key}>' in paragraph.text:
paragraph.text = paragraph.text.replace(f'<{key}>', value)
# Function to generate a Word document with interpretation
def generate_word_document(interpretation, patient_name="", test_date=""):
try:
template_path = os.path.join('PLANTILLAS', 'PLANTILLA_INTERPRETACION.docx')
# Verificar si existe la plantilla
if not os.path.exists(template_path):
st.warning(f"No se encontr贸 la plantilla en {template_path}. Usando documento en blanco.")
doc = Document()
doc.add_heading('Interpretaci贸n Test de Rorschach', 0)
doc.add_paragraph(interpretation)
else:
doc = Document(template_path)
# Preparar variables para la plantilla
variables = {
'INTERPRETACION': interpretation,
'NOMBRE_PACIENTE': patient_name,
'FECHA_EVALUACION': test_date,
'FECHA_INFORME': datetime.now().strftime("%d/%m/%Y")
}
replace_variables_word(doc, variables)
# Guardar el documento temporal
with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as tmp:
doc.save(tmp.name)
return tmp.name
except Exception as e:
st.error(f"Error al generar el documento: {str(e)}")
return None
# Interfaz de Streamlit mejorada
st.title("馃 Interpretaci贸n del Test de Rorschach")
st.markdown("""
Esta aplicaci贸n utiliza inteligencia artificial para ayudar en la interpretaci贸n preliminar
de respuestas al Test de Rorschach. **No sustituye el juicio cl铆nico profesional.**
""")
# Sidebar con opciones
with st.sidebar:
st.header("Configuraci贸n")
# Par谩metros del paciente
st.subheader("Datos del Paciente")
patient_name = st.text_input("Nombre del paciente (opcional)")
test_date = st.date_input("Fecha de evaluaci贸n", datetime.now()).strftime("%d/%m/%Y")
# Par谩metros del modelo
st.subheader("Par谩metros del Modelo")
temperature = st.slider("Temperatura", 0.1, 1.0, 0.7, 0.1,
help="Valores m谩s altos = respuestas m谩s creativas. Valores m谩s bajos = respuestas m谩s consistentes.")
max_tokens = st.slider("Longitud m谩xima", 200, 1500, 800, 100,
help="N煤mero m谩ximo de tokens en la respuesta")
# Chat history
if 'history' not in st.session_state:
st.session_state.history = []
# Explicaci贸n del uso
with st.expander("鈩癸笍 C贸mo usar esta aplicaci贸n"):
st.markdown("""
1. Escribe las respuestas del paciente a las l谩minas del Test de Rorschach en el campo de texto.
2. Incluye el n煤mero de l谩mina para cada respuesta, por ejemplo: "L谩mina I: Veo un murci茅lago".
3. Haz clic en "Generar Interpretaci贸n" para recibir el an谩lisis.
4. Puedes descargar la interpretaci贸n como documento Word.
**Nota importante**: Esta herramienta est谩 dise帽ada para asistir en la interpretaci贸n preliminar.
Siempre debe complementarse con el juicio cl铆nico de un profesional cualificado.
""")
# Uso de columnas para mejor distribuci贸n
col1, col2 = st.columns([3, 2])
with col1:
# User input - 谩rea de texto m谩s grande para m煤ltiples respuestas
entrada_usuario = st.text_area(
"Ingrese las respuestas del paciente a las l谩minas:",
height=200,
placeholder="Ejemplo:\nL谩mina I: Veo un murci茅lago\nL谩mina II: Dos personas chocando las manos, hay sangre\n..."
)
# Botones de acci贸n
col_btn1, col_btn2, _ = st.columns([1, 1, 2])
with col_btn1:
submit_button = st.button("Generar Interpretaci贸n", type="primary")
with col_btn2:
clear_button = st.button("Limpiar Historial")
if clear_button:
st.session_state.history = []
st.experimental_rerun()
# Generate response and create Word document
if submit_button and entrada_usuario:
with st.spinner("Analizando respuestas..."):
bot_response = generate(
entrada_usuario,
st.session_state.history,
temperature=temperature,
max_new_tokens=max_tokens
)
# A帽adir al historial
st.session_state.history.append((entrada_usuario, bot_response))
# Generar documento Word
document_path = generate_word_document(
bot_response,
patient_name=patient_name,
test_date=test_date
)
if document_path:
# Proporcionar enlace de descarga
with open(document_path, "rb") as file:
file_data = file.read()
# Nombre personalizado para el archivo
file_name = f"Interpretacion_Rorschach_{datetime.now().strftime('%Y%m%d')}.docx"
if patient_name:
file_name = f"Rorschach_{patient_name.replace(' ', '_')}_{datetime.now().strftime('%Y%m%d')}.docx"
with col2:
st.download_button(
label="馃搫 Descargar Interpretaci贸n (Word)",
data=file_data,
file_name=file_name,
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
)
# Display conversation en la segunda columna
with col2:
st.subheader("Historial de Interpretaciones")
if not st.session_state.history:
st.info("A煤n no hay interpretaciones generadas. Complete el formulario y haga clic en 'Generar Interpretaci贸n'.")
else:
# Mostrar la 煤ltima interpretaci贸n primero
for i, (user_msg, bot_msg) in enumerate(reversed(st.session_state.history)):
with st.expander(f"Interpretaci贸n {len(st.session_state.history) - i}", expanded=(i == 0)):
st.markdown("**Respuestas del paciente:**")
st.text(user_msg)
st.markdown("**Interpretaci贸n psicol贸gica:**")
st.markdown(bot_msg)
# Pie de p谩gina
st.markdown("---")
st.markdown("馃搶 **Nota**: Esta aplicaci贸n usa el modelo Mistral-7B para generar interpretaciones preliminares.")
st.markdown("鈿狅笍 Los resultados deben ser revisados por un profesional cualificado antes de usarse en contextos cl铆nicos.")