""" ============================================================================= THE FACTORY - Director ============================================================================= Coordina el proceso de generación iterativa. - Prepara contexto para el Executor - Decide cuándo converger - Gestiona presupuesto ============================================================================= """ import logging from typing import Dict, Any, Optional from config import FactoryConfig, FunctionType logger = logging.getLogger("factory.director") class Director: """ El Director coordina el proceso de generación iterativa. """ def __init__(self, config: FactoryConfig): self.config = config def prepare_context( self, seed: str, objective: str, function: FunctionType, previous_artifact: Optional[Any], feedback: Optional[str], iteration: int, context: Dict[str, Any] ) -> Dict[str, Any]: """ Prepara el contexto para el Executor. Args: seed: Prompt inicial objective: Objetivo a alcanzar function: Tipo de función previous_artifact: Artefacto de iteración anterior feedback: Feedback del Evaluator iteration: Número de iteración actual context: Contexto adicional del usuario Returns: Contexto preparado para el Executor """ exec_context = { "seed": seed, "objective": objective, "function": function, "iteration": iteration, "is_first_iteration": iteration == 1, "user_context": context } if iteration == 1: # Primera iteración: usar seed directamente exec_context["prompt"] = self._build_initial_prompt(seed, objective, function) else: # Iteraciones posteriores: incorporar feedback exec_context["previous_artifact"] = previous_artifact exec_context["feedback"] = feedback exec_context["prompt"] = self._build_refinement_prompt( seed, objective, function, previous_artifact, feedback, iteration ) # Seleccionar modelo apropiado exec_context["model"] = self._select_model(function, iteration, context) return exec_context def _build_initial_prompt( self, seed: str, objective: str, function: FunctionType ) -> str: """Construye prompt para primera iteración.""" if function == FunctionType.TEXT_GENERATION: return f"""Genera contenido de alta calidad basado en lo siguiente: SOLICITUD: {seed} OBJETIVO: {objective} Proporciona una respuesta completa, bien estructurada y profesional.""" elif function == FunctionType.CODE_GENERATION: return f"""Genera código de alta calidad basado en lo siguiente: SOLICITUD: {seed} OBJETIVO: {objective} El código debe: - Ser limpio y bien documentado - Seguir mejores prácticas - Incluir manejo de errores apropiado - Ser eficiente y mantenible""" elif function == FunctionType.IMAGE_GENERATION: return f"""{seed} Style: Professional, high quality, detailed Objective: {objective}""" elif function == FunctionType.DOCUMENT_GENERATION: return f"""Genera un documento profesional: TIPO DE DOCUMENTO: {seed} OBJETIVO: {objective} El documento debe ser: - Profesional y bien formateado - Completo con toda la información necesaria - Claro y fácil de leer""" else: return f"{seed}\n\nObjective: {objective}" def _build_refinement_prompt( self, seed: str, objective: str, function: FunctionType, previous_artifact: Any, feedback: str, iteration: int ) -> str: """Construye prompt para iteraciones de refinamiento.""" # Truncar artefacto anterior si es muy largo prev_str = str(previous_artifact) if len(prev_str) > 2000: prev_str = prev_str[:2000] + "\n[...truncado...]" if function in [FunctionType.TEXT_GENERATION, FunctionType.DOCUMENT_GENERATION]: return f"""Mejora el siguiente contenido basándote en el feedback: SOLICITUD ORIGINAL: {seed} OBJETIVO: {objective} CONTENIDO ANTERIOR (iteración {iteration - 1}): {prev_str} FEEDBACK A INCORPORAR: {feedback} Genera una versión mejorada que aborde el feedback mientras mantiene los aspectos positivos.""" elif function == FunctionType.CODE_GENERATION: return f"""Mejora el siguiente código basándote en el feedback: SOLICITUD ORIGINAL: {seed} OBJETIVO: {objective} CÓDIGO ANTERIOR (iteración {iteration - 1}): ``` {prev_str} ``` FEEDBACK A INCORPORAR: {feedback} Genera una versión mejorada del código.""" elif function == FunctionType.IMAGE_GENERATION: return f"""{seed} Previous attempt feedback: {feedback} Iteration: {iteration} Objective: {objective} Improve based on feedback while maintaining the core concept.""" else: return f"""Mejora basándote en el feedback: Original: {seed} Objetivo: {objective} Anterior: {prev_str} Feedback: {feedback} Genera versión mejorada.""" def _select_model( self, function: FunctionType, iteration: int, context: Dict[str, Any] ) -> str: """Selecciona el modelo apropiado.""" # Si el usuario especificó un modelo, usarlo if "model" in context: return context["model"] # Por defecto, usar el modelo configurado para la función return self.config.default_models.get(function, "claude-sonnet") def should_converge( self, confidence: float, iteration: int, previous_confidence: float, budget_used: float, budget_total: float ) -> bool: """ Decide si el job debe converger. Criterios: 1. Umbral de confianza alcanzado 2. Rendimientos decrecientes (mejora < threshold) 3. Presupuesto casi agotado """ # 1. Umbral de confianza if confidence >= self.config.convergence_threshold: logger.info(f"Convergencia por umbral: {confidence:.2f} >= {self.config.convergence_threshold}") return True # 2. Rendimientos decrecientes if iteration > 1 and confidence >= self.config.diminishing_returns_min_confidence: improvement = confidence - previous_confidence if improvement < self.config.diminishing_returns_threshold: logger.info(f"Convergencia por rendimientos decrecientes: mejora {improvement:.3f} < {self.config.diminishing_returns_threshold}") return True # 3. Presupuesto casi agotado (>90% usado) if budget_used >= budget_total * 0.9: logger.info(f"Convergencia por presupuesto: ${budget_used:.4f} >= 90% de ${budget_total:.4f}") return True return False