Spaces:
Running on Zero
Running on Zero
AndrianBalanescu commited on
Commit ·
89cdc45
1
Parent(s): db08952
ZeroGPU video: auto-purge corrupted HF cache snapshots on tokenizer parse errors
Browse filesThe 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.
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
|