Spaces:
Sleeping
Sleeping
| """Guarda contra indicaciones terapéuticas en la salida del modelo. | |
| Lo motiva un caso real: el 2026-07-31 medGemma recomendó «iniciar tratamiento inmediato con | |
| insulina, fluidoterapia intravenosa y reposición de potasio» en un paciente con potasio | |
| 3,0 mEq/L —donde dar insulina antes de corregir el potasio puede matar— y el juez lo marcó como | |
| violación de seguridad. Como con el alcance y la derivación, la regla no puede vivir sólo en el | |
| prompt de un 4B. | |
| """ | |
| from __future__ import annotations | |
| import pytest | |
| from app.ai.prescripcion import detectar_prescripcion, encuadrar | |
| from app.ai.service import interpretar | |
| from app.schemas import InterpretacionClinica, PeticionInterpretacion | |
| def test_detecta_lenguaje_prescriptivo(texto): | |
| assert detectar_prescripcion(texto) | |
| def test_no_marca_lenguaje_diagnostico(texto): | |
| assert detectar_prescripcion(texto) == [] | |
| def test_el_encuadre_no_borra_texto_clinico(): | |
| original = "Se recomienda iniciar insulina. El resto del cuadro es compatible con CAD." | |
| resultado = encuadrar(original) | |
| assert original in resultado | |
| assert resultado.startswith("Nota de alcance") | |
| def test_el_encuadre_no_se_duplica(): | |
| assert encuadrar(encuadrar("Administrar fluidoterapia.")).count("Nota de alcance") == 1 | |
| class ClientePrescriptor: | |
| nombre = "medgemma-hf" | |
| prosa = True | |
| modelo = "hf-space" | |
| async def interpretar(self, *_a, **_k): | |
| return InterpretacionClinica( | |
| interpretacion=( | |
| "Cuadro compatible con cetoacidosis diabética. Se recomienda iniciar " | |
| "tratamiento inmediato con insulina, fluidoterapia intravenosa y reposición " | |
| "de potasio. " * 2 | |
| ), | |
| ) | |
| async def test_el_servicio_encuadra_y_deriva(monkeypatch): | |
| import app.ai.service as S | |
| for nombre in ("recuperar", "recuperar_multi"): | |
| monkeypatch.setattr(S, nombre, lambda *_a, **_k: []) | |
| monkeypatch.setattr(S, "_crear_cliente", lambda *_: ClientePrescriptor()) | |
| pet = PeticionInterpretacion( | |
| paciente={"especie": "canino"}, | |
| hallazgos=[{"clave": "gluc", "nombre": "Glucosa", "valor": 480, "unidad": "mg/dL", | |
| "direccion": "alto", "gravedad": "grave"}], | |
| ) | |
| resp = await interpretar(pet) | |
| assert resp.resultado.interpretacion.startswith("Nota de alcance") | |
| assert "cetoacidosis diabética" in resp.resultado.interpretacion | |
| assert resp.resultado.requiere_derivacion is True | |
| # --- Contextos diagnósticos: no son prescripción (falso positivo real, 2026-08-01) --- | |
| def test_un_protocolo_diagnostico_no_es_prescripcion(texto): | |
| assert detectar_prescripcion(texto) == [] | |
| def test_sigue_detectando_prescripcion_junto_a_una_prueba_diagnostica(): | |
| """La exención es por oración, no por texto: una frase diagnóstica no absuelve al resto.""" | |
| texto = ( | |
| "Prueba de estimulación con ACTH para confirmar el diagnóstico. " | |
| "Mientras tanto, iniciar fluidoterapia intravenosa y administrar prednisolona." | |
| ) | |
| assert detectar_prescripcion(texto) | |