Skip to content

Commit 7731417

Browse files
committed
LTX2.3 improvements and bug fixes
1 parent 9616d1c commit 7731417

9 files changed

Lines changed: 259 additions & 225 deletions

File tree

src/maxdiffusion/configs/ltx2_3_video.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#hardware
22
hardware: 'tpu'
33
skip_jax_distributed_system: False
4-
attention: 'flash'
4+
attention: 'flash' # Supported attention: dot_product, flash, tokamax_flash, cudnn_flash_te, ring, tokamax_ring, ulysses, ulysses_custom, ulysses_ring
55
a2v_attention_kernel: 'flash'
66
v2a_attention_kernel: 'dot_product'
77
attention_sharding_uniform: True

src/maxdiffusion/configs/ltx2_video.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#hardware
22
hardware: 'tpu'
33
skip_jax_distributed_system: False
4-
attention: 'flash'
4+
attention: 'flash' # Supported attention: dot_product, flash, tokamax_flash, cudnn_flash_te, ring, tokamax_ring, ulysses, ulysses_custom, ulysses_ring
55
a2v_attention_kernel: 'dot_product'
66
v2a_attention_kernel: 'dot_product'
77
attention_sharding_uniform: True

src/maxdiffusion/generate_ltx2.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,9 @@ def run(config, pipeline=None, filename_prefix="", commit_hash=None):
237237

238238
# Export videos
239239
for i in range(len(videos)):
240-
video_path = f"{filename_prefix}ltx2_output_{getattr(config, 'seed', 0)}_{i}.mp4"
240+
model_name = getattr(config, "model_name", "ltx2") or "ltx2"
241+
model_name_prefix = model_name.replace(".", "_")
242+
video_path = f"{filename_prefix}{model_name_prefix}_output_{getattr(config, 'seed', 0)}_{i}.mp4"
241243
audio_i = audios[i] if audios is not None else None
242244

243245
audio_format = getattr(config, "audio_format", "s16")

src/maxdiffusion/models/attention_flax.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ def __init__(
13831383
self,
13841384
mesh: Mesh,
13851385
attention_kernel: str,
1386-
scale: int,
1386+
scale: float,
13871387
heads: int,
13881388
dim_head: int,
13891389
use_memory_efficient_attention: bool = False,
@@ -1475,7 +1475,7 @@ def apply_attention(self, query: Array, key: Array, value: Array, attention_mask
14751475
class AttentionOp(nn.Module):
14761476
mesh: Mesh
14771477
attention_kernel: str
1478-
scale: int
1478+
scale: float
14791479
heads: int
14801480
dim_head: int
14811481
use_memory_efficient_attention: bool = False

src/maxdiffusion/models/ltx2/attention_ltx2.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,8 @@ def apply_split_rotary_emb(x: Array, freqs: Tuple[Array, Array]) -> Array:
8888
first_x = split_x[..., 0, :]
8989
second_x = split_x[..., 1, :]
9090

91-
cos_u = jnp.expand_dims(cos, axis=-2)
92-
sin_u = jnp.expand_dims(sin, axis=-2)
93-
94-
out = split_x * cos_u
95-
96-
out_first = out[..., 0, :] - second_x * sin_u.squeeze(-2)
97-
out_second = out[..., 1, :] + first_x * sin_u.squeeze(-2)
91+
out_first = first_x * cos - second_x * sin
92+
out_second = second_x * cos + first_x * sin
9893

9994
out = jnp.stack([out_first, out_second], axis=-2)
10095
out = out.reshape(*out.shape[:-2], last_dim)
@@ -176,12 +171,6 @@ def prepare_video_coords(
176171
patch_ends = grid + patch_size_delta
177172

178173
# Combine start and end coordinates
179-
latent_coords = jnp.stack([grid, patch_ends], axis=-1) # [3, N_F, N_H, N_W, 2]
180-
latent_coords = latent_coords.transpose(1, 2, 3, 0, 4) # [N_F, N_H, N_W, 3, 2]
181-
latent_coords = latent_coords.reshape(-1, 3, 2) # [num_patches, 3, 2]
182-
latent_coords = jnp.expand_dims(latent_coords, 0) # [1, num_patches, 3, 2]
183-
latent_coords = jnp.tile(latent_coords, (batch_size, 1, 1, 1)) # [B, num_patches, 3, 2]
184-
185174
latent_coords = jnp.stack([grid, patch_ends], axis=-1) # [3, N_F, N_H, N_W, 2]
186175
latent_coords = latent_coords.reshape(3, -1, 2) # [3, num_patches, 2]
187176
latent_coords = jnp.expand_dims(latent_coords, 0) # [1, 3, num_patches, 2]
@@ -485,7 +474,7 @@ def __call__(
485474
# 3. Apply RoPE
486475
with jax.named_scope("Apply RoPE"):
487476
if rotary_emb is not None:
488-
if hasattr(self, "rope_type") and self.rope_type == "split":
477+
if self.rope_type == "split":
489478
# Split RoPE: passing full freqs [B, H, S, D//2]
490479
# apply_split_rotary_emb handles reshaping query/key
491480

src/maxdiffusion/models/ltx2/text_encoders/torchax_text_encoder.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@
2020
import jax
2121
from torchax import interop, default_env
2222

23-
# --- Monkeypatch transformers masking_utils to avoid torchax integer tracing bug ---
23+
import contextlib
2424
import transformers.masking_utils
2525

26-
_orig_sliding_window_overlay = transformers.masking_utils.sliding_window_overlay
27-
2826

2927
def _patched_sliding_window_overlay(sliding_window: int):
3028
# pylint: disable=unused-argument
@@ -44,6 +42,16 @@ def inner_mask(batch_idx: int, head_idx: int, q_idx: int, kv_idx: int) -> bool:
4442
return inner_mask
4543

4644

45+
@contextlib.contextmanager
46+
def patch_sliding_window_overlay():
47+
orig = transformers.masking_utils.sliding_window_overlay
48+
transformers.masking_utils.sliding_window_overlay = _patched_sliding_window_overlay
49+
try:
50+
yield
51+
finally:
52+
transformers.masking_utils.sliding_window_overlay = orig
53+
54+
4755
class TorchaxGemma3TextEncoder(interop.JittableModule):
4856
"""
4957
A jittable Torchax module for wrapping the HuggingFace PyTorch
@@ -57,8 +65,7 @@ def __call__(
5765
self, input_ids: jax.Array, attention_mask: jax.Array, output_hidden_states: bool = True
5866
) -> Tuple[jax.Array, ...]:
5967
# Dynamically patch transformers.masking_utils only during the duration of this call
60-
transformers.masking_utils.sliding_window_overlay = _patched_sliding_window_overlay
61-
try:
68+
with patch_sliding_window_overlay():
6269
with default_env():
6370
input_ids = interop.torch_view(input_ids)
6471
attention_mask = interop.torch_view(attention_mask)
@@ -72,9 +79,6 @@ def __call__(
7279
output_hidden_states=output_hidden_states,
7380
)
7481
return interop.jax_view(output)
75-
finally:
76-
# Restore original behavior to prevent side effects on other potential models in same env
77-
transformers.masking_utils.sliding_window_overlay = _orig_sliding_window_overlay
7882

7983
@staticmethod
8084
def _forward_inner(model, input_ids, attention_mask, output_hidden_states=True):

0 commit comments

Comments
 (0)