122 lines
4.2 KiB
Python
122 lines
4.2 KiB
Python
from llms.Modelos.Base_model import ModeloABC
|
|
from llms.Memory.Base_MemoryConv import MemoryConvABC
|
|
|
|
from datetime import datetime
|
|
from typing import Optional, List, Union
|
|
|
|
|
|
class AgenteAI:
|
|
def __init__(
|
|
self,
|
|
modelo: ModeloABC,
|
|
nombre: str,
|
|
descripcion: str,
|
|
system_prompt: str, # <- pertenece al agente
|
|
rol: str,
|
|
objetivos: List[str],
|
|
memoria: Optional[MemoryConvABC] = None,
|
|
version: str = "1.0.0",
|
|
tools: Optional[List] = None,
|
|
output_schema: Optional[dict] = None, # <- nuevo parámetro
|
|
):
|
|
self.modelo = modelo
|
|
self.memoria = memoria
|
|
self.tools = tools or []
|
|
self.output_schema = output_schema
|
|
|
|
self.nombre = nombre
|
|
self.descripcion = descripcion
|
|
self.system_prompt = system_prompt
|
|
self.rol = rol
|
|
self.objetivos = objetivos
|
|
self.version = version
|
|
|
|
self.created_at = datetime.now()
|
|
self.updated_at = self.created_at
|
|
self.numero_interacciones = 0
|
|
|
|
def actualizar_configuracion(self, **kwargs):
|
|
for clave, valor in kwargs.items():
|
|
if hasattr(self, clave):
|
|
setattr(self, clave, valor)
|
|
self.updated_at = datetime.now()
|
|
|
|
|
|
@property
|
|
def full_system_prompt(self) -> str:
|
|
partes = [
|
|
f"Tu nombre es: {self.nombre}",
|
|
f"Tu descripción: {self.descripcion}",
|
|
f"Tu Rol: {self.rol}",
|
|
f"Tus Objetivos: {', '.join(self.objetivos)}",
|
|
""
|
|
]
|
|
|
|
# Incluir herramientas disponibles
|
|
herramientas = self._obtener_descripcion_tools()
|
|
if herramientas:
|
|
partes.append("Estas son tus herramientas disponibles:\n")
|
|
partes.extend(herramientas)
|
|
partes.append("Úsalas cuando creas oportuno.\n")
|
|
|
|
partes.append(self.system_prompt)
|
|
|
|
if self.output_schema:
|
|
partes.append(
|
|
"SIEMPRE formatea la respuesta final siguiendo estrictamente el siguiente esquema JSON:"
|
|
)
|
|
partes.append(f"```json\n{self.output_schema}\n```")
|
|
|
|
return "\n".join(partes)
|
|
|
|
def _obtener_descripcion_tools(self) -> List[str]:
|
|
"""
|
|
Devuelve una lista de strings con el nombre y descripción de cada herramienta
|
|
recogida desde los servidores MCP conectados.
|
|
"""
|
|
descripciones = []
|
|
if not hasattr(self, "mcp_servers"):
|
|
return descripciones
|
|
|
|
for server in self.mcp_servers:
|
|
if hasattr(server, "tools") and server.tools:
|
|
for tool in server.tools:
|
|
# tool puede ser string o dict, depende cómo lo expongas
|
|
if isinstance(tool, str):
|
|
descripciones.append(f"- {tool}: [sin descripción]")
|
|
elif isinstance(tool, dict):
|
|
nombre = tool.get("name", "¿?")
|
|
descripcion = tool.get("description", "[sin descripción]")
|
|
descripciones.append(f"- {nombre}: {descripcion}")
|
|
elif hasattr(tool, "name"):
|
|
descripcion = getattr(tool, "description", "[sin descripción]")
|
|
descripciones.append(f"- {tool.name}: {descripcion}")
|
|
return descripciones
|
|
|
|
async def interactuar(self, prompt: str) -> str:
|
|
if not self.modelo:
|
|
raise ValueError("El agente no tiene un modelo asignado.")
|
|
|
|
historial = []
|
|
if self.memoria:
|
|
historial = self.memoria.cargar_historial_chat()
|
|
|
|
contexto = historial + [{"role": "user", "content": prompt}]
|
|
prompt_final = self._formatear_prompt(contexto)
|
|
|
|
# Espera la respuesta del modelo de forma asíncrona
|
|
respuesta = await self.modelo.responder(
|
|
prompt=prompt_final,
|
|
system_prompt=self.full_system_prompt
|
|
)
|
|
|
|
if self.memoria:
|
|
self.memoria.guardar_turno("user", prompt)
|
|
self.memoria.guardar_turno("assistant", respuesta)
|
|
|
|
self.numero_interacciones += 1
|
|
self.updated_at = datetime.now()
|
|
return respuesta
|
|
|
|
def _formatear_prompt(self, mensajes: List[dict]) -> str:
|
|
return "\n".join([f"{msg['role']}: {msg['content']}" for msg in mensajes]) |