liger-kernel-nightly 0.5.10.dev20250624183504__py3-none-any.whl → 0.6.4.dev20251121224847__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.

Potentially problematic release.


This version of liger-kernel-nightly might be problematic. Click here for more details.

Files changed (73) 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 +54 -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 +25 -5
  7. liger_kernel/chunked_loss/grpo_loss.py +46 -9
  8. liger_kernel/chunked_loss/jsd_loss.py +23 -7
  9. liger_kernel/ops/cross_entropy.py +118 -62
  10. liger_kernel/ops/fused_add_rms_norm.py +412 -0
  11. liger_kernel/ops/fused_linear_cross_entropy.py +113 -21
  12. liger_kernel/ops/geglu.py +1 -1
  13. liger_kernel/ops/grpo_loss.py +3 -1
  14. liger_kernel/ops/layer_norm.py +133 -79
  15. liger_kernel/ops/llama4_rope.py +225 -0
  16. liger_kernel/ops/poly_norm.py +386 -0
  17. liger_kernel/ops/rms_norm.py +2 -2
  18. liger_kernel/ops/rope.py +1 -1
  19. liger_kernel/ops/swiglu.py +1 -1
  20. liger_kernel/ops/tiled_mlp.py +136 -0
  21. liger_kernel/transformers/__init__.py +59 -0
  22. liger_kernel/transformers/cross_entropy.py +8 -3
  23. liger_kernel/transformers/experimental/__init__.py +5 -0
  24. liger_kernel/transformers/functional.py +38 -6
  25. liger_kernel/transformers/fused_add_rms_norm.py +39 -0
  26. liger_kernel/transformers/fused_linear_cross_entropy.py +16 -4
  27. liger_kernel/transformers/grpo_loss.py +56 -1
  28. liger_kernel/transformers/llama4_rope.py +93 -0
  29. liger_kernel/transformers/model/falcon_h1.py +122 -0
  30. liger_kernel/transformers/model/gemma.py +28 -8
  31. liger_kernel/transformers/model/gemma2.py +31 -8
  32. liger_kernel/transformers/model/gemma3.py +100 -110
  33. liger_kernel/transformers/model/glm4.py +18 -5
  34. liger_kernel/transformers/model/glm4v.py +163 -0
  35. liger_kernel/transformers/model/glm4v_moe.py +172 -0
  36. liger_kernel/transformers/model/hunyuan_v1.py +134 -0
  37. liger_kernel/transformers/model/internvl.py +157 -0
  38. liger_kernel/transformers/model/llama.py +26 -7
  39. liger_kernel/transformers/model/llama4.py +121 -0
  40. liger_kernel/transformers/model/llava.py +18 -6
  41. liger_kernel/transformers/model/loss_utils.py +34 -3
  42. liger_kernel/transformers/model/mistral.py +17 -10
  43. liger_kernel/transformers/model/mixtral.py +24 -9
  44. liger_kernel/transformers/model/mllama.py +18 -7
  45. liger_kernel/transformers/model/olmo2.py +18 -5
  46. liger_kernel/transformers/model/olmo3.py +142 -0
  47. liger_kernel/transformers/model/output_classes.py +147 -0
  48. liger_kernel/transformers/model/paligemma.py +41 -5
  49. liger_kernel/transformers/model/phi3.py +24 -159
  50. liger_kernel/transformers/model/qwen2.py +26 -4
  51. liger_kernel/transformers/model/qwen2_5_vl.py +21 -8
  52. liger_kernel/transformers/model/qwen2_vl.py +24 -7
  53. liger_kernel/transformers/model/qwen3.py +22 -6
  54. liger_kernel/transformers/model/qwen3_moe.py +27 -7
  55. liger_kernel/transformers/model/qwen3_next.py +146 -0
  56. liger_kernel/transformers/model/qwen3_vl.py +150 -0
  57. liger_kernel/transformers/model/qwen3_vl_moe.py +126 -0
  58. liger_kernel/transformers/model/smollm3.py +199 -0
  59. liger_kernel/transformers/model/smolvlm.py +158 -0
  60. liger_kernel/transformers/monkey_patch.py +1278 -116
  61. liger_kernel/transformers/multi_token_attention.py +1 -1
  62. liger_kernel/transformers/poly_norm.py +42 -0
  63. liger_kernel/transformers/rms_norm.py +7 -0
  64. liger_kernel/transformers/rope.py +43 -0
  65. liger_kernel/transformers/swiglu.py +17 -0
  66. liger_kernel/transformers/tiled_mlp.py +133 -0
  67. {liger_kernel_nightly-0.5.10.dev20250624183504.dist-info → liger_kernel_nightly-0.6.4.dev20251121224847.dist-info}/METADATA +29 -24
  68. liger_kernel_nightly-0.6.4.dev20251121224847.dist-info/RECORD +118 -0
  69. liger_kernel_nightly-0.5.10.dev20250624183504.dist-info/RECORD +0 -95
  70. {liger_kernel_nightly-0.5.10.dev20250624183504.dist-info → liger_kernel_nightly-0.6.4.dev20251121224847.dist-info}/LICENSE +0 -0
  71. {liger_kernel_nightly-0.5.10.dev20250624183504.dist-info → liger_kernel_nightly-0.6.4.dev20251121224847.dist-info}/NOTICE +0 -0
  72. {liger_kernel_nightly-0.5.10.dev20250624183504.dist-info → liger_kernel_nightly-0.6.4.dev20251121224847.dist-info}/WHEEL +0 -0
  73. {liger_kernel_nightly-0.5.10.dev20250624183504.dist-info → liger_kernel_nightly-0.6.4.dev20251121224847.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,8 @@ from transformers.utils.deprecation import deprecate_kwarg
12
12
 
13
13
  from liger_kernel.transformers.fused_linear_cross_entropy import LigerFusedLinearCrossEntropyLoss
14
14
  from liger_kernel.transformers.model.loss_utils import LigerForCausalLMLoss
15
+ from liger_kernel.transformers.model.loss_utils import unpack_cross_entropy_result
16
+ from liger_kernel.transformers.model.output_classes import LigerMoeCausalLMOutputWithPast
15
17
 
16
18
 
17
19
  def lce_forward_deprecated(
@@ -158,7 +160,7 @@ def lce_forward(
158
160
  logits_to_keep: Union[int, torch.Tensor] = 0,
159
161
  skip_logits: Optional[bool] = None,
160
162
  **kwargs,
161
- ) -> Union[Tuple, MoeCausalLMOutputWithPast]:
163
+ ) -> Union[Tuple, LigerMoeCausalLMOutputWithPast]:
162
164
  r"""
163
165
  Args:
164
166
  labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
@@ -226,6 +228,7 @@ def lce_forward(
226
228
  shift_labels = kwargs.pop("shift_labels", None)
227
229
  logits = None
228
230
  loss = None
231
+ token_accuracy = None
229
232
 
230
233
  if skip_logits and labels is None and shift_labels is None:
231
234
  raise ValueError("skip_logits is True, but labels and shift_labels are None")
@@ -234,8 +237,9 @@ def lce_forward(
234
237
  # By default, if in training mode, don't materialize logits
235
238
  skip_logits = self.training and (labels is not None or shift_labels is not None)
236
239
 
240
+ # Compute loss
237
241
  if skip_logits:
238
- loss = LigerForCausalLMLoss(
242
+ result = LigerForCausalLMLoss(
239
243
  hidden_states=kept_hidden_states,
240
244
  lm_head_weight=self.lm_head.weight,
241
245
  labels=labels,
@@ -243,13 +247,20 @@ def lce_forward(
243
247
  hidden_size=self.config.hidden_size,
244
248
  **kwargs,
245
249
  )
250
+ loss, _, token_accuracy = unpack_cross_entropy_result(result)
246
251
 
247
252
  else:
248
253
  logits = self.lm_head(kept_hidden_states)
249
254
 
250
255
  loss = None
251
- if labels is not None:
252
- loss = self.loss_function(logits, labels, self.vocab_size, **kwargs)
256
+ if labels is not None or shift_labels is not None:
257
+ loss = self.loss_function(
258
+ logits=logits,
259
+ labels=labels,
260
+ shift_labels=shift_labels,
261
+ vocab_size=self.vocab_size,
262
+ **kwargs,
263
+ )
253
264
  aux_loss = None
254
265
  if output_router_logits:
255
266
  aux_loss = load_balancing_loss_func(
@@ -262,17 +273,21 @@ def lce_forward(
262
273
  loss += self.router_aux_loss_coef * aux_loss.to(loss.device) # make sure to reside in the same device
263
274
 
264
275
  if not return_dict:
265
- output = (logits,) + outputs[1:]
276
+ output_tuple = (logits,) + outputs[1:]
266
277
  if output_router_logits:
267
- output = (aux_loss,) + output
268
- return (loss,) + output if loss is not None else output
278
+ output_tuple = (aux_loss,) + output_tuple
279
+ if token_accuracy is not None:
280
+ output_tuple = output_tuple + (token_accuracy,)
281
+ return (loss,) + output_tuple if loss is not None else output_tuple
269
282
 
270
- return MoeCausalLMOutputWithPast(
283
+ # Return custom output class with token_accuracy field
284
+ return LigerMoeCausalLMOutputWithPast(
271
285
  loss=loss,
272
286
  aux_loss=aux_loss,
273
287
  logits=logits,
274
288
  past_key_values=outputs.past_key_values,
275
289
  hidden_states=outputs.hidden_states,
276
290
  attentions=outputs.attentions,
277
- router_logits=outputs.router_logits,
291
+ router_logits=outputs.router_logits if return_dict else outputs[-1],
292
+ token_accuracy=token_accuracy,
278
293
  )
@@ -12,6 +12,8 @@ from transformers.utils.deprecation import deprecate_kwarg
12
12
 
13
13
  from liger_kernel.transformers.fused_linear_cross_entropy import LigerFusedLinearCrossEntropyLoss
14
14
  from liger_kernel.transformers.model.loss_utils import LigerForCausalLMLoss
15
+ from liger_kernel.transformers.model.loss_utils import unpack_cross_entropy_result
16
+ from liger_kernel.transformers.model.output_classes import LigerCausalLMOutputWithPast
15
17
 
16
18
 
17
19
  def lce_forward_deprecated(
@@ -149,7 +151,7 @@ def lce_forward(
149
151
  logits_to_keep: Union[int, torch.Tensor] = 0,
150
152
  skip_logits: Optional[bool] = None,
151
153
  **kwargs,
152
- ) -> Union[Tuple, CausalLMOutputWithPast]:
154
+ ) -> Union[Tuple, LigerCausalLMOutputWithPast]:
153
155
  r"""
154
156
  Args:
155
157
  labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
@@ -190,7 +192,9 @@ def lce_forward(
190
192
  output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
191
193
  )
192
194
  return_dict = return_dict if return_dict is not None else self.config.use_return_dict
193
-
195
+ # Filter out accum_dtype from kwargs for model call as MllamaTextModel doesn't accept it in transformers 4.49.0
196
+ # but preserve it for loss function calls
197
+ model_kwargs = {k: v for k, v in kwargs.items() if k != "accum_dtype"}
194
198
  # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)
195
199
  outputs = self.model(
196
200
  input_ids=input_ids,
@@ -206,7 +210,7 @@ def lce_forward(
206
210
  output_hidden_states=output_hidden_states,
207
211
  return_dict=return_dict,
208
212
  cache_position=cache_position,
209
- **kwargs,
213
+ **model_kwargs,
210
214
  )
211
215
 
212
216
  hidden_states = outputs[0]
@@ -217,6 +221,7 @@ def lce_forward(
217
221
  shift_labels = kwargs.pop("shift_labels", None)
218
222
  logits = None
219
223
  loss = None
224
+ token_accuracy = None
220
225
 
221
226
  if skip_logits and labels is None and shift_labels is None:
222
227
  raise ValueError("skip_logits is True, but labels and shift_labels are None")
@@ -226,7 +231,7 @@ def lce_forward(
226
231
  skip_logits = self.training and (labels is not None or shift_labels is not None)
227
232
 
228
233
  if skip_logits:
229
- loss = LigerForCausalLMLoss(
234
+ result = LigerForCausalLMLoss(
230
235
  hidden_states=kept_hidden_states,
231
236
  lm_head_weight=self.lm_head.weight,
232
237
  labels=labels,
@@ -234,25 +239,31 @@ def lce_forward(
234
239
  hidden_size=self.config.hidden_size,
235
240
  **kwargs,
236
241
  )
242
+ loss, _, token_accuracy = unpack_cross_entropy_result(result)
237
243
 
238
244
  else:
239
245
  logits = self.lm_head(kept_hidden_states)
240
- if labels is not None:
246
+ if labels is not None or shift_labels is not None:
241
247
  loss = self.loss_function(
242
248
  logits=logits,
243
249
  labels=labels,
250
+ shift_labels=shift_labels,
244
251
  vocab_size=self.config.vocab_size,
245
252
  **kwargs,
246
253
  )
247
254
 
248
255
  if not return_dict:
249
256
  output = (logits,) + outputs[1:]
250
- return (loss,) + output if loss is not None else output
257
+ output = (loss,) + output if loss is not None else output
258
+ output = output + (token_accuracy,) if token_accuracy is not None else output
259
+ return output
251
260
 
252
- return CausalLMOutputWithPast(
261
+ # Return custom output class with token_accuracy field
262
+ return LigerCausalLMOutputWithPast(
253
263
  loss=loss,
254
264
  logits=logits,
255
265
  past_key_values=outputs.past_key_values,
256
266
  hidden_states=outputs.hidden_states,
257
267
  attentions=outputs.attentions,
268
+ token_accuracy=token_accuracy,
258
269
  )
@@ -5,10 +5,11 @@ from typing import Union
5
5
 
6
6
  import torch
7
7
 
8
- from transformers.modeling_outputs import CausalLMOutputWithPast
9
8
  from transformers.utils.deprecation import deprecate_kwarg
10
9
 
11
10
  from liger_kernel.transformers.model.loss_utils import LigerForCausalLMLoss
11
+ from liger_kernel.transformers.model.loss_utils import unpack_cross_entropy_result
12
+ from liger_kernel.transformers.model.output_classes import LigerCausalLMOutputWithPast
12
13
 
13
14
 
14
15
  @deprecate_kwarg("num_logits_to_keep", version="4.50", new_name="logits_to_keep")
@@ -28,7 +29,7 @@ def lce_forward(
28
29
  logits_to_keep: Union[int, torch.Tensor] = 0,
29
30
  skip_logits: Optional[bool] = None,
30
31
  **kwargs,
31
- ) -> Union[Tuple, CausalLMOutputWithPast]:
32
+ ) -> Union[Tuple, LigerCausalLMOutputWithPast]:
32
33
  r"""
33
34
  Args:
34
35
  labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
@@ -91,6 +92,7 @@ def lce_forward(
91
92
  shift_labels = kwargs.pop("shift_labels", None)
92
93
  logits = None
93
94
  loss = None
95
+ token_accuracy = None
94
96
 
95
97
  if skip_logits and labels is None and shift_labels is None:
96
98
  raise ValueError("skip_logits is True, but labels and shift_labels are None")
@@ -99,8 +101,9 @@ def lce_forward(
99
101
  # By default, if in training mode, don't materialize logits
100
102
  skip_logits = self.training and (labels is not None or shift_labels is not None)
101
103
 
104
+ # Compute loss
102
105
  if skip_logits:
103
- loss = LigerForCausalLMLoss(
106
+ result = LigerForCausalLMLoss(
104
107
  hidden_states=kept_hidden_states,
105
108
  lm_head_weight=self.lm_head.weight,
106
109
  labels=labels,
@@ -108,21 +111,31 @@ def lce_forward(
108
111
  hidden_size=self.config.hidden_size,
109
112
  **kwargs,
110
113
  )
114
+ loss, _, token_accuracy = unpack_cross_entropy_result(result)
111
115
 
112
116
  else:
113
117
  logits = self.lm_head(kept_hidden_states)
114
- if labels is not None:
118
+ if labels is not None or shift_labels is not None:
115
119
  loss = self.loss_function(
116
120
  logits=logits,
117
121
  labels=labels,
122
+ shift_labels=shift_labels,
118
123
  vocab_size=self.config.vocab_size,
119
124
  **kwargs,
120
125
  )
121
126
 
122
- return CausalLMOutputWithPast(
127
+ if not return_dict:
128
+ output = (logits,) + outputs[1:]
129
+ output = ((loss,) + output) if loss is not None else output
130
+ output = output + (token_accuracy,) if token_accuracy is not None else output
131
+ return output
132
+
133
+ # Return custom output class with token_accuracy field
134
+ return LigerCausalLMOutputWithPast(
123
135
  loss=loss,
124
136
  logits=logits,
125
137
  past_key_values=outputs.past_key_values,
126
138
  hidden_states=outputs.hidden_states,
127
139
  attentions=outputs.attentions,
140
+ token_accuracy=token_accuracy,
128
141
  )
@@ -0,0 +1,142 @@
1
+ from typing import List
2
+ from typing import Optional
3
+ from typing import Tuple
4
+ from typing import Union
5
+
6
+ import torch
7
+
8
+ from transformers.modeling_outputs import BaseModelOutputWithPast
9
+ from transformers.utils.deprecation import deprecate_kwarg
10
+
11
+ from liger_kernel.transformers.model.loss_utils import LigerForCausalLMLoss
12
+ from liger_kernel.transformers.model.loss_utils import unpack_cross_entropy_result
13
+ from liger_kernel.transformers.model.output_classes import LigerCausalLMOutputWithPast
14
+
15
+
16
+ @deprecate_kwarg("num_logits_to_keep", version="4.50", new_name="logits_to_keep")
17
+ def lce_forward(
18
+ self,
19
+ input_ids: torch.LongTensor = None,
20
+ attention_mask: Optional[torch.Tensor] = None,
21
+ position_ids: Optional[torch.LongTensor] = None,
22
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
23
+ inputs_embeds: Optional[torch.FloatTensor] = None,
24
+ labels: Optional[torch.LongTensor] = None,
25
+ use_cache: Optional[bool] = None,
26
+ output_attentions: Optional[bool] = None,
27
+ output_hidden_states: Optional[bool] = None,
28
+ return_dict: Optional[bool] = None,
29
+ cache_position: Optional[torch.LongTensor] = None,
30
+ logits_to_keep: Union[int, torch.Tensor] = 0,
31
+ skip_logits: Optional[bool] = None,
32
+ **kwargs,
33
+ ) -> Union[Tuple, LigerCausalLMOutputWithPast]:
34
+ r"""
35
+ Args:
36
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
37
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
38
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
39
+ (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
40
+
41
+ logits_to_keep (`int` or `torch.Tensor`, *optional*):
42
+ If an `int`, compute logits for the last `logits_to_keep` tokens. If `0`, calculate logits for all
43
+ `input_ids` (special case). Only last token logits are needed for generation, and calculating them only for that
44
+ token can save memory, which becomes pretty significant for long sequences or large vocabulary size.
45
+ If a `torch.Tensor`, must be 1D corresponding to the indices to keep in the sequence length dimension.
46
+ This is useful when using packed tensor format (single dimension for batch and sequence length).
47
+
48
+ Returns:
49
+
50
+ Example:
51
+
52
+ ```python
53
+ >>> from transformers import AutoTokenizer, Olmo3ForCausalLM
54
+
55
+ >>> model = Olmo3ForCausalLM.from_pretrained("allenai/Olmo-3-7B-Instruct")
56
+ >>> tokenizer = AutoTokenizer.from_pretrained("allenai/Olmo-3-7B-Instruct")
57
+
58
+ >>> prompt = "Hey, are you conscious? Can you talk to me?"
59
+ >>> inputs = tokenizer(prompt, return_tensors="pt")
60
+
61
+ >>> # Generate
62
+ >>> generate_ids = model.generate(inputs.input_ids, max_length=30)
63
+ >>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
64
+ 'Hey, are you conscious? Can you talk to me?\nI’m not sure if you’re conscious of this, but I’m'
65
+ ```
66
+ """
67
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
68
+ output_hidden_states = (
69
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
70
+ )
71
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
72
+
73
+ # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)
74
+ outputs: BaseModelOutputWithPast = self.model(
75
+ input_ids=input_ids,
76
+ attention_mask=attention_mask,
77
+ position_ids=position_ids,
78
+ past_key_values=past_key_values,
79
+ inputs_embeds=inputs_embeds,
80
+ use_cache=use_cache,
81
+ output_attentions=output_attentions,
82
+ output_hidden_states=output_hidden_states,
83
+ return_dict=return_dict,
84
+ cache_position=cache_position,
85
+ **kwargs,
86
+ )
87
+
88
+ hidden_states = outputs[0]
89
+ # Only compute necessary logits, and do not upcast them to float if we are not computing the loss
90
+ slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
91
+ kept_hidden_states = hidden_states[:, slice_indices, :]
92
+
93
+ shift_labels = kwargs.pop("shift_labels", None)
94
+ logits = None
95
+ loss = None
96
+ token_accuracy = None
97
+
98
+ if skip_logits and labels is None and shift_labels is None:
99
+ raise ValueError("skip_logits is True, but labels and shift_labels are None")
100
+
101
+ if skip_logits is None:
102
+ # By default, if in training mode, don't materialize logits
103
+ skip_logits = self.training and (labels is not None or shift_labels is not None)
104
+
105
+ # Compute loss
106
+ if skip_logits:
107
+ result = LigerForCausalLMLoss(
108
+ hidden_states=kept_hidden_states,
109
+ lm_head_weight=self.lm_head.weight,
110
+ labels=labels,
111
+ shift_labels=shift_labels,
112
+ hidden_size=self.config.hidden_size,
113
+ **kwargs,
114
+ )
115
+ loss, _, token_accuracy = unpack_cross_entropy_result(result)
116
+
117
+ else:
118
+ logits = self.lm_head(kept_hidden_states)
119
+ if labels is not None or shift_labels is not None:
120
+ loss = self.loss_function(
121
+ logits=logits,
122
+ labels=labels,
123
+ shift_labels=shift_labels,
124
+ vocab_size=self.config.vocab_size,
125
+ **kwargs,
126
+ )
127
+
128
+ if not return_dict:
129
+ output = (logits,) + outputs[1:]
130
+ output = ((loss,) + output) if loss is not None else output
131
+ output = output + (token_accuracy,) if token_accuracy is not None else output
132
+ return output
133
+
134
+ # Return custom output class with token_accuracy field
135
+ return LigerCausalLMOutputWithPast(
136
+ loss=loss,
137
+ logits=logits,
138
+ past_key_values=outputs.past_key_values,
139
+ hidden_states=outputs.hidden_states,
140
+ attentions=outputs.attentions,
141
+ token_accuracy=token_accuracy,
142
+ )
@@ -0,0 +1,147 @@
1
+ """
2
+ Custom output classes for Liger-Kernel that extend transformers' ModelOutput classes
3
+ with optional token accuracy field.
4
+ """
5
+
6
+ from dataclasses import dataclass
7
+ from typing import Optional
8
+
9
+ import torch
10
+
11
+ from transformers.modeling_outputs import CausalLMOutputWithPast
12
+ from transformers.modeling_outputs import MoeCausalLMOutputWithPast
13
+
14
+ # The following model-specific outputs are optional and depend on the installed
15
+ # transformers version. Guard their imports so our module remains importable
16
+ # even when those models are not available in the environment.
17
+ try:
18
+ from transformers.models.gemma3.modeling_gemma3 import Gemma3CausalLMOutputWithPast as _Gemma3CausalLMOutputWithPast
19
+ except Exception:
20
+ _Gemma3CausalLMOutputWithPast = None
21
+
22
+ try:
23
+ from transformers.models.glm4v_moe.modeling_glm4v_moe import (
24
+ Glm4vMoeCausalLMOutputWithPast as _Glm4vMoeCausalLMOutputWithPast,
25
+ )
26
+ except Exception:
27
+ _Glm4vMoeCausalLMOutputWithPast = None
28
+
29
+ try:
30
+ from transformers.models.internvl.modeling_internvl import (
31
+ InternVLCausalLMOutputWithPast as _InternVLCausalLMOutputWithPast,
32
+ )
33
+ except Exception:
34
+ _InternVLCausalLMOutputWithPast = None
35
+
36
+ try:
37
+ from transformers.models.llava.modeling_llava import LlavaCausalLMOutputWithPast as _LlavaCausalLMOutputWithPast
38
+ except Exception:
39
+ _LlavaCausalLMOutputWithPast = None
40
+
41
+ try:
42
+ from transformers.models.paligemma.modeling_paligemma import (
43
+ PaliGemmaCausalLMOutputWithPast as _PaliGemmaCausalLMOutputWithPast,
44
+ )
45
+ except Exception:
46
+ _PaliGemmaCausalLMOutputWithPast = None
47
+
48
+ try:
49
+ from transformers.models.qwen2_5_vl.modeling_qwen2_5_vl import (
50
+ Qwen2_5_VLCausalLMOutputWithPast as _Qwen2_5_VLCausalLMOutputWithPast,
51
+ )
52
+ except Exception:
53
+ _Qwen2_5_VLCausalLMOutputWithPast = None
54
+
55
+ try:
56
+ from transformers.models.qwen2_vl.modeling_qwen2_vl import (
57
+ Qwen2VLCausalLMOutputWithPast as _Qwen2VLCausalLMOutputWithPast,
58
+ )
59
+ except Exception:
60
+ _Qwen2VLCausalLMOutputWithPast = None
61
+
62
+ try:
63
+ from transformers.models.qwen3_vl.modeling_qwen3_vl import (
64
+ Qwen3VLCausalLMOutputWithPast as _Qwen3VLCausalLMOutputWithPast,
65
+ )
66
+ except Exception:
67
+ _Qwen3VLCausalLMOutputWithPast = None
68
+
69
+ try:
70
+ from transformers.models.qwen3_vl_moe.modeling_qwen3_vl_moe import (
71
+ Qwen3VLMoeCausalLMOutputWithPast as _Qwen3VLMoeCausalLMOutputWithPast,
72
+ )
73
+ except Exception:
74
+ _Qwen3VLMoeCausalLMOutputWithPast = None
75
+
76
+
77
+ @dataclass
78
+ class LigerCausalLMOutputWithPast(CausalLMOutputWithPast):
79
+ token_accuracy: Optional[torch.FloatTensor] = None
80
+
81
+
82
+ @dataclass
83
+ class LigerMoeCausalLMOutputWithPast(MoeCausalLMOutputWithPast):
84
+ token_accuracy: Optional[torch.FloatTensor] = None
85
+
86
+
87
+ if _Gemma3CausalLMOutputWithPast is not None:
88
+
89
+ @dataclass
90
+ class LigerGemma3CausalLMOutputWithPast(_Gemma3CausalLMOutputWithPast):
91
+ token_accuracy: Optional[torch.FloatTensor] = None
92
+
93
+
94
+ if _Glm4vMoeCausalLMOutputWithPast is not None:
95
+
96
+ @dataclass
97
+ class LigerGlm4vMoeCausalLMOutputWithPast(_Glm4vMoeCausalLMOutputWithPast):
98
+ token_accuracy: Optional[torch.FloatTensor] = None
99
+
100
+
101
+ if _LlavaCausalLMOutputWithPast is not None:
102
+
103
+ @dataclass
104
+ class LigerLlavaCausalLMOutputWithPast(_LlavaCausalLMOutputWithPast):
105
+ token_accuracy: Optional[torch.FloatTensor] = None
106
+
107
+
108
+ if _InternVLCausalLMOutputWithPast is not None:
109
+
110
+ @dataclass
111
+ class LigerInternVLCausalLMOutputWithPast(_InternVLCausalLMOutputWithPast):
112
+ token_accuracy: Optional[torch.FloatTensor] = None
113
+
114
+
115
+ if _PaliGemmaCausalLMOutputWithPast is not None:
116
+
117
+ @dataclass
118
+ class LigerPaliGemmaCausalLMOutputWithPast(_PaliGemmaCausalLMOutputWithPast):
119
+ token_accuracy: Optional[torch.FloatTensor] = None
120
+
121
+
122
+ if _Qwen2_5_VLCausalLMOutputWithPast is not None:
123
+
124
+ @dataclass
125
+ class LigerQwen2_5_VLCausalLMOutputWithPast(_Qwen2_5_VLCausalLMOutputWithPast):
126
+ token_accuracy: Optional[torch.FloatTensor] = None
127
+
128
+
129
+ if _Qwen2VLCausalLMOutputWithPast is not None:
130
+
131
+ @dataclass
132
+ class LigerQwen2VLCausalLMOutputWithPast(_Qwen2VLCausalLMOutputWithPast):
133
+ token_accuracy: Optional[torch.FloatTensor] = None
134
+
135
+
136
+ if _Qwen3VLCausalLMOutputWithPast is not None:
137
+
138
+ @dataclass
139
+ class LigerQwen3VLCausalLMOutputWithPast(_Qwen3VLCausalLMOutputWithPast):
140
+ token_accuracy: Optional[torch.FloatTensor] = None
141
+
142
+
143
+ if _Qwen3VLMoeCausalLMOutputWithPast is not None:
144
+
145
+ @dataclass
146
+ class LigerQwen3VLMoeCausalLMOutputWithPast(_Qwen3VLMoeCausalLMOutputWithPast):
147
+ token_accuracy: Optional[torch.FloatTensor] = None
@@ -13,6 +13,9 @@ from transformers.utils import logging
13
13
  from transformers.utils.deprecation import deprecate_kwarg
14
14
 
15
15
  from liger_kernel.transformers.fused_linear_cross_entropy import LigerFusedLinearCrossEntropyLoss
16
+ from liger_kernel.transformers.model.loss_utils import LigerForCausalLMLoss
17
+ from liger_kernel.transformers.model.loss_utils import unpack_cross_entropy_result
18
+ from liger_kernel.transformers.model.output_classes import LigerPaliGemmaCausalLMOutputWithPast
16
19
 
17
20
  logger = logging.get_logger(__name__)
18
21
 
@@ -218,7 +221,7 @@ def lce_forward(
218
221
  logits_to_keep: Union[int, torch.Tensor] = 0,
219
222
  skip_logits: Optional[bool] = None,
220
223
  **lm_kwargs,
221
- ) -> Union[Tuple, PaliGemmaCausalLMOutputWithPast]:
224
+ ) -> Union[Tuple, LigerPaliGemmaCausalLMOutputWithPast]:
222
225
  r"""
223
226
  Args:
224
227
  labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
@@ -331,6 +334,7 @@ def lce_forward(
331
334
 
332
335
  loss = None
333
336
  logits = None
337
+ token_accuracy = None
334
338
 
335
339
  if skip_logits and labels is None:
336
340
  raise ValueError("skip_logits is True, but labels is None")
@@ -358,8 +362,16 @@ def lce_forward(
358
362
  shift_hidden_states = shift_hidden_states.view(-1, self.config.text_config.hidden_size)
359
363
  shift_labels = shift_labels.view(-1).to(hidden_device)
360
364
 
361
- lce = LigerFusedLinearCrossEntropyLoss()
362
- loss = lce(self.language_model.lm_head.weight, shift_hidden_states, shift_labels)
365
+ # Use LigerForCausalLMLoss with accuracy support and pass already shifted labels
366
+ result = LigerForCausalLMLoss(
367
+ hidden_states=shift_hidden_states,
368
+ lm_head_weight=self.language_model.lm_head.weight,
369
+ labels=None,
370
+ shift_labels=shift_labels,
371
+ hidden_size=self.config.text_config.hidden_size,
372
+ **lm_kwargs,
373
+ )
374
+ loss, _, token_accuracy = unpack_cross_entropy_result(result)
363
375
  else:
364
376
  logits = self.language_model.lm_head(hidden_states)
365
377
  if labels is not None:
@@ -382,15 +394,39 @@ def lce_forward(
382
394
  flat_logits = shift_logits.view(-1, self.config.text_config.vocab_size)
383
395
  flat_labels = shift_labels.view(-1).to(shift_logits.device)
384
396
  loss = loss_fct(flat_logits, flat_labels)
397
+ elif shift_labels is not None:
398
+ # Upcast to float if we need to compute the loss to avoid potential precision issues
399
+ logits = logits.float()
400
+ shift_logits = logits[..., :-1, :]
401
+ if attention_mask is not None:
402
+ # we use the input attention mask to shift the logits and labels, because it is 2D.
403
+ # we also crop attn mask in case it is longer, which happens in PrefixTuning with peft
404
+ shift_attention_mask = attention_mask[:, -shift_logits.shape[1] :].to(logits.device)
405
+ shift_logits = shift_logits[shift_attention_mask.to(logits.device) != 0].contiguous()
406
+ shift_labels = shift_labels[shift_attention_mask.to(shift_labels.device) != 0].contiguous()
407
+ else:
408
+ shift_logits = shift_logits.contiguous()
409
+ shift_labels = shift_labels.contiguous()
410
+ # Flatten the tokens
411
+ loss_fct = CrossEntropyLoss()
412
+
413
+ flat_logits = shift_logits.view(-1, self.config.text_config.vocab_size)
414
+ flat_labels = shift_labels.view(-1).to(shift_logits.device)
415
+ loss = loss_fct(flat_logits, flat_labels)
416
+
385
417
  if not return_dict:
386
418
  output = (logits,) + outputs[1:]
387
- return (loss,) + output if loss is not None else output
419
+ output = (loss,) + output if loss is not None else output
420
+ output = output + (token_accuracy,) if token_accuracy is not None else output
421
+ return output
388
422
 
389
- return PaliGemmaCausalLMOutputWithPast(
423
+ # Return PaliGemma output with token_accuracy field
424
+ return LigerPaliGemmaCausalLMOutputWithPast(
390
425
  loss=loss,
391
426
  logits=logits,
392
427
  past_key_values=outputs.past_key_values,
393
428
  hidden_states=outputs.hidden_states,
394
429
  attentions=outputs.attentions,
395
430
  image_hidden_states=image_features if pixel_values is not None else None,
431
+ token_accuracy=token_accuracy,
396
432
  )