tutur90 commited on
Commit
aa5ca32
·
verified ·
1 Parent(s): efceb44

Upload modeling.py

Browse files
Files changed (1) hide show
  1. modeling.py +526 -0
modeling.py ADDED
@@ -0,0 +1,526 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Optional, Union
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+ from transformers import (
6
+ M2M100Config,)
7
+
8
+ from transformers.models.m2m_100.modeling_m2m_100 import (
9
+ M2M100Encoder,
10
+ M2M100ScaledWordEmbedding,
11
+ M2M100ForConditionalGeneration,
12
+ M2M100Model,
13
+ shift_tokens_right,
14
+ logger)
15
+
16
+ from transformers.modeling_outputs import BaseModelOutput, BaseModelOutputWithPastAndCrossAttentions, Seq2SeqLMOutput, Seq2SeqModelOutput
17
+
18
+ from transformers.utils import auto_docstring
19
+
20
+ from torch.nn import CrossEntropyLoss
21
+
22
+ class Pooling(nn.Module):
23
+ """
24
+ Pooling layer for sequence representations.
25
+
26
+ Supports multiple pooling strategies: mean, cls, last, max, and none.
27
+ """
28
+
29
+ def __init__(self, pooling_type: str = "mean"):
30
+ super().__init__()
31
+ valid_types = {"mean", "cls", "last", "max", "none"}
32
+ if pooling_type not in valid_types:
33
+ raise ValueError(f"pooling_type must be one of {valid_types}, got {pooling_type}")
34
+ self.pooling_type = pooling_type
35
+
36
+ def forward(
37
+ self,
38
+ hidden_states: torch.Tensor,
39
+ attention_mask: Optional[torch.Tensor] = None
40
+ ) -> torch.Tensor:
41
+ """
42
+ Apply pooling to hidden states.
43
+
44
+ Args:
45
+ hidden_states: Tensor of shape (batch_size, seq_len, hidden_size)
46
+ attention_mask: Tensor of shape (batch_size, seq_len), values in {0, 1}
47
+
48
+ Returns:
49
+ Pooled tensor of shape (batch_size, 1, hidden_size) or (batch_size, seq_len, hidden_size) for none
50
+ """
51
+ if self.pooling_type == "none":
52
+ return hidden_states
53
+
54
+ if self.pooling_type == "cls":
55
+ return hidden_states[:, 0, :].unsqueeze(1)
56
+
57
+ elif self.pooling_type == "last":
58
+ return hidden_states[:, -1, :].unsqueeze(1)
59
+
60
+ elif self.pooling_type in ["mean", "max"]:
61
+ if attention_mask is None:
62
+ raise ValueError(f"attention_mask is required for {self.pooling_type} pooling")
63
+
64
+ # Expand attention mask to match hidden_states dimensions
65
+ mask = attention_mask.unsqueeze(-1)
66
+
67
+ if self.pooling_type == "mean":
68
+ # Apply mask and compute mean over valid tokens
69
+ masked_hidden = hidden_states * mask
70
+ sum_hidden = masked_hidden.sum(dim=1, keepdim=True)
71
+ sum_mask = mask.sum(dim=1, keepdim=True)
72
+
73
+ return sum_hidden / sum_mask
74
+
75
+ elif self.pooling_type == "max":
76
+ # Apply mask (set masked positions to large negative value)
77
+ masked_hidden = hidden_states.masked_fill(mask == 0, float('-inf'))
78
+ return masked_hidden.max(dim=1, keepdim=True)[0]
79
+
80
+ class SONARTextEncoder(M2M100Encoder):
81
+ """
82
+ Transformer encoder with pooling capabilities.
83
+
84
+ Inherits from M2M100Encoder and adds configurable pooling functionality.
85
+
86
+ Args:
87
+ config: M2M100Config with optional pooling_type attribute
88
+ embed_tokens: Optional embedding layer
89
+ """
90
+
91
+ def __init__(self, config: M2M100Config, embed_tokens: Optional[nn.Embedding] = None):
92
+ super().__init__(config, embed_tokens)
93
+
94
+ # Initialize pooling layer
95
+ pooling_type = getattr(config, 'pooling_type', 'mean')
96
+ self.pooling = Pooling(pooling_type)
97
+
98
+ def forward(
99
+ self,
100
+ input_ids: Optional[torch.Tensor] = None,
101
+ attention_mask: Optional[torch.Tensor] = None,
102
+ head_mask: Optional[torch.Tensor] = None,
103
+ inputs_embeds: Optional[torch.Tensor] = None,
104
+ output_attentions: Optional[bool] = None,
105
+ output_hidden_states: Optional[bool] = None,
106
+ return_dict: Optional[bool] = None,
107
+ ):
108
+ """
109
+ Forward pass with optional pooling.
110
+
111
+ Args:
112
+ input_ids: Input token ids
113
+ attention_mask: Attention mask for padding tokens
114
+ head_mask: Mask for attention heads
115
+ inputs_embeds: Pre-computed embeddings
116
+ output_attentions: Whether to return attention weights
117
+ output_hidden_states: Whether to return all hidden states
118
+ return_dict: Whether to return ModelOutput object
119
+ pool: Pooling strategy override (if None, uses config default)
120
+
121
+ Returns:
122
+ Model output with pooled representations
123
+ """
124
+ # Get encoder output
125
+ encoder_output = super().forward(
126
+ input_ids=input_ids,
127
+ attention_mask=attention_mask,
128
+ head_mask=head_mask,
129
+ inputs_embeds=inputs_embeds,
130
+ output_attentions=output_attentions,
131
+ output_hidden_states=output_hidden_states,
132
+ return_dict=return_dict,
133
+ )
134
+
135
+ # Extract hidden states
136
+ if return_dict:
137
+ hidden_states = encoder_output.last_hidden_state
138
+
139
+ else:
140
+ hidden_states = encoder_output[0]
141
+
142
+ pooled_output = self.pooling(hidden_states, attention_mask)
143
+
144
+ if return_dict:
145
+ encoder_output.last_hidden_state = pooled_output
146
+ else:
147
+ encoder_output = (pooled_output,) + encoder_output[1:]
148
+
149
+ return encoder_output
150
+
151
+ class SONARModel(M2M100Model):
152
+ """SONAR model based on M2M100."""
153
+
154
+ def __init__(self, config: M2M100Config):
155
+ super().__init__(config)
156
+
157
+ self.encoder = SONARTextEncoder(config, self.shared)
158
+
159
+ def forward(
160
+ self,
161
+ input_ids: Optional[torch.LongTensor] = None,
162
+ attention_mask: Optional[torch.Tensor] = None,
163
+ decoder_input_ids: Optional[torch.LongTensor] = None,
164
+ decoder_attention_mask: Optional[torch.LongTensor] = None,
165
+ head_mask: Optional[torch.Tensor] = None,
166
+ decoder_head_mask: Optional[torch.Tensor] = None,
167
+ cross_attn_head_mask: Optional[torch.Tensor] = None,
168
+ encoder_outputs: Optional[tuple[tuple[torch.FloatTensor]]] = None,
169
+ past_key_values: Optional[tuple[tuple[torch.FloatTensor]]] = None,
170
+ inputs_embeds: Optional[torch.FloatTensor] = None,
171
+ decoder_inputs_embeds: Optional[torch.FloatTensor] = None,
172
+ use_cache: Optional[bool] = None,
173
+ output_attentions: Optional[bool] = None,
174
+ output_hidden_states: Optional[bool] = None,
175
+ return_dict: Optional[bool] = None,
176
+ cache_position: Optional[torch.Tensor] = None,
177
+ return_logits: Optional[bool] = False,
178
+ ) -> Union[tuple[torch.Tensor], Seq2SeqModelOutput]:
179
+ r"""
180
+ decoder_input_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
181
+ Indices of decoder input sequence tokens in the vocabulary.
182
+
183
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
184
+ [`PreTrainedTokenizer.__call__`] for details.
185
+
186
+ [What are decoder input IDs?](../glossary#decoder-input-ids)
187
+
188
+ M2M100 uses the `eos_token_id` as the starting token for `decoder_input_ids` generation. If
189
+ `past_key_values` is used, optionally only the last `decoder_input_ids` have to be input (see
190
+ `past_key_values`).
191
+ decoder_attention_mask (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
192
+ Default behavior: generate a tensor that ignores pad tokens in `decoder_input_ids`. Causal mask will also
193
+ be used by default.
194
+ cross_attn_head_mask (`torch.Tensor` of shape `(decoder_layers, decoder_attention_heads)`, *optional*):
195
+ Mask to nullify selected heads of the cross-attention modules in the decoder. Mask values selected in `[0,
196
+ 1]`:
197
+
198
+ - 1 indicates the head is **not masked**,
199
+ - 0 indicates the head is **masked**.
200
+ """
201
+
202
+ outputs = super().forward(
203
+ input_ids,
204
+ attention_mask=attention_mask,
205
+ decoder_input_ids=decoder_input_ids,
206
+ decoder_attention_mask=decoder_attention_mask,
207
+ head_mask=head_mask,
208
+ decoder_head_mask=decoder_head_mask,
209
+ cross_attn_head_mask=cross_attn_head_mask,
210
+ encoder_outputs=encoder_outputs,
211
+ past_key_values=past_key_values,
212
+ inputs_embeds=inputs_embeds,
213
+ decoder_inputs_embeds=decoder_inputs_embeds,
214
+ use_cache=use_cache,
215
+ output_attentions=output_attentions,
216
+ output_hidden_states=output_hidden_states,
217
+ return_dict=return_dict,
218
+ cache_position=cache_position,
219
+ )
220
+
221
+ if return_logits:
222
+ lm_logits = self.decoder.lm_head(outputs[0])
223
+ if not return_dict:
224
+ outputs = (lm_logits,) + outputs[1:]
225
+ else:
226
+ outputs.last_hidden_state = lm_logits
227
+
228
+ return outputs
229
+
230
+
231
+
232
+
233
+ @auto_docstring
234
+ def forward(
235
+ self,
236
+ input_ids: Optional[torch.LongTensor] = None,
237
+ attention_mask: Optional[torch.Tensor] = None,
238
+ decoder_input_ids: Optional[torch.LongTensor] = None,
239
+ decoder_attention_mask: Optional[torch.LongTensor] = None,
240
+ head_mask: Optional[torch.Tensor] = None,
241
+ decoder_head_mask: Optional[torch.Tensor] = None,
242
+ cross_attn_head_mask: Optional[torch.Tensor] = None,
243
+ encoder_outputs: Optional[tuple[tuple[torch.FloatTensor]]] = None,
244
+ past_key_values: Optional[tuple[tuple[torch.FloatTensor]]] = None,
245
+ inputs_embeds: Optional[torch.FloatTensor] = None,
246
+ decoder_inputs_embeds: Optional[torch.FloatTensor] = None,
247
+ use_cache: Optional[bool] = None,
248
+ output_attentions: Optional[bool] = None,
249
+ output_hidden_states: Optional[bool] = None,
250
+ return_dict: Optional[bool] = None,
251
+ cache_position: Optional[torch.Tensor] = None,
252
+ ) -> Union[tuple[torch.Tensor], Seq2SeqModelOutput]:
253
+ r"""
254
+ decoder_input_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
255
+ Indices of decoder input sequence tokens in the vocabulary.
256
+
257
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
258
+ [`PreTrainedTokenizer.__call__`] for details.
259
+
260
+ [What are decoder input IDs?](../glossary#decoder-input-ids)
261
+
262
+ M2M100 uses the `eos_token_id` as the starting token for `decoder_input_ids` generation. If
263
+ `past_key_values` is used, optionally only the last `decoder_input_ids` have to be input (see
264
+ `past_key_values`).
265
+ decoder_attention_mask (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
266
+ Default behavior: generate a tensor that ignores pad tokens in `decoder_input_ids`. Causal mask will also
267
+ be used by default.
268
+ cross_attn_head_mask (`torch.Tensor` of shape `(decoder_layers, decoder_attention_heads)`, *optional*):
269
+ Mask to nullify selected heads of the cross-attention modules in the decoder. Mask values selected in `[0,
270
+ 1]`:
271
+
272
+ - 1 indicates the head is **not masked**,
273
+ - 0 indicates the head is **masked**.
274
+ """
275
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
276
+ output_hidden_states = (
277
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
278
+ )
279
+ use_cache = use_cache if use_cache is not None else self.config.use_cache
280
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
281
+
282
+
283
+
284
+ if encoder_outputs is None:
285
+ encoder_outputs = self.encoder(
286
+ input_ids=input_ids,
287
+ attention_mask=attention_mask,
288
+ head_mask=head_mask,
289
+ inputs_embeds=inputs_embeds,
290
+ output_attentions=output_attentions,
291
+ output_hidden_states=output_hidden_states,
292
+ return_dict=return_dict,
293
+ )
294
+
295
+
296
+ # If the user passed a tuple for encoder_outputs, we wrap it in a BaseModelOutput when return_dict=True
297
+ elif return_dict and not isinstance(encoder_outputs, BaseModelOutput):
298
+ encoder_outputs = BaseModelOutput(
299
+ last_hidden_state=encoder_outputs[0],
300
+ hidden_states=encoder_outputs[1] if len(encoder_outputs) > 1 else None,
301
+ attentions=encoder_outputs[2] if len(encoder_outputs) > 2 else None,
302
+ )
303
+ if attention_mask is not None:
304
+ if (encoder_outputs[0].size(1) != 1 and encoder_outputs[0].dim() == 3):
305
+ logger.warning_once(
306
+ f"Encoder is not pooled"
307
+ )
308
+ encoder_attention_mask = attention_mask
309
+ else:
310
+ encoder_attention_mask = attention_mask[:, :1]
311
+
312
+ # decoder outputs consists of (dec_features, past_key_value, dec_hidden, dec_attn)
313
+ decoder_outputs = self.decoder(
314
+ input_ids=decoder_input_ids,
315
+ attention_mask=decoder_attention_mask,
316
+ encoder_hidden_states=encoder_outputs[0],
317
+ encoder_attention_mask=encoder_attention_mask,
318
+ head_mask=decoder_head_mask,
319
+ cross_attn_head_mask=cross_attn_head_mask,
320
+ past_key_values=past_key_values,
321
+ inputs_embeds=decoder_inputs_embeds,
322
+ use_cache=use_cache,
323
+ output_attentions=output_attentions,
324
+ output_hidden_states=output_hidden_states,
325
+ return_dict=return_dict,
326
+ cache_position=cache_position,
327
+ )
328
+
329
+ if not return_dict:
330
+ return decoder_outputs + encoder_outputs
331
+
332
+ return Seq2SeqModelOutput(
333
+ last_hidden_state=decoder_outputs.last_hidden_state,
334
+ past_key_values=decoder_outputs.past_key_values,
335
+ decoder_hidden_states=decoder_outputs.hidden_states,
336
+ decoder_attentions=decoder_outputs.attentions,
337
+ cross_attentions=decoder_outputs.cross_attentions,
338
+ encoder_last_hidden_state=encoder_outputs.last_hidden_state,
339
+ encoder_hidden_states=encoder_outputs.hidden_states,
340
+ encoder_attentions=encoder_outputs.attentions,
341
+ )
342
+
343
+ class SONARForText2Text(M2M100ForConditionalGeneration):
344
+ """SONAR model for conditional generation tasks."""
345
+
346
+ # _tied_weights_keys = ["encoder.embed_tokens.weight", "decoder.embed_tokens.weight"]
347
+
348
+ def __init__(self, config: M2M100Config):
349
+ super().__init__(config)
350
+
351
+ self.model = SONARModel(config)
352
+
353
+ self.cross_entropy_loss = CrossEntropyLoss(
354
+ label_smoothing=0.1,
355
+ ignore_index=-100
356
+ )
357
+
358
+ self.mse_loss = nn.MSELoss()
359
+
360
+
361
+ self.mse_ratio = getattr(config, 'mse_ratio', 0.2)
362
+
363
+ def forward(
364
+ self,
365
+ input_ids: Optional[torch.LongTensor] = None,
366
+ attention_mask: Optional[torch.Tensor] = None,
367
+ target_ids: Optional[torch.LongTensor] = None,
368
+ target_attention_mask: Optional[torch.Tensor] = None,
369
+ mse_mask: Optional[torch.Tensor] = None,
370
+ decoder_input_ids: Optional[torch.LongTensor] = None,
371
+ decoder_attention_mask: Optional[torch.LongTensor] = None,
372
+ head_mask: Optional[torch.Tensor] = None,
373
+ decoder_head_mask: Optional[torch.Tensor] = None,
374
+ cross_attn_head_mask: Optional[torch.Tensor] = None,
375
+ encoder_outputs: Optional[tuple[tuple[torch.FloatTensor]]] = None,
376
+ past_key_values: Optional[tuple[tuple[torch.FloatTensor]]] = None,
377
+ inputs_embeds: Optional[torch.FloatTensor] = None,
378
+ decoder_inputs_embeds: Optional[torch.FloatTensor] = None,
379
+ labels: Optional[torch.LongTensor] = None,
380
+ use_cache: Optional[bool] = None,
381
+ output_attentions: Optional[bool] = None,
382
+ output_hidden_states: Optional[bool] = None,
383
+ return_dict: Optional[bool] = None,
384
+ cache_position: Optional[torch.Tensor] = None,
385
+ ) -> Union[tuple[torch.Tensor], Seq2SeqLMOutput]:
386
+ r"""
387
+ decoder_input_ids (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
388
+ Indices of decoder input sequence tokens in the vocabulary.
389
+
390
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
391
+ [`PreTrainedTokenizer.__call__`] for details.
392
+
393
+ [What are decoder input IDs?](../glossary#decoder-input-ids)
394
+
395
+ M2M100 uses the `eos_token_id` as the starting token for `decoder_input_ids` generation. If
396
+ `past_key_values` is used, optionally only the last `decoder_input_ids` have to be input (see
397
+ `past_key_values`).
398
+ decoder_attention_mask (`torch.LongTensor` of shape `(batch_size, target_sequence_length)`, *optional*):
399
+ Default behavior: generate a tensor that ignores pad tokens in `decoder_input_ids`. Causal mask will also
400
+ be used by default.
401
+ cross_attn_head_mask (`torch.Tensor` of shape `(decoder_layers, decoder_attention_heads)`, *optional*):
402
+ Mask to nullify selected heads of the cross-attention modules in the decoder. Mask values selected in `[0,
403
+ 1]`:
404
+
405
+ - 1 indicates the head is **not masked**,
406
+ - 0 indicates the head is **masked**.
407
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
408
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
409
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
410
+ (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
411
+
412
+ Example Translation:
413
+
414
+ ```python
415
+ >>> from transformers import AutoTokenizer, M2M100ForConditionalGeneration
416
+
417
+ >>> model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100_418M")
418
+ >>> tokenizer = AutoTokenizer.from_pretrained("facebook/m2m100_418M")
419
+
420
+ >>> text_to_translate = "Life is like a box of chocolates"
421
+ >>> model_inputs = tokenizer(text_to_translate, return_tensors="pt")
422
+
423
+ >>> # translate to French
424
+ >>> gen_tokens = model.generate(**model_inputs, forced_bos_token_id=tokenizer.get_lang_id("fr"))
425
+ >>> print(tokenizer.batch_decode(gen_tokens, skip_special_tokens=True))
426
+ ```
427
+ """
428
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
429
+
430
+ if labels is not None:
431
+ if decoder_input_ids is None:
432
+ decoder_input_ids = shift_tokens_right(
433
+ labels, self.config.pad_token_id, self.config.decoder_start_token_id
434
+ )
435
+
436
+ outputs = self.model(
437
+ input_ids,
438
+ attention_mask=attention_mask,
439
+ decoder_input_ids=decoder_input_ids,
440
+ encoder_outputs=encoder_outputs,
441
+ decoder_attention_mask=decoder_attention_mask,
442
+ head_mask=head_mask,
443
+ decoder_head_mask=decoder_head_mask,
444
+ cross_attn_head_mask=cross_attn_head_mask,
445
+ past_key_values=past_key_values,
446
+ inputs_embeds=inputs_embeds,
447
+ decoder_inputs_embeds=decoder_inputs_embeds,
448
+ use_cache=use_cache,
449
+ output_attentions=output_attentions,
450
+ output_hidden_states=output_hidden_states,
451
+ return_dict=return_dict,
452
+ cache_position=cache_position,
453
+ )
454
+ lm_logits = self.lm_head(outputs[0])
455
+
456
+ masked_lm_loss = None
457
+ if labels is not None:
458
+
459
+ labels = labels.to(lm_logits.device)
460
+
461
+ masked_lm_loss = self.cross_entropy_loss(lm_logits.view(-1, self.config.vocab_size), labels.view(-1))
462
+
463
+ # print(f"Cross Entropy Loss: {masked_lm_loss if masked_lm_loss is not None else 'N/A'}")
464
+
465
+ masked_lm_loss = masked_lm_loss.mean()
466
+
467
+ if mse_mask is not None and target_ids is None:
468
+ mse_mask = mse_mask.view(-1, 1, 1).to(outputs.encoder_last_hidden_state.device)
469
+ encoder_outputs = outputs.encoder_last_hidden_state.squeeze()
470
+ batch_size = encoder_outputs.size(0)
471
+
472
+ # Reshape to pair structure: [batch//2, 2, seq_len, hidden]
473
+ paired = encoder_outputs[:batch_size//2*2].view(batch_size//2, 2, *encoder_outputs.shape[1:]) * mse_mask
474
+
475
+ mse_loss = self.mse_loss(paired[:, 0], paired[:, 1])
476
+ masked_lm_loss += self.mse_ratio * mse_loss
477
+
478
+ if target_ids is not None and labels is not None:
479
+
480
+ target_ids = target_ids.to(lm_logits.device)
481
+ target_encoder_outputs = self.model.encoder(
482
+ input_ids=target_ids,
483
+ attention_mask=target_attention_mask,
484
+ return_dict=return_dict,
485
+ )
486
+
487
+ mse_loss = self.mse_loss(outputs.encoder_last_hidden_state, target_encoder_outputs.last_hidden_state)
488
+
489
+ masked_lm_loss += self.mse_ratio * mse_loss
490
+
491
+ # print(f"Masked LM Loss: {masked_lm_loss.item() if masked_lm_loss is not None else 'N/A'}")
492
+ # print(f"MSE Loss: {mse_loss.item() if mse_loss is not None else 'N/A'}")
493
+
494
+ if not return_dict:
495
+ output = (lm_logits,) + outputs[1:]
496
+ return ((masked_lm_loss,) + output) if masked_lm_loss is not None else output
497
+
498
+ return Seq2SeqLMOutput(
499
+ loss=masked_lm_loss,
500
+ logits=lm_logits,
501
+ past_key_values=outputs.past_key_values,
502
+ decoder_hidden_states=outputs.decoder_hidden_states,
503
+ decoder_attentions=outputs.decoder_attentions,
504
+ cross_attentions=outputs.cross_attentions,
505
+ encoder_last_hidden_state=outputs.encoder_last_hidden_state,
506
+ encoder_hidden_states=outputs.encoder_hidden_states,
507
+ encoder_attentions=outputs.encoder_attentions,
508
+ )
509
+
510
+ @classmethod
511
+ def from_m2m100_pretrained(cls, pretrained_model_name_or_path: str, *model_args, **kwargs):
512
+ model = M2M100ForConditionalGeneration.from_pretrained(pretrained_model_name_or_path, *model_args, **kwargs)
513
+
514
+ generation_config = model.generation_config
515
+
516
+ generation_config.early_stopping = True
517
+ generation_config.num_beams = 5
518
+ generation_config.max_length = 500
519
+
520
+ config = model.config
521
+ config.pooling_type = getattr(config, 'pooling_type', 'mean')
522
+
523
+ sonar_model = cls(model.config)
524
+ sonar_model.load_state_dict(model.state_dict(), strict=False)
525
+ sonar_model.generation_config = generation_config
526
+ return sonar_model