[diffusion] fix: fix CLIP text encoder attention mask not used (#14364)
Co-authored-by: niehen6174 <niehen.6174@gmail.com> Co-authored-by: Mick <mickjagger19@icloud.com>
This commit is contained in:
co-authored by
niehen6174
Mick
parent
498ea41ca6
commit
35ba6fe19e
@@ -9,6 +9,7 @@ from sglang.multimodal_gen.configs.models.encoders.base import (
|
|||||||
TextEncoderArchConfig,
|
TextEncoderArchConfig,
|
||||||
TextEncoderConfig,
|
TextEncoderConfig,
|
||||||
)
|
)
|
||||||
|
from sglang.multimodal_gen.runtime.platforms import AttentionBackendEnum
|
||||||
|
|
||||||
|
|
||||||
def _is_transformer_layer(n: str, m) -> bool:
|
def _is_transformer_layer(n: str, m) -> bool:
|
||||||
@@ -38,6 +39,11 @@ class CLIPTextArchConfig(TextEncoderArchConfig):
|
|||||||
bos_token_id: int = 49406
|
bos_token_id: int = 49406
|
||||||
eos_token_id: int = 49407
|
eos_token_id: int = 49407
|
||||||
text_len: int = 77
|
text_len: int = 77
|
||||||
|
_supported_attention_backends: set[AttentionBackendEnum] = field(
|
||||||
|
default_factory=lambda: {
|
||||||
|
AttentionBackendEnum.TORCH_SDPA, # Force TORCH_SDPA to support attention_mask
|
||||||
|
}
|
||||||
|
)
|
||||||
stacked_params_mapping: list[tuple[str, str, str]] = field(
|
stacked_params_mapping: list[tuple[str, str, str]] = field(
|
||||||
default_factory=lambda: [
|
default_factory=lambda: [
|
||||||
# (param_name, shard_name, shard_id)
|
# (param_name, shard_name, shard_id)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from sglang.multimodal_gen.runtime.models.encoders.base import ImageEncoder, Tex
|
|||||||
from sglang.multimodal_gen.runtime.models.encoders.vision import (
|
from sglang.multimodal_gen.runtime.models.encoders.vision import (
|
||||||
resolve_visual_encoder_outputs,
|
resolve_visual_encoder_outputs,
|
||||||
)
|
)
|
||||||
|
from sglang.multimodal_gen.runtime.platforms import AttentionBackendEnum
|
||||||
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__)
|
logger = init_logger(__name__)
|
||||||
@@ -181,7 +182,7 @@ class CLIPAttention(nn.Module):
|
|||||||
self.head_dim,
|
self.head_dim,
|
||||||
self.num_heads_per_partition,
|
self.num_heads_per_partition,
|
||||||
softmax_scale=self.scale,
|
softmax_scale=self.scale,
|
||||||
causal=False,
|
causal=True,
|
||||||
supported_attention_backends=config._supported_attention_backends,
|
supported_attention_backends=config._supported_attention_backends,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -195,6 +196,7 @@ class CLIPAttention(nn.Module):
|
|||||||
def forward(
|
def forward(
|
||||||
self,
|
self,
|
||||||
hidden_states: torch.Tensor,
|
hidden_states: torch.Tensor,
|
||||||
|
attention_mask: torch.Tensor | None = None,
|
||||||
):
|
):
|
||||||
"""Input shape: Batch x Time x Channel"""
|
"""Input shape: Batch x Time x Channel"""
|
||||||
|
|
||||||
@@ -219,7 +221,36 @@ class CLIPAttention(nn.Module):
|
|||||||
self.num_heads_per_partition,
|
self.num_heads_per_partition,
|
||||||
self.head_dim,
|
self.head_dim,
|
||||||
)
|
)
|
||||||
attn_output = self.attn(query_states, key_states, value_states)
|
|
||||||
|
if self.attn.backend == AttentionBackendEnum.TORCH_SDPA:
|
||||||
|
query_states = query_states.transpose(1, 2) # [B, H, S, D]
|
||||||
|
key_states = key_states.transpose(1, 2)
|
||||||
|
value_states = value_states.transpose(1, 2)
|
||||||
|
|
||||||
|
if attention_mask is not None:
|
||||||
|
# SDPA requires [B, 1, 1, S] or [B, S, S] format mask
|
||||||
|
if attention_mask.dim() == 2:
|
||||||
|
attn_mask = attention_mask[:, None, None, :].to(
|
||||||
|
dtype=query_states.dtype
|
||||||
|
)
|
||||||
|
attn_mask = (1.0 - attn_mask) * torch.finfo(query_states.dtype).min
|
||||||
|
else:
|
||||||
|
attn_mask = attention_mask
|
||||||
|
else:
|
||||||
|
attn_mask = None
|
||||||
|
|
||||||
|
attn_output = torch.nn.functional.scaled_dot_product_attention(
|
||||||
|
query_states,
|
||||||
|
key_states,
|
||||||
|
value_states,
|
||||||
|
attn_mask=attn_mask,
|
||||||
|
is_causal=True,
|
||||||
|
scale=self.scale,
|
||||||
|
)
|
||||||
|
attn_output = attn_output.transpose(1, 2)
|
||||||
|
else:
|
||||||
|
# Use LocalAttention (doesn't support attention_mask, but maintains compatibility)
|
||||||
|
attn_output = self.attn(query_states, key_states, value_states)
|
||||||
|
|
||||||
attn_output = attn_output.reshape(
|
attn_output = attn_output.reshape(
|
||||||
attn_output.shape[0],
|
attn_output.shape[0],
|
||||||
@@ -283,11 +314,18 @@ class CLIPEncoderLayer(nn.Module):
|
|||||||
self.mlp = CLIPMLP(config, quant_config=quant_config, prefix=f"{prefix}.mlp")
|
self.mlp = CLIPMLP(config, quant_config=quant_config, prefix=f"{prefix}.mlp")
|
||||||
self.layer_norm2 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
self.layer_norm2 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
||||||
|
|
||||||
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
def forward(
|
||||||
|
self,
|
||||||
|
hidden_states: torch.Tensor,
|
||||||
|
attention_mask: torch.Tensor | None = None,
|
||||||
|
) -> torch.Tensor:
|
||||||
residual = hidden_states
|
residual = hidden_states
|
||||||
|
|
||||||
hidden_states = self.layer_norm1(hidden_states)
|
hidden_states = self.layer_norm1(hidden_states)
|
||||||
hidden_states, _ = self.self_attn(hidden_states=hidden_states)
|
hidden_states, _ = self.self_attn(
|
||||||
|
hidden_states=hidden_states,
|
||||||
|
attention_mask=attention_mask,
|
||||||
|
)
|
||||||
hidden_states = residual + hidden_states
|
hidden_states = residual + hidden_states
|
||||||
|
|
||||||
residual = hidden_states
|
residual = hidden_states
|
||||||
@@ -334,13 +372,19 @@ class CLIPEncoder(nn.Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def forward(
|
def forward(
|
||||||
self, inputs_embeds: torch.Tensor, return_all_hidden_states: bool
|
self,
|
||||||
|
inputs_embeds: torch.Tensor,
|
||||||
|
return_all_hidden_states: bool,
|
||||||
|
attention_mask: torch.Tensor | None = None,
|
||||||
) -> torch.Tensor | list[torch.Tensor]:
|
) -> torch.Tensor | list[torch.Tensor]:
|
||||||
hidden_states_pool = [inputs_embeds]
|
hidden_states_pool = [inputs_embeds]
|
||||||
hidden_states = inputs_embeds
|
hidden_states = inputs_embeds
|
||||||
|
|
||||||
for idx, encoder_layer in enumerate(self.layers):
|
for idx, encoder_layer in enumerate(self.layers):
|
||||||
hidden_states = encoder_layer(hidden_states)
|
hidden_states = encoder_layer(
|
||||||
|
hidden_states,
|
||||||
|
attention_mask=attention_mask,
|
||||||
|
)
|
||||||
if return_all_hidden_states:
|
if return_all_hidden_states:
|
||||||
hidden_states_pool.append(hidden_states)
|
hidden_states_pool.append(hidden_states)
|
||||||
# If we have multiple feature sample layers, we return all hidden
|
# If we have multiple feature sample layers, we return all hidden
|
||||||
@@ -417,11 +461,8 @@ class CLIPTextTransformer(nn.Module):
|
|||||||
|
|
||||||
encoder_outputs = self.encoder(
|
encoder_outputs = self.encoder(
|
||||||
inputs_embeds=hidden_states,
|
inputs_embeds=hidden_states,
|
||||||
# attention_mask=attention_mask,
|
|
||||||
# causal_attention_mask=causal_attention_mask,
|
|
||||||
# output_attentions=output_attentions,
|
|
||||||
return_all_hidden_states=output_hidden_states,
|
return_all_hidden_states=output_hidden_states,
|
||||||
# return_dict=return_dict,
|
attention_mask=attention_mask,
|
||||||
)
|
)
|
||||||
|
|
||||||
last_hidden_state = encoder_outputs[-1]
|
last_hidden_state = encoder_outputs[-1]
|
||||||
|
|||||||
Reference in New Issue
Block a user