Spaces:
Paused
Paused
Update api/ltx/ltx_aduc_pipeline.py
Browse files- api/ltx/ltx_aduc_pipeline.py +86 -23
api/ltx/ltx_aduc_pipeline.py
CHANGED
|
@@ -49,14 +49,11 @@ def add_deps_to_path():
|
|
| 49 |
add_deps_to_path()
|
| 50 |
|
| 51 |
# --- Módulos da nossa Arquitetura ---
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
except ImportError as e:
|
| 58 |
-
logging.critical(f"A crucial import from the local API/architecture failed. Error: {e}", exc_info=True)
|
| 59 |
-
sys.exit(1)
|
| 60 |
|
| 61 |
# ==============================================================================
|
| 62 |
# --- CLASSE DE SERVIÇO (O ORQUESTRADOR) ---
|
|
@@ -183,31 +180,95 @@ class VideoService:
|
|
| 183 |
# --- UNIDADES DE TRABALHO E HELPERS INTERNOS ---
|
| 184 |
# ==========================================================================
|
| 185 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
@log_function_io
|
| 187 |
def _generate_single_chunk_low(self, **kwargs) -> Optional[torch.Tensor]:
|
| 188 |
-
"""[WORKER] Calls the
|
| 189 |
height_padded, width_padded = (self._align(d) for d in (kwargs['height'], kwargs['width']))
|
| 190 |
downscale_factor = self.config.get("downscale_factor", 0.6666666)
|
| 191 |
vae_scale_factor = self.pipeline.vae_scale_factor
|
| 192 |
downscaled_height = self._align(int(height_padded * downscale_factor), vae_scale_factor)
|
| 193 |
downscaled_width = self._align(int(width_padded * downscale_factor), vae_scale_factor)
|
| 194 |
|
|
|
|
| 195 |
first_pass_config = self.config.get("first_pass", {}).copy()
|
|
|
|
|
|
|
| 196 |
if kwargs.get("ltx_configs_override"):
|
| 197 |
-
self._apply_ui_overrides(first_pass_config, kwargs
|
| 198 |
|
|
|
|
| 199 |
pipeline_kwargs = {
|
| 200 |
-
"prompt": kwargs['prompt'],
|
| 201 |
-
"
|
| 202 |
-
"
|
| 203 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
}
|
| 205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
with torch.autocast(device_type=self.main_device.type, dtype=self.runtime_autocast_dtype, enabled="cuda" in self.main_device.type):
|
| 207 |
latents_raw = self.pipeline(**pipeline_kwargs).images
|
| 208 |
|
| 209 |
return latents_raw.to(self.main_device)
|
| 210 |
-
|
| 211 |
@log_function_io
|
| 212 |
def _finalize_generation(self, final_latents: torch.Tensor, base_filename: str, seed: int) -> Tuple[str, str]:
|
| 213 |
"""Delegates final decoding and encoding to specialist services."""
|
|
@@ -224,8 +285,14 @@ class VideoService:
|
|
| 224 |
return str(video_path), str(final_latents_path)
|
| 225 |
|
| 226 |
def _apply_ui_overrides(self, config_dict: Dict, overrides: Dict):
|
| 227 |
-
|
| 228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
|
| 230 |
def _save_and_log_video(self, pixel_tensor: torch.Tensor, base_filename: str) -> Path:
|
| 231 |
with tempfile.TemporaryDirectory() as temp_dir:
|
|
@@ -259,9 +326,5 @@ class VideoService:
|
|
| 259 |
# ==============================================================================
|
| 260 |
# --- INSTANCIAÇÃO SINGLETON ---
|
| 261 |
# ==============================================================================
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
logging.info("Global VideoService orchestrator instance created successfully.")
|
| 265 |
-
except Exception as e:
|
| 266 |
-
logging.critical(f"Failed to initialize VideoService: {e}", exc_info=True)
|
| 267 |
-
sys.exit(1)
|
|
|
|
| 49 |
add_deps_to_path()
|
| 50 |
|
| 51 |
# --- Módulos da nossa Arquitetura ---
|
| 52 |
+
from api.managers.gpu_manager import gpu_manager
|
| 53 |
+
from api.ltx.ltx_aduc_manager import ltx_pool_manager, LatentConditioningItem
|
| 54 |
+
from api.ltx.vae_aduc_pipeline import vae_server_singleton
|
| 55 |
+
from tools.video_encode_tool import video_encode_tool_singleton
|
| 56 |
+
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
# ==============================================================================
|
| 59 |
# --- CLASSE DE SERVIÇO (O ORQUESTRADOR) ---
|
|
|
|
| 180 |
# --- UNIDADES DE TRABALHO E HELPERS INTERNOS ---
|
| 181 |
# ==========================================================================
|
| 182 |
|
| 183 |
+
def _log_conditioning_items(self, items: List[ConditioningItem]):
|
| 184 |
+
"""
|
| 185 |
+
Logs detailed information about a list of ConditioningItem objects.
|
| 186 |
+
This is a dedicated debug helper function.
|
| 187 |
+
"""
|
| 188 |
+
# Só imprime o log se o nível de logging for DEBUG
|
| 189 |
+
if logging.getLogger().isEnabledFor(logging.INFO):
|
| 190 |
+
log_str = ["\n" + "="*25 + " INFO: Conditioning Items " + "="*25]
|
| 191 |
+
if not items:
|
| 192 |
+
log_str.append(" -> Lista de conditioning_items está vazia.")
|
| 193 |
+
else:
|
| 194 |
+
for i, item in enumerate(items):
|
| 195 |
+
if hasattr(item, 'media_item') and isinstance(item.media_item, torch.Tensor):
|
| 196 |
+
t = item.media_item
|
| 197 |
+
log_str.append(
|
| 198 |
+
f" -> Item [{i}]: "
|
| 199 |
+
f"Tensor(shape={list(t.shape)}, "
|
| 200 |
+
f"device='{t.device}', "
|
| 201 |
+
f"dtype={t.dtype}), "
|
| 202 |
+
f"Target Frame = {item.media_frame_number}, "
|
| 203 |
+
f"Strength = {item.conditioning_strength:.2f}"
|
| 204 |
+
)
|
| 205 |
+
else:
|
| 206 |
+
log_str.append(f" -> Item [{i}]: Não contém um tensor válido.")
|
| 207 |
+
log_str.append("="*75 + "\n")
|
| 208 |
+
|
| 209 |
+
# Usa o logger de debug para imprimir a mensagem completa
|
| 210 |
+
logging.info("\n".join(log_str))
|
| 211 |
+
|
| 212 |
+
|
| 213 |
@log_function_io
|
| 214 |
def _generate_single_chunk_low(self, **kwargs) -> Optional[torch.Tensor]:
|
| 215 |
+
"""[WORKER] Calls the pipeline to generate a single chunk of latents."""
|
| 216 |
height_padded, width_padded = (self._align(d) for d in (kwargs['height'], kwargs['width']))
|
| 217 |
downscale_factor = self.config.get("downscale_factor", 0.6666666)
|
| 218 |
vae_scale_factor = self.pipeline.vae_scale_factor
|
| 219 |
downscaled_height = self._align(int(height_padded * downscale_factor), vae_scale_factor)
|
| 220 |
downscaled_width = self._align(int(width_padded * downscale_factor), vae_scale_factor)
|
| 221 |
|
| 222 |
+
# 1. Começa com a configuração padrão
|
| 223 |
first_pass_config = self.config.get("first_pass", {}).copy()
|
| 224 |
+
|
| 225 |
+
# 2. Aplica os overrides da UI, se existirem
|
| 226 |
if kwargs.get("ltx_configs_override"):
|
| 227 |
+
self._apply_ui_overrides(first_pass_config, kwargs.get("ltx_configs_override"))
|
| 228 |
|
| 229 |
+
# 3. Monta o dicionário de argumentos SEM conditioning_items primeiro
|
| 230 |
pipeline_kwargs = {
|
| 231 |
+
"prompt": kwargs['prompt'],
|
| 232 |
+
"negative_prompt": kwargs['negative_prompt'],
|
| 233 |
+
"height": downscaled_height,
|
| 234 |
+
"width": downscaled_width,
|
| 235 |
+
"num_frames": kwargs['num_frames'],
|
| 236 |
+
"frame_rate": int(DEFAULT_FPS),
|
| 237 |
+
"generator": torch.Generator(device=self.main_device).manual_seed(kwargs['seed']),
|
| 238 |
+
"output_type": "latent",
|
| 239 |
+
#"conditioning_items": conditioning_items if conditioning_items else None,
|
| 240 |
+
"media_items": None,
|
| 241 |
+
"decode_timestep": self.config["decode_timestep"],
|
| 242 |
+
"decode_noise_scale": self.config["decode_noise_scale"],
|
| 243 |
+
"stochastic_sampling": self.config["stochastic_sampling"],
|
| 244 |
+
"image_cond_noise_scale": 0.01,
|
| 245 |
+
"is_video": True,
|
| 246 |
+
"vae_per_channel_normalize": True,
|
| 247 |
+
"mixed_precision": (self.config["precision"] == "mixed_precision"),
|
| 248 |
+
"offload_to_cpu": False,
|
| 249 |
+
"enhance_prompt": False,
|
| 250 |
+
#"skip_layer_strategy": SkipLayerStrategy.AttentionValues,
|
| 251 |
+
**first_pass_config
|
| 252 |
}
|
| 253 |
|
| 254 |
+
# --- Bloco de Logging para Depuração ---
|
| 255 |
+
# 4. Loga os argumentos do pipeline (sem os tensores de condição)
|
| 256 |
+
logging.info(f"\n[Info] Pipeline Arguments (BASE):\n {json.dumps(pipeline_kwargs, indent=2, default=str)}\n")
|
| 257 |
+
|
| 258 |
+
# Loga os conditioning_items separadamente com a nossa função helper
|
| 259 |
+
conditioning_items_list = kwargs.get('conditioning_items')
|
| 260 |
+
self._log_conditioning_items(conditioning_items_list)
|
| 261 |
+
# --- Fim do Bloco de Logging ---
|
| 262 |
+
|
| 263 |
+
# 5. Adiciona os conditioning_items ao dicionário
|
| 264 |
+
pipeline_kwargs['conditioning_items'] = conditioning_items_list
|
| 265 |
+
|
| 266 |
+
# 6. Executa o pipeline com o dicionário completo
|
| 267 |
with torch.autocast(device_type=self.main_device.type, dtype=self.runtime_autocast_dtype, enabled="cuda" in self.main_device.type):
|
| 268 |
latents_raw = self.pipeline(**pipeline_kwargs).images
|
| 269 |
|
| 270 |
return latents_raw.to(self.main_device)
|
| 271 |
+
|
| 272 |
@log_function_io
|
| 273 |
def _finalize_generation(self, final_latents: torch.Tensor, base_filename: str, seed: int) -> Tuple[str, str]:
|
| 274 |
"""Delegates final decoding and encoding to specialist services."""
|
|
|
|
| 285 |
return str(video_path), str(final_latents_path)
|
| 286 |
|
| 287 |
def _apply_ui_overrides(self, config_dict: Dict, overrides: Dict):
|
| 288 |
+
"""Applies advanced settings from the UI to a config dictionary."""
|
| 289 |
+
# Override step counts
|
| 290 |
+
for key in ["num_inference_steps", "skip_initial_inference_steps", "skip_final_inference_steps"]:
|
| 291 |
+
ui_value = overrides.get(key)
|
| 292 |
+
if ui_value and ui_value > 0:
|
| 293 |
+
config_dict[key] = ui_value
|
| 294 |
+
logging.info(f"Override: '{key}' set to {ui_value} by UI.")
|
| 295 |
+
|
| 296 |
|
| 297 |
def _save_and_log_video(self, pixel_tensor: torch.Tensor, base_filename: str) -> Path:
|
| 298 |
with tempfile.TemporaryDirectory() as temp_dir:
|
|
|
|
| 326 |
# ==============================================================================
|
| 327 |
# --- INSTANCIAÇÃO SINGLETON ---
|
| 328 |
# ==============================================================================
|
| 329 |
+
video_generation_service = VideoService()
|
| 330 |
+
logging.info("Global VideoService orchestrator instance created successfully.")
|
|
|
|
|
|
|
|
|
|
|
|