dagloop5 commited on
Commit
fc8c94a
·
verified ·
1 Parent(s): ffc7a7d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -39
app.py CHANGED
@@ -293,66 +293,158 @@ pipeline = LTX23DistilledA2VPipeline(
293
  distilled_checkpoint_path=checkpoint_path,
294
  spatial_upsampler_path=spatial_upsampler_path,
295
  gemma_root=gemma_root,
296
- # initial LoRAs (strengths set to zero by default; will be adjusted at runtime)
297
- loras=[
298
- (pose_lora_path, 0.0),
299
- (general_lora_path, 0.0),
300
- (motion_lora_path, 0.0),
301
- ],
302
  quantization=QuantizationPolicy.fp8_cast(), # keep FP8 quantization unchanged
303
  )
304
  # ----------------------------------------------------------------
305
 
306
- # ---- Insert block: helper to apply LoRA strengths at runtime (between lines 281 and 283) ----
307
  def apply_loras_to_pipeline(pose_strength: float, general_strength: float, motion_strength: float):
308
  """
309
- Best-effort attempt to set LoRA strengths on the existing pipeline without creating a new pipeline object.
310
- Tries common APIs that model_ledger / pipeline implementations may provide; falls back to setting
311
- pipeline.loras (for lazy fusion) and logs a note.
 
 
 
312
  """
313
- # Build the spec list (keep ordering consistent with the pipeline loras list created above)
314
- lora_specs = [
 
 
315
  (pose_lora_path, float(pose_strength)),
316
  (general_lora_path, float(general_strength)),
317
  (motion_lora_path, float(motion_strength)),
318
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  try:
320
- # Preferred: model_ledger exposes an apply_loras API that fuses adapters in-place.
321
- if hasattr(pipeline, "model_ledger") and hasattr(pipeline.model_ledger, "apply_loras"):
322
- print("[LoRA] Applying LoRAs via pipeline.model_ledger.apply_loras(...)")
323
- pipeline.model_ledger.apply_loras(lora_specs)
 
 
 
 
324
  return
325
-
326
- # Alternative: pipeline may have helper 'set_loras' or similar
327
  if hasattr(pipeline, "set_loras"):
328
- print("[LoRA] Applying LoRAs via pipeline.set_loras(...)")
329
- pipeline.set_loras(lora_specs)
330
- return
331
-
332
- # Fallback: set an attribute that some pipeline implementations inspect lazily.
333
- print("[LoRA] Setting pipeline.loras attribute (fallback). If pipeline supports lazy fusion, new strengths will be used.")
334
- pipeline.loras = lora_specs
335
- return
336
 
 
 
 
 
337
  except Exception as e:
338
- # Non-fatal: advise user and keep running with whatever pipeline state exists.
339
- print(f"[LoRA] Warning: failed to apply LoRAs at runtime: {type(e).__name__}: {e}")
340
- print("[LoRA] If you see this, the pipeline may require a restart or an explicit fusion API to apply LoRAs.")
341
- # ----------------------------------------------------------------
342
 
 
343
  # Preload all models for ZeroGPU tensor packing.
344
  print("Preloading all models (including Gemma and audio components)...")
345
  ledger = pipeline.model_ledger
346
- _transformer = ledger.transformer()
347
- _video_encoder = ledger.video_encoder()
348
- _video_decoder = ledger.video_decoder()
349
- _audio_encoder = ledger.audio_encoder()
350
- _audio_decoder = ledger.audio_decoder()
351
- _vocoder = ledger.vocoder()
352
- _spatial_upsampler = ledger.spatial_upsampler()
353
- _text_encoder = ledger.text_encoder()
354
- _embeddings_processor = ledger.gemma_embeddings_processor()
355
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  ledger.transformer = lambda: _transformer
357
  ledger.video_encoder = lambda: _video_encoder
358
  ledger.video_decoder = lambda: _video_decoder
@@ -362,7 +454,9 @@ ledger.vocoder = lambda: _vocoder
362
  ledger.spatial_upsampler = lambda: _spatial_upsampler
363
  ledger.text_encoder = lambda: _text_encoder
364
  ledger.gemma_embeddings_processor = lambda: _embeddings_processor
 
365
  print("All models preloaded (including Gemma text encoder and audio encoder)!")
 
366
 
367
  print("=" * 80)
368
  print("Pipeline ready!")
 
293
  distilled_checkpoint_path=checkpoint_path,
294
  spatial_upsampler_path=spatial_upsampler_path,
295
  gemma_root=gemma_root,
296
+ loras=[],
 
 
 
 
 
297
  quantization=QuantizationPolicy.fp8_cast(), # keep FP8 quantization unchanged
298
  )
