[diffusion] fix: use NDRotaryEmbedding in flux_2 (#15034)
This commit is contained in:
@@ -432,7 +432,8 @@ class FluxPosEmbed(nn.Module):
|
|||||||
|
|
||||||
def forward(self, ids: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
|
def forward(self, ids: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
|
||||||
pos = ids.float()
|
pos = ids.float()
|
||||||
# freqs_cos, freqs_sin = self.rope.forward(positions=pos)
|
# TODO: potential error: flux use n_axes = ids.shape[-1]
|
||||||
|
# see: https://github.com/huggingface/diffusers/blob/17c0e79dbdf53fb6705e9c09cc1a854b84c39249/src/diffusers/models/transformers/transformer_flux.py#L509
|
||||||
freqs_cos, freqs_sin = self.rope.forward_uncached(pos=pos)
|
freqs_cos, freqs_sin = self.rope.forward_uncached(pos=pos)
|
||||||
return freqs_cos.contiguous().float(), freqs_sin.contiguous().float()
|
return freqs_cos.contiguous().float(), freqs_sin.contiguous().float()
|
||||||
|
|
||||||
|
|||||||
@@ -12,28 +12,30 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from typing import Any, Dict, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
import torch.nn as nn
|
import torch.nn as nn
|
||||||
from diffusers.models.attention import AttentionModuleMixin
|
from diffusers.models.attention import AttentionModuleMixin
|
||||||
from diffusers.models.embeddings import (
|
from diffusers.models.embeddings import TimestepEmbedding, Timesteps
|
||||||
TimestepEmbedding,
|
|
||||||
Timesteps,
|
|
||||||
get_1d_rotary_pos_embed,
|
|
||||||
)
|
|
||||||
from diffusers.models.normalization import AdaLayerNormContinuous
|
from diffusers.models.normalization import AdaLayerNormContinuous
|
||||||
|
|
||||||
from sglang.multimodal_gen.configs.models.dits.flux import FluxConfig
|
from sglang.multimodal_gen.configs.models.dits.flux import FluxConfig
|
||||||
from sglang.multimodal_gen.runtime.layers.attention import USPAttention
|
from sglang.multimodal_gen.runtime.layers.attention import USPAttention
|
||||||
from sglang.multimodal_gen.runtime.layers.layernorm import RMSNorm
|
from sglang.multimodal_gen.runtime.layers.layernorm import RMSNorm
|
||||||
from sglang.multimodal_gen.runtime.layers.rotary_embedding import _apply_rotary_emb
|
from sglang.multimodal_gen.runtime.layers.rotary_embedding import (
|
||||||
|
NDRotaryEmbedding,
|
||||||
|
_apply_rotary_emb,
|
||||||
|
)
|
||||||
from sglang.multimodal_gen.runtime.models.dits.base import CachableDiT
|
from sglang.multimodal_gen.runtime.models.dits.base import CachableDiT
|
||||||
from sglang.multimodal_gen.runtime.models.dits.utils import (
|
from sglang.multimodal_gen.runtime.models.dits.utils import (
|
||||||
delete_projection_layers,
|
delete_projection_layers,
|
||||||
fuse_linear_projections,
|
fuse_linear_projections,
|
||||||
)
|
)
|
||||||
from sglang.multimodal_gen.runtime.platforms import AttentionBackendEnum
|
from sglang.multimodal_gen.runtime.platforms import (
|
||||||
|
AttentionBackendEnum,
|
||||||
|
current_platform,
|
||||||
|
)
|
||||||
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
||||||
|
|
||||||
logger = init_logger(__name__) # pylint: disable=invalid-name
|
logger = init_logger(__name__) # pylint: disable=invalid-name
|
||||||
@@ -627,35 +629,22 @@ class Flux2Modulation(nn.Module):
|
|||||||
|
|
||||||
|
|
||||||
class Flux2PosEmbed(nn.Module):
|
class Flux2PosEmbed(nn.Module):
|
||||||
# modified from https://github.com/black-forest-labs/flux/blob/c00d7c60b085fce8058b9df845e036090873f2ce/src/flux/modules/layers.py#L11
|
def __init__(self, theta: int, axes_dim: List[int]):
|
||||||
def __init__(self, theta: int, axes_dim: list[int]):
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.theta = theta
|
self.rope = NDRotaryEmbedding(
|
||||||
self.axes_dim = axes_dim
|
rope_dim_list=axes_dim,
|
||||||
|
rope_theta=theta,
|
||||||
|
use_real=False,
|
||||||
|
repeat_interleave_real=False,
|
||||||
|
dtype=torch.float32 if current_platform.is_mps() else torch.float64,
|
||||||
|
)
|
||||||
|
|
||||||
def forward(self, ids: torch.Tensor) -> torch.Tensor:
|
def forward(self, ids: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
|
||||||
# Expected ids shape: [S, len(self.axes_dim)]
|
|
||||||
cos_out = []
|
|
||||||
sin_out = []
|
|
||||||
pos = ids.float()
|
pos = ids.float()
|
||||||
is_mps = ids.device.type == "mps"
|
# TODO: potential error: flux use n_axes = ids.shape[-1]
|
||||||
is_npu = ids.device.type == "npu"
|
# see: https://github.com/huggingface/diffusers/blob/17c0e79dbdf53fb6705e9c09cc1a854b84c39249/src/diffusers/models/transformers/transformer_flux.py#L509
|
||||||
freqs_dtype = torch.float32 if (is_mps or is_npu) else torch.float64
|
freqs_cos, freqs_sin = self.rope.forward_uncached(pos=pos)
|
||||||
# Unlike Flux 1, loop over len(self.axes_dim) rather than ids.shape[-1]
|
return freqs_cos.contiguous().float(), freqs_sin.contiguous().float()
|
||||||
for i in range(len(self.axes_dim)):
|
|
||||||
cos, sin = get_1d_rotary_pos_embed(
|
|
||||||
self.axes_dim[i],
|
|
||||||
pos[..., i],
|
|
||||||
theta=self.theta,
|
|
||||||
repeat_interleave_real=True,
|
|
||||||
use_real=True,
|
|
||||||
freqs_dtype=freqs_dtype,
|
|
||||||
)
|
|
||||||
cos_out.append(cos)
|
|
||||||
sin_out.append(sin)
|
|
||||||
freqs_cos = torch.cat(cos_out, dim=-1).to(ids.device)
|
|
||||||
freqs_sin = torch.cat(sin_out, dim=-1).to(ids.device)
|
|
||||||
return freqs_cos, freqs_sin
|
|
||||||
|
|
||||||
|
|
||||||
class Flux2Transformer2DModel(CachableDiT):
|
class Flux2Transformer2DModel(CachableDiT):
|
||||||
|
|||||||
Reference in New Issue
Block a user