liger-kernel-nightly 0.5.6.dev20250403190551__py3-none-any.whl → 0.6.4.dev20251212103629__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. liger_kernel/chunked_loss/__init__.py +1 -0
  2. liger_kernel/chunked_loss/cosine_similarity_loss.py +136 -0
  3. liger_kernel/chunked_loss/dpo_loss.py +61 -3
  4. liger_kernel/chunked_loss/functional.py +2 -0
  5. liger_kernel/chunked_loss/fused_linear_distillation.py +13 -2
  6. liger_kernel/chunked_loss/fused_linear_ppo.py +35 -0
  7. liger_kernel/chunked_loss/fused_linear_preference.py +0 -1
  8. liger_kernel/chunked_loss/grpo_loss.py +76 -5
  9. liger_kernel/chunked_loss/jsd_loss.py +25 -9
  10. liger_kernel/ops/__init__.py +141 -0
  11. liger_kernel/ops/backends/README.md +151 -0
  12. liger_kernel/ops/backends/__init__.py +13 -0
  13. liger_kernel/ops/backends/_ascend/__init__.py +5 -0
  14. liger_kernel/ops/backends/_ascend/ops/__init__.py +15 -0
  15. liger_kernel/ops/backends/registry.py +61 -0
  16. liger_kernel/ops/cross_entropy.py +124 -64
  17. liger_kernel/ops/dyt.py +115 -180
  18. liger_kernel/ops/fused_add_rms_norm.py +416 -0
  19. liger_kernel/ops/fused_linear_cross_entropy.py +115 -22
  20. liger_kernel/ops/fused_neighborhood_attention.py +1022 -0
  21. liger_kernel/ops/geglu.py +3 -2
  22. liger_kernel/ops/group_norm.py +2 -1
  23. liger_kernel/ops/grpo_loss.py +312 -0
  24. liger_kernel/ops/jsd.py +2 -1
  25. liger_kernel/ops/kl_div.py +13 -6
  26. liger_kernel/ops/layer_norm.py +146 -78
  27. liger_kernel/ops/llama4_rope.py +225 -0
  28. liger_kernel/ops/multi_token_attention.py +207 -0
  29. liger_kernel/ops/poly_norm.py +390 -0
  30. liger_kernel/ops/rms_norm.py +283 -56
  31. liger_kernel/ops/rope.py +1 -1
  32. liger_kernel/ops/softmax.py +201 -0
  33. liger_kernel/ops/sparsemax.py +179 -0
  34. liger_kernel/ops/swiglu.py +1 -1
  35. liger_kernel/ops/tiled_mlp.py +136 -0
  36. liger_kernel/ops/utils.py +2 -0
  37. liger_kernel/transformers/__init__.py +205 -19
  38. liger_kernel/transformers/cross_entropy.py +9 -4
  39. liger_kernel/transformers/dyt.py +6 -4
  40. liger_kernel/transformers/experimental/__init__.py +5 -0
  41. liger_kernel/transformers/experimental/embedding.py +1 -1
  42. liger_kernel/transformers/fsdp.py +55 -0
  43. liger_kernel/transformers/functional.py +122 -20
  44. liger_kernel/transformers/fused_add_rms_norm.py +39 -0
  45. liger_kernel/transformers/fused_linear_cross_entropy.py +16 -5
  46. liger_kernel/transformers/fused_linear_jsd.py +1 -1
  47. liger_kernel/transformers/fused_neighborhood_attention.py +234 -0
  48. liger_kernel/transformers/geglu.py +1 -1
  49. liger_kernel/transformers/group_norm.py +1 -1
  50. liger_kernel/transformers/grpo_loss.py +153 -0
  51. liger_kernel/transformers/jsd.py +1 -1
  52. liger_kernel/transformers/kl_div.py +1 -1
  53. liger_kernel/transformers/layer_norm.py +1 -1
  54. liger_kernel/transformers/llama4_rope.py +93 -0
  55. liger_kernel/transformers/model/falcon_h1.py +122 -0
  56. liger_kernel/transformers/model/gemma.py +50 -25
  57. liger_kernel/transformers/model/gemma2.py +55 -23
  58. liger_kernel/transformers/model/gemma3.py +117 -120
  59. liger_kernel/transformers/model/glm4.py +141 -0
  60. liger_kernel/transformers/model/glm4v.py +163 -0
  61. liger_kernel/transformers/model/glm4v_moe.py +172 -0
  62. liger_kernel/transformers/model/gpt_oss.py +211 -0
  63. liger_kernel/transformers/model/hunyuan_v1.py +134 -0
  64. liger_kernel/transformers/model/internvl.py +157 -0
  65. liger_kernel/transformers/model/llama.py +102 -25
  66. liger_kernel/transformers/model/llama4.py +121 -0
  67. liger_kernel/transformers/model/llava.py +111 -136
  68. liger_kernel/transformers/model/loss_utils.py +50 -12
  69. liger_kernel/transformers/model/mistral.py +36 -23
  70. liger_kernel/transformers/model/mixtral.py +45 -25
  71. liger_kernel/transformers/model/mllama.py +39 -22
  72. liger_kernel/transformers/model/olmo2.py +40 -20
  73. liger_kernel/transformers/model/olmo3.py +142 -0
  74. liger_kernel/transformers/model/output_classes.py +147 -0
  75. liger_kernel/transformers/model/paligemma.py +50 -14
  76. liger_kernel/transformers/model/phi3.py +47 -177
  77. liger_kernel/transformers/model/qwen2.py +48 -21
  78. liger_kernel/transformers/model/qwen2_5_vl.py +62 -103
  79. liger_kernel/transformers/model/qwen2_vl.py +59 -108
  80. liger_kernel/transformers/model/qwen3.py +136 -0
  81. liger_kernel/transformers/model/qwen3_moe.py +152 -0
  82. liger_kernel/transformers/model/qwen3_next.py +146 -0
  83. liger_kernel/transformers/model/qwen3_vl.py +150 -0
  84. liger_kernel/transformers/model/qwen3_vl_moe.py +126 -0
  85. liger_kernel/transformers/model/smollm3.py +199 -0
  86. liger_kernel/transformers/model/smolvlm.py +158 -0
  87. liger_kernel/transformers/monkey_patch.py +1678 -160
  88. liger_kernel/transformers/multi_token_attention.py +64 -0
  89. liger_kernel/transformers/poly_norm.py +42 -0
  90. liger_kernel/transformers/qwen2vl_mrope.py +1 -1
  91. liger_kernel/transformers/rms_norm.py +48 -5
  92. liger_kernel/transformers/rope.py +45 -1
  93. liger_kernel/transformers/softmax.py +12 -0
  94. liger_kernel/transformers/sparsemax.py +16 -0
  95. liger_kernel/transformers/swiglu.py +39 -1
  96. liger_kernel/transformers/tiled_mlp.py +133 -0
  97. liger_kernel/transformers/trainer/orpo_trainer.py +1 -53
  98. liger_kernel/transformers/tvd.py +1 -1
  99. liger_kernel/utils.py +36 -0
  100. {liger_kernel_nightly-0.5.6.dev20250403190551.dist-info → liger_kernel_nightly-0.6.4.dev20251212103629.dist-info}/METADATA +68 -38
  101. liger_kernel_nightly-0.6.4.dev20251212103629.dist-info/RECORD +124 -0
  102. liger_kernel/transformers/gema3_rms.py +0 -8
  103. liger_kernel_nightly-0.5.6.dev20250403190551.dist-info/RECORD +0 -82
  104. {liger_kernel_nightly-0.5.6.dev20250403190551.dist-info → liger_kernel_nightly-0.6.4.dev20251212103629.dist-info}/LICENSE +0 -0
  105. {liger_kernel_nightly-0.5.6.dev20250403190551.dist-info → liger_kernel_nightly-0.6.4.dev20251212103629.dist-info}/NOTICE +0 -0
  106. {liger_kernel_nightly-0.5.6.dev20250403190551.dist-info → liger_kernel_nightly-0.6.4.dev20251212103629.dist-info}/WHEEL +0 -0
  107. {liger_kernel_nightly-0.5.6.dev20250403190551.dist-info → liger_kernel_nightly-0.6.4.dev20251212103629.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,55 @@
1
+ from typing import Any
2
+ from typing import Callable
3
+
4
+ from torch.distributed.fsdp import FullyShardedDataParallel
5
+
6
+
7
+ class _FSDPForwardRedirection:
8
+ """
9
+ Modified based on
10
+ https://github.com/Lightning-AI/pytorch-lightning/blob/d3f9c83d6efa4f1def36aa6c199600946cdb9117/src/lightning/pytorch/strategies/strategy.py#L601-L648
11
+ Redirect a method call through FullyShardedDataParallel.forward so that the FSDP module's root pre-forward and
12
+ post-forward can be properly executed around the method call.
13
+ This is needed in cases where we call a submodule of a FSDP module. For instance, when we want to call only
14
+ the `LlamaModel` part out of a FSDP-wrapped `LlamaForCausalLM` to get the hidden states without involving
15
+ GPU-memory-heavy `lm_head` and cross entropy computation, doing this directly (i.e. `model.model.forward()`)
16
+ will not work because the first `nn.Embedding` layer is not independently wrapped as a FSDP module (because of
17
+ the transformer-based wrapping policy), and not calling it through FSDP root module forward will not all-gather
18
+ its parameter, thus resulting in "RuntimeError: 'weight' must be 2-D" error. Similarly, if we want to call just
19
+ the `lm_head` part of a model, we need this trick too to properly get its params all-gathered.
20
+ """
21
+
22
+ def __call__(
23
+ self,
24
+ wrapper_module: FullyShardedDataParallel,
25
+ method: Callable,
26
+ *args: Any,
27
+ **kwargs: Any,
28
+ ):
29
+ """Reroutes a method call through the `wrapper_module`'s `forward` method.
30
+ Args:
31
+ wrapper_module: The module that has `original_module` wrapped.
32
+ original_module: The module that was wrapped inside `wrapper_module`.
33
+ method_name: The name of the method that should be called on the `original_module` after inputs get
34
+ redirected through the `wrapper_module`'s `forward` method.
35
+ *args: The positional arguments to the method `method_name`. They will get passed to a patched
36
+ `forward` method instead.
37
+ **kwargs: The keyword arguments to the method `method_name`. They will get passed to a patched
38
+ `forward` method instead.
39
+ """
40
+ assert isinstance(wrapper_module, FullyShardedDataParallel)
41
+ original_module = wrapper_module._fsdp_wrapped_module
42
+ original_forward = original_module.forward
43
+
44
+ def wrapped_forward(*_args: Any, **_kwargs: Any) -> Any:
45
+ # Unpatch ourselves immediately before calling the method `method_name`
46
+ # because itself may want to call the real `forward`
47
+ original_module.forward = original_forward # type: ignore[method-assign]
48
+ # Call the actual method e.g. `.training_step(...)`
49
+ out = method(*_args, **_kwargs)
50
+ return out
51
+
52
+ # Patch the original_module's forward so we can redirect the arguments back to the real method
53
+ original_module.forward = wrapped_forward # type: ignore[method-assign]
54
+ wrapper_output = wrapper_module(*args, **kwargs)
55
+ return wrapper_output
@@ -1,19 +1,35 @@
1
+ from dataclasses import dataclass
1
2
  from typing import Optional
2
3
 
3
- from liger_kernel.ops.cross_entropy import LigerCrossEntropyFunction
4
- from liger_kernel.ops.dyt import LigerDyTFunction
5
- from liger_kernel.ops.fused_linear_cross_entropy import LigerFusedLinearCrossEntropyFunction
6
- from liger_kernel.ops.fused_linear_jsd import LigerFusedLinearJSDFunction
7
- from liger_kernel.ops.geglu import LigerGELUMulFunction
8
- from liger_kernel.ops.group_norm import LigerGroupNormFunction
9
- from liger_kernel.ops.jsd import LigerJSDFunction
10
- from liger_kernel.ops.kl_div import LigerKLDivLossFunction
11
- from liger_kernel.ops.layer_norm import LigerLayerNormFunction
12
- from liger_kernel.ops.qwen2vl_mrope import LigerQwen2VLMRopeFunction
13
- from liger_kernel.ops.rms_norm import LigerRMSNormFunction
14
- from liger_kernel.ops.rope import LigerRopeFunction
15
- from liger_kernel.ops.swiglu import LigerSiLUMulFunction
16
- from liger_kernel.ops.tvd import LigerTVDLossFunction
4
+ import torch
5
+
6
+ from liger_kernel.ops import LigerCrossEntropyFunction
7
+ from liger_kernel.ops import LigerDyTFunction
8
+ from liger_kernel.ops import LigerFusedAddRMSNormFunction
9
+ from liger_kernel.ops import LigerFusedLinearCrossEntropyFunction
10
+ from liger_kernel.ops import LigerFusedLinearJSDFunction
11
+ from liger_kernel.ops import LigerFusedNeighborhoodAttentionFunction
12
+ from liger_kernel.ops import LigerGELUMulFunction
13
+ from liger_kernel.ops import LigerGroupNormFunction
14
+ from liger_kernel.ops import LigerJSDFunction
15
+ from liger_kernel.ops import LigerKLDivLossFunction
16
+ from liger_kernel.ops import LigerLayerNormFunction
17
+ from liger_kernel.ops import LigerMultiTokenAttentionFunction
18
+ from liger_kernel.ops import LigerPolyNormFunction
19
+ from liger_kernel.ops import LigerQwen2VLMRopeFunction
20
+ from liger_kernel.ops import LigerRMSNormFunction
21
+ from liger_kernel.ops import LigerRopeFunction
22
+ from liger_kernel.ops import LigerSiLUMulFunction
23
+ from liger_kernel.ops import LigerSoftmaxFunction
24
+ from liger_kernel.ops import LigerSparsemaxFunction
25
+ from liger_kernel.ops import LigerTVDLossFunction
26
+
27
+
28
+ @dataclass
29
+ class CrossEntropyOutput:
30
+ loss: torch.Tensor
31
+ z_loss: Optional[torch.Tensor] = None
32
+ token_accuracy: Optional[torch.Tensor] = None
17
33
 
18
34
 
19
35
  # conform to the function signature in https://pytorch.org/docs/stable/generated/torch.nn.functional.cross_entropy.html
@@ -30,8 +46,9 @@ def liger_cross_entropy(
30
46
  lse_square_scale: float = 0.0,
31
47
  softcap: Optional[float] = None,
32
48
  return_z_loss: bool = False,
49
+ return_token_accuracy: bool = False,
33
50
  ):
34
- loss, z_loss = LigerCrossEntropyFunction.apply(
51
+ loss, z_loss, token_accuracy = LigerCrossEntropyFunction.apply(
35
52
  input,
36
53
  target,
37
54
  weight,
@@ -41,10 +58,13 @@ def liger_cross_entropy(
41
58
  reduction,
42
59
  softcap,
43
60
  return_z_loss,
61
+ return_token_accuracy,
44
62
  )
45
- if not return_z_loss:
63
+
64
+ if not return_z_loss and not return_token_accuracy:
46
65
  return loss
47
- return loss, z_loss
66
+
67
+ return CrossEntropyOutput(loss=loss, z_loss=z_loss, token_accuracy=token_accuracy)
48
68
 
49
69
 
50
70
  def liger_fused_linear_cross_entropy(
@@ -59,8 +79,11 @@ def liger_fused_linear_cross_entropy(
59
79
  reduction: str = "mean",
60
80
  softcap: Optional[float] = None,
61
81
  return_z_loss: bool = False,
82
+ accum_dtype=None,
83
+ use_token_scaling: bool = False,
84
+ return_token_accuracy: bool = False,
62
85
  ):
63
- loss, z_loss = LigerFusedLinearCrossEntropyFunction.apply(
86
+ loss, z_loss, token_accuracy = LigerFusedLinearCrossEntropyFunction.apply(
64
87
  input,
65
88
  weight,
66
89
  target,
@@ -72,10 +95,15 @@ def liger_fused_linear_cross_entropy(
72
95
  reduction,
73
96
  softcap,
74
97
  return_z_loss,
98
+ accum_dtype,
99
+ use_token_scaling,
100
+ return_token_accuracy,
75
101
  )
76
- if not return_z_loss:
102
+
103
+ if not return_z_loss and not return_token_accuracy:
77
104
  return loss
78
- return loss, z_loss
105
+
106
+ return CrossEntropyOutput(loss=loss, z_loss=z_loss, token_accuracy=token_accuracy)
79
107
 
80
108
 
81
109
  def liger_fused_linear_jsd(
@@ -159,6 +187,68 @@ def liger_kl_div(
159
187
  )
160
188
 
161
189
 
190
+ def liger_sparsemax(
191
+ input,
192
+ dim: int = -1,
193
+ ):
194
+ return LigerSparsemaxFunction.apply(input, dim)
195
+
196
+
197
+ def liger_multi_token_attention(
198
+ scores,
199
+ weight,
200
+ bias=None,
201
+ stride: int = 1,
202
+ padding: int = 0,
203
+ dilation: int = 1,
204
+ groups: int = 1,
205
+ sparse: bool = False,
206
+ ):
207
+ """
208
+ Functional interface for multi-token attention.
209
+
210
+ Args:
211
+ scores: Input tensor of shape (B, C_in, L, L)
212
+ weight: Convolution weight tensor of shape (C_out, C_in // groups, K, K)
213
+ bias: Optional bias tensor of shape (C_out,)
214
+ stride: Stride for the convolution (default: 1)
215
+ padding: Padding for the convolution (default: 0)
216
+ dilation: Dilation factor for the convolution (default: 1)
217
+ groups: Number of groups for the convolution (default: 1)
218
+ sparse: Specifies if input tensors are expected to be sparse (default: False)
219
+ Returns:
220
+ Output tensor after applying multi-token attention.
221
+ """
222
+ return LigerMultiTokenAttentionFunction.apply(scores, weight, bias, stride, padding, dilation, groups, sparse)
223
+
224
+
225
+ def liger_fused_neighborhood_attention(
226
+ query,
227
+ key,
228
+ value,
229
+ kernel_size: int = 7,
230
+ dilation: int = 1,
231
+ scale: float = None,
232
+ ):
233
+ """
234
+ Liger fused neighborhood attention.
235
+
236
+ paper: https://arxiv.org/pdf/2504.16922
237
+
238
+ Args:
239
+ query: Query tensor of shape [batch_size, num_heads, seq_len, head_dim]
240
+ key: Key tensor of shape [batch_size, num_heads, seq_len, head_dim]
241
+ value: Value tensor of shape [batch_size, num_heads, seq_len, head_dim]
242
+ kernel_size: Size of the neighborhood window (default: 7)
243
+ dilation: Dilation factor for the neighborhood (default: 1)
244
+ scale: Scaling factor for attention scores (default: rsqrt(head_dim))
245
+
246
+ Returns:
247
+ Output tensor of shape [batch_size, num_heads, seq_len, head_dim]
248
+ """
249
+ return LigerFusedNeighborhoodAttentionFunction.apply(query, key, value, kernel_size, dilation, scale)
250
+
251
+
162
252
  def liger_tvd(
163
253
  input,
164
254
  target,
@@ -187,6 +277,14 @@ def liger_rms_norm(X, W, eps, offset: float = 0.0, casting_mode: str = "llama",
187
277
  return LigerRMSNormFunction.apply(X, W, eps, offset, casting_mode, in_place)
188
278
 
189
279
 
280
+ def liger_poly_norm(X, W, B, eps=1e-6, in_place=True):
281
+ return LigerPolyNormFunction.apply(X, W, B, eps, in_place)
282
+
283
+
284
+ def liger_fused_add_rms_norm(X, R, W, eps, offset: float = 0.0, casting_mode: str = "llama", in_place: bool = True):
285
+ return LigerFusedAddRMSNormFunction.apply(X, R, W, eps, offset, casting_mode, in_place)
286
+
287
+
190
288
  def liger_rope(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
191
289
  return LigerRopeFunction.apply(q, k, cos, sin, position_ids, unsqueeze_dim)
192
290
 
@@ -195,5 +293,9 @@ def liger_swiglu(a, b):
195
293
  return LigerSiLUMulFunction.apply(a, b)
196
294
 
197
295
 
296
+ def liger_softmax(x):
297
+ return LigerSoftmaxFunction.apply(x)
298
+
299
+
198
300
  def liger_dyt(x, alpha, gamma, beta):
199
301
  return LigerDyTFunction.apply(x, alpha, gamma, beta)
@@ -0,0 +1,39 @@
1
+ import torch
2
+ import torch.nn as nn
3
+
4
+ from liger_kernel.ops import LigerFusedAddRMSNormFunction
5
+
6
+
7
+ class LigerFusedAddRMSNorm(nn.Module):
8
+ def __init__(
9
+ self,
10
+ hidden_size,
11
+ eps=1e-6,
12
+ offset=0.0,
13
+ casting_mode="llama",
14
+ init_fn="ones",
15
+ in_place=False,
16
+ ):
17
+ super().__init__()
18
+ assert init_fn in [
19
+ "ones",
20
+ "zeros",
21
+ ], f"init_fn must be either 'ones' or 'zeros', got {init_fn}"
22
+ self.weight = nn.Parameter(torch.ones(hidden_size) if init_fn == "ones" else torch.zeros(hidden_size))
23
+ self.variance_epsilon, self.offset, self.casting_mode, self.in_place = (eps, offset, casting_mode, in_place)
24
+
25
+ def forward(self, hidden_states, residual):
26
+ return LigerFusedAddRMSNormFunction.apply(
27
+ hidden_states,
28
+ residual,
29
+ self.weight,
30
+ self.variance_epsilon,
31
+ self.offset,
32
+ self.casting_mode,
33
+ self.in_place,
34
+ )
35
+
36
+ def extra_repr(self):
37
+ return (
38
+ f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}, offset={self.offset}, in_place={self.in_place}"
39
+ )
@@ -2,7 +2,8 @@ from typing import Optional
2
2
 
3
3
  import torch
4
4
 
5
- from liger_kernel.ops.fused_linear_cross_entropy import LigerFusedLinearCrossEntropyFunction
5
+ from liger_kernel.ops import LigerFusedLinearCrossEntropyFunction
6
+ from liger_kernel.transformers.functional import CrossEntropyOutput
6
7
 
7
8
 
8
9
  class LigerFusedLinearCrossEntropyLoss(torch.nn.Module):
@@ -15,6 +16,9 @@ class LigerFusedLinearCrossEntropyLoss(torch.nn.Module):
15
16
  reduction: str = "mean",
16
17
  softcap: Optional[float] = None,
17
18
  return_z_loss: bool = False,
19
+ accum_dtype: Optional[torch.dtype] = None,
20
+ use_token_scaling: bool = False,
21
+ return_token_accuracy: bool = False,
18
22
  ):
19
23
  super().__init__()
20
24
  assert (label_smoothing >= 0) and (label_smoothing <= 1), (
@@ -24,7 +28,7 @@ class LigerFusedLinearCrossEntropyLoss(torch.nn.Module):
24
28
  "mean",
25
29
  "sum",
26
30
  "none",
27
- }, f"reduction must be one of 'mean', 'sum', or 'none'. Got: {reduction}"
31
+ }, f"reduction must be 'mean' or 'sum' or 'none'. Got: {reduction}"
28
32
  assert softcap is None or softcap > 0, f"softcap must greater than 0.0 or None. Got: {softcap}"
29
33
  self.ce_weight = ce_weight
30
34
  self.ignore_index = ignore_index
@@ -33,9 +37,12 @@ class LigerFusedLinearCrossEntropyLoss(torch.nn.Module):
33
37
  self.reduction = reduction
34
38
  self.softcap = softcap
35
39
  self.return_z_loss = return_z_loss
40
+ self.accum_dtype = accum_dtype
41
+ self.use_token_scaling = use_token_scaling
42
+ self.return_token_accuracy = return_token_accuracy
36
43
 
37
44
  def forward(self, lin_weight, _input, target, bias=None):
38
- loss, z_loss = LigerFusedLinearCrossEntropyFunction.apply(
45
+ loss, z_loss, token_accuracy = LigerFusedLinearCrossEntropyFunction.apply(
39
46
  _input,
40
47
  lin_weight,
41
48
  target,
@@ -47,7 +54,11 @@ class LigerFusedLinearCrossEntropyLoss(torch.nn.Module):
47
54
  self.reduction,
48
55
  self.softcap,
49
56
  self.return_z_loss,
57
+ self.accum_dtype,
58
+ self.use_token_scaling,
59
+ self.return_token_accuracy,
50
60
  )
51
- if not self.return_z_loss:
61
+ if not self.return_z_loss and not self.return_token_accuracy:
52
62
  return loss
53
- return loss, z_loss
63
+
64
+ return CrossEntropyOutput(loss=loss, z_loss=z_loss, token_accuracy=token_accuracy)
@@ -2,7 +2,7 @@ from typing import Optional
2
2
 
3
3
  import torch
4
4
 
5
- from liger_kernel.ops.fused_linear_jsd import LigerFusedLinearJSDFunction
5
+ from liger_kernel.ops import LigerFusedLinearJSDFunction
6
6
 
7
7
 
8
8
  class LigerFusedLinearJSD(torch.nn.Module):
@@ -0,0 +1,234 @@
1
+ import math
2
+
3
+ from typing import Optional
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+
8
+ from liger_kernel.ops import LigerFusedNeighborhoodAttentionFunction
9
+
10
+
11
+ class LigerFusedNeighborhoodAttention(nn.Module):
12
+ """
13
+ Liger Fused Neighborhood Attention Module.
14
+
15
+ Paper: https://arxiv.org/pdf/2504.16922
16
+
17
+ Fused Neighborhood attention restricts the attention mechanism to a local neighborhood
18
+ around each position, reducing computational complexity from O(n²) to O(n*k)
19
+ where k is the neighborhood size.
20
+
21
+ Args:
22
+ hidden_size (int): The hidden dimension size
23
+ num_heads (int): Number of attention heads
24
+ kernel_size (int): Size of the neighborhood window (default: 7)
25
+ dilation (int): Dilation factor for the neighborhood (default: 1)
26
+ bias (bool): Whether to use bias in linear projections (default: True)
27
+ dropout (float): Dropout probability (default: 0.0)
28
+ scale (Optional[float]): Scaling factor for attention scores.
29
+ If None, uses 1/sqrt(head_dim) (default: None)
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ hidden_size: int,
35
+ num_heads: int,
36
+ kernel_size: int = 7,
37
+ dilation: int = 1,
38
+ bias: bool = True,
39
+ dropout: float = 0.0,
40
+ scale: Optional[float] = None,
41
+ ):
42
+ super().__init__()
43
+
44
+ if hidden_size % num_heads != 0:
45
+ raise ValueError(f"hidden_size ({hidden_size}) must be divisible by num_heads ({num_heads})")
46
+
47
+ if kernel_size <= 0:
48
+ raise ValueError(f"kernel_size ({kernel_size}) must be positive")
49
+
50
+ if kernel_size % 2 == 0:
51
+ raise ValueError(f"kernel_size ({kernel_size}) must be odd")
52
+
53
+ if dilation < 1:
54
+ raise ValueError(f"dilation ({dilation}) must be positive")
55
+
56
+ self.hidden_size = hidden_size
57
+ self.num_heads = num_heads
58
+ self.head_dim = hidden_size // num_heads
59
+ self.kernel_size = kernel_size
60
+ self.dilation = dilation
61
+ self.scale = scale if scale is not None else 1.0 / math.sqrt(self.head_dim)
62
+ self.dropout_p = dropout
63
+
64
+ self.q_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
65
+ self.k_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
66
+ self.v_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
67
+
68
+ self.out_proj = nn.Linear(hidden_size, hidden_size, bias=bias)
69
+
70
+ if dropout > 0.0:
71
+ self.dropout = nn.Dropout(dropout)
72
+ else:
73
+ self.dropout = None
74
+
75
+ def forward(
76
+ self,
77
+ hidden_states: torch.Tensor,
78
+ attention_mask: Optional[torch.Tensor] = None,
79
+ ) -> torch.Tensor:
80
+ """
81
+ Forward pass of the fused neighborhood attention module.
82
+
83
+ Args:
84
+ hidden_states (torch.Tensor): Input tensor of shape [batch_size, seq_len, hidden_size]
85
+ attention_mask (Optional[torch.Tensor]): Attention mask (currently not supported)
86
+
87
+ Returns:
88
+ torch.Tensor: Output tensor of shape [batch_size, seq_len, hidden_size]
89
+ """
90
+ if attention_mask is not None:
91
+ raise NotImplementedError("Attention mask is not yet supported in LigerFusedNeighborhoodAttention")
92
+
93
+ batch_size, seq_len, hidden_size = hidden_states.shape
94
+
95
+ query = self.q_proj(hidden_states)
96
+ key = self.k_proj(hidden_states)
97
+ value = self.v_proj(hidden_states)
98
+
99
+ query = query.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
100
+ key = key.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
101
+ value = value.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
102
+
103
+ attn_output = LigerFusedNeighborhoodAttentionFunction.apply(
104
+ query, key, value, self.kernel_size, self.dilation, self.scale
105
+ )
106
+
107
+ attn_output = attn_output.transpose(1, 2).contiguous().view(batch_size, seq_len, hidden_size)
108
+
109
+ if self.dropout is not None:
110
+ attn_output = self.dropout(attn_output)
111
+
112
+ output = self.out_proj(attn_output)
113
+
114
+ return output
115
+
116
+ def extra_repr(self) -> str:
117
+ return (
118
+ f"hidden_size={self.hidden_size}, num_heads={self.num_heads}, "
119
+ f"head_dim={self.head_dim}, kernel_size={self.kernel_size}, "
120
+ f"dilation={self.dilation}, scale={self.scale}, dropout={self.dropout_p}"
121
+ )
122
+
123
+
124
+ class LigerFusedNeighborhoodAttentionLayer(nn.Module):
125
+ """
126
+ A complete neighborhood attention layer with layer norm and residual connection.
127
+
128
+ Args:
129
+ hidden_size (int): The hidden dimension size
130
+ num_heads (int): Number of attention heads
131
+ kernel_size (int): Size of the neighborhood window (default: 7)
132
+ dilation (int): Dilation factor for the neighborhood (default: 1)
133
+ bias (bool): Whether to use bias in linear projections (default: True)
134
+ dropout (float): Dropout probability (default: 0.0)
135
+ layer_norm_eps (float): Epsilon for layer normalization (default: 1e-5)
136
+ scale (Optional[float]): Scaling factor for attention scores (default: None)
137
+ """
138
+
139
+ def __init__(
140
+ self,
141
+ hidden_size: int,
142
+ num_heads: int,
143
+ kernel_size: int = 7,
144
+ dilation: int = 1,
145
+ bias: bool = True,
146
+ dropout: float = 0.0,
147
+ layer_norm_eps: float = 1e-5,
148
+ scale: Optional[float] = None,
149
+ ):
150
+ super().__init__()
151
+
152
+ self.attention = LigerFusedNeighborhoodAttention(
153
+ hidden_size=hidden_size,
154
+ num_heads=num_heads,
155
+ kernel_size=kernel_size,
156
+ dilation=dilation,
157
+ bias=bias,
158
+ dropout=dropout,
159
+ scale=scale,
160
+ )
161
+
162
+ self.layer_norm = nn.LayerNorm(hidden_size, eps=layer_norm_eps)
163
+
164
+ if dropout > 0.0:
165
+ self.dropout = nn.Dropout(dropout)
166
+ else:
167
+ self.dropout = None
168
+
169
+ def forward(
170
+ self,
171
+ hidden_states: torch.Tensor,
172
+ attention_mask: Optional[torch.Tensor] = None,
173
+ ) -> torch.Tensor:
174
+ """
175
+ Forward pass with residual connection and layer normalization.
176
+
177
+ Args:
178
+ hidden_states (torch.Tensor): Input tensor of shape [batch_size, seq_len, hidden_size]
179
+ attention_mask (Optional[torch.Tensor]): Attention mask (currently not supported)
180
+
181
+ Returns:
182
+ torch.Tensor: Output tensor of shape [batch_size, seq_len, hidden_size]
183
+ """
184
+ normed_hidden_states = self.layer_norm(hidden_states)
185
+
186
+ attn_output = self.attention(normed_hidden_states, attention_mask)
187
+
188
+ if self.dropout is not None:
189
+ attn_output = self.dropout(attn_output)
190
+
191
+ output = hidden_states + attn_output
192
+
193
+ return output
194
+
195
+
196
+ class LigerFusedNeighborhoodAttentionConfig:
197
+ """
198
+ Configuration class for Fused Neighborhood Attention.
199
+
200
+ This can be used to easily configure neighborhood attention parameters
201
+ for different model architectures.
202
+ """
203
+
204
+ def __init__(
205
+ self,
206
+ hidden_size: int = 768,
207
+ num_heads: int = 12,
208
+ kernel_size: int = 7,
209
+ dilation: int = 1,
210
+ bias: bool = True,
211
+ dropout: float = 0.0,
212
+ layer_norm_eps: float = 1e-5,
213
+ scale: Optional[float] = None,
214
+ ):
215
+ self.hidden_size = hidden_size
216
+ self.num_heads = num_heads
217
+ self.kernel_size = kernel_size
218
+ self.dilation = dilation
219
+ self.bias = bias
220
+ self.dropout = dropout
221
+ self.layer_norm_eps = layer_norm_eps
222
+ self.scale = scale
223
+
224
+ def to_dict(self):
225
+ return {
226
+ "hidden_size": self.hidden_size,
227
+ "num_heads": self.num_heads,
228
+ "kernel_size": self.kernel_size,
229
+ "dilation": self.dilation,
230
+ "bias": self.bias,
231
+ "dropout": self.dropout,
232
+ "layer_norm_eps": self.layer_norm_eps,
233
+ "scale": self.scale,
234
+ }
@@ -1,6 +1,6 @@
1
1
  import torch.nn as nn
2
2
 
3
- from liger_kernel.ops.geglu import LigerGELUMulFunction
3
+ from liger_kernel.ops import LigerGELUMulFunction
4
4
 
5
5
 
6
6
  class LigerGEGLUMLP(nn.Module):
@@ -1,7 +1,7 @@
1
1
  import torch
2
2
  import torch.nn as nn
3
3
 
4
- from liger_kernel.ops.group_norm import LigerGroupNormFunction
4
+ from liger_kernel.ops import LigerGroupNormFunction
5
5
 
6
6
 
7
7
  class LigerGroupNorm(nn.Module):