Agentes de IA y Function Calling: Herramientas para LLMs
Estás construyendo un agente de IA que necesita obtener datos en tiempo real, realizar cálculos o interactuar con API externas. Pero, ¿cómo salvas la brecha entre la generación de texto del LLM y la ejecución real de código? La respuesta es el function calling (también conocido como uso de herramientas). Permite que los LLM soliciten acciones específicas y que tu código las ejecute. Esta guía te lleva paso a paso por el diseño, la implementación y la depuración del function calling para agentes de IA.
¿Qué es el Function Calling?
El function calling es un mecanismo mediante el cual un LLM puede emitir una solicitud estructurada para llamar a una función que hayas definido. En lugar de generar texto libre, el modelo devuelve un objeto JSON con el nombre de la función y los argumentos. Tu aplicación ejecuta la función y devuelve el resultado al modelo. Esto permite que los agentes realicen acciones más allá de la generación de texto, como consultar bases de datos, enviar correos electrónicos o llamar a API.
Los principales proveedores de LLM como OpenAI, Anthropic y Google admiten function calling. La idea central es consistente: describes las herramientas disponibles, el modelo decide cuándo usarlas y tú te encargas de la ejecución.
Diseñar herramientas para LLMs
Unas herramientas bien diseñadas son cruciales para un comportamiento fiable del agente. Sigue estos principios:
- Nombres y descripciones claros: Usa nombres de función descriptivos y descripciones detalladas. El LLM se basa en ellos para elegir la herramienta adecuada.
- Parámetros simples: Mantén los parámetros al mínimo y usa tipos estándar (string, number, boolean, array, object). Evita estructuras anidadas complejas cuando sea posible.
- Idempotencia: Cuando sea posible, diseña herramientas idempotentes (seguras de reintentar) para gestionar fallos con elegancia.
- Manejo de errores: Devuelve mensajes de error informativos para que el LLM pueda ajustar su enfoque.
Ejemplo: herramienta de clima
Aquí tienes una definición de herramienta sencilla en formato JSON schema, comúnmente usada con la API de OpenAI:
{
"name": "get_weather",
"description": "Get the current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name, e.g., San Francisco"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["city"]
}
}
Implementar function calling: paso a paso
Vamos a construir un bucle de agente mínimo usando la API de OpenAI (el patrón se aplica a otros proveedores).
1. Define tus herramientas
Crea una lista de esquemas de herramientas y un mapeo de nombres de función a funciones reales de Python.
import json
import openai
# Tool schemas
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}
]
# Actual functions
def get_weather(city: str, unit: str = "celsius") -> dict:
# In reality, call a weather API
return {"city": city, "temperature": 22, "unit": unit, "condition": "sunny"}
# Map names to functions
function_map = {
"get_weather": get_weather
}
2. Crea el bucle del agente
El bucle del agente envía mensajes al LLM, comprueba si hay llamadas a herramientas, las ejecuta y repite hasta que el modelo devuelve una respuesta final.
def run_agent(user_message: str):
messages = [{"role": "user", "content": user_message}]
while True:
response = openai.ChatCompletion.create(
model="gpt-4",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message)
# If no tool calls, return the content
if not message.get("tool_calls"):
return message["content"]
# Execute each tool call
for tool_call in message.tool_calls:
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
if function_name in function_map:
result = function_map[function_name](**arguments)
else:
result = {"error": f"Unknown function: {function_name}"}
# Append tool result to messages
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
Este bucle continúa hasta que el LLM produce una respuesta sin llamadas a herramientas, lo que indica que tiene suficiente información.
3. Gestiona errores y casos límite
Los agentes del mundo real deben gestionar:
- Argumentos no válidos: Captura excepciones al parsear argumentos o llamar a funciones.
- Herramientas desconocidas: Devuelve un mensaje de error al LLM para que pueda corregirse.
- Timeouts: Establece tiempos de espera para llamadas a API externas para evitar bloqueos.
- Límites de tasa: Implementa reintentos con retroceso exponencial.
Buenas prácticas para agentes fiables
- Limita el número de herramientas: Demasiadas herramientas confunden al modelo. Agrupa funciones relacionadas o usa un enrutador.
- Valida las entradas: Sanea y valida todos los argumentos antes de la ejecución.
- Registra todo: Registra las llamadas a herramientas y los resultados para depuración y auditoría.
- Prueba con prompts variados: Asegúrate de que el agente selecciona las herramientas correctas en diferentes escenarios.
- Proporciona alternativas: Si una herramienta falla, el agente debería probar alternativas o pedir aclaraciones.
Comparación del soporte de function calling
| Proveedor | Nombre de la función | Formato |
|---|---|---|
| OpenAI | Function Calling | JSON Schema |
| Anthropic | Tool Use | JSON Schema |
| Function Calling | OpenAPI Schema |
Patrones avanzados
A medida que tu agente crece, considera estos patrones:
- Llamadas a herramientas en paralelo: Algunos modelos pueden solicitar varias herramientas a la vez. Ejecútalas de forma concurrente para mayor velocidad.
- Human-in-the-loop: Para acciones sensibles (por ejemplo, enviar dinero), requiere aprobación humana antes de la ejecución.
- Memoria: Almacena el historial de conversación y los resultados de herramientas para proporcionar contexto en sesiones largas.
- Enrutamiento de herramientas: Usa un clasificador ligero para seleccionar herramientas relevantes antes de llamar al LLM principal.
Depurar function calling
Cuando algo falla, comprueba:
- ¿Son claras e inequívocas las descripciones de las herramientas?
- ¿Son correctos los nombres y tipos de los parámetros?
- ¿Tiene el modelo suficiente contexto para elegir la herramienta correcta?
- ¿Estás gestionando correctamente los resultados de las herramientas (por ejemplo, serialización JSON)?
Usa logging para capturar el historial completo de mensajes y las llamadas a herramientas. A menudo, el problema es un desajuste entre los argumentos esperados y los reales.
Preguntas frecuentes
¿Cuál es la diferencia entre function calling y uso de herramientas?
Se refieren al mismo concepto. OpenAI lo llama "function calling", mientras que Anthropic usa "tool use". Ambos permiten que los LLM soliciten la ejecución de funciones externas.
¿Puedo usar function calling con modelos de código abierto?
Sí, algunos modelos de código abierto como Llama 3.1 admiten function calling, y frameworks como LangChain proporcionan abstracciones. Sin embargo, el soporte varía y es posible que necesites ajustar o usar formatos de prompt específicos.
¿Cómo evito que el LLM llame a funciones peligrosas?
Nunca expongas funciones peligrosas directamente. Usa listas de permitidos, valida las entradas e implementa comprobaciones de permisos. Para operaciones sensibles, requiere confirmación humana antes de la ejecución.
¿Listo para construir tu propio agente de IA? Empieza definiendo una herramienta sencilla y probando el bucle del agente. Para más herramientas de desarrollo, consulta nuestro JSON Formatter para depurar payloads de llamadas a herramientas.