File size: 5,747 Bytes
f79e1f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cc791c7
f79e1f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78ac422
f79e1f0
 
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import gradio as gr
from google.adk.agents import Agent
from google.adk.sessions import InMemorySessionService
from google.adk.runners import Runner
from google.adk.agents import LlmAgent
from google.genai import types
from typing import Dict, Any
from google.adk.models.lite_llm import LiteLlm
import uuid
import asyncio
from google import genai
import os

#download_files_from_drive_tool = FunctionTool(func=download_files_from_drive)
# --- Definición de Mod

# Definir función para el Agente Revisor

# Envolver funciones como herramientas de ADK
# Es importante que el nombre de la herramienta sea el mismo que el nombre de la función para el ADK
instruction = """Sos un auditor clínico experto. Que debes validar la pertinencia clínica de una orden médica. Identifica el estudio solicitado, el diagnóstico y la justificación clínica. Posteriormente analiza si el estudio solicitado está clínicamente justificado.

**IMPORTANTE**: Inpendientemente recuerda que la Guía Práctica Clínica dice: `Se recomienda que ante un paciente con Dolor lumbar sin respuesta al tratamiento después de 4-6 semanas de evolución considerar la utilidad de estudios de imagen. El tratamiento con paracetamol es insuficiente para justificar estudios de imagen.`


Formato de respuesta en bullets:

**Evaluación de pertinencia clínica**: [observaciones]

**Resultado**: [✅ Aprobado | ❌ Rechazado]

**Notas para el médico solicitante (Solo en el caso de rechazo)**: - [información]

Fuente: (Ministerio de Salud Pública. Dolor lumbar: Guía Práctica Clínica (GPC). Primera Edición. Quito: Dirección Nacional de Normatización; 2015)

IMPORTANTE_ Siempre debes citar la fuente."""
def consultar_guia_medica(consulta: str) -> str:
    client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"))
    
    try:
        response = client.models.generate_content(
            model="gemini-2.0-flash",
            contents=f"""Responde la siguiente consulta en base a la guia de Dolor Lumbar y cita la fuente de la recomendación:

{consulta}
"""
        )
        print("RESPONSE", response)
        return response.candidates[0].content.parts[0].text
    except Exception as e:
        print(e)


APP_NAME = "predoc_app"



root_agent = LlmAgent(
    model=LiteLlm(model="openai/gpt-4.1"),
    generate_content_config=types.GenerateContentConfig(
        temperature=0.0,
    ),
    name="Agente_Auditor",
    instruction=instruction,
    description="Agente especialista en dolor lumbar",
    #tools=[consultar_guia_medica]
)

session_service = InMemorySessionService()

# Esta función se conecta a ChatInterface
def respond(message, history):
    # Detectar si es inicio de conversación (history vacío o con 0 mensajes)
    print("HISTORY",history)
    if history is None or len(history) == 0:
        user_id = str(uuid.uuid4())
        session_id = str(uuid.uuid4())
        print(f"🔄 Nueva sesión: {session_id}")

        async def create_session():
            await session_service.create_session(
                app_name=APP_NAME,
                user_id=user_id,
                session_id=session_id
            )
        asyncio.run(create_session())
        # Guardar en algún lado user_id y session_id para usar en las próximas llamadas
        # Por simplicidad acá lo guardamos en variables globales
        global CURRENT_USER_ID, CURRENT_SESSION_ID
        CURRENT_USER_ID = user_id
        CURRENT_SESSION_ID = session_id
    else:
        # Usar IDs existentes
        user_id = CURRENT_USER_ID
        session_id = CURRENT_SESSION_ID

    runner = Runner(agent=root_agent, app_name=APP_NAME, session_service=session_service)

    def call_agent_text(query):
        content = types.Content(role='user', parts=[types.Part(text=query)])
        events = runner.run(user_id=user_id, session_id=session_id, new_message=content)
        for event in events:
            if event.is_final_response():
                return event.content.parts[0].text
        return "No se obtuvo respuesta."

    def call_agent_image(query):
        images = []
        for q in query:
            with open(q, 'rb') as f:
                image_bytes = f.read()
            images.append(types.Part.from_bytes(data=image_bytes, mime_type='image/jpeg'))

        content = types.Content(role='user', parts=images)
        events = runner.run(user_id=user_id, session_id=session_id, new_message=content)
        for event in events:
            if event.is_final_response():
                return event.content.parts[0].text
        return "No se obtuvo respuesta."

    def call_agent_both(image, text):
        with open(image[0], 'rb') as f:
            image_bytes = f.read()
        content = types.Content(
            role='user',
            parts=[
                types.Part.from_bytes(data=image_bytes, mime_type='image/jpeg'),
                types.Part(text=text)
            ]
        )
        events = runner.run(user_id=user_id, session_id=session_id, new_message=content)
        for event in events:
            if event.is_final_response():
                return event.content.parts[0].text
        return "No se obtuvo respuesta."

    # Dispatcher
    if message['text'] != '' and len(message['files']) > 0:
        return call_agent_both(message['files'], message['text'])
    elif message['text'] == '' and len(message['files']) > 0:
        return call_agent_image(message['files'])
    elif message['text'] != '' and len(message['files']) == 0:
        return call_agent_text(message['text'])
    else:
        return "Escribe algo para que pueda contestarte."

# Inicializamos demo sin el argumento state
demo = gr.ChatInterface(fn=respond, title="Agente Auditor", multimodal=True)

demo.launch(debug=True)