Files
factory/director.py
ARCHITECT 1cad39bc9e Initial commit: THE FACTORY - Iterative Image Generation
Tasks:
- image_generate: Generate image from prompt
- image_variant: Generate variant of existing image
- image_upscale: Increase resolution

Models: SDXL, Flux, SDXL-Turbo
RunPod Serverless Handler
2026-01-06 08:28:16 +00:00

255 lines
6.9 KiB
Python

"""
=============================================================================
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