// js/analysisModule.js (Revisado y corregido) export async function analyzeMedical(text) { if (!text || text.trim() === '') { console.log("No text provided to analyze."); return ''; } // Cargar configuración de forma segura const configString = localStorage.getItem('iaConfig'); if (!configString) { throw new Error('Configuración IA no encontrada en localStorage. Por favor, configure los proveedores primero.'); } let cfg; try { cfg = JSON.parse(configString); } catch (e) { throw new Error('Error al parsear la configuración IA desde localStorage.'); } // Validar que la configuración necesaria existe para evitar errores if (!cfg || !cfg.llm || !cfg.llm.provider || !cfg.llm.model || !cfg.llm.apiKeys) { throw new Error('La configuración del LLM está incompleta o corrupta. Por favor, guarde la configuración de nuevo.'); } const provider = cfg.llm.provider; const model = cfg.llm.model; const apiKey = cfg.llm.apiKeys[provider]; if (!apiKey) { throw new Error(`No se encontró la API Key para el proveedor LLM seleccionado: ${provider}.`); } // Determinar endpoint según proveedor let url; if (provider === 'openai') { url = 'https://api.openai.com/v1/chat/completions'; } else if (provider === 'deepseek') { url = 'https://api.deepseek.com/v1/chat/completions'; } else { throw new Error(`Proveedor LLM no soportado: ${provider}`); } const systemMessage = 'Eres un médico experto especializado en generar informes clínicos breves concisos y estructurados.'; const userPrompt = `Te daré la transcripción detallada de mi conversación con la paciente y tú escribe una descripción breve de la enfermedad actual y la exploración física de un paciente en contexto clínico, siguiendo estas características:\nEnfermedad actual:\n- Incluye la edad, el género y el motivo de consulta del paciente. (si no te doy algún dato, omite mencionarlo).\n- Detalla brevemente la evolución de síntomas y su progresión.\n- Describe brevemente los signos y antecedentes relevantes con lenguaje técnico comprensible.\nExploración física:\n- Describe brevemente los hallazgos objetivos observados en la exploración.\n- Usa términos médicos precisos, sin juicios diagnósticos.\nTareas del modelo:\n- Responde de forma concreta en dos párrafos, sin títulos 'Enfermedad actual:' ni 'Exploración física:'. \n- El primero para la enfermedad actual.\n- El segundo para la exploración.\nTranscripción: ${text}`; let messages; if (provider === 'openai') { // Para OpenAI, es común enviar el system prompt como parte del primer mensaje de usuario messages = [{ role: 'user', content: `${systemMessage}\n\n${userPrompt}` }]; } else { // Para otros como DeepSeek, el rol 'system' está bien soportado messages = [ { role: 'system', content: systemMessage }, { role: 'user', content: userPrompt } ]; } const payload = { model: model, messages: messages, temperature: 1 }; const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` }; try { const res = await fetch(url, { method: 'POST', headers: headers, body: JSON.stringify(payload) }); if (!res.ok) { const errorBody = await res.text(); console.error("Error response from API:", errorBody); throw new Error(`Error en la llamada a la API de análisis: ${res.status} - ${res.statusText}`); } const data = await res.json(); return data.choices?.[0]?.message?.content || ''; } catch (error) { console.error("Fallo al ejecutar la solicitud de análisis:", error); throw error; // Re-lanza el error para que el código que llama pueda manejarlo } }