Jtapsa commited on
Commit
63a376c
·
verified ·
1 Parent(s): 49c5a7f

Add moep.py to main

Browse files
Files changed (1) hide show
  1. moep.py +529 -0
moep.py ADDED
@@ -0,0 +1,529 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from dataclasses import dataclass
3
+ from typing import Optional, Tuple, List, Union
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+
9
+ from transformers import PreTrainedModel, PretrainedConfig
10
+ from transformers import AutoConfig, AutoModelForCausalLM
11
+
12
+
13
+ from transformers.modeling_outputs import (
14
+ BaseModelOutput,
15
+ CausalLMOutput,
16
+ )
17
+
18
+
19
+ @dataclass
20
+ class BaseModelOutputWithAux(BaseModelOutput):
21
+ aux_loss: Optional[torch.Tensor] = None
22
+
23
+
24
+ def create_causal_mask(seq_len: int, device=None, dtype=torch.float32):
25
+ mask = torch.full((seq_len, seq_len), torch.finfo(dtype).min, device=device, dtype=dtype)
26
+ mask = torch.triu(mask, diagonal=1)
27
+ return mask
28
+
29
+
30
+ def create_sw_mask(seq_len: int, window_size: Optional[int], device=None, dtype=torch.float32):
31
+ if not window_size:
32
+ return None
33
+ i = torch.arange(seq_len, device=device)
34
+ j = torch.arange(seq_len, device=device)
35
+ allowed = (j[None, :] <= i[:, None]) & (j[None, :] >= i[:, None] - (window_size - 1))
36
+ mask = torch.zeros((seq_len, seq_len), device=device, dtype=dtype)
37
+ mask = mask.masked_fill(~allowed, torch.finfo(dtype).min)
38
+ return mask
39
+
40
+
41
+ class Linear(nn.Module):
42
+ def __init__(self, in_dim: int, out_dim: int, b: bool = True):
43
+ super().__init__()
44
+ self.linear = nn.Linear(in_dim, out_dim, bias=b)
45
+
46
+ def forward(self, x: torch.Tensor):
47
+ return self.linear(x)
48
+
49
+
50
+ class Layer_norm(nn.Module):
51
+ def __init__(self, dim: int, eps: float = 1e-5, b: bool = True):
52
+ super().__init__()
53
+ self.layer_norm = nn.LayerNorm(dim, eps=eps, elementwise_affine=b)
54
+
55
+ def forward(self, x: torch.Tensor):
56
+ return self.layer_norm(x)
57
+
58
+
59
+ class MLP(nn.Module):
60
+ def __init__(self, in_dim: int, hidden_dim: int, dim_out: Optional[int] = None, b: bool = True):
61
+ super().__init__()
62
+ self.linear1 = nn.Linear(in_dim, hidden_dim, bias=b)
63
+ out_dim = in_dim if dim_out is None else dim_out
64
+ self.linear2 = nn.Linear(hidden_dim, out_dim, bias=b)
65
+
66
+ @staticmethod
67
+ def gelu_new(x: torch.Tensor):
68
+ return 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * x ** 3)))
69
+
70
+ def forward(self, x: torch.Tensor):
71
+ x = self.linear1(x)
72
+ x = self.gelu_new(x)
73
+ x = self.linear2(x)
74
+ return x
75
+
76
+
77
+ class SelfAttention(nn.Module):
78
+ def __init__(self, dim: int, n_heads: int, attn_dropout: float = 0.1):
79
+ super().__init__()
80
+ assert dim % n_heads == 0, "dim must be divisible by n_heads"
81
+ self.dim = dim
82
+ self.n_heads = n_heads
83
+ self.head_dim = dim // n_heads
84
+ self.Q = nn.Linear(dim, dim, bias=True)
85
+ self.K = nn.Linear(dim, dim, bias=True)
86
+ self.V = nn.Linear(dim, dim, bias=True)
87
+ self.O = nn.Linear(dim, dim, bias=True)
88
+ self.attn_dropout = nn.Dropout(attn_dropout)
89
+
90
+ def forward(self, x: torch.Tensor, *, causal_mask: Optional[torch.Tensor] = None, key_padding_mask: Optional[torch.Tensor] = None):
91
+ # x: [B,S,D]
92
+ B, S, D = x.shape
93
+ H = self.n_heads
94
+ Dh = self.head_dim
95
+
96
+ q = self.Q(x).view(B, S, H, Dh).transpose(1, 2) # [B,H,S,Dh]
97
+ k = self.K(x).view(B, S, H, Dh).transpose(1, 2)
98
+ v = self.V(x).view(B, S, H, Dh).transpose(1, 2)
99
+
100
+ attn = (q @ k.transpose(-2, -1)) / math.sqrt(Dh) # [B,H,S,S]
101
+ neg_inf = torch.finfo(attn.dtype).min
102
+
103
+ if causal_mask is not None:
104
+ attn = attn + causal_mask[None, None, :, :]
105
+
106
+ if key_padding_mask is not None: # True at PAD keys
107
+ attn = attn.masked_fill(key_padding_mask[:, None, None, :], neg_inf)
108
+
109
+ attn = F.softmax(attn, dim=-1)
110
+ attn = self.attn_dropout(attn)
111
+ out = (attn @ v).transpose(1, 2).contiguous().view(B, S, D)
112
+
113
+ if key_padding_mask is not None:
114
+ query_mask = (~key_padding_mask).to(out.dtype).unsqueeze(-1) # [B,S,1]
115
+ out = out * query_mask
116
+
117
+ return self.O(out)
118
+
119
+
120
+ class Layer_Block(nn.Module):
121
+ def __init__(self, dim: int, n_heads: int, ffn_multp: int, dropout: float = 0.1, attn_dropout: float = 0.1):
122
+ super().__init__()
123
+ self.norm_1 = Layer_norm(dim)
124
+ self.norm_2 = Layer_norm(dim)
125
+ self.attention = SelfAttention(dim, n_heads, attn_dropout)
126
+ self.feedforward = MLP(dim, dim * ffn_multp)
127
+ self.dropout1 = nn.Dropout(dropout)
128
+ self.dropout2 = nn.Dropout(dropout)
129
+
130
+ def forward(self, x: torch.Tensor, *, causal_mask=None, key_padding_mask=None):
131
+ residual = x
132
+ x = self.norm_1(x)
133
+ x = self.attention(x, causal_mask=causal_mask, key_padding_mask=key_padding_mask)
134
+ x = self.dropout1(x)
135
+ x = residual + x
136
+
137
+ residual = x
138
+ x = self.norm_2(x)
139
+ x = self.feedforward(x)
140
+ x = self.dropout2(x)
141
+ x = residual + x
142
+ return x
143
+
144
+
145
+ class Top_k_Router(nn.Module):
146
+ def __init__(self, dim: int, n_experts: int, k: int):
147
+ super().__init__()
148
+ self.n_experts = n_experts
149
+ self.k = k
150
+ self.router = Linear(dim, n_experts)
151
+
152
+ def forward(self, x: torch.Tensor):
153
+ # x: [T, D]
154
+ logits = self.router(x)
155
+ probs = F.softmax(logits, dim=-1)
156
+ topk_prob, topk_idx = torch.topk(probs, k=self.k, dim=-1)
157
+ topk_prob = topk_prob / (topk_prob.sum(dim=-1, keepdim=True) + 1e-9)
158
+
159
+ p_mean = probs.mean(dim=0)
160
+ T, E = probs.size()
161
+ one_hot = F.one_hot(topk_idx, num_classes=E).sum(dim=1)
162
+ f_mean = one_hot.float().mean(dim=0) / float(self.k)
163
+ aux_loss = (E * (p_mean * f_mean).sum())
164
+
165
+ return topk_idx, topk_prob, aux_loss
166
+
167
+
168
+ class MoE_Block(nn.Module):
169
+ def __init__(self, dim_in: int, n_experts: int, k: int, dim_hidden: int, dim_out: Optional[int] = None):
170
+ super().__init__()
171
+ self.n_experts = n_experts
172
+ self.k = k
173
+ self.dim_out = dim_in if dim_out is None else dim_out
174
+ self.router = Top_k_Router(dim_in, n_experts, k)
175
+ self.experts = nn.ModuleList([nn.Linear(dim_in, self.dim_out, bias=True) for _ in range(n_experts)])
176
+
177
+ def forward(self, x: torch.Tensor):
178
+ # x: [B,S,D]
179
+ B, S, D = x.shape
180
+ T = B * S
181
+ x_flat = x.view(T, D)
182
+
183
+ topk_idx, topk_prob, aux_loss = self.router(x_flat) # [T,k], [T,k]
184
+ y_flat = x_flat.new_zeros((T, self.dim_out))
185
+
186
+ for slot in range(self.k):
187
+ e_ids = topk_idx[:, slot]
188
+ e_prob = topk_prob[:, slot].unsqueeze(-1) # [T,1]
189
+ for e in range(self.n_experts):
190
+ idx = (e_ids == e).nonzero(as_tuple=False).squeeze(1)
191
+ if idx.numel() == 0:
192
+ continue
193
+ y_e = self.experts[e](x_flat.index_select(0, idx)) # [Ne, dim_out]
194
+ y_flat.index_add_(0, idx, y_e * e_prob.index_select(0, idx))
195
+
196
+ return y_flat.view(B, S, self.dim_out), aux_loss
197
+
198
+
199
+ class ParallelLayer(nn.Module):
200
+ def __init__(self, dim: int, n_heads: int, n_blocks: int, k: int, ffn_multp: int, dropout: float = 0.1, attn_dropout: float = 0.1):
201
+ super().__init__()
202
+ self.dim = dim
203
+ self.n_blocks = n_blocks
204
+ self.blocks = nn.ModuleList([Layer_Block(dim, n_heads, ffn_multp, dropout, attn_dropout) for _ in range(n_blocks)])
205
+ self.router = Top_k_Router(dim, n_blocks, k)
206
+
207
+ def forward(self, x: torch.Tensor, *, causal_mask=None, key_padding_mask=None):
208
+ B, S, D = x.shape
209
+ T = B * S
210
+ outs = [blk(x, causal_mask=causal_mask, key_padding_mask=key_padding_mask) for blk in self.blocks]
211
+
212
+ Y = torch.stack([y.view(T, D) for y in outs], dim=1) # [T, n_blocks, D]
213
+
214
+ x_flat = x.view(T, D)
215
+ topk_idx, topk_prob, aux_loss = self.router(x_flat) # [T,k], [T,k]
216
+
217
+ gather_idx = topk_idx.unsqueeze(-1).expand(-1, -1, D) # [T,k,D]
218
+ Y_topk = torch.gather(Y, dim=1, index=gather_idx) # [T,k,D]
219
+ y_flat = (Y_topk * topk_prob.unsqueeze(-1)).sum(dim=1) # [T,D]
220
+
221
+ return y_flat.view(B, S, D), aux_loss
222
+
223
+
224
+ class MoEPLMConfig(PretrainedConfig):
225
+ model_type = "moep_lm"
226
+
227
+ def __init__(
228
+ self,
229
+ vocab_size: int = 16384,
230
+ bos_token_id = 1,
231
+ eos_token_id = 2,
232
+ pad_token_id = 3,
233
+ mask_token_id = 4,
234
+ max_position_embeddings: int = 1024,
235
+ n_layers: int = 12,
236
+ ffn_multp: int = 4,
237
+ dim: int = 348,
238
+ n_heads: int = 6,
239
+ # Parallel specifics
240
+ n_parallel_blocks: int = 4,
241
+ parallel_dim: int = 192,
242
+ parallel_n_heads: int = 3,
243
+ parallel_k: int = 2,
244
+ sliding_window: Optional[int] = None,
245
+ # MoE specifics
246
+ n_experts: int = 4,
247
+ moe_k: int = 2,
248
+ # Dropouts / norms
249
+ attn_pdrop: float = 0.1,
250
+ embd_pdrop: float = 0.1,
251
+ resid_pdrop: float = 0.1,
252
+ layer_norm_epsilon: float = 1e-5,
253
+ tie_word_embeddings: bool = True,
254
+ **kwargs,
255
+ ):
256
+ super().__init__(
257
+ vocab_size=vocab_size,
258
+ pad_token_id=pad_token_id,
259
+ bos_token_id=bos_token_id,
260
+ eos_token_id=eos_token_id,
261
+ **kwargs,
262
+ )
263
+
264
+ # Special tokens
265
+ self.mask_token_id = mask_token_id
266
+
267
+ # Core dims
268
+ self.vocab_size = vocab_size
269
+ self.max_position_embeddings = max_position_embeddings
270
+ self.n_layers = n_layers
271
+ self.ffn_multp = ffn_multp
272
+ self.dim = dim
273
+ self.n_heads = n_heads
274
+
275
+ # Parallel specifics
276
+ self.n_parallel_blocks = n_parallel_blocks
277
+ self.parallel_dim = parallel_dim
278
+ self.parallel_n_heads = parallel_n_heads
279
+ self.parallel_k = parallel_k
280
+ self.sliding_window = sliding_window
281
+
282
+ # MoE specifics
283
+ self.n_experts = n_experts
284
+ self.moe_k = moe_k
285
+
286
+ # Dropouts / norms
287
+ self.attn_pdrop = attn_pdrop
288
+ self.embd_pdrop = embd_pdrop
289
+ self.resid_pdrop = resid_pdrop
290
+ self.layer_norm_epsilon = layer_norm_epsilon
291
+
292
+ # Tying
293
+ self.tie_word_embeddings = tie_word_embeddings
294
+
295
+ class MoEPModel(PreTrainedModel):
296
+ config_class = MoEPLMConfig
297
+
298
+ def __init__(self, config: MoEPLMConfig):
299
+ super().__init__(config)
300
+ self.config = config
301
+
302
+ # --- embeddings ---
303
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.dim, padding_idx=config.pad_token_id)
304
+ self.embed_positions = nn.Embedding(config.max_position_embeddings, config.dim)
305
+ self.embd_dropout = nn.Dropout(config.embd_pdrop)
306
+
307
+
308
+ self.layers = nn.ModuleList()
309
+
310
+ # Large Layer
311
+ self.layers.append(Layer_Block(config.dim,
312
+ config.n_heads,
313
+ config.ffn_multp,
314
+ dropout=config.resid_pdrop,
315
+ attn_dropout=config.attn_pdrop))
316
+
317
+ # MoE Linear
318
+ self.layers.append(MoE_Block(config.dim,
319
+ config.n_experts,
320
+ config.moe_k,
321
+ dim_hidden=config.dim * 2,
322
+ dim_out=config.parallel_dim))
323
+
324
+ # Parallel Layers
325
+ for _ in range(config.n_layers - 2):
326
+ self.layers.append(ParallelLayer(config.parallel_dim,
327
+ config.parallel_n_heads,
328
+ config.n_parallel_blocks,
329
+ config.parallel_k,
330
+ config.ffn_multp,
331
+ dropout=config.resid_pdrop,
332
+ attn_dropout=config.attn_pdrop))
333
+
334
+ # MoE Linear
335
+ self.layers.append(MoE_Block(config.parallel_dim,
336
+ config.n_experts,
337
+ config.moe_k,
338
+ dim_hidden=config.parallel_dim * config.ffn_multp,
339
+ dim_out=config.dim))
340
+
341
+ # Large Layer
342
+ self.layers.append(Layer_Block(config.dim,
343
+ config.n_heads,
344
+ config.ffn_multp,
345
+ dropout=config.resid_pdrop,
346
+ attn_dropout=config.attn_pdrop))
347
+
348
+ self.norm = Layer_norm(config.dim)
349
+ self.post_init()
350
+
351
+ def get_input_embeddings(self):
352
+ return self.embed_tokens
353
+
354
+ def set_input_embeddings(self, new_embeddings):
355
+ self.embed_tokens = new_embeddings
356
+
357
+ def _init_weights(self, module):
358
+ if isinstance(module, (nn.Linear, nn.Embedding)):
359
+ nn.init.normal_(module.weight, mean=0.0, std=0.02)
360
+ if isinstance(module, nn.Linear) and module.bias is not None:
361
+ nn.init.zeros_(module.bias)
362
+
363
+ def forward(
364
+ self,
365
+ input_ids: torch.LongTensor,
366
+ attention_mask: Optional[torch.Tensor] = None,
367
+ return_dict: bool = True,
368
+ return_aux: Optional[bool] = False,
369
+ return_aux_dict: Optional[bool] = False,
370
+ **unused,
371
+ ) -> Union[BaseModelOutputWithAux, BaseModelOutput, Tuple]:
372
+
373
+ device = input_ids.device
374
+ B, S = input_ids.shape
375
+
376
+ key_padding = input_ids.eq(self.config.pad_token_id) if attention_mask is None else (attention_mask == 0)
377
+
378
+ # embeddings
379
+ x = self.embed_tokens(input_ids)
380
+
381
+ mask_dtype = x.dtype
382
+ causal = create_causal_mask(S, device=device, dtype=mask_dtype)
383
+ sw = create_sw_mask(S, self.config.sliding_window, device=device, dtype=mask_dtype)
384
+ sw_mask = causal if sw is None else torch.minimum(causal, sw)
385
+
386
+
387
+ pos = torch.arange(S, device=device)
388
+ pos = pos.unsqueeze(0).expand(B, S)
389
+ x = x + self.embed_positions(pos)
390
+ x = self.embd_dropout(x)
391
+
392
+ aux_total = None
393
+
394
+
395
+ # First large
396
+ x = self.layers[0](x, causal_mask=causal, key_padding_mask=key_padding)
397
+
398
+ # MoE shrink
399
+ x, aux = self.layers[1](x)
400
+
401
+ if aux is not None:
402
+ aux_total = aux
403
+
404
+ idx = 2
405
+ for i in range(self.config.n_layers - 2):
406
+ use_sw = (self.config.sliding_window is not None) and (i % 2 == 1)
407
+ mask = sw_mask if use_sw else causal
408
+ x, aux = self.layers[idx](x, causal_mask=mask, key_padding_mask=key_padding)
409
+ if aux is not None:
410
+ aux_total += aux
411
+ idx += 1
412
+
413
+ # MoE grow
414
+ x, aux = self.layers[idx](x)
415
+
416
+ if aux is not None:
417
+ aux_total += aux
418
+
419
+ idx += 1
420
+
421
+ # Second large
422
+ x = self.layers[idx](x, causal_mask=causal, key_padding_mask=key_padding)
423
+
424
+ last_hidden = self.norm(x)
425
+
426
+ if not return_dict:
427
+ return (last_hidden, aux_total) if return_aux else (last_hidden,)
428
+
429
+ if return_aux_dict:
430
+ return BaseModelOutputWithAux(
431
+ last_hidden_state=last_hidden,
432
+ hidden_states=None,
433
+ attentions=None,
434
+ aux_loss=aux_total,
435
+ )
436
+ else:
437
+ return BaseModelOutput(
438
+ last_hidden_state=last_hidden,
439
+ hidden_states=None,
440
+ attentions=None,
441
+ )
442
+
443
+
444
+ class MoEPForCausalLM(PreTrainedModel):
445
+ config_class = MoEPLMConfig
446
+
447
+ def __init__(self, config: MoEPLMConfig):
448
+ super().__init__(config)
449
+ self.config = config
450
+ self.model = MoEPModel(config)
451
+ self.lm_head = nn.Linear(config.dim, config.vocab_size, bias=False)
452
+ if config.tie_word_embeddings:
453
+ self.lm_head.weight = self.model.embed_tokens.weight
454
+ self.post_init()
455
+
456
+ def get_input_embeddings(self):
457
+ return self.model.get_input_embeddings()
458
+
459
+ def set_input_embeddings(self, new_embeddings):
460
+ self.model.set_input_embeddings(new_embeddings)
461
+ if self.config.tie_word_embeddings:
462
+ self.lm_head.weight = self.model.embed_tokens.weight
463
+
464
+ def _init_weights(self, module):
465
+ if isinstance(module, (nn.Linear, nn.Embedding)):
466
+ nn.init.normal_(module.weight, mean=0.0, std=0.02)
467
+ if isinstance(module, nn.Linear) and module.bias is not None:
468
+ nn.init.zeros_(module.bias)
469
+
470
+ def forward(
471
+ self,
472
+ input_ids: torch.LongTensor,
473
+ attention_mask: Optional[torch.Tensor] = None,
474
+ labels: Optional[torch.LongTensor] = None,
475
+ return_dict: bool = True,
476
+ return_aux: Optional[bool] = False,
477
+ aux_loss_weight: Optional[float] = 0.2,
478
+ **unused,
479
+ ) -> Union[CausalLMOutput, Tuple]:
480
+
481
+
482
+ if return_aux:
483
+ base_out = self.model(input_ids=input_ids,
484
+ attention_mask=attention_mask,
485
+ return_aux_dict=True,
486
+ return_aux=True)
487
+ else:
488
+ base_out = self.model(input_ids=input_ids,
489
+ attention_mask=attention_mask)
490
+
491
+ logits = self.lm_head(base_out.last_hidden_state).float()
492
+
493
+ loss = None
494
+
495
+ if labels is not None:
496
+
497
+ shift_logits = logits[:, :-1, :].contiguous()
498
+ shift_labels = labels[:, 1:].contiguous()
499
+
500
+ pad_id = self.config.pad_token_id
501
+ if pad_id is not None:
502
+ shift_labels = shift_labels.masked_fill(shift_labels == pad_id, -100)
503
+
504
+ loss = F.cross_entropy(
505
+ shift_logits.view(-1, shift_logits.size(-1)),
506
+ shift_labels.view(-1),
507
+ ignore_index=-100,
508
+ )
509
+
510
+
511
+ aux = getattr(base_out, "aux_loss", None)
512
+ if aux is not None:
513
+ loss = loss + aux_loss_weight * aux
514
+
515
+ if not return_dict:
516
+ return (loss, logits) if loss is not None else (logits,)
517
+
518
+ return CausalLMOutput(
519
+ loss=loss,
520
+ logits=logits,
521
+ hidden_states=base_out.hidden_states,
522
+ attentions=base_out.attentions,
523
+ )
524
+
525
+ AutoConfig.register("moep_lm", MoEPLMConfig)
526
+ AutoModelForCausalLM.register(MoEPLMConfig, MoEPForCausalLM)
527
+
528
+
529
+