AndrianBalanescu commited on
Commit
89cdc45
·
1 Parent(s): db08952

ZeroGPU video: auto-purge corrupted HF cache snapshots on tokenizer parse errors

Browse files

The LTX-Video and CogVideoX-5B pipelines were failing with
'Error parsing line in spiece.model' because the Space's persistent
HF cache held truncated tokenizer downloads. On such errors we now
purge the broken models--org--repo snapshot, evict the in-memory
pipeline cache, and retry the generation with a fresh download.

Refs: Albina Bondar video generation batch.

Files changed (1) hide show
  1. app.py +59 -0
app.py CHANGED
@@ -1233,6 +1233,52 @@ def generate_zerogpu_video(
1233
  repo_id = VIDEO_MODELS.get(model_choice, "cerspense/zeroscope_v2_576w")
1234
  out_video_path = f"/tmp/zerogpu_video_{int(time.time())}_{abs(hash(prompt)) % 10000}.mp4"
1235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1236
  try:
1237
  import torch
1238
  from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
@@ -1271,6 +1317,19 @@ def generate_zerogpu_video(
1271
  export_to_video(video_frames, out_video_path, fps=int(fps))
1272
  return out_video_path
1273
  except Exception as exc:
 
 
 
 
 
 
 
 
 
 
 
 
 
1274
  print(f"[ZeroGPU Video] Direct pipeline exception: {exc}, running ffmpeg dynamic visualizer fallback...", flush=True)
1275
  try:
1276
  from engine.model_dispatcher import ModelDispatcher
 
1233
  repo_id = VIDEO_MODELS.get(model_choice, "cerspense/zeroscope_v2_576w")
1234
  out_video_path = f"/tmp/zerogpu_video_{int(time.time())}_{abs(hash(prompt)) % 10000}.mp4"
1235
 
1236
+ def _purge_corrupt_hf_cache(err_text: str):
1237
+ """Nuke the broken model snapshot from the HF cache when a tokenizer/blob parse fails."""
1238
+ import re as _re
1239
+ m = _re.search(r"models--([\w.\-]+)--([\w.\-]+)", err_text)
1240
+ if m:
1241
+ broken = os.path.join("/root/.cache/huggingface/hub", f"models--{m.group(1)}--{m.group(2)}")
1242
+ if os.path.exists(broken):
1243
+ print(f"[ZeroGPU Video] Purging corrupted HF cache: {broken}", flush=True)
1244
+ shutil.rmtree(broken, ignore_errors=True)
1245
+ _video_pipeline_cache.pop(repo_id, None)
1246
+ return True
1247
+ return False
1248
+
1249
+ def _retry_video_generation(prompt, negative_prompt, model_choice, num_frames, fps, guidance_scale, seed):
1250
+ """Fresh re-run of the pipeline body after a cache purge (recursive safe: 1 level)."""
1251
+ import torch
1252
+ from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
1253
+ from diffusers.utils import export_to_video
1254
+
1255
+ device = "cuda" if torch.cuda.is_available() else "cpu"
1256
+ dtype = torch.float16 if device == "cuda" else torch.float32
1257
+ pipe = DiffusionPipeline.from_pretrained(repo_id, torch_dtype=dtype)
1258
+ if hasattr(pipe, "scheduler"):
1259
+ try:
1260
+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
1261
+ except Exception:
1262
+ pass
1263
+ if hasattr(pipe, "enable_model_cpu_offload") and device == "cuda":
1264
+ pipe.enable_model_cpu_offload()
1265
+ else:
1266
+ pipe = pipe.to(device)
1267
+ _video_pipeline_cache[repo_id] = pipe
1268
+
1269
+ actual_seed = seed if (seed and int(seed) >= 0) else random.randint(0, 2**31 - 1)
1270
+ generator = torch.Generator(device=device).manual_seed(actual_seed)
1271
+ video_frames = pipe(
1272
+ prompt=prompt.strip(),
1273
+ negative_prompt=negative_prompt.strip() if negative_prompt else None,
1274
+ num_inference_steps=24,
1275
+ guidance_scale=float(guidance_scale),
1276
+ num_frames=int(num_frames),
1277
+ generator=generator
1278
+ ).frames[0]
1279
+ export_to_video(video_frames, out_video_path, fps=int(fps))
1280
+ return out_video_path
1281
+
1282
  try:
1283
  import torch
1284
  from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
 
1317
  export_to_video(video_frames, out_video_path, fps=int(fps))
1318
  return out_video_path
1319
  except Exception as exc:
1320
+ # Auto-recovery: corrupted HF cache snapshots (e.g. truncated spiece.model)
1321
+ # are purged once, then the whole pipeline load is retried fresh.
1322
+ if "Error parsing" in str(exc) or "spiece.model" in str(exc) or "tokenizer" in str(exc).lower():
1323
+ if _purge_corrupt_hf_cache(str(exc)):
1324
+ try:
1325
+ print(f"[ZeroGPU Video] Retrying {repo_id} with fresh download...", flush=True)
1326
+ return generate_zerogpu_video.__wrapped__(
1327
+ prompt, negative_prompt, model_choice, num_frames, fps, guidance_scale, seed
1328
+ ) if hasattr(generate_zerogpu_video, "__wrapped__") else _retry_video_generation(
1329
+ prompt, negative_prompt, model_choice, num_frames, fps, guidance_scale, seed
1330
+ )
1331
+ except Exception as retry_exc:
1332
+ print(f"[ZeroGPU Video] Retry also failed: {retry_exc}", flush=True)
1333
  print(f"[ZeroGPU Video] Direct pipeline exception: {exc}, running ffmpeg dynamic visualizer fallback...", flush=True)
1334
  try:
1335
  from engine.model_dispatcher import ModelDispatcher