[CPU] Add frontend support for Gemma (#12590)
This commit is contained in:
@@ -398,6 +398,8 @@ register_chat_template(
|
|||||||
"user": ("<start_of_turn>user\n", "<end_of_turn>\n"),
|
"user": ("<start_of_turn>user\n", "<end_of_turn>\n"),
|
||||||
"assistant": ("<start_of_turn>model\n", "<end_of_turn>\n"),
|
"assistant": ("<start_of_turn>model\n", "<end_of_turn>\n"),
|
||||||
},
|
},
|
||||||
|
image_token="<start_of_image>",
|
||||||
|
audio_token="<start_of_audio>",
|
||||||
style=ChatTemplateStyle.PLAIN,
|
style=ChatTemplateStyle.PLAIN,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,14 +35,17 @@ from sglang.srt.layers.linear import (
|
|||||||
from sglang.srt.layers.logits_processor import LogitsProcessor
|
from sglang.srt.layers.logits_processor import LogitsProcessor
|
||||||
from sglang.srt.layers.quantization.base_config import QuantizationConfig
|
from sglang.srt.layers.quantization.base_config import QuantizationConfig
|
||||||
from sglang.srt.layers.radix_attention import AttentionType, RadixAttention
|
from sglang.srt.layers.radix_attention import AttentionType, RadixAttention
|
||||||
from sglang.srt.layers.rotary_embedding import apply_rotary_pos_emb
|
from sglang.srt.layers.rotary_embedding import apply_rotary_pos_emb, get_rope
|
||||||
from sglang.srt.layers.vocab_parallel_embedding import ParallelLMHead
|
from sglang.srt.layers.vocab_parallel_embedding import ParallelLMHead
|
||||||
from sglang.srt.model_executor.forward_batch_info import ForwardBatch
|
from sglang.srt.model_executor.forward_batch_info import ForwardBatch
|
||||||
from sglang.srt.model_loader.weight_utils import (
|
from sglang.srt.model_loader.weight_utils import (
|
||||||
default_weight_loader,
|
default_weight_loader,
|
||||||
maybe_remap_kv_scale_name,
|
maybe_remap_kv_scale_name,
|
||||||
)
|
)
|
||||||
from sglang.srt.utils import add_prefix, make_layers
|
from sglang.srt.utils import add_prefix, cpu_has_amx_support, is_cpu, make_layers
|
||||||
|
|
||||||
|
_is_cpu = is_cpu()
|
||||||
|
_is_cpu_amx_available = cpu_has_amx_support()
|
||||||
|
|
||||||
|
|
||||||
# Aligned with HF's implementation, using sliding window inclusive with the last token
|
# Aligned with HF's implementation, using sliding window inclusive with the last token
|
||||||
@@ -141,7 +144,8 @@ class Gemma3Attention(nn.Module):
|
|||||||
config, "head_dim", hidden_size // config.num_attention_heads
|
config, "head_dim", hidden_size // config.num_attention_heads
|
||||||
)
|
)
|
||||||
self.head_dim = head_dim
|
self.head_dim = head_dim
|
||||||
|
partial_rotary_factor = getattr(config, "partial_rotary_factor", 1)
|
||||||
|
self.rotary_dim = int(partial_rotary_factor * self.head_dim)
|
||||||
self.q_size = self.num_heads * self.head_dim
|
self.q_size = self.num_heads * self.head_dim
|
||||||
|
|
||||||
self.kv_size = self.num_kv_heads * self.head_dim
|
self.kv_size = self.num_kv_heads * self.head_dim
|
||||||
@@ -197,7 +201,14 @@ class Gemma3Attention(nn.Module):
|
|||||||
)
|
)
|
||||||
self.rope_scaling = {"rope_type": "default"}
|
self.rope_scaling = {"rope_type": "default"}
|
||||||
self.sliding_window = None
|
self.sliding_window = None
|
||||||
|
self.rotary_emb = get_rope(
|
||||||
|
self.head_dim,
|
||||||
|
rotary_dim=self.rotary_dim,
|
||||||
|
max_position=max_position_embeddings,
|
||||||
|
base=self.rope_theta,
|
||||||
|
rope_scaling=self.rope_scaling,
|
||||||
|
is_neox_style=getattr(config, "rope_is_neox_style", True),
|
||||||
|
)
|
||||||
self.attn = RadixAttention(
|
self.attn = RadixAttention(
|
||||||
self.num_heads,
|
self.num_heads,
|
||||||
self.head_dim,
|
self.head_dim,
|
||||||
@@ -217,8 +228,39 @@ class Gemma3Attention(nn.Module):
|
|||||||
self.q_norm = Gemma3RMSNorm(dim=config.head_dim, eps=config.rms_norm_eps)
|
self.q_norm = Gemma3RMSNorm(dim=config.head_dim, eps=config.rms_norm_eps)
|
||||||
self.k_norm = Gemma3RMSNorm(dim=config.head_dim, eps=config.rms_norm_eps)
|
self.k_norm = Gemma3RMSNorm(dim=config.head_dim, eps=config.rms_norm_eps)
|
||||||
|
|
||||||
def forward(
|
def forward_cpu(
|
||||||
self,
|
self,
|
||||||
|
positions: torch.Tensor,
|
||||||
|
hidden_states: torch.Tensor,
|
||||||
|
position_embeddings: Tuple[torch.Tensor, torch.Tensor],
|
||||||
|
forward_batch: ForwardBatch,
|
||||||
|
**kwargs,
|
||||||
|
) -> torch.Tensor:
|
||||||
|
qkv, _ = self.qkv_proj(hidden_states)
|
||||||
|
# [s, h * head_dim]
|
||||||
|
q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
|
||||||
|
|
||||||
|
# [s, h, head_dim]
|
||||||
|
q = q.unflatten(-1, (self.num_heads, self.head_dim)).unsqueeze(0)
|
||||||
|
q = self.q_norm(q)
|
||||||
|
k = k.unflatten(-1, (self.num_kv_heads, self.head_dim)).unsqueeze(0)
|
||||||
|
k = self.k_norm(k)
|
||||||
|
q, k = self.rotary_emb(positions, q, k)
|
||||||
|
|
||||||
|
attn_output = self.attn(q, k, v, forward_batch=forward_batch)
|
||||||
|
|
||||||
|
# Compatible with triton backend which returns [1, s, h, head_dim]
|
||||||
|
if attn_output.dim() == 4 and attn_output.shape[0] == 1:
|
||||||
|
attn_output = attn_output.squeeze(0)
|
||||||
|
attn_output = attn_output.flatten(-2, -1)
|
||||||
|
# [s, h * head_dim]
|
||||||
|
|
||||||
|
output, _ = self.o_proj(attn_output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
def forward_native(
|
||||||
|
self,
|
||||||
|
positions: torch.Tensor,
|
||||||
hidden_states: torch.Tensor,
|
hidden_states: torch.Tensor,
|
||||||
position_embeddings: Tuple[torch.Tensor, torch.Tensor],
|
position_embeddings: Tuple[torch.Tensor, torch.Tensor],
|
||||||
forward_batch: ForwardBatch,
|
forward_batch: ForwardBatch,
|
||||||
@@ -257,6 +299,22 @@ class Gemma3Attention(nn.Module):
|
|||||||
output, _ = self.o_proj(attn_output)
|
output, _ = self.o_proj(attn_output)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def forward(
|
||||||
|
self,
|
||||||
|
positions: torch.Tensor,
|
||||||
|
hidden_states: torch.Tensor,
|
||||||
|
position_embeddings: Tuple[torch.Tensor, torch.Tensor],
|
||||||
|
forward_batch: ForwardBatch,
|
||||||
|
**kwargs,
|
||||||
|
) -> torch.Tensor:
|
||||||
|
if _is_cpu and _is_cpu_amx_available:
|
||||||
|
return self.forward_cpu(
|
||||||
|
positions, hidden_states, position_embeddings, forward_batch, **kwargs
|
||||||
|
)
|
||||||
|
return self.forward_native(
|
||||||
|
positions, hidden_states, position_embeddings, forward_batch, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Gemma3DecoderLayer(nn.Module):
|
class Gemma3DecoderLayer(nn.Module):
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -555,6 +613,18 @@ class Gemma3TextModel(PreTrainedModel):
|
|||||||
else:
|
else:
|
||||||
hidden_states = input_embeds
|
hidden_states = input_embeds
|
||||||
|
|
||||||
|
if _is_cpu and _is_cpu_amx_available:
|
||||||
|
for layer in self.layers:
|
||||||
|
layer_outputs = layer(
|
||||||
|
positions=positions,
|
||||||
|
position_embeddings_global=None,
|
||||||
|
position_embeddings_local=None,
|
||||||
|
hidden_states=hidden_states,
|
||||||
|
forward_batch=forward_batch,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
hidden_states = layer_outputs[0]
|
||||||
|
else:
|
||||||
if positions.dim() == 1:
|
if positions.dim() == 1:
|
||||||
positions = einops.rearrange(positions, "s -> 1 s")
|
positions = einops.rearrange(positions, "s -> 1 s")
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class SiglipVisionEmbeddings(nn.Module):
|
|||||||
patch_embeds = self.patch_embedding(
|
patch_embeds = self.patch_embedding(
|
||||||
pixel_values.to(dtype=target_dtype)
|
pixel_values.to(dtype=target_dtype)
|
||||||
) # shape = [*, width, grid, grid]
|
) # shape = [*, width, grid, grid]
|
||||||
embeddings = patch_embeds.flatten(2).transpose(1, 2)
|
embeddings = patch_embeds.flatten(2).transpose(1, 2).contiguous()
|
||||||
# interpolate_pos_encoding is never used in sglang
|
# interpolate_pos_encoding is never used in sglang
|
||||||
embeddings = embeddings + self.position_embedding(self.position_ids)
|
embeddings = embeddings + self.position_embedding(self.position_ids)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user