[diffusion] fix: align encoder of flux klein with official (#24008)
This commit is contained in:
@@ -158,6 +158,7 @@ class Qwen3Attention(nn.Module):
|
|||||||
self,
|
self,
|
||||||
positions: torch.Tensor,
|
positions: torch.Tensor,
|
||||||
hidden_states: torch.Tensor,
|
hidden_states: torch.Tensor,
|
||||||
|
attention_lengths: tuple[int, ...] | None = None,
|
||||||
) -> torch.Tensor:
|
) -> torch.Tensor:
|
||||||
# QKV projection
|
# QKV projection
|
||||||
qkv, _ = self.qkv_proj(hidden_states)
|
qkv, _ = self.qkv_proj(hidden_states)
|
||||||
@@ -185,13 +186,61 @@ class Qwen3Attention(nn.Module):
|
|||||||
k = k.reshape(batch_size, seq_len, self.num_kv_heads, self.head_dim)
|
k = k.reshape(batch_size, seq_len, self.num_kv_heads, self.head_dim)
|
||||||
|
|
||||||
# Attention
|
# Attention
|
||||||
attn_output = self.attn(q, k, v)
|
attn_output = self._masked_causal_attention(q, k, v, attention_lengths)
|
||||||
attn_output = attn_output.reshape(batch_size, seq_len, -1)
|
attn_output = attn_output.reshape(batch_size, seq_len, -1)
|
||||||
|
|
||||||
# Output projection
|
# Output projection
|
||||||
output, _ = self.o_proj(attn_output)
|
output, _ = self.o_proj(attn_output)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def _masked_causal_attention(
|
||||||
|
self,
|
||||||
|
q: torch.Tensor,
|
||||||
|
k: torch.Tensor,
|
||||||
|
v: torch.Tensor,
|
||||||
|
attention_lengths: tuple[int, ...] | None,
|
||||||
|
) -> torch.Tensor:
|
||||||
|
if attention_lengths is None:
|
||||||
|
return self.attn(q, k, v)
|
||||||
|
|
||||||
|
seq_len = q.shape[1]
|
||||||
|
if all(valid_len == seq_len for valid_len in attention_lengths):
|
||||||
|
return self.attn(q, k, v)
|
||||||
|
|
||||||
|
outputs: list[torch.Tensor] = []
|
||||||
|
for batch_index, valid_len in enumerate(attention_lengths):
|
||||||
|
q_item = q[batch_index : batch_index + 1]
|
||||||
|
k_item = k[batch_index : batch_index + 1]
|
||||||
|
v_item = v[batch_index : batch_index + 1]
|
||||||
|
|
||||||
|
real_output = self.attn(
|
||||||
|
q_item[:, :valid_len],
|
||||||
|
k_item[:, :valid_len],
|
||||||
|
v_item[:, :valid_len],
|
||||||
|
)
|
||||||
|
if valid_len == seq_len:
|
||||||
|
outputs.append(real_output)
|
||||||
|
continue
|
||||||
|
|
||||||
|
pad_q = q_item[:, valid_len:].transpose(1, 2)
|
||||||
|
real_k = k_item[:, :valid_len].transpose(1, 2)
|
||||||
|
real_v = v_item[:, :valid_len].transpose(1, 2)
|
||||||
|
if self.num_heads != self.num_kv_heads:
|
||||||
|
repeat_factor = self.num_heads // self.num_kv_heads
|
||||||
|
real_k = real_k.repeat_interleave(repeat_factor, dim=1)
|
||||||
|
real_v = real_v.repeat_interleave(repeat_factor, dim=1)
|
||||||
|
pad_output = torch.nn.functional.scaled_dot_product_attention(
|
||||||
|
pad_q,
|
||||||
|
real_k,
|
||||||
|
real_v,
|
||||||
|
dropout_p=0.0,
|
||||||
|
is_causal=False,
|
||||||
|
scale=self.scaling,
|
||||||
|
).transpose(1, 2)
|
||||||
|
outputs.append(torch.cat([real_output, pad_output], dim=1))
|
||||||
|
|
||||||
|
return torch.cat(outputs, dim=0)
|
||||||
|
|
||||||
|
|
||||||
class Qwen3DecoderLayer(nn.Module):
|
class Qwen3DecoderLayer(nn.Module):
|
||||||
"""Qwen3 transformer decoder layer."""
|
"""Qwen3 transformer decoder layer."""
|
||||||
@@ -241,6 +290,7 @@ class Qwen3DecoderLayer(nn.Module):
|
|||||||
positions: torch.Tensor,
|
positions: torch.Tensor,
|
||||||
hidden_states: torch.Tensor,
|
hidden_states: torch.Tensor,
|
||||||
residual: torch.Tensor | None,
|
residual: torch.Tensor | None,
|
||||||
|
attention_lengths: tuple[int, ...] | None = None,
|
||||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||||
# Self Attention
|
# Self Attention
|
||||||
if residual is None:
|
if residual is None:
|
||||||
@@ -249,7 +299,11 @@ class Qwen3DecoderLayer(nn.Module):
|
|||||||
else:
|
else:
|
||||||
hidden_states, residual = self.input_layernorm(hidden_states, residual)
|
hidden_states, residual = self.input_layernorm(hidden_states, residual)
|
||||||
|
|
||||||
hidden_states = self.self_attn(positions=positions, hidden_states=hidden_states)
|
hidden_states = self.self_attn(
|
||||||
|
positions=positions,
|
||||||
|
hidden_states=hidden_states,
|
||||||
|
attention_lengths=attention_lengths,
|
||||||
|
)
|
||||||
|
|
||||||
# MLP
|
# MLP
|
||||||
hidden_states, residual = self.post_attention_layernorm(hidden_states, residual)
|
hidden_states, residual = self.post_attention_layernorm(hidden_states, residual)
|
||||||
@@ -335,6 +389,13 @@ class Qwen3ForCausalLM(TextEncoder):
|
|||||||
0, hidden_states.shape[1], device=hidden_states.device
|
0, hidden_states.shape[1], device=hidden_states.device
|
||||||
).unsqueeze(0)
|
).unsqueeze(0)
|
||||||
|
|
||||||
|
attention_lengths = None
|
||||||
|
if attention_mask is not None:
|
||||||
|
attention_lengths = tuple(
|
||||||
|
int(valid_len)
|
||||||
|
for valid_len in attention_mask.sum(dim=-1).detach().cpu().tolist()
|
||||||
|
)
|
||||||
|
|
||||||
all_hidden_states: tuple[Any, ...] | None = () if output_hidden_states else None
|
all_hidden_states: tuple[Any, ...] | None = () if output_hidden_states else None
|
||||||
|
|
||||||
for layer in self.layers:
|
for layer in self.layers:
|
||||||
@@ -344,7 +405,9 @@ class Qwen3ForCausalLM(TextEncoder):
|
|||||||
if residual is None
|
if residual is None
|
||||||
else (hidden_states + residual,)
|
else (hidden_states + residual,)
|
||||||
)
|
)
|
||||||
hidden_states, residual = layer(position_ids, hidden_states, residual)
|
hidden_states, residual = layer(
|
||||||
|
position_ids, hidden_states, residual, attention_lengths
|
||||||
|
)
|
||||||
|
|
||||||
hidden_states, _ = self.norm(hidden_states, residual)
|
hidden_states, _ = self.norm(hidden_states, residual)
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ CASE_THRESHOLDS: Dict[str, Dict[ComponentType, float]] = {
|
|||||||
"flux_2_image_t2i": {ComponentType.TRANSFORMER: 0.99},
|
"flux_2_image_t2i": {ComponentType.TRANSFORMER: 0.99},
|
||||||
"flux_2_image_t2i_layerwise_offload": {ComponentType.TRANSFORMER: 0.99},
|
"flux_2_image_t2i_layerwise_offload": {ComponentType.TRANSFORMER: 0.99},
|
||||||
"flux_2_image_t2i_2_gpus": {ComponentType.TRANSFORMER: 0.99},
|
"flux_2_image_t2i_2_gpus": {ComponentType.TRANSFORMER: 0.99},
|
||||||
"flux_2_klein_ti2i_2_gpus": {ComponentType.TRANSFORMER: 0.975},
|
|
||||||
"flux_2_ti2i": {ComponentType.TRANSFORMER: 0.99},
|
"flux_2_ti2i": {ComponentType.TRANSFORMER: 0.99},
|
||||||
"flux_2_t2i_customized_vae_path": {ComponentType.TRANSFORMER: 0.99},
|
"flux_2_t2i_customized_vae_path": {ComponentType.TRANSFORMER: 0.99},
|
||||||
"fast_hunyuan_video": {ComponentType.TRANSFORMER: 0.99},
|
"fast_hunyuan_video": {ComponentType.TRANSFORMER: 0.99},
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ ACCURACY_TWO_GPU_CASE_IDS = (
|
|||||||
"zimage_image_t2i_2_gpus_non_square",
|
"zimage_image_t2i_2_gpus_non_square",
|
||||||
"flux_image_t2i_2_gpus",
|
"flux_image_t2i_2_gpus",
|
||||||
"flux_2_image_t2i_2_gpus",
|
"flux_2_image_t2i_2_gpus",
|
||||||
"flux_2_klein_ti2i_2_gpus",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ACCURACY_ONE_GPU_CASES = _select_accuracy_cases(
|
ACCURACY_ONE_GPU_CASES = _select_accuracy_cases(
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
"mean_abs_diff_threshold": 8.0
|
"mean_abs_diff_threshold": 8.0
|
||||||
},
|
},
|
||||||
"flux_2_klein_image_t2i": {
|
"flux_2_klein_image_t2i": {
|
||||||
"clip_threshold": 0.83,
|
"clip_threshold": 0.94,
|
||||||
"ssim_threshold": 0.52,
|
"ssim_threshold": 0.78,
|
||||||
"psnr_threshold": 9.3,
|
"psnr_threshold": 17.0,
|
||||||
"mean_abs_diff_threshold": 68.0
|
"mean_abs_diff_threshold": 17.0
|
||||||
},
|
},
|
||||||
"zimage_image_t2i": {
|
"zimage_image_t2i": {
|
||||||
"clip_threshold": 0.92,
|
"clip_threshold": 0.92,
|
||||||
@@ -193,12 +193,6 @@
|
|||||||
"psnr_threshold": 18.7,
|
"psnr_threshold": 18.7,
|
||||||
"mean_abs_diff_threshold": 8.0
|
"mean_abs_diff_threshold": 8.0
|
||||||
},
|
},
|
||||||
"flux_2_klein_ti2i_2_gpus": {
|
|
||||||
"clip_threshold": 0.92,
|
|
||||||
"ssim_threshold": 0.77,
|
|
||||||
"psnr_threshold": 18.4,
|
|
||||||
"mean_abs_diff_threshold": 18.0
|
|
||||||
},
|
|
||||||
"wan2_2_t2v_a14b_teacache_2gpu": {
|
"wan2_2_t2v_a14b_teacache_2gpu": {
|
||||||
"clip_threshold": 0.90,
|
"clip_threshold": 0.90,
|
||||||
"ssim_threshold": 0.72,
|
"ssim_threshold": 0.72,
|
||||||
|
|||||||
@@ -616,13 +616,6 @@ TWO_GPU_CASES = [
|
|||||||
),
|
),
|
||||||
T2I_sampling_params,
|
T2I_sampling_params,
|
||||||
),
|
),
|
||||||
DiffusionTestCase(
|
|
||||||
"flux_2_klein_ti2i_2_gpus",
|
|
||||||
DiffusionServerArgs(
|
|
||||||
model_path="black-forest-labs/FLUX.2-klein-4B",
|
|
||||||
),
|
|
||||||
TI2I_sampling_params,
|
|
||||||
),
|
|
||||||
DiffusionTestCase(
|
DiffusionTestCase(
|
||||||
"ltx_2.3_one_stage_ti2v",
|
"ltx_2.3_one_stage_ti2v",
|
||||||
DiffusionServerArgs(
|
DiffusionServerArgs(
|
||||||
|
|||||||
@@ -2119,27 +2119,6 @@
|
|||||||
"expected_median_denoise_ms": 151.72,
|
"expected_median_denoise_ms": 151.72,
|
||||||
"estimated_full_test_time_s": 129.3
|
"estimated_full_test_time_s": 129.3
|
||||||
},
|
},
|
||||||
"flux_2_klein_ti2i_2_gpus": {
|
|
||||||
"stages_ms": {
|
|
||||||
"InputValidationStage": 35.39,
|
|
||||||
"DecodingStage": 6.68,
|
|
||||||
"TextEncodingStage": 160.46,
|
|
||||||
"TimestepPreparationStage": 27.82,
|
|
||||||
"LatentPreparationStage": 0.4,
|
|
||||||
"DenoisingStage": 364.99,
|
|
||||||
"ImageVAEEncodingStage": 65.69
|
|
||||||
},
|
|
||||||
"denoise_step_ms": {
|
|
||||||
"0": 30.19,
|
|
||||||
"1": 63.04,
|
|
||||||
"2": 89.37,
|
|
||||||
"3": 89.7
|
|
||||||
},
|
|
||||||
"expected_e2e_ms": 827.17,
|
|
||||||
"expected_avg_denoise_ms": 68.93,
|
|
||||||
"expected_median_denoise_ms": 77.89,
|
|
||||||
"estimated_full_test_time_s": 120.8
|
|
||||||
},
|
|
||||||
"flux_2_image_t2i_upscaling_4x": {
|
"flux_2_image_t2i_upscaling_4x": {
|
||||||
"stages_ms": {
|
"stages_ms": {
|
||||||
"TextEncodingStage": 494.65,
|
"TextEncodingStage": 494.65,
|
||||||
|
|||||||
Reference in New Issue
Block a user