Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- app.py +69 -63
- src/models/transformers/loomvideo.py +2 -0
- src/models/transformers/qwen3vl.py +31 -8
app.py
CHANGED
|
@@ -13,6 +13,7 @@ from omegaconf import OmegaConf
|
|
| 13 |
from PIL import Image
|
| 14 |
from typing import List, Optional
|
| 15 |
import tempfile
|
|
|
|
| 16 |
import random
|
| 17 |
|
| 18 |
from torchvision import transforms
|
|
@@ -176,7 +177,12 @@ def temporal_downsample_for_vlm(pil_frames: List[Image.Image], cfg) -> List[Imag
|
|
| 176 |
print("Building LoomVideo model...")
|
| 177 |
model = load_model(config)
|
| 178 |
print("Loading LoomVideo checkpoint...")
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
model.to(dtype=torch.bfloat16, device="cuda")
|
| 181 |
model.eval()
|
| 182 |
print("Model loaded successfully.")
|
|
@@ -205,6 +211,20 @@ def _get_guidance_scale_visual(guidance_scale_visual: Optional[float]) -> float:
|
|
| 205 |
return OmegaConf.select(config, "generation.guidance_scale_visual", default=1.5)
|
| 206 |
|
| 207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
# ---------------------------------------------------------------------------
|
| 209 |
# Inference functions
|
| 210 |
# ---------------------------------------------------------------------------
|
|
@@ -261,18 +281,17 @@ def generate_t2v(
|
|
| 261 |
else:
|
| 262 |
generator = None
|
| 263 |
|
| 264 |
-
generate_kwargs =
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
}
|
| 276 |
|
| 277 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 278 |
output = model.generate(**generate_kwargs)
|
|
@@ -348,23 +367,18 @@ def generate_edit(
|
|
| 348 |
else:
|
| 349 |
generator = None
|
| 350 |
|
| 351 |
-
generate_kwargs =
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
"guidance_scale": _get_guidance_scale(guidance_scale, is_edit=True),
|
| 364 |
-
"guidance_scale_visual": _get_guidance_scale_visual(guidance_scale_visual),
|
| 365 |
-
"source_pixel_values": [source_tensor],
|
| 366 |
-
"generator": generator,
|
| 367 |
-
}
|
| 368 |
|
| 369 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 370 |
output = model.generate(**generate_kwargs)
|
|
@@ -433,24 +447,19 @@ def generate_ref_edit(
|
|
| 433 |
else:
|
| 434 |
generator = None
|
| 435 |
|
| 436 |
-
generate_kwargs =
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
"guidance_scale_visual": _get_guidance_scale_visual(guidance_scale_visual),
|
| 450 |
-
"source_pixel_values": [source_video_tensor],
|
| 451 |
-
"ref_pixel_values": ref_image_tensors,
|
| 452 |
-
"generator": generator,
|
| 453 |
-
}
|
| 454 |
|
| 455 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 456 |
output = model.generate(**generate_kwargs)
|
|
@@ -524,21 +533,18 @@ def generate_mi2v(
|
|
| 524 |
else:
|
| 525 |
generator = None
|
| 526 |
|
| 527 |
-
generate_kwargs =
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
"ref_pixel_values": ref_image_tensors,
|
| 540 |
-
"generator": generator,
|
| 541 |
-
}
|
| 542 |
|
| 543 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 544 |
output = model.generate(**generate_kwargs)
|
|
|
|
| 13 |
from PIL import Image
|
| 14 |
from typing import List, Optional
|
| 15 |
import tempfile
|
| 16 |
+
from huggingface_hub import hf_hub_download
|
| 17 |
import random
|
| 18 |
|
| 19 |
from torchvision import transforms
|
|
|
|
| 177 |
print("Building LoomVideo model...")
|
| 178 |
model = load_model(config)
|
| 179 |
print("Loading LoomVideo checkpoint...")
|
| 180 |
+
ckpt_file = hf_hub_download(
|
| 181 |
+
repo_id=LOOMVIDEO_CKPT,
|
| 182 |
+
filename="Stage3/gen_model.pth",
|
| 183 |
+
repo_type="model",
|
| 184 |
+
)
|
| 185 |
+
load_checkpoint(model, ckpt_file)
|
| 186 |
model.to(dtype=torch.bfloat16, device="cuda")
|
| 187 |
model.eval()
|
| 188 |
print("Model loaded successfully.")
|
|
|
|
| 211 |
return OmegaConf.select(config, "generation.guidance_scale_visual", default=1.5)
|
| 212 |
|
| 213 |
|
| 214 |
+
def _build_generate_kwargs(inputs, **extra):
|
| 215 |
+
"""Build kwargs dict for model.generate() from processor outputs."""
|
| 216 |
+
kwargs = {
|
| 217 |
+
"input_ids": inputs["input_ids"],
|
| 218 |
+
"attention_mask": inputs["attention_mask"],
|
| 219 |
+
}
|
| 220 |
+
# Pass through optional keys that the processor may produce
|
| 221 |
+
for key in ["pixel_values", "pixel_values_videos", "image_grid_thw", "video_grid_thw", "mm_token_type_ids"]:
|
| 222 |
+
if key in inputs:
|
| 223 |
+
kwargs[key] = inputs[key]
|
| 224 |
+
kwargs.update(extra)
|
| 225 |
+
return kwargs
|
| 226 |
+
|
| 227 |
+
|
| 228 |
# ---------------------------------------------------------------------------
|
| 229 |
# Inference functions
|
| 230 |
# ---------------------------------------------------------------------------
|
|
|
|
| 281 |
else:
|
| 282 |
generator = None
|
| 283 |
|
| 284 |
+
generate_kwargs = _build_generate_kwargs(
|
| 285 |
+
inputs,
|
| 286 |
+
negative_prompt=_get_negative_prompt(None),
|
| 287 |
+
height=height,
|
| 288 |
+
width=width,
|
| 289 |
+
num_frames=num_frames,
|
| 290 |
+
num_inference_steps=num_inference_steps,
|
| 291 |
+
guidance_scale=_get_guidance_scale(guidance_scale, is_edit=False),
|
| 292 |
+
guidance_scale_visual=_get_guidance_scale_visual(guidance_scale_visual),
|
| 293 |
+
generator=generator,
|
| 294 |
+
)
|
|
|
|
| 295 |
|
| 296 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 297 |
output = model.generate(**generate_kwargs)
|
|
|
|
| 367 |
else:
|
| 368 |
generator = None
|
| 369 |
|
| 370 |
+
generate_kwargs = _build_generate_kwargs(
|
| 371 |
+
inputs,
|
| 372 |
+
negative_prompt=_get_negative_prompt(None),
|
| 373 |
+
height=height,
|
| 374 |
+
width=width,
|
| 375 |
+
num_frames=num_frames,
|
| 376 |
+
num_inference_steps=num_inference_steps,
|
| 377 |
+
guidance_scale=_get_guidance_scale(guidance_scale, is_edit=True),
|
| 378 |
+
guidance_scale_visual=_get_guidance_scale_visual(guidance_scale_visual),
|
| 379 |
+
source_pixel_values=[source_tensor],
|
| 380 |
+
generator=generator,
|
| 381 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
|
| 383 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 384 |
output = model.generate(**generate_kwargs)
|
|
|
|
| 447 |
else:
|
| 448 |
generator = None
|
| 449 |
|
| 450 |
+
generate_kwargs = _build_generate_kwargs(
|
| 451 |
+
inputs,
|
| 452 |
+
negative_prompt=_get_negative_prompt(None),
|
| 453 |
+
height=height,
|
| 454 |
+
width=width,
|
| 455 |
+
num_frames=num_frames,
|
| 456 |
+
num_inference_steps=num_inference_steps,
|
| 457 |
+
guidance_scale=_get_guidance_scale(guidance_scale, is_edit=True),
|
| 458 |
+
guidance_scale_visual=_get_guidance_scale_visual(guidance_scale_visual),
|
| 459 |
+
source_pixel_values=[source_video_tensor],
|
| 460 |
+
ref_pixel_values=ref_image_tensors,
|
| 461 |
+
generator=generator,
|
| 462 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 463 |
|
| 464 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 465 |
output = model.generate(**generate_kwargs)
|
|
|
|
| 533 |
else:
|
| 534 |
generator = None
|
| 535 |
|
| 536 |
+
generate_kwargs = _build_generate_kwargs(
|
| 537 |
+
inputs,
|
| 538 |
+
negative_prompt=_get_negative_prompt(None),
|
| 539 |
+
height=height,
|
| 540 |
+
width=width,
|
| 541 |
+
num_frames=num_frames,
|
| 542 |
+
num_inference_steps=num_inference_steps,
|
| 543 |
+
guidance_scale=_get_guidance_scale(guidance_scale, is_edit=False),
|
| 544 |
+
guidance_scale_visual=_get_guidance_scale_visual(guidance_scale_visual),
|
| 545 |
+
ref_pixel_values=ref_image_tensors,
|
| 546 |
+
generator=generator,
|
| 547 |
+
)
|
|
|
|
|
|
|
|
|
|
| 548 |
|
| 549 |
with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
|
| 550 |
output = model.generate(**generate_kwargs)
|
src/models/transformers/loomvideo.py
CHANGED
|
@@ -846,6 +846,7 @@ class LoomVideo(ModelMixin):
|
|
| 846 |
pixel_values_videos: Optional[torch.FloatTensor] = None,
|
| 847 |
image_grid_thw: Optional[torch.LongTensor] = None,
|
| 848 |
video_grid_thw: Optional[torch.LongTensor] = None,
|
|
|
|
| 849 |
negative_prompt: Optional[str] = None,
|
| 850 |
height: int = 480,
|
| 851 |
width: int = 832,
|
|
@@ -925,6 +926,7 @@ class LoomVideo(ModelMixin):
|
|
| 925 |
pixel_values_videos=pixel_values_videos,
|
| 926 |
image_grid_thw=image_grid_thw,
|
| 927 |
video_grid_thw=video_grid_thw,
|
|
|
|
| 928 |
)
|
| 929 |
all_hidden_states_full = outputs_full["hidden_states"]
|
| 930 |
|
|
|
|
| 846 |
pixel_values_videos: Optional[torch.FloatTensor] = None,
|
| 847 |
image_grid_thw: Optional[torch.LongTensor] = None,
|
| 848 |
video_grid_thw: Optional[torch.LongTensor] = None,
|
| 849 |
+
mm_token_type_ids: Optional[torch.IntTensor] = None,
|
| 850 |
negative_prompt: Optional[str] = None,
|
| 851 |
height: int = 480,
|
| 852 |
width: int = 832,
|
|
|
|
| 926 |
pixel_values_videos=pixel_values_videos,
|
| 927 |
image_grid_thw=image_grid_thw,
|
| 928 |
video_grid_thw=video_grid_thw,
|
| 929 |
+
mm_token_type_ids=mm_token_type_ids,
|
| 930 |
)
|
| 931 |
all_hidden_states_full = outputs_full["hidden_states"]
|
| 932 |
|
src/models/transformers/qwen3vl.py
CHANGED
|
@@ -191,6 +191,7 @@ class Qwen3VLModel(Qwen3VLModel):
|
|
| 191 |
image_grid_thw: Optional[torch.LongTensor] = None,
|
| 192 |
video_grid_thw: Optional[torch.LongTensor] = None,
|
| 193 |
cache_position: Optional[torch.LongTensor] = None,
|
|
|
|
| 194 |
**kwargs: Unpack[TransformersKwargs],
|
| 195 |
) -> Union[tuple, Qwen3VLModelOutputWithPast]:
|
| 196 |
"""Forward pass that extracts visual features, applies DeepStack injection,
|
|
@@ -205,7 +206,12 @@ class Qwen3VLModel(Qwen3VLModel):
|
|
| 205 |
video_mask = None
|
| 206 |
|
| 207 |
if pixel_values is not None:
|
| 208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
image_embeds = torch.cat(image_embeds, dim=0).to(inputs_embeds.device, inputs_embeds.dtype)
|
| 210 |
image_mask, _ = self.get_placeholder_mask(
|
| 211 |
input_ids, inputs_embeds=inputs_embeds, image_features=image_embeds
|
|
@@ -213,7 +219,12 @@ class Qwen3VLModel(Qwen3VLModel):
|
|
| 213 |
inputs_embeds = inputs_embeds.masked_scatter(image_mask, image_embeds)
|
| 214 |
|
| 215 |
if pixel_values_videos is not None:
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
video_embeds = torch.cat(video_embeds, dim=0).to(inputs_embeds.device, inputs_embeds.dtype)
|
| 218 |
_, video_mask = self.get_placeholder_mask(
|
| 219 |
input_ids, inputs_embeds=inputs_embeds, video_features=video_embeds
|
|
@@ -264,12 +275,24 @@ class Qwen3VLModel(Qwen3VLModel):
|
|
| 264 |
or (past_key_values is None or past_key_values.get_seq_length() == 0)
|
| 265 |
)
|
| 266 |
if (prefill_compiled_stage or prefill_noncompiled_stage) or self.rope_deltas is None:
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
self.rope_deltas = rope_deltas
|
| 274 |
else:
|
| 275 |
batch_size, seq_length, _ = inputs_embeds.shape
|
|
|
|
| 191 |
image_grid_thw: Optional[torch.LongTensor] = None,
|
| 192 |
video_grid_thw: Optional[torch.LongTensor] = None,
|
| 193 |
cache_position: Optional[torch.LongTensor] = None,
|
| 194 |
+
mm_token_type_ids: Optional[torch.IntTensor] = None,
|
| 195 |
**kwargs: Unpack[TransformersKwargs],
|
| 196 |
) -> Union[tuple, Qwen3VLModelOutputWithPast]:
|
| 197 |
"""Forward pass that extracts visual features, applies DeepStack injection,
|
|
|
|
| 206 |
video_mask = None
|
| 207 |
|
| 208 |
if pixel_values is not None:
|
| 209 |
+
_img_out = self.get_image_features(pixel_values, image_grid_thw)
|
| 210 |
+
if isinstance(_img_out, (list, tuple)):
|
| 211 |
+
image_embeds, deepstack_image_embeds = _img_out
|
| 212 |
+
else:
|
| 213 |
+
image_embeds = _img_out.pooler_output
|
| 214 |
+
deepstack_image_embeds = _img_out.deepstack_features
|
| 215 |
image_embeds = torch.cat(image_embeds, dim=0).to(inputs_embeds.device, inputs_embeds.dtype)
|
| 216 |
image_mask, _ = self.get_placeholder_mask(
|
| 217 |
input_ids, inputs_embeds=inputs_embeds, image_features=image_embeds
|
|
|
|
| 219 |
inputs_embeds = inputs_embeds.masked_scatter(image_mask, image_embeds)
|
| 220 |
|
| 221 |
if pixel_values_videos is not None:
|
| 222 |
+
_vid_out = self.get_video_features(pixel_values_videos, video_grid_thw)
|
| 223 |
+
if isinstance(_vid_out, (list, tuple)):
|
| 224 |
+
video_embeds, deepstack_video_embeds = _vid_out
|
| 225 |
+
else:
|
| 226 |
+
video_embeds = _vid_out.pooler_output
|
| 227 |
+
deepstack_video_embeds = _vid_out.deepstack_features
|
| 228 |
video_embeds = torch.cat(video_embeds, dim=0).to(inputs_embeds.device, inputs_embeds.dtype)
|
| 229 |
_, video_mask = self.get_placeholder_mask(
|
| 230 |
input_ids, inputs_embeds=inputs_embeds, video_features=video_embeds
|
|
|
|
| 275 |
or (past_key_values is None or past_key_values.get_seq_length() == 0)
|
| 276 |
)
|
| 277 |
if (prefill_compiled_stage or prefill_noncompiled_stage) or self.rope_deltas is None:
|
| 278 |
+
# Handle transformers 5.x which requires mm_token_type_ids
|
| 279 |
+
import inspect
|
| 280 |
+
rope_sig = inspect.signature(self.get_rope_index)
|
| 281 |
+
if 'mm_token_type_ids' in rope_sig.parameters:
|
| 282 |
+
position_ids, rope_deltas = self.get_rope_index(
|
| 283 |
+
input_ids,
|
| 284 |
+
mm_token_type_ids if mm_token_type_ids is not None else torch.zeros_like(input_ids, dtype=torch.int32),
|
| 285 |
+
image_grid_thw,
|
| 286 |
+
video_grid_thw,
|
| 287 |
+
attention_mask=attention_mask_tensor,
|
| 288 |
+
)
|
| 289 |
+
else:
|
| 290 |
+
position_ids, rope_deltas = self.get_rope_index(
|
| 291 |
+
input_ids,
|
| 292 |
+
image_grid_thw,
|
| 293 |
+
video_grid_thw,
|
| 294 |
+
attention_mask=attention_mask_tensor,
|
| 295 |
+
)
|
| 296 |
self.rope_deltas = rope_deltas
|
| 297 |
else:
|
| 298 |
batch_size, seq_length, _ = inputs_embeds.shape
|