File size: 2,994 Bytes
70e641d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf9f7d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7dba92c
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""Pruebas del esquema estructurado y la validaci贸n que reemplaza a limpiarRespuesta."""

from __future__ import annotations

import pytest
from pydantic import ValidationError

from app.schemas import (
    Diferencial,
    InterpretacionClinica,
    PeticionInterpretacion,
)


def test_interpretacion_valida():
    inter = InterpretacionClinica(
        interpretacion="Anemia microc铆tica compatible con ferropenia.",
        diferenciales=[
            Diferencial(nombre="Ferropenia", probabilidad="alta", evidencia=["VCM bajo"], citas=["Thrall, 3陋 ed., p. 210"])
        ],
        siguientes_pruebas=["Perfil de hierro"],
        confianza="media",
        requiere_derivacion=True,
    )
    assert inter.idioma == "es"
    assert inter.diferenciales[0].probabilidad == "alta"


def test_interpretacion_rechaza_vacia():
    with pytest.raises(ValidationError):
        InterpretacionClinica(interpretacion="   ")


def test_probabilidad_invalida_rechazada():
    with pytest.raises(ValidationError):
        Diferencial(nombre="X", probabilidad="segur铆sima")


def test_peticion_limita_a_4_imagenes():
    pet = PeticionInterpretacion(
        paciente={"especie": "canino"},
        imagenes=[f"data:image/png;base64,AAAA{i}" for i in range(10)],
    )
    assert len(pet.imagenes) == 4


def test_json_schema_generable_para_tool_use():
    # El cliente Claude/medGemma pasa este schema como salida estructurada.
    esquema = InterpretacionClinica.model_json_schema()
    assert "diferenciales" in esquema["properties"]
    assert esquema["properties"]["requiere_derivacion"]["type"] == "boolean"


def test_el_esquema_estructurado_exige_contenido():
    """El esquema por defecto admite `{"interpretacion": "..."}` con todo lo dem谩s vac铆o;
    el endurecido se lo pide expl铆citamente al modelo."""
    from app.schemas import esquema_estructurado

    esquema = esquema_estructurado()
    for campo in ("hallazgos_clave", "diferenciales", "siguientes_pruebas"):
        assert esquema["properties"][campo]["minItems"] == 1
        assert campo in esquema["required"]


def test_el_esquema_por_defecto_sigue_siendo_permisivo():
    """La ruta de prosa construye la interpretaci贸n sin campos estructurados y debe validar."""
    from app.schemas import InterpretacionClinica

    interp = InterpretacionClinica(interpretacion="S贸lo prosa.")
    assert interp.diferenciales == []


def test_analitos_medidos_es_opcional():
    """Retrocompatible: una petici贸n de un cliente que no lo manda sigue siendo v谩lida, y el
    prompt y la guarda de invenci贸n se apagan solos ante la lista vac铆a."""
    pet = PeticionInterpretacion.model_validate({"paciente": {"especie": "canino"}})
    assert pet.analitos_medidos == []


def test_analitos_medidos_conserva_las_claves():
    pet = PeticionInterpretacion.model_validate(
        {"paciente": {"especie": "felino"}, "analitos_medidos": ["calc", "fosf", "creat"]}
    )
    assert pet.analitos_medidos == ["calc", "fosf", "creat"]