akhaliq HF Staff commited on
Commit
9ef249f
·
verified ·
1 Parent(s): 1c5a9bb

Restore run.py with enhance_prompt binding (was overwritten by bad upload)

Browse files
Files changed (1) hide show
  1. run.py +75 -1
run.py CHANGED
@@ -17,8 +17,11 @@ import os
17
  os.environ.setdefault("PYTORCH_ALLOC_CONF", "backend:cudaMallocAsync")
18
  os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "backend:cudaMallocAsync")
19
 
 
20
  import random
21
  import tempfile
 
 
22
 
23
  import gradio as gr
24
  import PIL.Image
@@ -247,6 +250,38 @@ def _generate_gpu(prompt, image_path, height, width, num_frames, seed, decoder,
247
  return path, num_frames
248
 
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  def _extract_path(image_value):
251
  """Image ports arrive from the canvas as a {path|url} dict, a path string, or None."""
252
  if isinstance(image_value, dict):
@@ -254,6 +289,45 @@ def _extract_path(image_value):
254
  return image_value or None
255
 
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  def generate_video(prompt, image_path=None, height=1472, width=832, duration_s=2,
258
  seed=42, decoder="conv", auto_len=False, randomize_seed=True):
259
  """Workflow-facing wrapper, bound as a `fn` operator. CPU work (seed, frame
@@ -282,7 +356,7 @@ def generate_video(prompt, image_path=None, height=1472, width=832, duration_s=2
282
 
283
  demo = gr.Workflow(
284
  graph="workflow.json",
285
- bind={"generate_video": generate_video},
286
  )
287
 
288
  if __name__ == "__main__":
 
17
  os.environ.setdefault("PYTORCH_ALLOC_CONF", "backend:cudaMallocAsync")
18
  os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "backend:cudaMallocAsync")
19
 
20
+ import hashlib
21
  import random
22
  import tempfile
23
+ import time
24
+ from collections import OrderedDict
25
 
26
  import gradio as gr
27
  import PIL.Image
 
250
  return path, num_frames
251
 
252
 
253
+ # -----------------------------------------------------------------------------
254
+ # Prompt enhancement — same mechanism and Space as the original demo (Gemma-4 on
255
+ # a separate ZeroGPU Space). Authenticated with this Space's HF_TOKEN, so no
256
+ # anonymous rate-limit bucket. Client rebuilt past a TTL: the ZeroGPU proxy
257
+ # token it carries expires.
258
+ # -----------------------------------------------------------------------------
259
+ ENHANCER_SPACE = "diffusers-internal-dev/LTX-2.4-Prompt-Enhancer"
260
+ _enh = {"client": None, "built_at": 0.0}
261
+ _ENH_CLIENT_TTL_S = 900
262
+
263
+ _ENH_CACHE: OrderedDict[tuple[str, str | None], str] = OrderedDict()
264
+ _ENH_CACHE_MAX = 64
265
+
266
+
267
+ def _image_key(path: str | None) -> str | None:
268
+ if not path:
269
+ return None
270
+ with open(path, "rb") as fh:
271
+ return hashlib.sha256(fh.read()).hexdigest()[:16]
272
+
273
+
274
+ def _enhancer_client(fresh: bool = False):
275
+ from gradio_client import Client
276
+
277
+ if fresh or _enh["client"] is None or (time.monotonic() - _enh["built_at"]) > _ENH_CLIENT_TTL_S:
278
+ _enh["client"] = Client(
279
+ ENHANCER_SPACE, token=HF_TOKEN, httpx_kwargs={"timeout": 300.0}
280
+ )
281
+ _enh["built_at"] = time.monotonic()
282
+ return _enh["client"]
283
+
284
+
285
  def _extract_path(image_value):
286
  """Image ports arrive from the canvas as a {path|url} dict, a path string, or None."""
287
  if isinstance(image_value, dict):
 
289
  return image_value or None
290
 
291
 
292
+ def enhance_prompt(prompt, image_path=None, do_enhance=True):
293
+ """CPU step (runs before any GPU is acquired): rewrite the prompt into a
294
+ detailed LTX-2.5-style caption via the enhancer Space. Falls back to the
295
+ raw prompt if the enhancer is unavailable. Bound as a `fn` operator."""
296
+ if not prompt or not str(prompt).strip():
297
+ raise gr.Error("Please enter a prompt.")
298
+ prompt = str(prompt).strip()
299
+ image_path = _extract_path(image_path)
300
+ if not do_enhance:
301
+ return prompt
302
+
303
+ key = (prompt, _image_key(image_path))
304
+ cached = _ENH_CACHE.get(key)
305
+ if cached is not None:
306
+ _ENH_CACHE.move_to_end(key)
307
+ return cached
308
+
309
+ from gradio_client import handle_file
310
+
311
+ args = (prompt, handle_file(image_path) if image_path else None)
312
+ try:
313
+ try:
314
+ enhanced = _enhancer_client().predict(*args, api_name="/enhance")
315
+ except Exception as first: # noqa: BLE001
316
+ # Usually an expired ZeroGPU proxy token; retry once with a fresh client.
317
+ print(f"[enhance] first attempt failed ({first!r}); fresh client retry", flush=True)
318
+ enhanced = _enhancer_client(fresh=True).predict(*args, api_name="/enhance")
319
+ except Exception as e: # noqa: BLE001
320
+ print(f"[enhance] failed, using raw prompt: {e!r}", flush=True)
321
+ gr.Warning(f"Prompt enhancement unavailable ({type(e).__name__}) — using your prompt as written.")
322
+ return prompt
323
+
324
+ enhanced = enhanced or prompt
325
+ _ENH_CACHE[key] = enhanced
326
+ while len(_ENH_CACHE) > _ENH_CACHE_MAX:
327
+ _ENH_CACHE.popitem(last=False)
328
+ return enhanced
329
+
330
+
331
  def generate_video(prompt, image_path=None, height=1472, width=832, duration_s=2,
332
  seed=42, decoder="conv", auto_len=False, randomize_seed=True):
333
  """Workflow-facing wrapper, bound as a `fn` operator. CPU work (seed, frame
 
356
 
357
  demo = gr.Workflow(
358
  graph="workflow.json",
359
+ bind={"enhance_prompt": enhance_prompt, "generate_video": generate_video},
360
  )
361
 
362
  if __name__ == "__main__":