Spaces:
Running
Running
| 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 | |
| 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.") |