From 16d5072ff472fe28ca6d7fe6a3a9e55746ce0799 Mon Sep 17 00:00:00 2001 From: aserrador Date: Thu, 26 Feb 2026 20:49:25 -0500 Subject: [PATCH] Deleted unused files --- README_TOOLS.md | 148 -------- STRUCTURE.txt | 75 ---- docs/AGENDA_TOOLS_EXAMPLE.py | 484 ------------------------ docs/CHANGES_SUMMARY.md | 99 ----- docs/INICIO.txt | 133 ------- docs/QUICK_START.py | 345 ----------------- docs/README_REGISTRY.md | 280 -------------- docs/REGISTRY_IMPLEMENTATION_SUMMARY.md | 171 --------- docs/TOOLS_DOCUMENTATION_INDEX.md | 229 ----------- docs/TOOLS_GUIDE.md | 351 ----------------- docs/TOOL_REGISTRY_GUIDE.md | 457 ---------------------- docs/examples/tool_registry_examples.py | 210 ---------- 12 files changed, 2982 deletions(-) delete mode 100644 README_TOOLS.md delete mode 100644 STRUCTURE.txt delete mode 100644 docs/AGENDA_TOOLS_EXAMPLE.py delete mode 100644 docs/CHANGES_SUMMARY.md delete mode 100644 docs/INICIO.txt delete mode 100644 docs/QUICK_START.py delete mode 100644 docs/README_REGISTRY.md delete mode 100644 docs/REGISTRY_IMPLEMENTATION_SUMMARY.md delete mode 100644 docs/TOOLS_DOCUMENTATION_INDEX.md delete mode 100644 docs/TOOLS_GUIDE.md delete mode 100644 docs/TOOL_REGISTRY_GUIDE.md delete mode 100644 docs/examples/tool_registry_examples.py diff --git a/README_TOOLS.md b/README_TOOLS.md deleted file mode 100644 index 4ead814..0000000 --- a/README_TOOLS.md +++ /dev/null @@ -1,148 +0,0 @@ -# 🚀 NaliiaBot - Patrón Registry para Herramientas - -Bienvenido al sistema de **herramientas (tools)** de NaliiaBot. - -## 📚 Documentación - -Toda la documentación está en la carpeta **[`docs/`](docs/)** - -### ⭐ Comienza aquí: - -1. **[docs/INICIO.txt](docs/INICIO.txt)** - Bienvenida y guía visual (2 min) -2. **[docs/TOOLS_DOCUMENTATION_INDEX.md](docs/TOOLS_DOCUMENTATION_INDEX.md)** - Índice maestro (10 min) -3. **[docs/QUICK_START.py](docs/QUICK_START.py)** - Tutorial interactivo (5 min) - -### 📖 Documentación completa: - -| Archivo | Descripción | -|---------|-----------| -| [docs/INICIO.txt](docs/INICIO.txt) | Bienvenida con instrucciones visuales | -| [docs/TOOLS_DOCUMENTATION_INDEX.md](docs/TOOLS_DOCUMENTATION_INDEX.md) | Índice y navegación de toda la documentación | -| [docs/QUICK_START.py](docs/QUICK_START.py) | Tutorial de 5 minutos para empezar | -| [docs/TOOLS_GUIDE.md](docs/TOOLS_GUIDE.md) | Guía completa del patrón Registry | -| [docs/AGENDA_TOOLS_EXAMPLE.py](docs/AGENDA_TOOLS_EXAMPLE.py) | 5 herramientas reales de ejemplo | -| [docs/REGISTRY_IMPLEMENTATION_SUMMARY.md](docs/REGISTRY_IMPLEMENTATION_SUMMARY.md) | Resumen de la implementación | -| [docs/README_REGISTRY.md](docs/README_REGISTRY.md) | Resumen ejecutivo | -| [docs/TOOL_REGISTRY_GUIDE.md](docs/TOOL_REGISTRY_GUIDE.md) | Guía de patrones y mejores prácticas | -| [docs/CHANGES_SUMMARY.md](docs/CHANGES_SUMMARY.md) | Qué cambió en el sistema | - -## 🏗️ Estructura del proyecto - -``` -NaliiaBot/ -├── 📁 docs/ ← Toda la documentación -│ ├── INICIO.txt -│ ├── TOOLS_DOCUMENTATION_INDEX.md -│ ├── QUICK_START.py -│ ├── TOOLS_GUIDE.md -│ ├── AGENDA_TOOLS_EXAMPLE.py -│ └── ... (más documentación) -│ -├── 📁 src/naliiabot/bot/tools/ -│ ├── __init__.py -│ ├── tool_registry.py (infraestructura) -│ └── tools.py (← Aquí van TUS herramientas) -│ -└── 📁 tests/ - └── test_naliia_agent_tools.py -``` - -## ✨ ¿Qué es el patrón Registry? - -Sistema centralizado para registrar y gestionar herramientas del agente: - -1. **Definir** - Crear una herramienta que herede de `BaseTool` -2. **Registrar** - Agregar a `ToolRegistry` -3. **Usar** - Pasar al `Agent` para que el LLM las use - -```python -# Crear -class MiTool(BaseTool): - def name(self): return "mi_herramienta" - # ... - -# Registrar -registry = ToolRegistry() -registry.register(MiTool()) - -# Usar -agent = Agent(model=modelo, tools=registry.get_all_tools_as_langchain()) -``` - -## 🎯 Próximos pasos - -1. **Lee** la bienvenida: [docs/INICIO.txt](docs/INICIO.txt) -2. **Entiende** la estructura: [docs/TOOLS_DOCUMENTATION_INDEX.md](docs/TOOLS_DOCUMENTATION_INDEX.md) -3. **Sigue** el tutorial: [docs/QUICK_START.py](docs/QUICK_START.py) -4. **Crea** tus herramientas en: `src/naliiabot/bot/tools/tools.py` - -## 📝 Crear tu primera herramienta - -En `src/naliiabot/bot/tools/tools.py`: - -```python -from typing import Any, Dict -from .tool_registry import BaseTool - -class MiPrimeraHerramienta(BaseTool): - @property - def name(self) -> str: - return "mi_herramienta" - - @property - def description(self) -> str: - return "Descripción de qué hace mi herramienta" - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "param1": { - "type": "string", - "description": "Un parámetro" - } - }, - "required": ["param1"] - } - - def invoke(self, **kwargs) -> str: - param = kwargs.get("param1") - return f"Resultado para {param}" -``` - -Luego regístrala: - -```python -from src.naliiabot.bot.tools import ToolRegistry -from src.naliiabot.bot.tools.tools import MiPrimeraHerramienta - -registry = ToolRegistry() -registry.register(MiPrimeraHerramienta()) -tools = registry.get_all_tools_as_langchain() -``` - -## 🔗 Enlaces rápidos - -| Necesito... | Ir a... | -|-----------|---------| -| Entender el sistema | [docs/TOOLS_DOCUMENTATION_INDEX.md](docs/TOOLS_DOCUMENTATION_INDEX.md) | -| Un tutorial rápido | [docs/QUICK_START.py](docs/QUICK_START.py) | -| Crear una herramienta | [docs/TOOLS_GUIDE.md](docs/TOOLS_GUIDE.md#2-crear-una-herramienta-personalizada) | -| Ver ejemplos | [docs/AGENDA_TOOLS_EXAMPLE.py](docs/AGENDA_TOOLS_EXAMPLE.py) | -| Registrar tools | [docs/TOOLS_GUIDE.md](docs/TOOLS_GUIDE.md#3-registrar-y-usar-herramientas) | -| Métodos disponibles | [docs/TOOLS_GUIDE.md](docs/TOOLS_GUIDE.md#4-métodos-disponibles-del-toolregistry) | -| Hacer tests | [docs/TOOLS_GUIDE.md](docs/TOOLS_GUIDE.md#7-mejores-prácticas) | - -## ✅ ¿Qué obtienes? - -✅ Sistema centralizado de herramientas -✅ Documentación completa y detallada -✅ Ejemplos funcionales -✅ Tests automáticos -✅ Guías paso a paso -✅ Listo para producción - ---- - -**Comenzar:** Lee [docs/INICIO.txt](docs/INICIO.txt) ahora (2 minutos) diff --git a/STRUCTURE.txt b/STRUCTURE.txt deleted file mode 100644 index e91d863..0000000 --- a/STRUCTURE.txt +++ /dev/null @@ -1,75 +0,0 @@ -╔════════════════════════════════════════════════════════════════════════════╗ -║ ESTRUCTURA DEL PROYECTO ║ -║ ║ -║ NaliiaBot - Patrón Registry ║ -╚════════════════════════════════════════════════════════════════════════════╝ - - -📁 RAÍZ DEL PROYECTO -═══════════════════════════════════════════════════════════════════════════ - -README.md ← Empieza aquí (proyecto) -README_TOOLS.md ← Documentación de tools -pyproject.toml -htmlcov/ - - -📁 docs/ 📚 DOCUMENTACIÓN COMPLETA -═══════════════════════════════════════════════════════════════════════════ - - INICIO.txt ← Bienvenida (2 min) ⭐ - - TOOLS_DOCUMENTATION_INDEX.md ← Índice maestro (10 min) ⭐ - - QUICK_START.py ← Tutorial interactivo (5 min) ⭐ - - TOOLS_GUIDE.md ← Guía completa (20 min) - - AGENDA_TOOLS_EXAMPLE.py ← 5 herramientas reales (15 min) - - REGISTRY_IMPLEMENTATION_SUMMARY.md - - README_REGISTRY.md - - TOOL_REGISTRY_GUIDE.md - - CHANGES_SUMMARY.md - - -📁 src/naliiabot/bot/tools/ 🔧 CÓDIGO DEL REGISTRY -═══════════════════════════════════════════════════════════════════════════ - - __init__.py ← Exporta: ToolRegistry, BaseTool - - tool_registry.py ← Infraestructura (BaseTool + Registry) - - tools.py ← ← ← TUS HERRAMIENTAS VAN AQUÍ - - -📁 src/naliiabot/bot/agent/ 🤖 AGENTE -═══════════════════════════════════════════════════════════════════════════ - - agent.py ← Agente principal - - schemas.py ← Schemas del agente - - -📁 tests/ ✅ TESTS -═══════════════════════════════════════════════════════════════════════════ - - test_naliia_agent_tools.py ← Tests de las tools - - test_agent.py ← Tests del agente - - -═══════════════════════════════════════════════════════════════════════════ - -🚀 COMIENZA AQUÍ: - - 1. Lee: README.md - 2. Lee: docs/TOOLS_DOCUMENTATION_INDEX.md - 3. Lee: docs/QUICK_START.py - 4. Crea: src/naliiabot/bot/tools/tools.py (tus herramientas) - 5. Testa: pytest tests/test_naliia_agent_tools.py - -═══════════════════════════════════════════════════════════════════════════ diff --git a/docs/AGENDA_TOOLS_EXAMPLE.py b/docs/AGENDA_TOOLS_EXAMPLE.py deleted file mode 100644 index 16156ca..0000000 --- a/docs/AGENDA_TOOLS_EXAMPLE.py +++ /dev/null @@ -1,484 +0,0 @@ -""" -Ejemplo práctico: Herramientas para gestión de agenda. - -Este archivo muestra cómo implementar tools reales para el agente Naliia -que está enfocado en gestión de agenda. - -NOTA: Este es un archivo de ejemplo para entender la estructura. -Para usar estas herramientas reales, cópilas al archivo: - src/naliiabot/bot/tools/tools.py -""" - -from typing import Any, Dict -from src.naliiabot.bot.tools.tool_registry import BaseTool - - -class ObtenerAgendaTool(BaseTool): - """ - Obtiene los eventos de la agenda del usuario para una fecha. - - Ejemplo de uso por el LLM: - - "¿Qué tengo programado para el 15 de febrero?" - - "Muéstrame mi agenda de hoy" - """ - - @property - def name(self) -> str: - return "obtener_agenda" - - @property - def description(self) -> str: - return ( - "Obtiene los eventos programados en la agenda del usuario " - "para una fecha específica. Retorna una lista con hora, título " - "y descripción de cada evento." - ) - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "fecha": { - "type": "string", - "description": "Fecha en formato YYYY-MM-DD (ej: 2026-02-15)", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$" - }, - "usuario_id": { - "type": "string", - "description": "ID único del usuario" - } - }, - "required": ["fecha", "usuario_id"] - } - - def invoke(self, **kwargs) -> str: - """ - Ejecuta la obtención de eventos. - - Args: - fecha: Fecha a consultar (YYYY-MM-DD) - usuario_id: ID del usuario - - Returns: - String con los eventos o mensaje de error - """ - fecha = kwargs.get("fecha", "") - usuario_id = kwargs.get("usuario_id", "") - - if not fecha or not usuario_id: - return "Error: Se requieren 'fecha' y 'usuario_id'" - - try: - # Aquí iría la consulta real a base de datos - # eventos = db.obtener_eventos(usuario_id, fecha) - - # Simulación para el ejemplo - eventos_simulados = { - "2026-02-15": [ - {"hora": "09:00", "titulo": "Standup", "duracion": 30}, - {"hora": "10:30", "titulo": "Reunión con equipo", "duracion": 60}, - {"hora": "14:00", "titulo": "Review", "duracion": 45}, - ] - } - - eventos = eventos_simulados.get(fecha, []) - - if not eventos: - return f"No hay eventos programados para {fecha}" - - resultado = f"Agenda para {fecha}:\n" - for evento in eventos: - resultado += f" • {evento['hora']}: {evento['titulo']} ({evento['duracion']} min)\n" - - return resultado - - except Exception as e: - return f"Error al obtener agenda: {str(e)}" - - -class AgregarEventoTool(BaseTool): - """ - Agrega un nuevo evento a la agenda del usuario. - - Ejemplo de uso: - - "Agrega una reunión el 15 de febrero a las 10:00" - - "Programa una llamada el 20/02 a las 14:30 por 45 minutos" - """ - - @property - def name(self) -> str: - return "agregar_evento" - - @property - def description(self) -> str: - return ( - "Agrega un nuevo evento a la agenda del usuario. " - "Requiere título, fecha, hora de inicio y duración." - ) - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "usuario_id": { - "type": "string", - "description": "ID del usuario propietario de la agenda" - }, - "titulo": { - "type": "string", - "description": "Título o nombre del evento" - }, - "fecha": { - "type": "string", - "description": "Fecha en formato YYYY-MM-DD", - "pattern": "^\\d{4}-\\d{2}-\\d{2}$" - }, - "hora_inicio": { - "type": "string", - "description": "Hora de inicio en formato HH:MM (24h)", - "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$" - }, - "duracion_minutos": { - "type": "integer", - "description": "Duración del evento en minutos", - "default": 30, - "minimum": 5, - "maximum": 480 - }, - "descripcion": { - "type": "string", - "description": "Descripción adicional del evento (opcional)" - }, - "participantes": { - "type": "array", - "items": {"type": "string"}, - "description": "Lista de emails de participantes (opcional)" - } - }, - "required": ["usuario_id", "titulo", "fecha", "hora_inicio"] - } - - def invoke(self, **kwargs) -> str: - """ - Agrega un evento a la agenda. - - Returns: - Confirmación del evento agregado o mensaje de error - """ - usuario_id = kwargs.get("usuario_id") - titulo = kwargs.get("titulo") - fecha = kwargs.get("fecha") - hora = kwargs.get("hora_inicio") - duracion = kwargs.get("duracion_minutos", 30) - descripcion = kwargs.get("descripcion", "") - participantes = kwargs.get("participantes", []) - - # Validaciones - if not all([usuario_id, titulo, fecha, hora]): - return "Error: Faltan parámetros requeridos" - - try: - # Aquí iría la lógica para guardar en BD - # db.agregar_evento(usuario_id, titulo, fecha, hora, duracion, etc) - - resultado = ( - f"✓ Evento agregado correctamente\n" - f" Título: {titulo}\n" - f" Fecha: {fecha}\n" - f" Hora: {hora}\n" - f" Duración: {duracion} minutos" - ) - - if descripcion: - resultado += f"\n Descripción: {descripcion}" - - if participantes: - resultado += f"\n Participantes: {', '.join(participantes)}" - - return resultado - - except Exception as e: - return f"Error al agregar evento: {str(e)}" - - -class ModificarEventoTool(BaseTool): - """ - Modifica los detalles de un evento existente. - - Ejemplo de uso: - - "Cambia la reunión de las 10:00 a las 11:00" - - "Aumenta la duración de la reunión a 60 minutos" - """ - - @property - def name(self) -> str: - return "modificar_evento" - - @property - def description(self) -> str: - return ( - "Modifica los detalles de un evento existente en la agenda. " - "Se puede cambiar hora, duración, título o descripción." - ) - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "evento_id": { - "type": "string", - "description": "ID único del evento a modificar" - }, - "usuario_id": { - "type": "string", - "description": "ID del usuario propietario" - }, - "titulo": { - "type": "string", - "description": "Nuevo título (opcional)" - }, - "hora_inicio": { - "type": "string", - "description": "Nueva hora en formato HH:MM (opcional)" - }, - "duracion_minutos": { - "type": "integer", - "description": "Nueva duración en minutos (opcional)" - }, - "descripcion": { - "type": "string", - "description": "Nueva descripción (opcional)" - } - }, - "required": ["evento_id", "usuario_id"] - } - - def invoke(self, **kwargs) -> str: - evento_id = kwargs.get("evento_id") - usuario_id = kwargs.get("usuario_id") - - cambios = {} - if "titulo" in kwargs: - cambios["titulo"] = kwargs["titulo"] - if "hora_inicio" in kwargs: - cambios["hora_inicio"] = kwargs["hora_inicio"] - if "duracion_minutos" in kwargs: - cambios["duracion_minutos"] = kwargs["duracion_minutos"] - if "descripcion" in kwargs: - cambios["descripcion"] = kwargs["descripcion"] - - if not cambios: - return "Error: No hay cambios para aplicar" - - try: - # db.modificar_evento(usuario_id, evento_id, cambios) - - resultado = f"✓ Evento {evento_id} modificado:\n" - for campo, valor in cambios.items(): - resultado += f" • {campo}: {valor}\n" - - return resultado - - except Exception as e: - return f"Error al modificar evento: {str(e)}" - - -class EliminarEventoTool(BaseTool): - """ - Elimina un evento de la agenda. - - Ejemplo de uso: - - "Elimina la reunión de las 10:00" - - "Cancela el evento 'Standup' del 15 de febrero" - """ - - @property - def name(self) -> str: - return "eliminar_evento" - - @property - def description(self) -> str: - return ( - "Elimina un evento de la agenda del usuario. " - "Requiere confirmación para evitar eliminaciones accidentales." - ) - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "evento_id": { - "type": "string", - "description": "ID único del evento a eliminar" - }, - "usuario_id": { - "type": "string", - "description": "ID del usuario propietario" - }, - "confirmar": { - "type": "boolean", - "description": "Confirmación de eliminación", - "default": False - } - }, - "required": ["evento_id", "usuario_id", "confirmar"] - } - - def invoke(self, **kwargs) -> str: - evento_id = kwargs.get("evento_id") - usuario_id = kwargs.get("usuario_id") - confirmar = kwargs.get("confirmar", False) - - if not confirmar: - return ( - f"⚠️ Confirmación requerida para eliminar evento {evento_id}. " - f"Por favor, confirma: confirmar=true" - ) - - try: - # db.eliminar_evento(usuario_id, evento_id) - - return f"✓ Evento {evento_id} eliminado correctamente de la agenda" - - except Exception as e: - return f"Error al eliminar evento: {str(e)}" - - -class ListarAgendaTool(BaseTool): - """ - Lista todos los eventos del usuario en un rango de fechas. - - Ejemplo de uso: - - "Muestra mi agenda de la próxima semana" - - "¿Qué tengo programado entre el 10 y el 20 de febrero?" - """ - - @property - def name(self) -> str: - return "listar_agenda" - - @property - def description(self) -> str: - return ( - "Lista todos los eventos de la agenda del usuario " - "dentro de un rango de fechas especificado." - ) - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "usuario_id": { - "type": "string", - "description": "ID del usuario" - }, - "fecha_inicio": { - "type": "string", - "description": "Fecha de inicio en formato YYYY-MM-DD" - }, - "fecha_fin": { - "type": "string", - "description": "Fecha de fin en formato YYYY-MM-DD" - }, - "filtro_titulo": { - "type": "string", - "description": "Filtrar por título del evento (opcional)" - } - }, - "required": ["usuario_id", "fecha_inicio", "fecha_fin"] - } - - def invoke(self, **kwargs) -> str: - usuario_id = kwargs.get("usuario_id") - fecha_inicio = kwargs.get("fecha_inicio") - fecha_fin = kwargs.get("fecha_fin") - filtro = kwargs.get("filtro_titulo", "") - - try: - # eventos = db.listar_eventos(usuario_id, fecha_inicio, fecha_fin, filtro) - - resultado = ( - f"Agenda de {fecha_inicio} a {fecha_fin}:\n" - f" • Total de eventos: 3\n" - f" • Horas ocupadas: 9\n" - f" • Tiempo libre: 7 horas" - ) - - return resultado - - except Exception as e: - return f"Error al listar agenda: {str(e)}" - - -# ============================================================================ -# CÓMO USAR ESTAS HERRAMIENTAS -# ============================================================================ - -""" -OPCIÓN 1: Copiar a tools.py - -1. Copia las clases de herramientas a: src/naliiabot/bot/tools/tools.py -2. En tu código principal: - - from src.naliiabot.bot.tools import ToolRegistry - from src.naliiabot.bot.tools.tools import ( - ObtenerAgendaTool, - AgregarEventoTool, - ModificarEventoTool, - EliminarEventoTool, - ListarAgendaTool - ) - from src.naliiabot.bot.agent.agent import Agent - from langchain_anthropic import ChatAnthropic - - # Configurar - modelo = ChatAnthropic(model="claude-3-5-sonnet-20241022") - registry = ToolRegistry() - - # Registrar herramientas - registry.register(ObtenerAgendaTool()) - registry.register(AgregarEventoTool()) - registry.register(ModificarEventoTool()) - registry.register(EliminarEventoTool()) - registry.register(ListarAgendaTool()) - - # Crear agente - agent = Agent( - model=modelo, - tools=registry.get_all_tools_as_langchain() - ) - -OPCIÓN 2: Usar factory pattern - -Crea src/naliiabot/bot/tools/factory.py: - - from .tool_registry import ToolRegistry - from .tools import ( - ObtenerAgendaTool, - AgregarEventoTool, - ModificarEventoTool, - EliminarEventoTool, - ListarAgendaTool - ) - - def crear_registry_agenda() -> ToolRegistry: - registry = ToolRegistry() - registry.register(ObtenerAgendaTool()) - registry.register(AgregarEventoTool()) - registry.register(ModificarEventoTool()) - registry.register(EliminarEventoTool()) - registry.register(ListarAgendaTool()) - return registry - -Luego úsalo: - - from src.naliiabot.bot.tools.factory import crear_registry_agenda - - registry = crear_registry_agenda() - tools = registry.get_all_tools_as_langchain() -""" diff --git a/docs/CHANGES_SUMMARY.md b/docs/CHANGES_SUMMARY.md deleted file mode 100644 index c7e6d6c..0000000 --- a/docs/CHANGES_SUMMARY.md +++ /dev/null @@ -1,99 +0,0 @@ -# Cambios realizados: Patrón Registry para Tools - -## ✅ Cambios completados - -### 1. **tools.py** - Limpiado ✓ -**Antes:** Contenía herramientas de ejemplo (Calculator, Greeter, Weather, Time) -**Ahora:** Vacío y listo para tus herramientas personalizadas - -```python -""" -Implementaciones concretas de herramientas del agente. -Define aquí tus herramientas personalizadas que extienden BaseTool -""" - -from typing import Any, Dict -from .tool_registry import BaseTool - -# Define aquí tus herramientas personalizadas -# Ejemplo: class MiHerramienta(BaseTool): ... -``` - -### 2. **__init__.py** - Actualizado ✓ -**Antes:** Importaba CalculatorTool, GreeterTool -**Ahora:** Solo exporta BaseTool y ToolRegistry - -```python -from .tool_registry import ToolRegistry, BaseTool - -__all__ = ["ToolRegistry", "BaseTool"] -``` - -### 3. **tool_registry.py** - Mantiene la infraestructura ✓ -Contiene: -- `BaseTool`: Clase abstracta para todas las tools -- `ToolRegistry`: Clase para registrar y gestionar tools - -### 4. **Documentación - Nueva ✓** -Creado: `TOOLS_GUIDE.md` con ejemplos completos de cómo: -- Crear herramientas personalizadas -- Usar el ToolRegistry -- Integrar con el Agent -- Ejemplos de tools para gestionar agenda - -## 📁 Estructura final - -``` -src/naliiabot/bot/tools/ -├── __init__.py # Exporta ToolRegistry y BaseTool -├── tool_registry.py # Base + Registry (infraestructura) -└── tools.py # TUS HERRAMIENTAS AQUÍ (vacío, listo para usar) -``` - -## 🚀 Próximos pasos - -1. **Define tus herramientas** en `tools.py`: - ```python - class ObtenerAgendaTool(BaseTool): - @property - def name(self) -> str: - return "obtener_agenda" - # ... más detalles en TOOLS_GUIDE.md - ``` - -2. **Registra y usa** en tu código: - ```python - from src.naliiabot.bot.tools import ToolRegistry - from src.naliiabot.bot.tools.tools import ObtenerAgendaTool - - registry = ToolRegistry() - registry.register(ObtenerAgendaTool()) - tools = registry.get_all_tools_as_langchain() - ``` - -3. **Lee TOOLS_GUIDE.md** para ejemplos detallados con: - - Herramientas para gestión de agenda - - Cómo validar argumentos - - Patrones recomendados - - Testing de tools - -## 📚 Referencias - -- [TOOLS_GUIDE.md](./TOOLS_GUIDE.md) - Guía completa con ejemplos -- [tool_registry.py](./src/naliiabot/bot/tools/tool_registry.py) - Código de la infraestructura -- [tests/test_naliia_agent_tools.py](./tests/test_naliia_agent_tools.py) - Tests de tools - -## ✨ Beneficios del patrón Registry - -✅ **Centralizado**: Un único lugar para todas las tools -✅ **Extensible**: Fácil agregar nuevas tools -✅ **Testeable**: Cada tool se prueba de forma independiente -✅ **Mantenible**: Cambios aislados en cada tool -✅ **Reutilizable**: Mismo registry en múltiples agentes -✅ **Validado**: Schema automático para argumentos -✅ **Documentado**: Inspección de tools disponibles - ---- - -**Nota:** Las herramientas de ejemplo (Calculator, Greeter, Weather, Time) han sido removidas. -Ahora el proyecto está limpio y listo para que implementes las tools que necesitas. diff --git a/docs/INICIO.txt b/docs/INICIO.txt deleted file mode 100644 index 18057db..0000000 --- a/docs/INICIO.txt +++ /dev/null @@ -1,133 +0,0 @@ -╔════════════════════════════════════════════════════════════════════════════╗ -║ ║ -║ 🎉 SISTEMA DE TOOLS IMPLEMENTADO 🎉 ║ -║ ║ -║ ✅ Patrón Registry para NaliiaBot ║ -║ ║ -╚════════════════════════════════════════════════════════════════════════════╝ - -📚 DOCUMENTACIÓN DISPONIBLE: - - 🗺️ TOOLS_DOCUMENTATION_INDEX.md - └─ Punto de partida. Lee esto primero. (10 min) - - 🚀 QUICK_START.py - └─ Tutorial interactivo. Ejecutar y aprender. (5 min) - - 📖 TOOLS_GUIDE.md - └─ Guía completa con ejemplos. (20 min) - - 💼 AGENDA_TOOLS_EXAMPLE.py - └─ 5 herramientas reales funcionando. (15 min) - - 📋 REGISTRY_IMPLEMENTATION_SUMMARY.md - └─ Qué se hizo y cómo. (10 min) - - -🏗️ ESTRUCTURA DEL PROYECTO: - - src/naliiabot/bot/tools/ - ├── __init__.py - ├── tool_registry.py (infraestructura) - └── tools.py (← TUS HERRAMIENTAS AQUÍ) - - tests/ - └── test_naliia_agent_tools.py (tests automáticos) - - -🚀 COMIENZA CON ESTOS 3 PASOS: - - 1️⃣ Abre: TOOLS_DOCUMENTATION_INDEX.md - └─ Entiende la estructura - - 2️⃣ Abre: QUICK_START.py - └─ Crea tu primera herramienta - - 3️⃣ Abre: src/naliiabot/bot/tools/tools.py - └─ Agrega tus herramientas aquí - - -📊 ¿QUÉ ES EL PATRÓN REGISTRY? - - Un sistema para registrar y gestionar herramientas de forma centralizada. - - Flujo: - 1. Define una herramienta (clase que hereda de BaseTool) - 2. Regístrala en el ToolRegistry - 3. Pásala al Agent - 4. El LLM ahora puede usarla - - -✨ BENEFICIOS: - - ✅ Centralizado - Un único lugar para todas las tools - ✅ Extensible - Agregar tools sin tocar código existente - ✅ Testeable - Cada tool se prueba independientemente - ✅ Mantenible - Cambios aislados - ✅ Escalable - Funciona con 1 o 100 tools - ✅ Validado - Schema automático de argumentos - - -💻 EJEMPLO RÁPIDO (copiar y pegar): - - # 1. Crear una herramienta - class MiTool(BaseTool): - @property - def name(self) -> str: - return "mi_herramienta" - - @property - def description(self) -> str: - return "Descripción" - - @property - def args_schema(self): - return {"type": "object", "properties": {}} - - def invoke(self, **kwargs) -> str: - return "resultado" - - # 2. Registrar - registry = ToolRegistry() - registry.register(MiTool()) - tools = registry.get_all_tools_as_langchain() - - # 3. Usar con Agent - agent = Agent(model=modelo, tools=tools) - - -🎯 PRÓXIMOS PASOS: - - Ahora mismo: - [ ] Abre TOOLS_DOCUMENTATION_INDEX.md - [ ] Lee QUICK_START.py - [ ] Intenta crear una herramienta - - Después: - [ ] Revisa ejemplos en AGENDA_TOOLS_EXAMPLE.py - [ ] Crea tus herramientas personalizadas - [ ] Escribe tests - - -❓ ¿PREGUNTAS? - - ¿Cómo creo una tool? - → TOOLS_GUIDE.md sección 2 - - ¿Cómo registro tools? - → TOOLS_GUIDE.md sección 3 - - ¿Cuáles son los métodos disponibles? - → TOOLS_GUIDE.md sección 4 - - ¿Necesito ejemplos? - → AGENDA_TOOLS_EXAMPLE.py - - -═══════════════════════════════════════════════════════════════════════════════ - - 🎓 TODO LISTO PARA EMPEZAR - - 👉 Comienza por: TOOLS_DOCUMENTATION_INDEX.md - -═══════════════════════════════════════════════════════════════════════════════ diff --git a/docs/QUICK_START.py b/docs/QUICK_START.py deleted file mode 100644 index 93d26e1..0000000 --- a/docs/QUICK_START.py +++ /dev/null @@ -1,345 +0,0 @@ -#!/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) diff --git a/docs/README_REGISTRY.md b/docs/README_REGISTRY.md deleted file mode 100644 index 92c0989..0000000 --- a/docs/README_REGISTRY.md +++ /dev/null @@ -1,280 +0,0 @@ -# ✅ RESUMEN: Implementación completada del Patrón Registry - -## 🎉 ¿Qué se logró? - -Se implementó un **sistema profesional de herramientas** para el agente Naliia usando el patrón **Registry**. El proyecto está completamente documentado y listo para que agregues tus propias tools. - ---- - -## 📊 Cambios realizados - -### ✅ Código modificado - -| Archivo | Cambio | Razón | -|---------|--------|-------| -| `src/naliiabot/bot/tools/tools.py` | Limpiado de tools de ejemplo | Tools de ejemplo no son aplicables a tu caso | -| `src/naliiabot/bot/tools/__init__.py` | Removidas importaciones de ejemplos | Mantener el módulo limpio | - -### ✅ Infraestructura existente - -Estos archivos ya estaban y funcionan perfectamente: - -| Archivo | Descripción | -|---------|-----------| -| `src/naliiabot/bot/tools/tool_registry.py` | Patrón Registry (BaseTool + ToolRegistry) | -| `tests/test_naliia_agent_tools.py` | Tests para validar tools | - -### ✅ Documentación nueva (8 archivos) - -| Archivo | Propósito | Tiempo de lectura | -|---------|----------|-----------------| -| **TOOLS_DOCUMENTATION_INDEX.md** | 🗺️ Índice y navegación | 10 min | -| **QUICK_START.py** | 🚀 Tutorial interactivo | 5 min | -| **TOOLS_GUIDE.md** | 📖 Guía completa | 20 min | -| **AGENDA_TOOLS_EXAMPLE.py** | 💼 Ejemplos reales de 5 tools | 15 min | -| **REGISTRY_IMPLEMENTATION_SUMMARY.md** | 📋 Resumen de implementación | 10 min | -| **CHANGES_SUMMARY.md** | 📝 Qué cambió | 5 min | -| **TOOL_REGISTRY_GUIDE.md** | 📚 Guía de patrones | 20 min | - ---- - -## 🏗️ Estructura actual - -``` -NaliiaBot/ -│ -├── 📚 DOCUMENTACIÓN (nueva) -│ ├── TOOLS_DOCUMENTATION_INDEX.md ← EMPIEZA POR AQUÍ -│ ├── QUICK_START.py -│ ├── TOOLS_GUIDE.md -│ ├── AGENDA_TOOLS_EXAMPLE.py -│ ├── REGISTRY_IMPLEMENTATION_SUMMARY.md -│ ├── CHANGES_SUMMARY.md -│ └── TOOL_REGISTRY_GUIDE.md -│ -├── 📁 src/naliiabot/bot/tools/ -│ ├── __init__.py ✨ (actualizado) -│ ├── tool_registry.py (infraestructura existente) -│ └── tools.py ✨ (limpiado, listo para tus tools) -│ -└── 📁 tests/ - └── test_naliia_agent_tools.py (tests completos) -``` - ---- - -## 🎯 Próximos pasos - -### Opción 1: Aprender el sistema (20 minutos) -``` -1. Abre: TOOLS_DOCUMENTATION_INDEX.md -2. Lee: QUICK_START.py -3. Revisa: TOOLS_GUIDE.md -4. Entiendido ✅ -``` - -### Opción 2: Empezar con un ejemplo (15 minutos) -``` -1. Abre: AGENDA_TOOLS_EXAMPLE.py -2. Copia una de las 5 herramientas -3. Pégala en: src/naliiabot/bot/tools/tools.py -4. Registra y usa ✅ -``` - -### Opción 3: Crear tu primera tool (10 minutos) -``` -1. Abre: src/naliiabot/bot/tools/tools.py -2. Define una clase que herede de BaseTool -3. Implementa: name, description, args_schema, invoke() -4. Registra en tu main.py ✅ -``` - ---- - -## 📖 Recomendación de lectura - -**Primero (5 min):** -``` -TOOLS_DOCUMENTATION_INDEX.md -``` -Es el índice maestro. Te orienta hacia lo que necesitas. - -**Segundo (5-20 min):** -Elige según tu necesidad: -- Rápido: **QUICK_START.py** -- Completo: **TOOLS_GUIDE.md** -- Práctico: **AGENDA_TOOLS_EXAMPLE.py** - ---- - -## ✨ Lo que ahora puedes hacer - -✅ **Crear herramientas personalizadas** -- Documentación paso a paso -- Ejemplos reales funcionales -- Tests automáticos - -✅ **Registrar herramientas de forma centralizada** -- Un único `ToolRegistry` -- Fácil de escalar -- Validación automática - -✅ **Integrar con el Agent** -- Herramientas listas para LangChain -- Compatible con modelos Anthropic -- Flujo completo documentado - -✅ **Testear herramientas** -- Tests unitarios incluidos -- Cobertura completa -- Fácil de mantener - ---- - -## 🚀 ¿Qué sigue? - -### Corto plazo (hoy) -- [ ] Lee TOOLS_DOCUMENTATION_INDEX.md (10 min) -- [ ] Sigue QUICK_START.py (5 min) -- [ ] Crea tu primera tool simple (10 min) - -### Mediano plazo (esta semana) -- [ ] Revisa AGENDA_TOOLS_EXAMPLE.py -- [ ] Crea tools para tu caso de uso -- [ ] Escribe tests - -### Largo plazo (próximas semanas) -- [ ] Integra con BD real -- [ ] Crea factory de tools -- [ ] Deploy en producción - ---- - -## 📊 Estadísticas - -| Métrica | Valor | -|---------|-------| -| Archivos modificados | 2 | -| Archivos documentación creados | 8 | -| Líneas de documentación | ~800 | -| Ejemplos de herramientas | 7 (6 en ejemplos + tests) | -| Métodos de ToolRegistry | 6+ | -| Tests incluidos | 10+ casos | -| Tiempo para aprender | 20-30 min | - ---- - -## 🎓 Ventajas del patrón Registry implementado - -| Ventaja | Beneficio | -|---------|-----------| -| ✅ **Centralizado** | Una fuente única de verdad | -| ✅ **Extensible** | Agregar tools sin tocar código existente | -| ✅ **Testeable** | Cada tool se prueba independientemente | -| ✅ **Mantenible** | Cambios aislados | -| ✅ **Escalable** | Funciona con 1 o 100 tools | -| ✅ **Validado** | Schema automático | -| ✅ **Documentado** | Fácil inspeccionar | -| ✅ **Profesional** | Patrón estándar de la industria | - ---- - -## 💡 Ejemplos rápidos - -### Crear una tool (3 minutos) -```python -from typing import Any, Dict -from .tool_registry import BaseTool - -class MiTool(BaseTool): - @property - def name(self) -> str: - return "mi_herramienta" - - @property - def description(self) -> str: - return "Descripción de qué hace" - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": {"param": {"type": "string"}}, - "required": ["param"] - } - - def invoke(self, **kwargs) -> str: - return f"Resultado para {kwargs.get('param')}" -``` - -### Registrar una tool (2 minutos) -```python -from src.naliiabot.bot.tools import ToolRegistry -from src.naliiabot.bot.tools.tools import MiTool - -registry = ToolRegistry() -registry.register(MiTool()) -tools = registry.get_all_tools_as_langchain() -``` - -### Usar con Agent (2 minutos) -```python -from src.naliiabot.bot.agent.agent import Agent - -agent = Agent(model=modelo, tools=tools) -resultado = agent.invoke({"messages": [...]}) -``` - ---- - -## ❓ FAQ Rápido - -**P: ¿Por dónde empiezo?** -R: Lee `TOOLS_DOCUMENTATION_INDEX.md` - -**P: ¿Quiero un ejemplo simple?** -R: Abre `QUICK_START.py` - -**P: ¿Necesito ejemplos reales?** -R: Mira `AGENDA_TOOLS_EXAMPLE.py` - -**P: ¿Cómo conecto con BD?** -R: Lee sección "Conectar a base de datos" en `TOOLS_GUIDE.md` - -**P: ¿Cómo testo mis tools?** -R: Usa `tests/test_naliia_agent_tools.py` como referencia - -**P: ¿Es seguro modificar tools.py?** -R: Sí, es exactamente para eso - ---- - -## ✅ Checklist de implementación - -- [x] Infraestructura de Registry implementada -- [x] Documentación completa creada -- [x] Ejemplos funcionales provistos -- [x] Tests incluidos -- [x] Code limpiado -- [x] Estructura lista para usar -- [x] Guías de inicio rápido -- [x] Índice de navegación - ---- - -## 🎯 Conclusión - -**Tu proyecto está listo.** - -El patrón Registry está implementado, documentado y listo para que crees tus herramientas personalizadas. La documentación es completa, con ejemplos prácticos y tests. - -### Comienza aquí: -``` -👉 TOOLS_DOCUMENTATION_INDEX.md -``` - ---- - -**Implementación completada:** 15 Feb 2026 -**Status:** ✅ Listo para producción -**Soporte:** Ver documentación incluida diff --git a/docs/REGISTRY_IMPLEMENTATION_SUMMARY.md b/docs/REGISTRY_IMPLEMENTATION_SUMMARY.md deleted file mode 100644 index c0ba7d4..0000000 --- a/docs/REGISTRY_IMPLEMENTATION_SUMMARY.md +++ /dev/null @@ -1,171 +0,0 @@ -# ✅ Resumen: Implementación del Patrón Registry para Tools - -## 📋 Qué se hizo - -Se implementó el **patrón Registry** para gestionar las herramientas del agente Naliia de forma centralizada, escalable y fácil de mantener. - -### Archivos modificados: - -| Archivo | Cambio | Estado | -|---------|--------|--------| -| `src/naliiabot/bot/tools/tools.py` | Removidas tools de ejemplo (Calculator, Greeter, Weather, Time) | ✅ Limpio | -| `src/naliiabot/bot/tools/__init__.py` | Removidas importaciones de tools de ejemplo | ✅ Actualizado | - -### Archivos ya existentes (infraestructura): - -| Archivo | Descripción | -|---------|-----------| -| `src/naliiabot/bot/tools/tool_registry.py` | Patrón Registry: `BaseTool` + `ToolRegistry` | - -### Archivos de documentación y ejemplos creados: - -| Archivo | Contenido | -|---------|-----------| -| **TOOLS_GUIDE.md** | Guía completa con ejemplos de uso | -| **AGENDA_TOOLS_EXAMPLE.py** | 5 herramientas reales para gestión de agenda | -| **CHANGES_SUMMARY.md** | Resumen de cambios | - -## 🎯 Estado actual - -El proyecto está listo para que **definas tus propias herramientas** en: - -``` -src/naliiabot/bot/tools/tools.py ← Aquí van TUS tools -``` - -## 📚 Cómo empezar - -### 1. Lee la documentación - -```bash -# Abre estos archivos en orden: -1. CHANGES_SUMMARY.md # Resumen rápido -2. TOOLS_GUIDE.md # Guía detallada -3. AGENDA_TOOLS_EXAMPLE.py # Ejemplos prácticos -``` - -### 2. Define una herramienta simple - -En `src/naliiabot/bot/tools/tools.py`: - -```python -from typing import Any, Dict -from .tool_registry import BaseTool - -class MiPrimeraHerramienta(BaseTool): - @property - def name(self) -> str: - return "mi_herramienta" - - @property - def description(self) -> str: - return "Descripción de qué hace" - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "param1": { - "type": "string", - "description": "Un parámetro" - } - }, - "required": ["param1"] - } - - def invoke(self, **kwargs) -> str: - param = kwargs.get("param1") - return f"Resultado para {param}" -``` - -### 3. Registra y usa - -```python -from src.naliiabot.bot.tools import ToolRegistry -from src.naliiabot.bot.tools.tools import MiPrimeraHerramienta - -registry = ToolRegistry() -registry.register(MiPrimeraHerramienta()) -tools = registry.get_all_tools_as_langchain() - -# Usar con el Agent -agent = Agent(model=modelo, tools=tools) -``` - -## 🔍 Inspeccionar el ToolRegistry - -```python -registry = ToolRegistry() -registry.register(MiHerramienta()) - -# Ver todas las tools -tools = registry.get_all_tools() - -# Ver nombres disponibles -nombres = registry.list_tool_names() # ['mi_herramienta', ...] - -# Obtener una específica -herramienta = registry.get_tool("mi_herramienta") - -# Verificar si existe -existe = registry.has_tool("mi_herramienta") # True - -# Obtener descripción -desc = registry.get_tool_description("mi_herramienta") -``` - -## ✨ Ventajas - -✅ **Centralizado** - Una única fuente de verdad para todas las tools -✅ **Extensible** - Agregar nuevas tools sin tocar código existente -✅ **Testeable** - Cada tool se prueba de forma independiente -✅ **Mantenible** - Cambios aislados en cada tool -✅ **Validado** - Schema automático de argumentos -✅ **Documentado** - Fácil inspeccionar tools disponibles -✅ **Seguro** - Sin tools de ejemplo conflictivas - -## 📁 Estructura de directorios - -``` -NaliiaBot/ -├── src/naliiabot/bot/tools/ -│ ├── __init__.py # Exporta ToolRegistry, BaseTool -│ ├── tool_registry.py # Infraestructura (BaseTool + ToolRegistry) -│ └── tools.py # ← TUS HERRAMIENTAS AQUÍ (vacío y listo) -│ -├── tests/ -│ └── test_naliia_agent_tools.py # Tests de tools (ya creados) -│ -├── TOOLS_GUIDE.md # Guía completa -├── AGENDA_TOOLS_EXAMPLE.py # Ejemplos reales para agenda -├── CHANGES_SUMMARY.md # Resumen de cambios -└── README.md -``` - -## 🚀 Próximos pasos sugeridos - -1. **Lee TOOLS_GUIDE.md** para entender completamente el patrón -2. **Copia ejemplos de AGENDA_TOOLS_EXAMPLE.py** si necesitas tools de agenda -3. **Crea tus propias herramientas** en `src/naliiabot/bot/tools/tools.py` -4. **Escribe tests** para tus tools (usa test_naliia_agent_tools.py como referencia) -5. **Integra con el API** en `src/naliiabotapi/main.py` - -## ❓ Preguntas frecuentes - -**P: ¿Cómo agrego una nueva herramienta?** -R: Define una clase que herede de `BaseTool` en `tools.py` y registra en `ToolRegistry` - -**P: ¿Puedo usar varias registries?** -R: Sí, puedes crear múltiples `ToolRegistry` si necesitas diferentes conjuntos de tools - -**P: ¿Cómo conecto una tool con una BD real?** -R: En el método `invoke()`, hace la consulta a tu BD. Los ejemplos aquí usan datos simulados. - -**P: ¿Necesito modificar agent.py?** -R: No, `agent.py` ya soporta tools. Solo necesitas crear las tools y pasar a `Agent(tools=...)` - ---- - -**Última actualización:** 15 Feb 2026 -**Status:** ✅ Implementación completada y documentada diff --git a/docs/TOOLS_DOCUMENTATION_INDEX.md b/docs/TOOLS_DOCUMENTATION_INDEX.md deleted file mode 100644 index 821089a..0000000 --- a/docs/TOOLS_DOCUMENTATION_INDEX.md +++ /dev/null @@ -1,229 +0,0 @@ -# 📚 Índice de Documentación: Patrón Registry para Tools - -Bienvenido al sistema de Tools de **NaliiaBot** usando el patrón Registry. - -## 🚀 Comienza por aquí - -**Si es tu primer día con esto:** - -1. **[QUICK_START.py](QUICK_START.py)** ⭐ (5 minutos) - - Tutorial interactivo paso a paso - - Ejemplo simple que funciona inmediatamente - - Puedes ejecutarlo: `python QUICK_START.py` - -2. **[REGISTRY_IMPLEMENTATION_SUMMARY.md](REGISTRY_IMPLEMENTATION_SUMMARY.md)** (10 minutos) - - Qué se hizo y por qué - - Cómo está organizado ahora - - Próximos pasos - -3. **[TOOLS_GUIDE.md](TOOLS_GUIDE.md)** (20 minutos) - - Guía completa del patrón Registry - - Métodos disponibles - - Mejores prácticas - -## 📖 Documentación por tema - -### Para crear herramientas - -| Documento | Contenido | -|-----------|-----------| -| **[TOOLS_GUIDE.md](TOOLS_GUIDE.md#2-crear-una-herramienta-personalizada)** | Cómo crear una herramienta básica | -| **[TOOLS_GUIDE.md](TOOLS_GUIDE.md#5-ejemplo-completo)** | Ejemplo completo con validaciones | -| **[AGENDA_TOOLS_EXAMPLE.py](AGENDA_TOOLS_EXAMPLE.py)** | 5 herramientas reales para agenda | - -### Para usar tools - -| Documento | Contenido | -|-----------|-----------| -| **[TOOLS_GUIDE.md](TOOLS_GUIDE.md#3-registrar-y-usar-herramientas)** | Cómo registrar y usar tools | -| **[TOOLS_GUIDE.md](TOOLS_GUIDE.md#4-métodos-disponibles)** | API completo de ToolRegistry | -| **[TOOLS_GUIDE.md](TOOLS_GUIDE.md#6-usar-con-el-agent)** | Integración con Agent | - -### Para entender la arquitectura - -| Documento | Contenido | -|-----------|-----------| -| **[REGISTRY_IMPLEMENTATION_SUMMARY.md](REGISTRY_IMPLEMENTATION_SUMMARY.md)** | Estructura general | -| **[CHANGES_SUMMARY.md](CHANGES_SUMMARY.md)** | Qué cambió respecto a antes | -| **[src/naliiabot/bot/tools/tool_registry.py](src/naliiabot/bot/tools/tool_registry.py)** | Código fuente del Registry | - -## 🎯 Casos de uso comunes - -### Caso 1: Crear una herramienta simple -``` -1. Lee: QUICK_START.py -2. Lee: TOOLS_GUIDE.md (sección 2) -3. Copia código de QUICK_START.py a tools.py -4. Listo ✅ -``` - -### Caso 2: Crear herramientas para gestionar agenda -``` -1. Lee: AGENDA_TOOLS_EXAMPLE.py -2. Adapta los ejemplos a tu lógica -3. Copia a tools.py -4. Registra en tu main.py -5. Listo ✅ -``` - -### Caso 3: Entender cómo funciona el Registry -``` -1. Lee: REGISTRY_IMPLEMENTATION_SUMMARY.md -2. Revisa: tool_registry.py -3. Lee: TOOLS_GUIDE.md (sección 4) -4. Experimenta con los métodos -5. Entiendido ✅ -``` - -### Caso 4: Hacer pruebas de tools -``` -1. Abre: tests/test_naliia_agent_tools.py -2. Agrega tus tests -3. Ejecuta: pytest tests/test_naliia_agent_tools.py -v -4. Testeado ✅ -``` - -## 📂 Estructura de archivos - -``` -NaliiaBot/ -│ -├── 📄 QUICK_START.py ← EMPIEZA AQUÍ -├── 📄 REGISTRY_IMPLEMENTATION_SUMMARY.md ← Resumen -├── 📄 TOOLS_GUIDE.md ← Guía completa -├── 📄 AGENDA_TOOLS_EXAMPLE.py ← Ejemplos reales -├── 📄 CHANGES_SUMMARY.md ← Qué cambió -├── 📄 TOOLS_DOCUMENTATION_INDEX.md ← Este archivo -│ -├── 📁 src/naliiabot/bot/tools/ -│ ├── __init__.py ← Exporta BaseTool, ToolRegistry -│ ├── tool_registry.py ← Infraestructura (código fuente) -│ └── tools.py ← ← TUS HERRAMIENTAS AQUÍ -│ -└── 📁 tests/ - └── test_naliia_agent_tools.py ← Tests de tools -``` - -## 🔍 Búsqueda rápida - -### Necesito... - -- **Crear mi primera tool** → [QUICK_START.py](QUICK_START.py) -- **Entender el patrón Registry** → [TOOLS_GUIDE.md](TOOLS_GUIDE.md) -- **Ver ejemplos de tools reales** → [AGENDA_TOOLS_EXAMPLE.py](AGENDA_TOOLS_EXAMPLE.py) -- **Saber qué cambió** → [CHANGES_SUMMARY.md](CHANGES_SUMMARY.md) -- **Registrar herramientas** → [TOOLS_GUIDE.md#3](TOOLS_GUIDE.md#3-registrar-y-usar-herramientas) -- **Ver métodos de ToolRegistry** → [TOOLS_GUIDE.md#4](TOOLS_GUIDE.md#4-métodos-disponibles-del-toolregistry) -- **Hacer tests** → [tests/test_naliia_agent_tools.py](tests/test_naliia_agent_tools.py) -- **Ver el código del Registry** → [src/naliiabot/bot/tools/tool_registry.py](src/naliiabot/bot/tools/tool_registry.py) - -## 📊 Recomendación de lectura - -### Para nuevos usuarios (20 minutos) -``` -1. QUICK_START.py (5 min) -2. TOOLS_GUIDE.md (15 min) - ↓ - Ahora puedes crear tools -``` - -### Para desarrollo completo (1 hora) -``` -1. QUICK_START.py (5 min) -2. REGISTRY_IMPLEMENTATION_SUMMARY.md (10 min) -3. TOOLS_GUIDE.md (20 min) -4. AGENDA_TOOLS_EXAMPLE.py (15 min) -5. Revisar tests (10 min) - ↓ - Experto en el patrón -``` - -### Para entender la arquitectura (30 minutos) -``` -1. CHANGES_SUMMARY.md (10 min) -2. tool_registry.py (15 min) -3. tests/test_naliia_agent_tools.py (5 min) - ↓ - Entiendes cómo está construido -``` - -## 🎓 Conceptos clave - -### BaseTool -Clase abstracta que define qué es una herramienta: -- `name`: Identificador único -- `description`: Para que el LLM sepa cuándo usarla -- `args_schema`: Qué argumentos acepta (JSON Schema) -- `invoke()`: Cómo se ejecuta - -**Leer en:** [TOOLS_GUIDE.md#estructura-básica](TOOLS_GUIDE.md#1-estructura-básica) - -### ToolRegistry -Clase que administra todas las herramientas: -- `register()`: Agregar una herramienta -- `get_tool()`: Obtener una específica -- `get_all_tools()`: Obtener todas (BaseTool) -- `get_all_tools_as_langchain()`: Obtener en formato LangChain - -**Leer en:** [TOOLS_GUIDE.md#métodos-disponibles](TOOLS_GUIDE.md#4-métodos-disponibles-del-toolregistry) - -### El flujo completo -``` -Tool (BaseTool) - ↓ -Registry (ToolRegistry) - ↓ -Agent (recibe tools) - ↓ -LLM (usa las tools) -``` - -**Leer en:** [TOOLS_GUIDE.md#uso-con-el-agent](TOOLS_GUIDE.md#6-usar-con-el-agent) - -## ✅ Checklist: Empezar a usar Tools - -- [ ] Leí QUICK_START.py -- [ ] Entiendo qué es BaseTool -- [ ] Entiendo qué es ToolRegistry -- [ ] Creé una herramienta simple en tools.py -- [ ] Registré la herramienta -- [ ] Usé la herramienta con Agent -- [ ] Los tests pasan -- [ ] Leí ejemplos de agenda (AGENDA_TOOLS_EXAMPLE.py) -- [ ] Sé cómo conectar con BD -- [ ] Sé cómo manejar errores - -Si marcaste todo ✅, ¡estás listo para trabajar con el sistema de tools! - -## 🆘 Necesito ayuda - -- **¿Cómo creo una tool?** → [TOOLS_GUIDE.md#2](TOOLS_GUIDE.md#2-crear-una-herramienta-personalizada) -- **¿Cuáles son los métodos?** → [TOOLS_GUIDE.md#4](TOOLS_GUIDE.md#4-métodos-disponibles-del-toolregistry) -- **¿Tengo un error?** → [TOOLS_GUIDE.md#7](TOOLS_GUIDE.md#7-ventajas-del-patrón-registry) -- **¿Quiero ejemplos?** → [AGENDA_TOOLS_EXAMPLE.py](AGENDA_TOOLS_EXAMPLE.py) - -## 📞 Resumen rápido - -### Lo esencial (30 segundos) - -```python -# 1. Crear una tool -class MiTool(BaseTool): - def name(self) -> str: - return "mi_tool" - # ... más detalles - -# 2. Registrar -registry = ToolRegistry() -registry.register(MiTool()) - -# 3. Usar -agent = Agent(model=modelo, tools=registry.get_all_tools_as_langchain()) -``` - -Eso es todo. El resto está en la documentación. - ---- - -**Última actualización:** 15 Feb 2026 -**Status:** ✅ Documentación completa diff --git a/docs/TOOLS_GUIDE.md b/docs/TOOLS_GUIDE.md deleted file mode 100644 index 82356df..0000000 --- a/docs/TOOLS_GUIDE.md +++ /dev/null @@ -1,351 +0,0 @@ -# Guía: Usar ToolRegistry para crear herramientas en NaliiaBot - -El patrón **Registry** permite gestionar de forma centralizada todas las herramientas del agente. Aquí te muestro cómo usarlo. - -## 1. Estructura básica - -El proyecto tiene esta estructura de tools: - -``` -src/naliiabot/bot/tools/ -├── __init__.py -├── tool_registry.py # Base + Registry -└── tools.py # Tus herramientas personalizadas -``` - -## 2. Crear una herramienta personalizada - -En el archivo `src/naliiabot/bot/tools/tools.py`, define tu herramienta: - -```python -from typing import Any, Dict -from .tool_registry import BaseTool - -class ObtenerAgendaTool(BaseTool): - """Obtiene los eventos de la agenda del usuario.""" - - @property - def name(self) -> str: - return "obtener_agenda" - - @property - def description(self) -> str: - return "Obtiene los eventos programados en la agenda del usuario para una fecha específica." - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "fecha": { - "type": "string", - "description": "Fecha en formato YYYY-MM-DD" - }, - "usuario_id": { - "type": "string", - "description": "ID del usuario" - } - }, - "required": ["fecha", "usuario_id"] - } - - def invoke(self, **kwargs) -> str: - fecha = kwargs.get("fecha") - usuario_id = kwargs.get("usuario_id") - - # Aquí va la lógica real: consultar DB, API, etc. - # Por ahora es un ejemplo simulado - return f"Eventos para {usuario_id} el {fecha}: Reunión 10:00, Almuerzo 12:30" -``` - -## 3. Registrar y usar herramientas - -### Opción A: En el código principal - -```python -from src.naliiabot.bot.tools.tool_registry import ToolRegistry -from src.naliiabot.bot.tools.tools import ObtenerAgendaTool, OtraHerramienta -from src.naliiabot.bot.agent.agent import Agent - -# Crear el registry -registry = ToolRegistry() - -# Registrar las herramientas -registry.register(ObtenerAgendaTool()) -registry.register(OtraHerramienta()) - -# Obtener en formato LangChain -herramientas_langchain = registry.get_all_tools_as_langchain() - -# Crear el agente con las herramientas -agent = Agent(model=mi_modelo, tools=herramientas_langchain) -``` - -### Opción B: Crear una factory para simplificar - -Crea un archivo `src/naliiabot/bot/tools/factory.py`: - -```python -from .tool_registry import ToolRegistry -from .tools import ObtenerAgendaTool, OtraHerramienta - -def create_tool_registry() -> ToolRegistry: - """Factory para crear el registry con todas las tools.""" - registry = ToolRegistry() - registry.register(ObtenerAgendaTool()) - registry.register(OtraHerramienta()) - return registry -``` - -Luego úsalo así: - -```python -from src.naliiabot.bot.tools.factory import create_tool_registry -from src.naliiabot.bot.agent.agent import Agent - -registry = create_tool_registry() -tools = registry.get_all_tools_as_langchain() - -agent = Agent(model=mi_modelo, tools=tools) -``` - -## 4. Métodos disponibles del ToolRegistry - -```python -registry = ToolRegistry() - -# Registrar una herramienta -registry.register(MiHerramienta()) - -# Obtener una herramienta específica -herramienta = registry.get_tool("obtener_agenda") - -# Obtener todas las herramientas como BaseTool -todas = registry.get_all_tools() - -# Obtener todas como LangChain Tools (para usar con Agent) -herramientas_lc = registry.get_all_tools_as_langchain() - -# Verificar si existe una herramienta -existe = registry.has_tool("obtener_agenda") - -# Listar nombres de todas las herramientas -nombres = registry.list_tool_names() - -# Obtener descripción de una herramienta -desc = registry.get_tool_description("obtener_agenda") -``` - -## 5. Ejemplo completo: Herramienta para gestionar agenda - -```python -from typing import Any, Dict -from .tool_registry import BaseTool -from datetime import datetime - -class AgregarEventoTool(BaseTool): - """Agrega un evento a la agenda del usuario.""" - - @property - def name(self) -> str: - return "agregar_evento" - - @property - def description(self) -> str: - return "Agrega un nuevo evento a la agenda del usuario." - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "usuario_id": { - "type": "string", - "description": "ID del usuario" - }, - "titulo": { - "type": "string", - "description": "Título del evento" - }, - "fecha": { - "type": "string", - "description": "Fecha en formato YYYY-MM-DD" - }, - "hora_inicio": { - "type": "string", - "description": "Hora de inicio en formato HH:MM" - }, - "duracion_minutos": { - "type": "integer", - "description": "Duración del evento en minutos", - "default": 30 - }, - "descripcion": { - "type": "string", - "description": "Descripción del evento (opcional)" - } - }, - "required": ["usuario_id", "titulo", "fecha", "hora_inicio"] - } - - def invoke(self, **kwargs) -> str: - usuario_id = kwargs.get("usuario_id") - titulo = kwargs.get("titulo") - fecha = kwargs.get("fecha") - hora = kwargs.get("hora_inicio") - duracion = kwargs.get("duracion_minutos", 30) - descripcion = kwargs.get("descripcion", "") - - try: - # Aquí iría la lógica para guardar en BD - # base_de_datos.agregar_evento(...) - - return ( - f"✓ Evento '{titulo}' agregado con éxito\n" - f"Fecha: {fecha}\n" - f"Hora: {hora}\n" - f"Duración: {duracion} minutos" - ) - except Exception as e: - return f"Error al agregar evento: {str(e)}" - - -class ModificarEventoTool(BaseTool): - """Modifica un evento existente.""" - - @property - def name(self) -> str: - return "modificar_evento" - - @property - def description(self) -> str: - return "Modifica los detalles de un evento existente en la agenda." - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "evento_id": { - "type": "string", - "description": "ID del evento a modificar" - }, - "titulo": { - "type": "string", - "description": "Nuevo título (opcional)" - }, - "hora_inicio": { - "type": "string", - "description": "Nueva hora en formato HH:MM (opcional)" - }, - "duracion_minutos": { - "type": "integer", - "description": "Nueva duración en minutos (opcional)" - } - }, - "required": ["evento_id"] - } - - def invoke(self, **kwargs) -> str: - evento_id = kwargs.get("evento_id") - - try: - # Lógica para actualizar en BD - return f"✓ Evento {evento_id} modificado correctamente" - except Exception as e: - return f"Error al modificar evento: {str(e)}" - - -class EliminarEventoTool(BaseTool): - """Elimina un evento de la agenda.""" - - @property - def name(self) -> str: - return "eliminar_evento" - - @property - def description(self) -> str: - return "Elimina un evento de la agenda del usuario." - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "evento_id": { - "type": "string", - "description": "ID del evento a eliminar" - }, - "usuario_id": { - "type": "string", - "description": "ID del usuario propietario" - } - }, - "required": ["evento_id", "usuario_id"] - } - - def invoke(self, **kwargs) -> str: - evento_id = kwargs.get("evento_id") - - try: - # Lógica para eliminar de BD - return f"✓ Evento {evento_id} eliminado correctamente" - except Exception as e: - return f"Error al eliminar evento: {str(e)}" -``` - -## 6. Usar con el Agent - -Una vez que has creado tus herramientas, úsalas con el agente: - -```python -from src.naliiabot.bot.tools.tool_registry import ToolRegistry -from src.naliiabot.bot.tools.tools import ( - ObtenerAgendaTool, - AgregarEventoTool, - ModificarEventoTool, - EliminarEventoTool -) -from src.naliiabot.bot.agent.agent import Agent -from langchain_anthropic import ChatAnthropic - -# Crear modelo -modelo = ChatAnthropic(model="claude-3-5-sonnet-20241022") - -# Crear registry y registrar herramientas -registry = ToolRegistry() -registry.register(ObtenerAgendaTool()) -registry.register(AgregarEventoTool()) -registry.register(ModificarEventoTool()) -registry.register(EliminarEventoTool()) - -# Crear agente con las herramientas -agent = Agent( - model=modelo, - tools=registry.get_all_tools_as_langchain() -) - -# Usar el agente -resultado = agent.invoke({ - "messages": [ - HumanMessage(content="Agrega una reunión el 15 de febrero a las 10:00") - ] -}) -``` - -## 7. Ventajas del patrón Registry - -✅ **Centralización**: Todas las tools en un solo lugar -✅ **Escalabilidad**: Fácil agregar nuevas herramientas -✅ **Testabilidad**: Cada tool se prueba independientemente -✅ **Mantenibilidad**: Cambios en una tool no afectan otras -✅ **Reusabilidad**: Las tools se pueden usar en múltiples agentes -✅ **Validación**: Verificación automática de esquemas -✅ **Inspección**: Fácil listar y documentar tools disponibles - -## 8. Próximos pasos - -1. Define tus herramientas específicas en `tools.py` -2. Crea un factory o inicializar el registry en tu main -3. Prueba con tests unitarios (los tests ya están en `test_naliia_agent_tools.py`) -4. Integra con el API FastAPI en `src/naliiabotapi/main.py` diff --git a/docs/TOOL_REGISTRY_GUIDE.md b/docs/TOOL_REGISTRY_GUIDE.md deleted file mode 100644 index c78c3c3..0000000 --- a/docs/TOOL_REGISTRY_GUIDE.md +++ /dev/null @@ -1,457 +0,0 @@ -# Tool Registry Pattern - Documentación - -## 📋 Descripción General - -El **Tool Registry** es un patrón de diseño que centraliza la gestión de herramientas (tools) del agente conversacional. Proporciona: - -- ✅ Registro centralizado de herramientas -- ✅ Validación de herramientas -- ✅ Gestión dinámica (añadir/remover tools) -- ✅ Interfaz fluida con Builder -- ✅ Fácil integración con el Agent -- ✅ Conversión a formato LangChain - ---- - -## 🏗️ Arquitectura - -### Componentes Principales - -``` -BaseTool (ABC) - ├── CalculatorTool - ├── GreeterTool - ├── WeatherTool - └── TimeTool - -ToolRegistry - └── Gestiona instancias de BaseTool - -ToolRegistryBuilder - └── Interfaz fluida para crear registros - -Agent - └── Integración con ToolRegistry -``` - ---- - -## 📝 Uso Básico - -### 1. Crear un Registry Básico - -```python -from src.naliiabot.bot.tools.tool_registry import ToolRegistry -from src.naliiabot.bot.tools.tools import CalculatorTool, GreeterTool - -# Crear el registro -registry = ToolRegistry() - -# Registrar herramientas -registry.register(CalculatorTool()) -registry.register(GreeterTool()) - -# Verificar -print(f"Tools registradas: {len(registry)}") # Output: 2 -``` - -### 2. Usar el Builder Pattern - -```python -from src.naliiabot.bot.tools.tool_registry import ToolRegistryBuilder - -registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .add(GreeterTool()) - .add(WeatherTool()) - .build()) -``` - -### 3. Integrar con el Agent - -```python -from src.naliiabot.bot.agent.agent import Agent, AgentConfig - -registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .add(GreeterTool()) - .build()) - -config = AgentConfig( - system_prompt="You are a helpful assistant", - max_iterations=5 -) - -agent = Agent(model=your_model, config=config, tools=registry) -``` - ---- - -## 🔧 API del ToolRegistry - -### Métodos Principales - -#### `register(tool: BaseTool) -> None` -Registra una nueva herramienta. - -```python -registry.register(CalculatorTool()) -``` - -#### `register_multiple(tools: List[BaseTool]) -> None` -Registra múltiples herramientas de una vez. - -```python -registry.register_multiple([ - CalculatorTool(), - GreeterTool(), - WeatherTool() -]) -``` - -#### `unregister(tool_name: str) -> None` -Desregistra una herramienta. - -```python -registry.unregister("calculator") -``` - -#### `get_tool(tool_name: str) -> Optional[BaseTool]` -Obtiene una herramienta específica. - -```python -calculator = registry.get_tool("calculator") -result = calculator.invoke(a=5, b=3, operation="add") -``` - -#### `get_all_tools() -> List[BaseTool]` -Obtiene todas las herramientas registradas. - -```python -all_tools = registry.get_all_tools() -for tool in all_tools: - print(f"- {tool.name}") -``` - -#### `get_langchain_tools() -> List[Tool]` -Convierte a formato LangChain Tool. - -```python -langchain_tools = registry.get_langchain_tools() -``` - -#### `has_tool(tool_name: str) -> bool` -Verifica si una herramienta existe. - -```python -if registry.has_tool("calculator"): - print("Calculator disponible") -``` - -#### `list_tools() -> Dict[str, str]` -Lista todas las herramientas con descripción. - -```python -tools_info = registry.list_tools() -# {"calculator": "Performs math operations", ...} -``` - -#### `clear() -> None` -Limpia el registro. - -```python -registry.clear() -``` - ---- - -## 🛠️ Crear una Nueva Tool - -### Paso 1: Extender BaseTool - -```python -from src.naliiabot.bot.tools.tool_registry import BaseTool -from typing import Any, Dict - -class MiHerramienta(BaseTool): - @property - def name(self) -> str: - return "mi_herramienta" - - @property - def description(self) -> str: - return "Descripción de qué hace mi herramienta" - - @property - def args_schema(self) -> Dict[str, Any]: - return { - "type": "object", - "properties": { - "param1": { - "type": "string", - "description": "Parámetro 1" - } - }, - "required": ["param1"] - } - - def invoke(self, **kwargs) -> str: - param1 = kwargs.get("param1") - # Implementar lógica - return f"Resultado: {param1}" -``` - -### Paso 2: Registrar - -```python -registry = ToolRegistry() -registry.register(MiHerramienta()) -``` - ---- - -## 📊 Herramientas Incluidas - -### CalculatorTool -Realiza operaciones matemáticas básicas. - -```python -tool = CalculatorTool() -result = tool.invoke(a=10, b=5, operation="add") # "Result: 10 add 5 = 15" -``` - -Operaciones soportadas: -- `add` - Suma -- `subtract` - Resta -- `multiply` - Multiplicación -- `divide` - División - -### GreeterTool -Proporciona saludos personalizados. - -```python -tool = GreeterTool() -result = tool.invoke(name="Alice", tone="formal") -``` - -Tonos disponibles: -- `formal` - Saludo formal -- `casual` - Saludo casual -- `friendly` - Saludo amigable - -### WeatherTool -Obtiene información del clima. - -```python -tool = WeatherTool() -result = tool.invoke(location="Madrid", units="celsius") -``` - -### TimeTool -Obtiene la hora actual. - -```python -tool = TimeTool() -result = tool.invoke(format="24h", timezone="UTC") -``` - ---- - -## 🧪 Testing - -### Tests Disponibles - -```bash -pytest tests/test_tool_registry.py -v -``` - -Categorías de tests: - -1. **TestBaseTool** - Pruebas de herramientas individuales -2. **TestToolRegistry** - Pruebas del registro -3. **TestToolRegistryBuilder** - Pruebas del builder -4. **TestAgentWithRegistry** - Integración con Agent -5. **TestPracticalUseCases** - Casos de uso prácticos - -### Escribir un Test - -```python -def test_mi_herramienta(): - """Prueba mi herramienta.""" - registry = ToolRegistry() - registry.register(MiHerramienta()) - - tool = registry.get_tool("mi_herramienta") - result = tool.invoke(param1="test") - - assert "test" in result -``` - ---- - -## 🔄 Casos de Uso - -### Caso 1: Agente de Servicio al Cliente - -```python -customer_service_registry = (ToolRegistryBuilder() - .add(GreeterTool()) - .add(WeatherTool()) - .add(TimeTool()) - .build()) -``` - -### Caso 2: Agente Matemático - -```python -math_agent_registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .build()) -``` - -### Caso 3: Agente Multipropósito - -```python -general_registry = (ToolRegistryBuilder() - .add_multiple([ - CalculatorTool(), - GreeterTool(), - WeatherTool(), - TimeTool() - ]) - .build()) -``` - -### Caso 4: Registro Dinámico - -```python -registry = ToolRegistry() - -# Añadir basado en configuración -if config.enable_calculator: - registry.register(CalculatorTool()) - -if config.enable_greeting: - registry.register(GreeterTool()) -``` - ---- - -## ✨ Ventajas del Patrón - -### 1. **Centralización** -Todas las tools en un lugar. - -### 2. **Extensibilidad** -Fácil añadir nuevas tools sin modificar el Agent. - -### 3. **Validación** -Valida que las tools sean de tipo correcto. - -### 4. **Mantenibilidad** -Código limpio y organizado. - -### 5. **Testing** -Fácil de testear y mockear. - -### 6. **Reutilización** -Registros pueden compartirse entre agentes. - ---- - -## 🚀 Ejemplos Completos - -Ver `examples/tool_registry_examples.py` para: - -- Ejemplo 1: Registry Básico -- Ejemplo 2: Builder Pattern -- Ejemplo 3: Integración con Agent -- Ejemplo 4: Registración Dinámica -- Ejemplo 5: Manejo de Errores -- Ejemplo 6: Ejecución de Herramientas -- Ejemplo 7: Formato LangChain - -```bash -python examples/tool_registry_examples.py -``` - ---- - -## 🎯 Mejores Prácticas - -### 1. Nombres Descriptivos -```python -# ✅ Bien -tool.name = "get_weather" -tool.name = "calculate_math" - -# ❌ Evitar -tool.name = "tool1" -tool.name = "t" -``` - -### 2. Descripciones Claras -```python -# ✅ Bien -description = "Gets weather info for a location. Returns temperature, humidity, conditions." - -# ❌ Evitar -description = "Gets weather" -``` - -### 3. Usar Builder para Registros Complejos -```python -# ✅ Bien -registry = (ToolRegistryBuilder() - .add(Tool1()) - .add(Tool2()) - .build()) - -# ❌ Evitar -registry = ToolRegistry() -registry.register(Tool1()) -registry.register(Tool2()) -``` - -### 4. Validar Argumentos -```python -# ✅ Bien -def invoke(self, **kwargs) -> str: - a = kwargs.get("a") - if a is None: - return "Error: Missing parameter 'a'" - return str(a * 2) -``` - ---- - -## 📚 Referencias - -- [BaseTool](src/naliiabot/bot/tools/tool_registry.py#L8) -- [ToolRegistry](src/naliiabot/bot/tools/tool_registry.py#L60) -- [ToolRegistryBuilder](src/naliiabot/bot/tools/tool_registry.py#L190) -- [Herramientas](src/naliiabot/bot/tools/tools.py) -- [Tests](tests/test_tool_registry.py) -- [Ejemplos](examples/tool_registry_examples.py) - ---- - -## ❓ FAQ - -**P: ¿Puedo cambiar el nombre de una herramienta?** -R: No directamente. Desregistra con el nombre antiguo y registra una nueva instancia. - -**P: ¿Qué pasa si dos tools tienen el mismo nombre?** -R: Se lanza `ValueError`. Cada tool debe tener un nombre único. - -**P: ¿Puedo heredar de BaseTool múltiples veces?** -R: No es recomendado. Usa composición en su lugar. - -**P: ¿Cómo convertir todo a formato LangChain?** -R: Usa `registry.get_langchain_tools()`. - ---- - -## 📞 Soporte - -Para reportar bugs o sugerencias, abre un issue en el repositorio. diff --git a/docs/examples/tool_registry_examples.py b/docs/examples/tool_registry_examples.py deleted file mode 100644 index 86a7ad8..0000000 --- a/docs/examples/tool_registry_examples.py +++ /dev/null @@ -1,210 +0,0 @@ -""" -Ejemplos de uso del patrón Registry con el Agent. - -Muestra diferentes formas de usar el ToolRegistry con el agente. -""" - -from src.naliiabot.bot.tools.tool_registry import ToolRegistry, ToolRegistryBuilder -from src.naliiabot.bot.tools.tools import ( - CalculatorTool, - GreeterTool, - WeatherTool, - TimeTool -) -from src.naliiabot.bot.agent.agent import Agent, AgentConfig - - -def example_1_basic_registry(): - """Ejemplo 1: Crear un registry básico y usarlo.""" - print("\n" + "="*60) - print("EJEMPLO 1: Registry Básico") - print("="*60) - - # Crear el registro - registry = ToolRegistry() - - # Registrar herramientas - registry.register(CalculatorTool()) - registry.register(GreeterTool()) - - # Ver herramientas disponibles - print(f"\nHerramientas disponibles: {len(registry)}") - for name, description in registry.list_tools().items(): - print(f" - {name}: {description[:50]}...") - - # Obtener una herramienta específica - calc = registry.get_tool("calculator") - result = calc.invoke(a=10, b=5, operation="add") - print(f"\nResultado de cálculo: {result}") - - -def example_2_builder_pattern(): - """Ejemplo 2: Usar el builder para crear un registry.""" - print("\n" + "="*60) - print("EJEMPLO 2: Builder Pattern") - print("="*60) - - # Usar el builder fluido - registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .add(GreeterTool()) - .add(WeatherTool()) - .add(TimeTool()) - .build()) - - print(f"\nRegistro creado con {len(registry)} herramientas") - print(f"Contenido: {registry}") - - -def example_3_agent_integration(): - """Ejemplo 3: Integrar registry con Agent.""" - print("\n" + "="*60) - print("EJEMPLO 3: Integración con Agent") - print("="*60) - - # Crear registro de tools - registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .add(GreeterTool()) - .add(WeatherTool()) - .build()) - - # Crear configuración - config = AgentConfig( - system_prompt="You are a helpful assistant with access to tools.", - max_iterations=5 - ) - - # Aquí iría el modelo real (mock para ejemplo) - # agent = Agent(model=your_model, config=config, tools=registry) - print(f"Agent configurado con {len(registry.get_all_tools())} herramientas") - print("Tools disponibles:") - for tool in registry.get_all_tools(): - print(f" - {tool.name}: {tool.description}") - - -def example_4_dynamic_tools(): - """Ejemplo 4: Registración dinámica de herramientas.""" - print("\n" + "="*60) - print("EJEMPLO 4: Registración Dinámica") - print("="*60) - - registry = ToolRegistry() - - # Fase 1: herramientas básicas - registry.register(CalculatorTool()) - print(f"Paso 1 - Herramientas: {len(registry)}") - - # Fase 2: añadir más - registry.register(GreeterTool()) - registry.register(WeatherTool()) - print(f"Paso 2 - Herramientas: {len(registry)}") - - # Fase 3: remover según necesidad - registry.unregister("calculator") - print(f"Paso 3 - Herramientas: {len(registry)}") - - # Ver estado final - print(f"\nHerramientas finales:") - for tool in registry.get_all_tools(): - print(f" - {tool.name}") - - -def example_5_error_handling(): - """Ejemplo 5: Manejo de errores.""" - print("\n" + "="*60) - print("EJEMPLO 5: Manejo de Errores") - print("="*60) - - registry = ToolRegistry() - - # Intentar operación inválida - try: - registry.register("not a tool") - except TypeError as e: - print(f"Error esperado: {e}") - - # Registrar herramienta - registry.register(CalculatorTool()) - - # Intentar registrar duplicada - try: - registry.register(CalculatorTool()) - except ValueError as e: - print(f"Error esperado: {e}") - - # Intentar desregistrar inexistente - try: - registry.unregister("nonexistent") - except KeyError as e: - print(f"Error esperado: {e}") - - -def example_6_tool_execution(): - """Ejemplo 6: Ejecutar herramientas desde el registry.""" - print("\n" + "="*60) - print("EJEMPLO 6: Ejecución de Herramientas") - print("="*60) - - registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .add(GreeterTool()) - .add(WeatherTool()) - .add(TimeTool()) - .build()) - - # Ejecutar calculator - calc_tool = registry.get_tool("calculator") - calc_result = calc_tool.invoke(a=15, b=3, operation="multiply") - print(f"\nCalculadora: {calc_result}") - - # Ejecutar greeter - greeter = registry.get_tool("greeter") - greeting = greeter.invoke(name="Alice", tone="formal") - print(f"Saludo: {greeting}") - - # Ejecutar weather - weather = registry.get_tool("get_weather") - weather_result = weather.invoke(location="Barcelona", units="celsius") - print(f"Clima: {weather_result}") - - # Ejecutar time - time_tool = registry.get_tool("get_time") - time_result = time_tool.invoke(format="24h", timezone="CET") - print(f"Hora: {time_result}") - - -def example_7_langchain_format(): - """Ejemplo 7: Convertir a formato LangChain.""" - print("\n" + "="*60) - print("EJEMPLO 7: Formato LangChain") - print("="*60) - - registry = (ToolRegistryBuilder() - .add(CalculatorTool()) - .add(GreeterTool()) - .build()) - - # Obtener herramientas en formato LangChain - langchain_tools = registry.get_langchain_tools() - - print(f"\nHerramientas en formato LangChain: {len(langchain_tools)}") - for tool in langchain_tools: - print(f" - Nombre: {tool.name}") - print(f" Descripción: {tool.description[:50]}...") - - -if __name__ == "__main__": - print("\n🚀 EJEMPLOS DE USO DEL TOOL REGISTRY") - - example_1_basic_registry() - example_2_builder_pattern() - example_3_agent_integration() - example_4_dynamic_tools() - example_5_error_handling() - example_6_tool_execution() - example_7_langchain_format() - - print("\n" + "="*60) - print("✅ Ejemplos completados") - print("="*60 + "\n")