Spaces:
Sleeping
Sleeping
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) |