299
  # ----------------------------------------------------------------
300
 
301
+ # ---- REPLACE apply_loras_to_pipeline WITH THIS IMPLEMENTATION ----
302
  def apply_loras_to_pipeline(pose_strength: float, general_strength: float, motion_strength: float):
303
  """
304
+ Rebuild the transformer with the requested LoRA strengths and hot-swap into the ledger.
305
+ Strategy (in order):
306
+ 1. If the ledger/builder object exists and exposes 'lora' + 'loras' + the original transformer factory,
307
+ mutate builder.loras (clear and append .lora(...)) and call the saved original factory to rebuild.
308
+ 2. If a dedicated ledger.apply_loras or pipeline.set_loras exists, try calling them.
309
+ 3. Fallback: set pipeline.loras attribute (best-effort, may be ignored).
310
  """
311
+ ledger = pipeline.model_ledger
312
+
313
+ # Build convenience list (paths may be None if download failed)
314
+ lora_entries = [
315
  (pose_lora_path, float(pose_strength)),
316
  (general_lora_path, float(general_strength)),
317
  (motion_lora_path, float(motion_strength)),
318
  ]
319
+
320
+ # 1) Preferred: mutate the builder used by the ledger, then call the original transformer factory.
321
+ builder = getattr(ledger, "builder", None) or getattr(ledger, "_builder", None)
322
+
323
+ if builder is not None:
324
+ try:
325
+ # Clear existing builder.loras if present.
326
+ if hasattr(builder, "loras") and isinstance(getattr(builder, "loras"), list):
327
+ try:
328
+ builder.loras.clear()
329
+ except Exception:
330
+ # fallback: reassign
331
+ try:
332
+ setattr(builder, "loras", [])
333
+ except Exception:
334
+ pass
335
+
336
+ # If there is an explicit builder.lora(...) helper, use it to register LoRAs.
337
+ if hasattr(builder, "lora"):
338
+ for path, strength in lora_entries:
339
+ try:
340
+ if path is None:
341
+ continue
342
+ # Always register (builder.lora should create the proper LoRA object expected by build).
343
+ # The builder may accept strength==0.0; if not, register only >0.0 to avoid extra work.
344
+ if float(strength) != 0.0:
345
+ builder.lora(path, float(strength))
346
+ except Exception as e:
347
+ print(f"[LoRA] builder.lora(...) failed for {path}: {type(e).__name__}: {e}")
348
+ else:
349
+ # If there's no builder.lora helper, try to append sensible objects into builder.loras.
350
+ # We don't know the exact LoRA object type, so we skip if we can't.
351
+ print("[LoRA] builder has no 'lora' helper; attempting to set builder.loras to an empty list.")
352
+ try:
353
+ setattr(builder, "loras", [])
354
+ except Exception:
355
+ pass
356
+
357
+ # Use the saved original transformer factory to (re)create a transformer using the mutated builder.
358
+ # The original factory should call builder.build(...) internally.
359
+ if "_orig_transformer_factory" in globals():
360
+ print("[LoRA] Rebuilding transformer from builder and hot-swapping into ledger...")
361
+ try:
362
+ new_transformer = _orig_transformer_factory()
363
+ # free previous cached transformer to reduce peak memory
364
+ global _transformer
365
+ try:
366
+ # delete previous Python ref and empty cache; underlying CUDA memory should be released when
367
+ # the module is garbage-collected. We proactively call torch.cuda.empty_cache().
368
+ del _transformer
369
+ except Exception:
370
+ pass
371
+ torch.cuda.empty_cache()
372
+
373
+ # install new transformer as the one returned by ledger.transformer()
374
+ _transformer = new_transformer
375
+ ledger.transformer = lambda: _transformer
376
+ print("[LoRA] Transformer rebuilt and hot-swapped successfully.")
377
+ return
378
+ except Exception as e:
379
+ print(f"[LoRA] Error while rebuilding transformer via original factory: {type(e).__name__}: {e}")
380
+ # fallthrough to other attempts
381
+ else:
382
+ print("[LoRA] _orig_transformer_factory is not available; cannot rebuild transformer via builder.")
383
+ except Exception as e:
384
+ print(f"[LoRA] Unexpected error while manipulating builder: {type(e).__name__}: {e}")
385
+ # proceed to fallbacks below
386
+
387
+ # 2) Try high-level APIs if present (some pipeline/ledger versions expose helpers)
388
  try:
