#!/usr/bin/env python3 """ QUICK START: Cómo crear tu primera herramienta en 5 minutos Este archivo es un tutorial paso a paso que puedes ejecutar. """ # ============================================================================ # PASO 1: Entender la estructura # ============================================================================ """ El patrón Registry funciona así: 1. DEFINIR una herramienta (en tools.py): - Crear una clase que herede de BaseTool - Implementar: name, description, args_schema, invoke() 2. REGISTRAR la herramienta: - Crear ToolRegistry() - Llamar registry.register(MiHerramienta()) 3. USAR las herramientas: - Pasar registry.get_all_tools_as_langchain() al Agent - El Agent ahora puede usar tus tools """ # ============================================================================ # PASO 2: Crear tu primera herramienta # ============================================================================ """ Abre: src/naliiabot/bot/tools/tools.py Y pega este código (reemplaza el contenido): """ EJEMPLO_HERRAMIENTA = ''' """ Implementaciones concretas de herramientas del agente. """ from typing import Any, Dict from .tool_registry import BaseTool class ObtenerHoraActualTool(BaseTool): """ Herramienta simple que retorna la hora actual. El LLM puede usar esto para responder: "¿Qué hora es?" """ @property def name(self) -> str: return "obtener_hora" @property def description(self) -> str: return "Retorna la hora actual del sistema." @property def args_schema(self) -> Dict[str, Any]: return { "type": "object", "properties": { "formato": { "type": "string", "enum": ["12h", "24h"], "description": "Formato de hora deseado", "default": "24h" } }, "required": [] } def invoke(self, **kwargs) -> str: from datetime import datetime formato = kwargs.get("formato", "24h") ahora = datetime.now() if formato == "12h": return ahora.strftime("%I:%M %p") else: return ahora.strftime("%H:%M:%S") class SaludarTool(BaseTool): """ Herramienta para saludar al usuario. """ @property def name(self) -> str: return "saludar" @property def description(self) -> str: return "Saluda al usuario de forma amable." @property def args_schema(self) -> Dict[str, Any]: return { "type": "object", "properties": { "nombre": { "type": "string", "description": "Nombre de la persona a saludar" } }, "required": ["nombre"] } def invoke(self, **kwargs) -> str: nombre = kwargs.get("nombre", "Usuario") return f"¡Hola {nombre}! 👋 Bienvenido a Naliia" ''' # ============================================================================ # PASO 3: Usar tus herramientas # ============================================================================ """ En tu código principal (ejemplo en main.py): """ EJEMPLO_USO = ''' from src.naliiabot.bot.tools import ToolRegistry from src.naliiabot.bot.tools.tools import ObtenerHoraActualTool, SaludarTool from src.naliiabot.bot.agent.agent import Agent from langchain_anthropic import ChatAnthropic # 1. Crear el modelo LLM modelo = ChatAnthropic(model="claude-3-5-sonnet-20241022") # 2. Crear el registry de tools registry = ToolRegistry() # 3. Registrar las herramientas registry.register(ObtenerHoraActualTool()) registry.register(SaludarTool()) # 4. Crear el agente con las tools agent = Agent( model=modelo, tools=registry.get_all_tools_as_langchain() ) # 5. Usar el agente from langchain_core.messages import HumanMessage resultado = agent.invoke({ "messages": [ HumanMessage(content="Hola, ¿qué hora es?") ] }) print(resultado) ''' # ============================================================================ # PASO 4: Verificar que funciona # ============================================================================ """ Ejecuta en la terminal: cd /home/aserrador/Desktop/01-OneCluster/02-Desarrollo/03-Naliia/NaliiaBot python -m pytest tests/test_naliia_agent_tools.py -v Deberías ver los tests pasando. """ # ============================================================================ # PASO 5: Crear herramientas más complejas # ============================================================================ """ Para herramientas con lógica real: 1. Conectar a base de datos: - Importa el cliente de tu BD - En invoke(), haz la consulta - Retorna el resultado como string 2. Manejar errores: - Try/except en invoke() - Retorna un mensaje de error claro 3. Validar argumentos: - Usa el args_schema para definir requerimientos - El LLM sabe qué argumentos necesita Ejemplo con BD: """ EJEMPLO_CON_BD = ''' from typing import Any, Dict from .tool_registry import BaseTool from tu_modulo.database import get_db class ObtenerClienteTool(BaseTool): @property def name(self) -> str: return "obtener_cliente" @property def description(self) -> str: return "Obtiene información de un cliente por ID" @property def args_schema(self) -> Dict[str, Any]: return { "type": "object", "properties": { "cliente_id": { "type": "string", "description": "ID del cliente" } }, "required": ["cliente_id"] } def invoke(self, **kwargs) -> str: cliente_id = kwargs.get("cliente_id") try: db = get_db() cliente = db.clientes.find_one({"_id": cliente_id}) if not cliente: return f"Cliente {cliente_id} no encontrado" return f"Nombre: {cliente['nombre']}, Email: {cliente['email']}" except Exception as e: return f"Error al obtener cliente: {str(e)}" ''' # ============================================================================ # TIPS Y BUENAS PRÁCTICAS # ============================================================================ TIPS = """ ✅ BUENAS PRÁCTICAS: 1. **Nombres claros**: "obtener_agenda" mejor que "get_agenda_info" 2. **Descripciones detalladas**: El LLM las lee para decidir cuándo usar la tool 3. **Args schema completo**: - Describe qué es cada parámetro - Especifica si es requerido - Usa enum para valores limitados - Añade ejemplos en description 4. **Manejo de errores**: Siempre captura excepciones en invoke() 5. **Retorna strings**: invoke() debe retornar texto plano, no objetos 6. **Validación**: Valida argumentos en invoke() antes de usarlos 7. **Logging**: Usa logging para debugging en producción 8. **Tests**: Crea tests unitarios para cada tool ❌ ERRORES COMUNES: - No retornar string desde invoke() - Olvidar el args_schema completo - No manejar excepciones - Nombres de tools con espacios o caracteres especiales - Tools que hacen demasiadas cosas (una responsabilidad) 🔍 DEBUGGING: # Ver todas las tools registradas print(registry.list_tool_names()) # Ver schema de una tool herramienta = registry.get_tool("mi_herramienta") print(herramienta.args_schema) # Ver descripción print(registry.get_tool_description("mi_herramienta")) """ # ============================================================================ # ESTRUCTURA FINAL # ============================================================================ ESTRUCTURA = """ Después de seguir estos pasos, tu proyecto tendrá: src/naliiabot/bot/tools/ ├── __init__.py │ └── Exporta: ToolRegistry, BaseTool ├── tool_registry.py │ └── Contiene: BaseTool (clase abstracta), ToolRegistry (registro) └── tools.py └── TUS herramientas (ObtenerHoraActualTool, SaludarTool, etc.) tests/ └── test_naliia_agent_tools.py └── Tests para las tools (ya creado) src/naliiabotapi/ └── main.py └── Crea el registry, inicializa el agent, lanza el API DOCUMENTACIÓN: ├── TOOLS_GUIDE.md ← Lee primero ├── AGENDA_TOOLS_EXAMPLE.py ← Ejemplos reales ├── REGISTRY_IMPLEMENTATION_SUMMARY.md ← Resumen ├── CHANGES_SUMMARY.md ← Qué cambió └── QUICK_START.md (este archivo) ← Tutorial """ if __name__ == "__main__": print("=" * 80) print("QUICK START: Patrón Registry para Tools en NaliiaBot") print("=" * 80) print("\n📖 PASOS:") print("\n1️⃣ CREA tu primera herramienta") print(" → Abre: src/naliiabot/bot/tools/tools.py") print(" → Pega el código de EJEMPLO_HERRAMIENTA\n") print("2️⃣ REGISTRA la herramienta") print(" → Crea ToolRegistry()") print(" → Llama registry.register(MiHerramienta())\n") print("3️⃣ USA con el Agent") print(" → Pasa registry.get_all_tools_as_langchain() a Agent\n") print("4️⃣ TESTA tus tools") print(" → python -m pytest tests/test_naliia_agent_tools.py -v\n") print("5️⃣ LEE la documentación") print(" → TOOLS_GUIDE.md - Guía completa") print(" → AGENDA_TOOLS_EXAMPLE.py - Ejemplos reales\n") print("=" * 80) print("¡Listo! Ya tienes todo lo que necesitas para empezar 🚀") print("=" * 80)