CoolFace
Modelpublic

Azrail/smallm_70_rope

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes43downloads
model.py816 linesDownload Raw Back to root
1import torch2from torch import nn3import torch.nn.functional as F4from transformers import PreTrainedModel, GenerationMixin5from transformers.cache_utils import Cache, DynamicCache6from transformers.modeling_outputs import (7    BaseModelOutputWithPast,8    CausalLMOutputWithPast,9)10from .config import SmalLmConfig11from typing import Optional12import logging13from einops import rearrange14from transformers.modeling_attn_mask_utils import AttentionMaskConverter15from einops._torch_specific import allow_ops_in_compiled_graph16 17allow_ops_in_compiled_graph()18from transformers.utils import is_flash_attn_2_available19 20if is_flash_attn_2_available():21    from flash_attn import flash_attn_varlen_func22    from flash_attn.bert_padding import unpad_input, pad_input23 24 25 26logger = logging.getLogger(__name__)27 28 29class SwiGLU(nn.Module):30    def __init__(31        self, input_size: int, hidden_size: int, bias: bool = False, *args, **kwargs32    ):33        super().__init__(*args, **kwargs)34        self.input_size = input_size35        self.hidden_size = hidden_size36        self.up_proj = nn.Linear(input_size, hidden_size * 2, bias=bias)37        self.down_proj = nn.Linear(hidden_size, input_size, bias=bias)38 39    def forward(self, x):40        up_gate = self.up_proj(x)41        up, gate = rearrange(up_gate, "... (d span) -> span ... d", d=self.hidden_size)42        down = F.silu(gate) * up43        return self.down_proj(down)44 45 46class Router(nn.Module):47    def __init__(self, config: SmalLmConfig, *args, **kwargs):48        49        super().__init__(*args, **kwargs)50        self.config = config51        self.experts_to_select = self.config.token_experts - self.config.shared_experts52        self.gate = nn.Linear(config.hidden_size, config.routed_experts, bias=False)53        self.gate_noise = (54            nn.Linear(config.hidden_size, config.routed_experts, bias=False)55            if config.noisy_experts is True56            else None57        )58        self.bias_coef = config.balancing_coef59        self.register_buffer(60            "bias", torch.zeros(config.routed_experts), persistent=True61        )62        self.register_buffer(63            "expert_counts", torch.zeros(config.routed_experts), persistent=False64        )65 66    def forward(self, x: torch.Tensor) -> tuple[torch.Tensor]:67        # calculating with fp32 for stability68        # num_tokens n_shared_experts69        gate_logits = self.gate(x)70        if self.gate_noise is not None:71            gate_logits_noise = F.softplus(self.gate_noise(x))72            gate_logits_noise = torch.randn_like(gate_logits_noise) * gate_logits_noise73            gate_logits = gate_logits + gate_logits_noise74 75        gate_weights = gate_logits.sigmoid()76        original_weights = gate_weights77 78        gate_weights = gate_weights + self.bias79 80        _, top_experts_idx = torch.topk(gate_weights, self.experts_to_select, dim=-1)81        counts = torch.bincount(82            top_experts_idx.flatten(), minlength=self.config.routed_experts83        ).detach()84        if self.training:85            self.expert_counts += counts86        top_experts_weights = original_weights.gather(1, top_experts_idx)87        top_experts_weights = top_experts_weights / top_experts_weights.sum(88            dim=-1, keepdim=True89        )90        return top_experts_idx, top_experts_weights.type_as(x), counts.tolist()91 92    def update_bias(self):93        mean = self.expert_counts.float().mean()94        delta = self.bias_coef * torch.sign(mean - self.expert_counts)95        self.bias += delta96        self.expert_counts.zero_()97 98 99class MoE(nn.Module):100    def __init__(self, config: SmalLmConfig, *args, **kwargs):101        super().__init__(*args, **kwargs)102        self.config = config103        self.shared_experts = SwiGLU(104            config.hidden_size,105            config.shared_experts * config.expert_size,106            config.moe_bias,107        )108        self.routed_experts = nn.ModuleList(109            [110                SwiGLU(config.hidden_size, config.expert_size, config.moe_bias)111                for _ in range(config.routed_experts)112            ]113        )114        self.router = Router(config)115 116    def forward(self, x: torch.Tensor) -> torch.Tensor:117        shape = x.size()118        x = x.view(-1, self.config.hidden_size)119        experts_idx, experts_weights, counts = self.router(x)120        out = torch.zeros_like(x)121        for i, expert in enumerate(self.routed_experts):122            if counts[i] == 0:123                continue124            idx, pos = torch.where(experts_idx == i)125            out[idx] += expert(x[idx]) * experts_weights[idx, pos, None]126        shared_out = self.shared_experts(x)127        return (out + shared_out).view(shape)128 129 130def build_alibi_bias(config: SmalLmConfig) -> torch.Tensor:131    """Build ALiBi for specified number of heads:132 133    Returns:134        Tensor with ALiBi biases, shape: [num heads]135    """136    bias = (137        2**-8138        / config.num_attention_heads139        * torch.arange(1, config.num_attention_heads + 1).float()140    )141    return bias142 143 144def calc_rotation(num_rotaitions, dim, base, seq_len):145    return (146        dim147        * torch.log(torch.tensor(seq_len).float() / (num_rotaitions * 2 * torch.pi))148        / torch.log(torch.tensor(base))149    )150 151 152def get_ramp_interpolation(min_idx, max_idx, thetas_dim, eps=1e-6):153    if min_idx == max_idx:154        max_idx += eps155    mult = (torch.arange(thetas_dim) - min_idx) / (max_idx - min_idx)156    mult = torch.clamp(mult, 0, 1)157    return 1 - mult158 159 160def build_rope_bias(config: SmalLmConfig) -> torch.Tensor:161    dim = config.head_size162 163    theta = 1.0 / (config.rope_base ** (torch.arange(0, dim, 2).float() / dim))164 165    # neural tangent kernel by part korrection166    if config.max_seq_len > config.original_seq_len:167        scale = config.max_seq_len / config.original_seq_len168        # from idea that lambda = 2pi / theta_i and lmbad = seq_len / num_rotations, lambda - wavelen169        low_interpolation_idx = max(170            0,171            torch.ceil(172                calc_rotation(173                    config.high_rotations,174                    dim,175                    config.rope_base,176                    config.original_seq_len,177                )178            ).item(),179        )180        high_interpolation_idx = min(181            dim - 1,182            torch.floor(183                calc_rotation(184                    config.low_rotations, dim, config.rope_base, config.original_seq_len185                )186            ).item(),187        )188        interpolation_mult = get_ramp_interpolation(189            low_interpolation_idx, high_interpolation_idx, dim // 2190        )191        theta = (1 - interpolation_mult) * theta / scale + interpolation_mult * theta192 193    seq_idx = torch.arange(config.max_seq_len)194    seq_theta = torch.outer(seq_idx, theta)195    bias = torch.polar(torch.ones_like(seq_theta), seq_theta)196    return bias197 198 199def apply_rope_bias(x: torch.Tensor, precompute_bias: torch.Tensor) -> torch.Tensor:200    ini_dtype = x.dtype201    # for stbility to fp32, also need for torch202    x = rearrange(x.float(), "b n s (d i) -> b n s d i", i=2).contiguous()203    x = torch.view_as_complex(x)204    x = x * precompute_bias205    x = torch.view_as_real(x)206    x = rearrange(x, "b n s d i -> b n s (d i)")207    return x.to(ini_dtype)208 209 210def flash_attention_forward(211        module: nn.Module,212        x: torch.Tensor,213        query: torch.Tensor,214        key: torch.Tensor,215        value: torch.Tensor,216        attention_mask: torch.Tensor,217        alibi_slope: Optional[torch.Tensor]218) -> torch.Tensor:219        query = rearrange(query, "b n s d -> b s n d")220        key = rearrange(key, "b n s d -> b s n d")221        value = rearrange(value, "b n s d -> b s n d")222        query, idx_q, cu_seqlens_q, max_seqlen_q, _ = unpad_input(query, attention_mask)223        key, _, cu_seqlens_k, max_seqlen_k, _ = unpad_input(key, attention_mask)224        value, _, _, _, _ = unpad_input(value, attention_mask)225 226        key = key.contiguous()227        value = value.contiguous()228        query = query.contiguous()229 230        attention_probs = flash_attn_varlen_func(231            query,232            key,233            value,234            cu_seqlens_q=cu_seqlens_q,235            cu_seqlens_k=cu_seqlens_k,236            max_seqlen_q=max_seqlen_q,237            max_seqlen_k=max_seqlen_k,238            dropout_p=module.config.attention_dropout if module.training else 0.0,239            causal=True,240            alibi_slopes=alibi_slope if module.config.attention_bias == "alibi" else None,241        )242        attention_probs = pad_input(attention_probs, idx_q, x.size(0), x.size(1))243        out = rearrange(attention_probs, "b s n d -> b s (n d)")244        return out, None245 246 247def sdpa_attention_forward(248    module: nn.Module,249    x: torch.Tensor,250    query: torch.Tensor,251    key: torch.Tensor,252    value: torch.Tensor,253    attention_mask: torch.Tensor,254    alibi_slope: Optional[torch.Tensor]255) -> torch.Tensor:256    is_causal = attention_mask is None and query.size(-2) > 1257 258    attention_probs = F.scaled_dot_product_attention(259        query,260        key,261        value,262        attn_mask=attention_mask,263        enable_gqa=True,264        is_causal=is_causal,265        dropout_p=module.config.attention_dropout if module.training else 0.0,266    )267    out = rearrange(attention_probs, "b n s d -> b s (n d)")268    269    return out, None270 271def eager_attention_forward(272    module: nn.Module,273    x: torch.Tensor,274    query: torch.Tensor,275    key: torch.Tensor,276    value: torch.Tensor,277    attention_mask: torch.Tensor,278    alibi_slope: Optional[torch.Tensor]279) -> torch.Tensor:280    query = rearrange(query, 'b (kv group) s d -> b kv group s d', kv=module.config.num_kv_heads, group=module.head_per_group)281    key = rearrange(key, 'b kv s d -> b kv 1 s d')282    value = rearrange(283        value, 'b kv s d -> b kv 1 s d'284        )285    attention_weights = query @ key.transpose(-1, -2)286    attention_probs = F.dropout(attention_weights / torch.sqrt(287        torch.tensor(value.size(-1), device=x.device)288        ),289        p=module.config.attention_dropout if module.training else 0.0290        )291    if alibi_slope is not None:292        alibi_slope = rearrange(293            alibi_slope, 'b n s s -> b kv group s s', kv=module.config.num_kv_heads, group=module.head_per_group294            )295        attention_probs = attention_probs + alibi_slope296    elif alibi_slope is None and attention_mask is not None:297        attention_mask = attention_mask.expand(-1, module.config.num_attention_heads, -1, -1)298        attention_mask = rearrange(299            attention_mask, 'b (kv group) s1 s2 -> b kv group s1 s2', kv=module.config.num_kv_heads, group=module.head_per_group300            )301        attention_probs = attention_probs + attention_mask302    attention_probs = F.softmax(attention_probs, dim=-1)303    attention_probs = attention_probs @ value304    out = rearrange(attention_probs, "b kv group s d -> b s (kv group d)")305    return out, attention_weights306 307 308ALL_ATTENTION_FUNCTIONS = {309    "eager": eager_attention_forward,310    "sdpa": sdpa_attention_forward,311    "flash_attention_2": flash_attention_forward,312}313 314 315class CausalSelfAttention(nn.Module):316    def __init__(self, config: SmalLmConfig, layer_idx: int, *args, **kwargs):317        super().__init__(*args, **kwargs)318        if config.num_attention_heads % config.num_kv_heads != 0:319            raise ValueError("Num attention heads should divided by num kv heads")320 321        self.config = config322        self.layer_idx = layer_idx323        self.head_per_group = config.num_attention_heads // config.num_kv_heads324        self.q_proj = nn.Linear(325            config.hidden_size,326            config.head_size * config.num_attention_heads,327            bias=config.attention_bias,328        )329        self.kv_proj = nn.Linear(330            config.hidden_size,331            config.head_size * config.num_kv_heads * 2,332            bias=config.attention_bias,333        )334        self.out_proj = nn.Linear(335            config.head_size * config.num_attention_heads,336            config.hidden_size,337            bias=config.attention_bias,338        )339 340    def forward(341        self,342        x: torch.Tensor,343        attention_mask: torch.Tensor,344        past_key_values: Optional[Cache | torch.FloatTensor],345        cache_position: Optional[torch.LongTensor],346        bias: torch.Tensor,347    ):348        q = self.q_proj(x)349        kv = self.kv_proj(x)350        q = rearrange(q, "b s (n d) -> b n s d", n=self.config.num_attention_heads)351        k, v = rearrange(kv, "b s (n d q) -> q b n s d", q=2, d=self.config.head_size)352 353        if self.config.positional_bias_type == "rope":354            k = apply_rope_bias(k, bias)355            q = apply_rope_bias(q, bias)356 357        if past_key_values is not None:358            # for static cache359            cach_kwargs = {"cache_position": cache_position}360            k, v = past_key_values.update(361                key_states=k,362                value_states=v,363                layer_idx=self.layer_idx,364                cache_kwargs=cach_kwargs,365            )366 367        attention_interface = eager_attention_forward368        if self.config._attn_implementation != "eager":369            attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]370 371        out, attention_weights = attention_interface(372            self,373            x,374            q,375            k,376            v,377            attention_mask,378            bias if self.config.positional_bias_type == "alibi" else None379        )380 381        out = self.out_proj(out)382        return out, attention_weights383 384 385class WeightedResidual(nn.Module):386    def __init__(self, config: SmalLmConfig, *args, **kwargs):387        super().__init__(*args, **kwargs)388        self.weight = nn.Parameter(389            torch.ones(config.hidden_size), requires_grad=config.static_residual390        )391 392    def forward(self, short, long):393        return self.weight * short + long394 395 396class Block(nn.Module):397    def __init__(self, config: SmalLmConfig, layer_idx: int, *args, **kwargs):398        super().__init__(*args, **kwargs)399        self.attn_norm = nn.RMSNorm(400            config.hidden_size,401            eps=config.rms_norm_eps,402            elementwise_affine=config.rms_affine,403        )404        self.ffn_norm = nn.RMSNorm(405            config.hidden_size,406            eps=config.rms_norm_eps,407            elementwise_affine=config.rms_affine,408        )409        self.dropout1 = nn.Dropout(config.layer_dropout)410        self.dropout2 = nn.Dropout(config.layer_dropout)411        self.attention = CausalSelfAttention(config, layer_idx)412        self.mlp = (413            MoE(config)414            if (415                config.use_moe416                and layer_idx % config.moe_period == 0417                and layer_idx > config.no_moe_layers418            )419            else SwiGLU(config.hidden_size, config.intermediate_size, config.mlp_bias)420        )421        self.attention_residual = WeightedResidual(config)422        self.ffn_residual = WeightedResidual(config)423 424    def forward(425        self,426        inputs_embeds: torch.Tensor,427        attention_mask: torch.Tensor,428        past_key_values: Optional[Cache | torch.FloatTensor],429        output_attentions: bool,430        cache_position: Optional[torch.LongTensor],431        bias: torch.Tensor,432    ) -> tuple[torch.FloatTensor, Optional[torch.FloatTensor]]:433        identity = inputs_embeds434 435        # attention block436        out = self.attn_norm(inputs_embeds)437        out, attention_probs = self.attention(438            out, attention_mask, past_key_values, cache_position, bias439        )440        out = self.dropout1(out)441        identity = self.attention_residual(identity, out)442 443        # swiglu / MoE block444        out = self.dropout2(self.mlp(self.ffn_norm(identity)))445        out = self.ffn_residual(identity, out)446        if output_attentions:447            return out, attention_probs448        return (out,)449 450 451class SmalLmPreTrainedModel(PreTrainedModel):452    config_class = SmalLmConfig453    base_model_prefix = "model"454    supports_gradient_checkpointing = True455    _no_split_modules = ["Block"]456    _skip_keys_device_placement = "past_key_values"457    _supports_sdpa = True458    _supports_flash_attn_2 = True459    def __init__(self, *inputs, **kwargs):460        super().__init__(*inputs, **kwargs)461 462    def _init_weights(self, module):463        std = self.config.initializer_range464        if isinstance(module, nn.Linear):465            torch.nn.init.normal_(module.weight, mean=0.0, std=std)466            if module.bias is not None:467                torch.nn.init.zeros_(module.bias)468        elif isinstance(module, nn.Embedding):469            torch.nn.init.normal_(module.weight, mean=0.0, std=std)470            module.weight.data[self.pad_idx].zero_()471 472 473class SmalLmModel(SmalLmPreTrainedModel):474    def __init__(self, config: SmalLmConfig, *args, **kwargs):475        super().__init__(config, *args, **kwargs)476        self.config = config477        self.pad_idx = config.pad_token_id478        self.pad_token_id = config.pad_token_id479        self.vocab_size = config.vocab_size480        self.config = config481        precompute_bias = (482            build_alibi_bias(config)483            if config.positional_bias_type == "alibi"484            else build_rope_bias(config)485        )486        self.register_buffer("precompute_bias", precompute_bias, persistent=False)487        # не забыть про sharing weights на output голове self.embedding.weight = self.output.weight488        self.embedding = nn.Embedding(489            self.vocab_size, config.hidden_size, padding_idx=config.pad_token_id490        )491        self.embedding_dropout = nn.Dropout(config.embedding_dropout)492        self.layers = nn.ModuleList(493            [Block(config, idx) for idx in range(1, config.num_hidden_layers + 1)]494        )495        self.out_norm = nn.RMSNorm(496            config.hidden_size,497            eps=config.rms_norm_eps,498            elementwise_affine=config.rms_affine,499        )500 501        self.gradient_checkpointing = False502        self.post_init()503 504    def get_input_embeddings(self):505        return self.embedding506 507    def set_input_embeddings(self, value):508        self.embedding = value509 510    def forward(511        self,512        # input options513        input_ids: torch.LongTensor = None,514        attention_mask: Optional[torch.Tensor] = None,515        inputs_embeds: Optional[torch.FloatTensor] = None,516        # output options517        output_attentions: Optional[bool] = None,518        output_hidden_states: Optional[bool] = None,519        return_dict: Optional[bool] = None,520        # cache options521        use_cache: Optional[bool] = None,522        past_key_values: Optional[Cache | torch.FloatTensor] = None,523        cache_position: Optional[torch.LongTensor] = None,524        position_ids: Optional[torch.LongTensor] = None,525        **kwargs,526    ) -> tuple | BaseModelOutputWithPast:527        # check additional parameters528        output_hidden_states = (529            output_hidden_states530            if output_hidden_states is not None531            else self.config.output_hidden_states532        )533        use_cache = (534            use_cache535            if use_cache is not None536            else (False if self.training else self.config.use_cache)537        )538        return_dict = (539            return_dict if return_dict is not None else self.config.return_dict540        )541 542        if input_ids is not None and inputs_embeds is not None:543            raise ValueError(544                "You must specify only input_ids or inputs_embeds, not both"545            )546 547        if self.training and use_cache:548            use_cache = False549 550        if inputs_embeds is None:551            inputs_embeds = self.embedding(input_ids)552 553        if use_cache and past_key_values is None:554            past_key_values = DynamicCache()555 556        # calculating position for StaticCache557        if cache_position is None:558            last_position = (559                past_key_values.get_seq_length() if past_key_values is not None else 0560            )561            cache_position = torch.arange(562                last_position,563                last_position + inputs_embeds.size(1),564                device=inputs_embeds.device,565            )566 567        causal_mask = self._get_causal_masks(568            attention_mask, inputs_embeds, past_key_values, cache_position569        )570        if self.config.positional_bias_type == "rope":571            end_pos = (572                inputs_embeds.size(1)573                if past_key_values is None574                else cache_position[-1] + 1575            )576            start_pos = 0 if past_key_values is None else cache_position[0]577            bias = self.precompute_bias[start_pos:end_pos]578 579        elif self.config.positional_bias_type == "alibi":580            if self.config._attn_implementation == "flash_attention_2":581                bias = self.precompute_bias582            else:583                i = torch.arange(584                    (585                        inputs_embeds.size(1)586                        if past_key_values is None587                        else cache_position[-1] + 1588                    ),589                    device=inputs_embeds.device,590                )591                bias = i[:, None] - i[None, :]592                bias = torch.tril(bias).expand(593                    inputs_embeds.size(0), self.config.num_attention_heads, -1, -1594                ) * rearrange(self.precompute_bias, "n -> 1 n 1 1")595                if causal_mask is not None:596                    causal_mask = causal_mask + bias597                else:598                    causal_mask = bias599 600        hidden_state = inputs_embeds601        hidden_states = [hidden_state] if output_hidden_states else None602        attentions = [] if output_attentions else None603        for idx, layer in enumerate(self.layers, 1):604            if self.gradient_checkpointing:605                # for details see:606                # https://github.com/huggingface/transformers/blob/main/src/transformers/modeling_utils.py#L3107607                # https://github.com/huggingface/transformers/blob/main/src/transformers/modeling_utils.py#L3149608                layer_out = self._gradient_checkpointing_func(609                    layer.__call__,610                    hidden_state,611                    causal_mask,612                    past_key_values,613                    output_attentions,614                    cache_position,615                    bias,616                )617            else:618                layer_out = layer(619                    hidden_state,620                    causal_mask,621                    past_key_values,622                    output_attentions,623                    cache_position,624                    bias,625                )626            hidden_state = layer_out[0]627            if output_hidden_states:628                hidden_states.append(hidden_state)629            if output_attentions:630                attentions.append(layer_out[1])631 632        hidden_state = self.out_norm(hidden_state)633        out = BaseModelOutputWithPast(634            last_hidden_state=hidden_state,635            past_key_values=past_key_values if use_cache else None,636            hidden_states=tuple(hidden_states) if hidden_states is not None else None,637            attentions=tuple(attentions) if attentions is not None else None,638        )639        return out if return_dict else out.to_tuple()640 641    def _get_causal_masks(642        self,643        attention_mask: Optional[torch.Tensor],644        inputs_embeds: torch.Tensor,645        past_key_values: Optional[torch.Tensor],646        cache_position: Optional[torch.Tensor],647    ):648        if self.config._attn_implementation == "flash_attention_2":649            if attention_mask is None:650                attention_mask = torch.ones(651                    (inputs_embeds.size(0), inputs_embeds.size(1)), device=inputs_embeds.device652                    ).long()653            return attention_mask654        dtype, device = inputs_embeds.dtype, inputs_embeds.device655        past_token = (656            past_key_values.get_seq_length() if past_key_values is not None else 0657        )658        if attention_mask is not None and torch.all(attention_mask == 0.0):659            return None660        if AttentionMaskConverter._ignore_causal_mask_sdpa(661            attention_mask=attention_mask,662            inputs_embeds=inputs_embeds,663            past_key_values_length=past_token,664            is_training=self.training,665        ):666            return None667 668        sequence_length = inputs_embeds.size(1)669        target_length = (670            attention_mask.size(-1)671            if isinstance(attention_mask, torch.Tensor)672            else past_token + sequence_length + 1673        )674 675        causal_mask = self._prepare_4d_causal_attention_mask_with_cache_position(676            attention_mask=attention_mask,677            sequence_length=sequence_length,678            target_length=target_length,679            dtype=dtype,680            device=device,681            cache_position=cache_position,682            batch_size=inputs_embeds.size(0),683        )684 685        min_dtype = torch.finfo(dtype).min686        causal_mask = AttentionMaskConverter._unmask_unattended(causal_mask, min_dtype)687        return causal_mask688 689    @staticmethod690    def _prepare_4d_causal_attention_mask_with_cache_position(691        attention_mask: Optional[torch.Tensor],692        sequence_length: int,693        target_length: int,694        dtype: torch.dtype,695        device: torch.device,696        cache_position: Optional[torch.Tensor],697        batch_size: int,698    ):699        if attention_mask is not None and attention_mask.dim() == 4:700            causal_mask = attention_mask701        else:702            min_dtype = torch.finfo(dtype).min703            causal_mask = torch.full(704                (sequence_length, target_length),705                fill_value=min_dtype,706                dtype=dtype,707                device=device,708            )709            if sequence_length != 1:710                causal_mask = torch.triu(causal_mask, diagonal=1)711            causal_mask *= torch.arange(712                target_length, device=device713            ) > cache_position.reshape(-1, 1)714            causal_mask = causal_mask[None, None, :, :].expand(batch_size, 1, -1, -1)715            if attention_mask is not None:716                causal_mask = causal_mask.clone()717                mask_length = attention_mask.shape[-1]718                padding_mask = (719                    causal_mask[:, :, :, :mask_length]720                    + attention_mask[:, None, None, :]721                )722                padding_mask = padding_mask == 0723                causal_mask[:, :, :, :mask_length] = causal_mask[724                    :, :, :, :mask_length725                ].masked_fill(padding_mask, min_dtype)726        return causal_mask727 728 729class SmalLmForCausalLM(SmalLmPreTrainedModel, GenerationMixin):730    _tied_weights_keys = ["lm_head.weight"]731 732    def __init__(self, config: SmalLmConfig, *args, **kwargs):733        super().__init__(config, *args, **kwargs)734        self.config = config735        self.model = SmalLmModel(config)736        self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)737        self.post_init()738 739    def get_output_embeddings(self):740        return self.lm_head741 742    def set_output_embeddings(self, new_embeddings):743        self.lm_head = new_embeddings744 745    def forward(746        self,747        # input options748        input_ids: torch.LongTensor = None,749        attention_mask: Optional[torch.Tensor] = None,750        inputs_embeds: Optional[torch.FloatTensor] = None,751        # output options752        output_attentions: Optional[bool] = None,753        output_hidden_states: Optional[bool] = None,754        return_dict: Optional[bool] = None,755        # cache options756        use_cache: Optional[bool] = None,757        past_key_values: Optional[Cache | torch.FloatTensor] = None,758        cache_position: Optional[torch.LongTensor] = None,759        # generation options760        labels: Optional[torch.Tensor] = None,761        logits_to_keep: int | torch.Tensor = 0,762        **kwargs,763    ) -> tuple | CausalLMOutputWithPast:764        output_attentions = (765            output_attentions766            if output_attentions is not None767            else self.config.output_attentions768        )769        output_hidden_states = (770            output_hidden_states771            if output_hidden_states is not None772            else self.config.output_hidden_states773        )774        use_cache = use_cache if use_cache is not None else self.config.use_cache775        return_dict = (776            return_dict if return_dict is not None else self.config.return_dict777        )778 779        model_outputs = self.model(780            input_ids=input_ids,781            attention_mask=attention_mask,782            past_key_values=past_key_values,783            inputs_embeds=inputs_embeds,784            use_cache=use_cache,785            output_attentions=output_attentions,786            output_hidden_states=output_hidden_states,787            return_dict=return_dict,788            cache_position=cache_position,789            **kwargs,790        )791 792        hidden_states = model_outputs[0]793        slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep794        logits = self.lm_head(hidden_states[:, slice_indices, :])795 796        loss = None797        if labels is not None:798            loss = self.loss_function(799                logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs800                )801 802        if not return_dict:803            output = (logits, model_outputs[1:])804            return (loss, output) if loss is not None else output805 806        return CausalLMOutputWithPast(807            loss=loss,808            logits=logits,809            past_key_values=model_outputs.past_key_values,810            hidden_states=model_outputs.hidden_states,811            attentions=model_outputs.attentions,812        )813 814 815__all__ = ["SmalLmForCausalLM", "SmalLmModel", "SmalLmPreTrainedModel"]816