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
255 lines
6.9 KiB
Python
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
|