| import inspect |
| from dataclasses import dataclass |
| from typing import Optional |
|
|
| import torch |
| import torch.nn as nn |
|
|
| from .fused_linear_cross_entropy import LigerFusedLinearCrossEntropyFunction |
| from .geglu import LigerGELUMulFunction |
| from .rms_norm import LigerRMSNormFunction |
| from .rope import LigerRopeFunction |
| from .swiglu import LigerSiLUMulFunction |
| from .tiled_mlp import apply_tiled_mlp |
|
|
|
|
| |
| class LigerRMSNorm(nn.Module): |
| weight: nn.Parameter |
| variance_epsilon: float |
|
|
| def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: |
| return LigerRMSNormFunction.apply( |
| hidden_states, |
| self.weight, |
| self.variance_epsilon, |
| 0, |
| "llama", |
| True, |
| None, |
| ) |
|
|
| def extra_repr(self): |
| return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}" |
|
|
|
|
| class LigerLinear(nn.Module): |
| weight: nn.Parameter |
| bias: nn.Parameter | None |
|
|
| can_torch_compile = True |
|
|
| def forward(self, input: torch.Tensor) -> torch.Tensor: |
| def _forward(module, x): |
| return nn.functional.linear(x, module.weight, module.bias) |
|
|
| compute_params = [p for p in self.parameters() if p.requires_grad] |
|
|
| return apply_tiled_mlp( |
| fn=_forward, |
| mlp_module=self, |
| x=input, |
| num_shards=None, |
| compute_params=compute_params, |
| ) |
|
|
|
|
| class LigerSwiGLUMLP(nn.Module): |
| gate_proj: nn.Linear |
| up_proj: nn.Linear |
| down_proj: nn.Linear |
|
|
| can_torch_compile = True |
|
|
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| return self.down_proj(LigerSiLUMulFunction.apply(self.gate_proj(x), self.up_proj(x))) |
|
|
|
|
| class LigerGEGLUMLP(nn.Module): |
| gate_proj: nn.Linear |
| up_proj: nn.Linear |
| down_proj: nn.Linear |
|
|
| can_torch_compile = True |
|
|
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| return self.down_proj(LigerGELUMulFunction.apply(self.gate_proj(x), self.up_proj(x))) |
|
|
|
|
| class LigerTiledSwiGLUMLP(nn.Module): |
| gate_proj: nn.Linear |
| up_proj: nn.Linear |
| down_proj: nn.Linear |
|
|
| can_torch_compile = True |
|
|
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| def _mlp_forward(module, x): |
| """Internal MLP forward function for tiled computation.""" |
| gate = module.gate_proj(x) |
| up = module.up_proj(x) |
| return module.down_proj(LigerSiLUMulFunction.apply(gate, up)) |
|
|
| compute_params = [p for p in self.parameters() if p.requires_grad] |
|
|
| return apply_tiled_mlp( |
| fn=_mlp_forward, |
| mlp_module=self, |
| x=x, |
| num_shards=None, |
| compute_params=compute_params, |
| ) |
|
|
|
|
| class LigerTiledGEGLUMLP(nn.Module): |
| gate_proj: nn.Linear |
| up_proj: nn.Linear |
| down_proj: nn.Linear |
|
|
| can_torch_compile = True |
|
|
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| def _mlp_forward(module, x): |
| """Internal MLP forward function for tiled computation.""" |
| gate = module.gate_proj(x) |
| up = module.up_proj(x) |
| return module.down_proj(LigerGELUMulFunction.apply(gate, up)) |
|
|
| compute_params = [p for p in self.parameters() if p.requires_grad] |
|
|
| return apply_tiled_mlp( |
| fn=_mlp_forward, |
| mlp_module=self, |
| x=x, |
| num_shards=None, |
| compute_params=compute_params, |
| ) |
|
|
|
|
| def liger_rotary_pos_emb( |
| q: torch.Tensor, |
| k: torch.Tensor, |
| cos: torch.Tensor, |
| sin: torch.Tensor, |
| unsqueeze_dim: int = 1, |
| ) -> tuple[torch.Tensor, torch.Tensor]: |
| """Apply standard rotary positional embedding to ``q`` and ``k``.""" |
| return LigerRopeFunction.apply(q, k, cos, sin, None, unsqueeze_dim) |
|
|
|
|
| @dataclass |
| class CrossEntropyOutput: |
| loss: torch.Tensor |
| z_loss: Optional[torch.Tensor] = None |
| token_accuracy: Optional[torch.Tensor] = None |
| predicted_tokens: Optional[torch.Tensor] = None |
|
|
|
|
| def liger_fused_linear_cross_entropy( |
| input: torch.Tensor, |
| weight: torch.Tensor, |
| target: torch.Tensor, |
| bias: Optional[torch.Tensor] = None, |
| ce_weight: Optional[torch.Tensor] = None, |
| ignore_index: int = -100, |
| lse_square_scale: float = 0.0, |
| label_smoothing: float = 0.0, |
| reduction: str = "mean", |
| softcap: Optional[float] = None, |
| return_z_loss: bool = False, |
| accum_dtype: Optional[torch.dtype] = None, |
| use_token_scaling: bool = False, |
| return_token_accuracy: bool = False, |
| return_predicted_tokens: bool = False, |
| ): |
| loss, z_loss, token_accuracy, predicted_tokens = LigerFusedLinearCrossEntropyFunction.apply( |
| input, |
| weight, |
| target, |
| bias, |
| ce_weight, |
| ignore_index, |
| lse_square_scale, |
| label_smoothing, |
| reduction, |
| softcap, |
| return_z_loss, |
| accum_dtype, |
| use_token_scaling, |
| return_token_accuracy, |
| return_predicted_tokens, |
| ) |
| if not return_z_loss and not return_token_accuracy and not return_predicted_tokens: |
| return loss |
| return CrossEntropyOutput( |
| loss=loss, |
| z_loss=z_loss, |
| token_accuracy=token_accuracy, |
| predicted_tokens=predicted_tokens, |
| ) |
|
|
|
|
| |
| |
| |
| @torch.compiler.disable |
| def LigerForCausalLMLoss( |
| logits: None, |
| labels: torch.Tensor, |
| vocab_size: int, |
| num_items_in_batch: Optional[int] = None, |
| ignore_index: int = -100, |
| shift_labels: Optional[torch.Tensor] = None, |
| hidden_states: torch.Tensor | None = None, |
| lm_head_weight: torch.Tensor | None = None, |
| lm_head_bias: torch.Tensor | None = None, |
| **kwargs, |
| ): |
| |
| hidden_size = kwargs.pop("hidden_size", None) |
| final_logit_softcapping = kwargs.pop("final_logit_softcapping", None) |
|
|
| if hidden_size is None or hidden_states is None or lm_head_weight is None: |
| raise ValueError( |
| f"`LigerForCausalLMLoss` requires the LLM's weight (found `{lm_head_weight is not None}`)," |
| f"the last hidden state (found `{hidden_states is not None}`), and the `hidden_size`" |
| f"(found `{hidden_size is not None}`). Please make sure to pass the necessary kwargs." |
| ) |
|
|
| applicable_params = inspect.signature(liger_fused_linear_cross_entropy).parameters |
| kwargs = {k: v for k, v in kwargs.items() if k in applicable_params} |
|
|
| if shift_labels is None: |
| labels = nn.functional.pad(labels, (0, 1), value=ignore_index) |
| shift_labels = labels[..., 1:].contiguous() |
|
|
| hidden_states = hidden_states.view(-1, hidden_size) |
| shift_labels = shift_labels.view(-1).to(hidden_states.device) |
|
|
| reduction = "sum" if num_items_in_batch is not None else "mean" |
| loss = liger_fused_linear_cross_entropy( |
| hidden_states, |
| lm_head_weight, |
| shift_labels, |
| bias=lm_head_bias, |
| reduction=reduction, |
| ignore_index=ignore_index, |
| softcap=final_logit_softcapping, |
| return_token_accuracy=False, |
| return_predicted_tokens=False, |
| **kwargs, |
| ) |
|
|
| if reduction == "sum": |
| loss = loss / num_items_in_batch |
|
|
| return loss |
|
|
|
|
| |
| |
| liger_rotary_pos_emb.can_torch_compile = True |
| LigerForCausalLMLoss.can_torch_compile = True |
|
|
|
|
| __all__ = [ |
| "LigerRMSNorm", |
| "LigerLinear", |
| "LigerSwiGLUMLP", |
| "LigerGEGLUMLP", |
| "LigerTiledSwiGLUMLP", |
| "LigerTiledGEGLUMLP", |
| "liger_rotary_pos_emb", |
| "LigerForCausalLMLoss", |
| ] |
|
|