feat: Add docs

This commit is contained in:
2026-02-15 16:03:09 -05:00
parent e28c42ddd8
commit 9823bc19d2
14 changed files with 3208 additions and 0 deletions

351
docs/TOOLS_GUIDE.md Normal file
View File

@@ -0,0 +1,351 @@
# 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`