389
+ if hasattr(ledger, "apply_loras"):
390
+ print("[LoRA] Calling ledger.apply_loras(...)")
391
+ # Best-effort call (signature may vary across versions)
392
+ try:
393
+ ledger.apply_loras([{"path": p, "strength": s} for p, s in lora_entries if p is not None])
394
+ except Exception:
395
+ # also try a simpler form
396
+ ledger.apply_loras(lora_entries)
397
  return
 
 
398
  if hasattr(pipeline, "set_loras"):
399
+ print("[LoRA] Calling pipeline.set_loras(...)")
400
+ try:
401
+ pipeline.set_loras(lora_entries)
402
+ return
403
+ except Exception as e:
404
+ print(f"[LoRA] pipeline.set_loras failed: {type(e).__name__}: {e}")
405
+ except Exception as e:
406
+ print(f"[LoRA] Exception when trying high-level apply APIs: {type(e).__name__}: {e}")
407
 
408
+ # 3) Fallback: set pipeline.loras attribute (best-effort, may not be used)
409
+ try:
410
+ print("[LoRA] Falling back to pipeline.loras attribute assignment (best-effort).")
411
+ pipeline.loras = [(p, float(s)) for p, s in lora_entries if p is not None]
412
  except Exception as e:
413
+ print(f"[LoRA] Fallback pipeline.loras assignment failed: {type(e).__name__}: {e}")
414
+
415
+ print("[LoRA] apply_loras_to_pipeline finished (some approaches may not have taken effect).")
416
+ # ---- END replacement ----
417
 
418
+ # ---- REPLACE PRELOAD BLOCK START ----
419
  # Preload all models for ZeroGPU tensor packing.
420
  print("Preloading all models (including Gemma and audio components)...")
421
  ledger = pipeline.model_ledger
 
 
 
 
 
 
 
 
 
422
 
423
+ # Save the original factory methods so we can rebuild individual components later.
424
+ # These are bound callables on ledger that will call the builder when invoked.
425
+ _orig_transformer_factory = ledger.transformer
426
+ _orig_video_encoder_factory = ledger.video_encoder
427
+ _orig_video_decoder_factory = ledger.video_decoder
428
+ _orig_audio_encoder_factory = ledger.audio_encoder
429
+ _orig_audio_decoder_factory = ledger.audio_decoder
430
+ _orig_vocoder_factory = ledger.vocoder
431
+ _orig_spatial_upsampler_factory = ledger.spatial_upsampler
432
+ _orig_text_encoder_factory = ledger.text_encoder
433
+ _orig_gemma_embeddings_factory = ledger.gemma_embeddings_processor
434
+
435
+ # Call the original factories once to create the cached instances we will serve by default.
436
+ _transformer = _orig_transformer_factory()
437
+ _video_encoder = _orig_video_encoder_factory()
438
+ _video_decoder = _orig_video_decoder_factory()
439
+ _audio_encoder = _orig_audio_encoder_factory()
440
+ _audio_decoder = _orig_audio_decoder_factory()
441
+ _vocoder = _orig_vocoder_factory()
442
+ _spatial_upsampler = _orig_spatial_upsampler_factory()
443
+ _text_encoder = _orig_text_encoder_factory()
444
+ _embeddings_processor = _orig_gemma_embeddings_factory()
445
+
446
+ # Replace ledger methods with lightweight lambdas that return the cached instances.
447
+ # We keep the original factories above so we can call them later to rebuild components.
448
  ledger.transformer = lambda: _transformer
449
  ledger.video_encoder = lambda: _video_encoder
450
  ledger.video_decoder = lambda: _video_decoder
 
454
  ledger.spatial_upsampler = lambda: _spatial_upsampler
455
  ledger.text_encoder = lambda: _text_encoder
456
  ledger.gemma_embeddings_processor = lambda: _embeddings_processor
457
+
458
  print("All models preloaded (including Gemma text encoder and audio encoder)!")
459
+ # ---- REPLACE PRELOAD BLOCK END ----
460
 
461
  print("=" * 80)
462
  print("Pipeline ready!")