Johnblick187 commited on
Commit
f46564f
·
verified ·
1 Parent(s): 63a6988

Update modeling_smartcoder_moe.py

Browse files
Files changed (1) hide show
  1. modeling_smartcoder_moe.py +52 -92
modeling_smartcoder_moe.py CHANGED
@@ -1,4 +1,4 @@
1
- """
2
  modeling_smartcoder_moe.py
3
  Custom model class for SmartCoderMoE.
4
 
@@ -13,18 +13,7 @@ Architecture (from tensor inspection):
13
  router: [32, 2048] router logits
14
  - LayerNorm: weight+bias (input_layernorm, post_attention_layernorm)
15
  - Final norm: model.norm.weight/bias
16
-
17
- NOTE ON THE EXPERT KEYS:
18
- The checkpoint stores the batched expert tensors as `experts_fc.weight` /
19
- `experts_proj.weight` (i.e. they were saved as a module holding a `.weight`
20
- Parameter). The previous version of this file declared them as bare
21
- `nn.Parameter` (`experts_fc`, no `.weight`) and tried to paper over the mismatch
22
- with a `_load_from_state_dict` remap hook — which does NOT fire correctly under
23
- `from_pretrained`, producing UNEXPECTED `experts_fc.weight` / MISSING
24
- `experts_fc`. The fix here is structural: wrap each batched expert tensor in a
25
- tiny `ExpertWeight` module so its natural state_dict key is `experts_fc.weight`,
26
- matching the checkpoint exactly. No load hook required.
27
- """
28
 
29
  import math
30
  import torch
@@ -82,23 +71,18 @@ class SmartCoderMoEConfig(PretrainedConfig):
82
 
83
  # ── RoPE ──────────────────────────────────────────────────────────────────────
84
  def rotate_half(x):
85
- x1, x2 = x[..., : x.shape[-1] // 2], x[..., x.shape[-1] // 2:]
86
  return torch.cat([-x2, x1], dim=-1)
87
 
88
-
89
  def apply_rotary_emb(q, k, cos, sin):
90
  return (q * cos) + (rotate_half(q) * sin), \
91
  (k * cos) + (rotate_half(k) * sin)
92
 
93
-
94
  class RotaryEmbedding(nn.Module):
95
  def __init__(self, dim, max_pos=16384, base=10000.0):
96
  super().__init__()
97
  inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
98
- # persistent=False: inv_freq is a computed constant, NOT a trained weight.
99
- # The checkpoint correctly omits it; marking it non-persistent means it is
100
- # not expected in the state_dict, killing the spurious MISSING warning.
101
- self.register_buffer("inv_freq", inv_freq, persistent=False)
102
  self._cached_len = 0
103
 
104
  def _build_cache(self, seq_len, device):
@@ -121,32 +105,20 @@ class LayerNormWithBias(nn.Module):
121
  def __init__(self, hidden_size, eps=1e-5):
122
  super().__init__()
123
  self.weight = nn.Parameter(torch.ones(hidden_size))
124
- self.bias = nn.Parameter(torch.zeros(hidden_size))
125
  self.eps = eps
126
 
127
  def forward(self, x):
128
  return F.layer_norm(x, x.shape[-1:], self.weight, self.bias, self.eps)
129
 
130
 
131
- # ── Expert weight holder ──────────────────────────────────────────────────────
132
- class ExpertWeight(nn.Module):
133
- """
134
- Thin wrapper so a batched expert tensor registers under the key
135
- `<name>.weight`, matching how the checkpoint saved it. The forward indexes
136
- `.weight` directly; this module exists purely to produce the right key.
137
- """
138
- def __init__(self, *shape):
139
- super().__init__()
140
- self.weight = nn.Parameter(torch.empty(*shape))
141
-
142
-
143
  # ── Attention ─────────────────────────────────────────────────────────────────
144
  class SmartCoderAttention(nn.Module):
145
  def __init__(self, config: SmartCoderMoEConfig):
146
  super().__init__()
147
- self.num_heads = config.num_attention_heads
148
  self.num_kv_heads = config.num_key_value_heads
149
- self.head_dim = config.head_dim
150
  self.num_kv_groups = self.num_heads // self.num_kv_heads
151
 
152
  self.q_proj = nn.Linear(config.hidden_size, config.num_attention_heads * config.head_dim, bias=True)
@@ -163,17 +135,15 @@ class SmartCoderAttention(nn.Module):
163
  v = self.v_proj(hidden_states).view(B, T, self.num_kv_heads, self.head_dim).transpose(1, 2)
164
 
165
  cos, sin = self.rotary_emb(T, hidden_states.device)
166
- cos = cos[:, :, :T, : self.head_dim]
167
- sin = sin[:, :, :T, : self.head_dim]
168
  q, k = apply_rotary_emb(q, k, cos, sin)
169
 
170
  k = k.repeat_interleave(self.num_kv_groups, dim=1)
171
  v = v.repeat_interleave(self.num_kv_groups, dim=1)
172
 
173
  attn = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.head_dim)
174
- causal = torch.triu(
175
- torch.full((T, T), float("-inf"), device=q.device, dtype=q.dtype), diagonal=1
176
- )
177
  attn = attn + causal.unsqueeze(0).unsqueeze(0)
178
  if attention_mask is not None:
179
  attn = attn + attention_mask
@@ -186,27 +156,26 @@ class SmartCoderAttention(nn.Module):
186
  class SmartCoderMoEMLP(nn.Module):
187
  def __init__(self, config: SmartCoderMoEConfig):
188
  super().__init__()
189
- H = config.hidden_size
190
  DI = config.dense_intermediate_size
191
  NE = config.num_experts
192
  EI = config.expert_intermediate_size
193
 
194
  self.num_experts = NE
195
- self.top_k = config.num_experts_per_tok
196
 
197
- self.dense_fc = nn.Linear(H, DI, bias=True)
198
- self.dense_proj = nn.Linear(DI, H, bias=True)
199
- # Wrapped so keys are experts_fc.weight / experts_proj.weight (matches ckpt)
200
- self.experts_fc = ExpertWeight(NE, EI, H)
201
- self.experts_proj = ExpertWeight(NE, H, EI)
202
- self.router = nn.Linear(H, NE, bias=False)
203
 
204
  def forward(self, x):
205
  B, T, H = x.shape
206
 
207
  dense_out = self.dense_proj(F.gelu(self.dense_fc(x)))
208
 
209
- router_logits = self.router(x)
210
  router_weights = F.softmax(router_logits, dim=-1)
211
  top_weights, top_indices = router_weights.topk(self.top_k, dim=-1)
212
  top_weights = top_weights / top_weights.sum(dim=-1, keepdim=True)
@@ -214,16 +183,13 @@ class SmartCoderMoEMLP(nn.Module):
214
  expert_out = torch.zeros_like(x)
215
  x_flat = x.view(B * T, H)
216
 
217
- fc_all = self.experts_fc.weight # [NE, EI, H]
218
- proj_all = self.experts_proj.weight # [NE, H, EI]
219
-
220
  for k in range(self.top_k):
221
  expert_ids = top_indices[:, :, k].reshape(B * T)
222
- weights = top_weights[:, :, k].reshape(B * T, 1)
223
- fc_w = fc_all[expert_ids] # [BT, EI, H]
224
- proj_w = proj_all[expert_ids] # [BT, H, EI]
225
  hidden = F.gelu(torch.bmm(fc_w, x_flat.unsqueeze(-1)).squeeze(-1))
226
- out = torch.bmm(proj_w, hidden.unsqueeze(-1)).squeeze(-1)
227
  expert_out = expert_out + (out * weights).view(B, T, H)
228
 
229
  return dense_out + expert_out
@@ -233,10 +199,10 @@ class SmartCoderMoEMLP(nn.Module):
233
  class SmartCoderDecoderLayer(nn.Module):
234
  def __init__(self, config: SmartCoderMoEConfig):
235
  super().__init__()
236
- self.input_layernorm = LayerNormWithBias(config.hidden_size, config.rms_norm_eps)
237
- self.self_attn = SmartCoderAttention(config)
238
  self.post_attention_layernorm = LayerNormWithBias(config.hidden_size, config.rms_norm_eps)
239
- self.mlp = SmartCoderMoEMLP(config)
240
 
241
  def forward(self, hidden_states, attention_mask=None, **kwargs):
242
  residual = hidden_states
@@ -257,10 +223,8 @@ class SmartCoderMoEModel(nn.Module):
257
  def __init__(self, config: SmartCoderMoEConfig):
258
  super().__init__()
259
  self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
260
- self.layers = nn.ModuleList(
261
- [SmartCoderDecoderLayer(config) for _ in range(config.num_hidden_layers)]
262
- )
263
- self.norm = LayerNormWithBias(config.hidden_size, config.rms_norm_eps)
264
 
265
  def forward(self, input_ids, attention_mask=None, **kwargs):
266
  hidden_states = self.embed_tokens(input_ids)
@@ -277,25 +241,20 @@ class SmartCoderMoEForCausalLM(PreTrainedModel, GenerationMixin):
277
 
278
  def __init__(self, config: SmartCoderMoEConfig):
279
  super().__init__(config)
280
- self.model = SmartCoderMoEModel(config)
281
  self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
282
  self.post_init()
283
 
284
- # No _load_from_state_dict / load_state_dict override needed:
285
- # the module structure now produces experts_fc.weight / experts_proj.weight
286
- # natively, matching the checkpoint, and inv_freq is non-persistent.
287
-
288
- def get_input_embeddings(self):
289
- return self.model.embed_tokens
290
-
291
- def set_input_embeddings(self, value):
292
- self.model.embed_tokens = value
293
-
294
- def get_output_embeddings(self):
295
- return self.lm_head
296
 
297
- def set_output_embeddings(self, new_embeddings):
298
- self.lm_head = new_embeddings
299
 
300
  def forward(
301
  self,
@@ -326,7 +285,7 @@ class SmartCoderMoEForCausalLM(PreTrainedModel, GenerationMixin):
326
  return {"input_ids": input_ids}
327
 
328
 
329
- # ── Loader (standalone helper) ────────────────────────────────────────────────
330
  def load_smartcoder_moe(model_id="Johnblick187/SmartCoderMoE", dtype=torch.bfloat16):
331
  import os
332
  from huggingface_hub import snapshot_download
@@ -348,26 +307,27 @@ def load_smartcoder_moe(model_id="Johnblick187/SmartCoderMoE", dtype=torch.bfloa
348
  for f in sf_files:
349
  state_dict.update(load_file(str(f)))
350
 
351
- # Keys now match natively (experts_fc.weight / experts_proj.weight) no remap.
 
 
 
 
 
 
 
 
 
 
352
  missing, unexpected = model.load_state_dict(state_dict, strict=False)
353
- # inv_freq is non-persistent so it will show as "missing"; that is expected
354
- # and harmless (recomputed at init). Filter it from the report.
355
- missing = [m for m in missing if "inv_freq" not in m]
356
  if missing:
357
- print(f"Missing (unexpected!): {missing[:5]}{'...' if len(missing) > 5 else ''}")
358
- else:
359
- print("No unexpected missing keys.")
360
  if unexpected:
361
- print(f"Unexpected: {unexpected[:5]}{'...' if len(unexpected) > 5 else ''}")
362
- else:
363
- print("No unexpected keys.")
364
 
365
  model = model.to(dtype)
366
- print(f"Loaded! Params: {sum(p.numel() for p in model.parameters()) / 1e9:.2f}B")
367
  return model, config
368
 
369
-
370
  from transformers import AutoConfig, AutoModelForCausalLM
371
-
372
  AutoConfig.register("smartcoder_moe", SmartCoderMoEConfig)
373
  AutoModelForCausalLM.register(SmartCoderMoEConfig, SmartCoderMoEForCausalLM)
 
1
+ ""
2
  modeling_smartcoder_moe.py
3
  Custom model class for SmartCoderMoE.
4
 
 
13
  router: [32, 2048] router logits
14
  - LayerNorm: weight+bias (input_layernorm, post_attention_layernorm)
15
  - Final norm: model.norm.weight/bias
16
+ ""
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  import math
19
  import torch
 
71
 
72
  # ── RoPE ──────────────────────────────────────────────────────────────────────
73
  def rotate_half(x):
74
+ x1, x2 = x[..., :x.shape[-1]//2], x[..., x.shape[-1]//2:]
75
  return torch.cat([-x2, x1], dim=-1)
76
 
 
77
  def apply_rotary_emb(q, k, cos, sin):
78
  return (q * cos) + (rotate_half(q) * sin), \
79
  (k * cos) + (rotate_half(k) * sin)
80
 
 
81
  class RotaryEmbedding(nn.Module):
82
  def __init__(self, dim, max_pos=16384, base=10000.0):
83
  super().__init__()
84
  inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
85
+ self.register_buffer("inv_freq", inv_freq)
 
 
 
86
  self._cached_len = 0
87
 
88
  def _build_cache(self, seq_len, device):
 
105
  def __init__(self, hidden_size, eps=1e-5):
106
  super().__init__()
107
  self.weight = nn.Parameter(torch.ones(hidden_size))
108
+ self.bias = nn.Parameter(torch.zeros(hidden_size))
109
  self.eps = eps
110
 
111
  def forward(self, x):
112
  return F.layer_norm(x, x.shape[-1:], self.weight, self.bias, self.eps)
113
 
114
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  # ── Attention ─────────────────────────────────────────────────────────────────
116
  class SmartCoderAttention(nn.Module):
117
  def __init__(self, config: SmartCoderMoEConfig):
118
  super().__init__()
119
+ self.num_heads = config.num_attention_heads
120
  self.num_kv_heads = config.num_key_value_heads
121
+ self.head_dim = config.head_dim
122
  self.num_kv_groups = self.num_heads // self.num_kv_heads
123
 
124
  self.q_proj = nn.Linear(config.hidden_size, config.num_attention_heads * config.head_dim, bias=True)
 
135
  v = self.v_proj(hidden_states).view(B, T, self.num_kv_heads, self.head_dim).transpose(1, 2)
136
 
137
  cos, sin = self.rotary_emb(T, hidden_states.device)
138
+ cos = cos[:, :, :T, :self.head_dim]
139
+ sin = sin[:, :, :T, :self.head_dim]
140
  q, k = apply_rotary_emb(q, k, cos, sin)
141
 
142
  k = k.repeat_interleave(self.num_kv_groups, dim=1)
143
  v = v.repeat_interleave(self.num_kv_groups, dim=1)
144
 
145
  attn = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.head_dim)
146
+ causal = torch.triu(torch.full((T, T), float("-inf"), device=q.device, dtype=q.dtype), diagonal=1)
 
 
147
  attn = attn + causal.unsqueeze(0).unsqueeze(0)
148
  if attention_mask is not None:
149
  attn = attn + attention_mask
 
156
  class SmartCoderMoEMLP(nn.Module):
157
  def __init__(self, config: SmartCoderMoEConfig):
158
  super().__init__()
159
+ H = config.hidden_size
160
  DI = config.dense_intermediate_size
161
  NE = config.num_experts
162
  EI = config.expert_intermediate_size
163
 
164
  self.num_experts = NE
165
+ self.top_k = config.num_experts_per_tok
166
 
167
+ self.dense_fc = nn.Linear(H, DI, bias=True)
168
+ self.dense_proj = nn.Linear(DI, H, bias=True)
169
+ self.experts_fc = nn.Parameter(torch.empty(NE, EI, H))
170
+ self.experts_proj = nn.Parameter(torch.empty(NE, H, EI))
171
+ self.router = nn.Linear(H, NE, bias=False)
 
172
 
173
  def forward(self, x):
174
  B, T, H = x.shape
175
 
176
  dense_out = self.dense_proj(F.gelu(self.dense_fc(x)))
177
 
178
+ router_logits = self.router(x)
179
  router_weights = F.softmax(router_logits, dim=-1)
180
  top_weights, top_indices = router_weights.topk(self.top_k, dim=-1)
181
  top_weights = top_weights / top_weights.sum(dim=-1, keepdim=True)
 
183
  expert_out = torch.zeros_like(x)
184
  x_flat = x.view(B * T, H)
185
 
 
 
 
186
  for k in range(self.top_k):
187
  expert_ids = top_indices[:, :, k].reshape(B * T)
188
+ weights = top_weights[:, :, k].reshape(B * T, 1)
189
+ fc_w = self.experts_fc[expert_ids]
190
+ proj_w = self.experts_proj[expert_ids]
191
  hidden = F.gelu(torch.bmm(fc_w, x_flat.unsqueeze(-1)).squeeze(-1))
192
+ out = torch.bmm(proj_w, hidden.unsqueeze(-1)).squeeze(-1)
193
  expert_out = expert_out + (out * weights).view(B, T, H)
194
 
195
  return dense_out + expert_out
 
199
  class SmartCoderDecoderLayer(nn.Module):
200
  def __init__(self, config: SmartCoderMoEConfig):
201
  super().__init__()
202
+ self.input_layernorm = LayerNormWithBias(config.hidden_size, config.rms_norm_eps)
203
+ self.self_attn = SmartCoderAttention(config)
204
  self.post_attention_layernorm = LayerNormWithBias(config.hidden_size, config.rms_norm_eps)
205
+ self.mlp = SmartCoderMoEMLP(config)
206
 
207
  def forward(self, hidden_states, attention_mask=None, **kwargs):
208
  residual = hidden_states
 
223
  def __init__(self, config: SmartCoderMoEConfig):
224
  super().__init__()
225
  self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
226
+ self.layers = nn.ModuleList([SmartCoderDecoderLayer(config) for _ in range(config.num_hidden_layers)])
227
+ self.norm = LayerNormWithBias(config.hidden_size, config.rms_norm_eps)
 
 
228
 
229
  def forward(self, input_ids, attention_mask=None, **kwargs):
230
  hidden_states = self.embed_tokens(input_ids)
 
241
 
242
  def __init__(self, config: SmartCoderMoEConfig):
243
  super().__init__(config)
244
+ self.model = SmartCoderMoEModel(config)
245
  self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
246
  self.post_init()
247
 
248
+ def _load_from_state_dict(self, state_dict, prefix, *args, **kwargs):
249
+ remapped = {}
250
+ for k, v in state_dict.items():
251
+ k = k.replace('experts_fc.weight', 'experts_fc')
252
+ k = k.replace('experts_proj.weight', 'experts_proj')
253
+ remapped[k] = v
254
+ super()._load_from_state_dict(remapped, prefix, *args, **kwargs)
 
 
 
 
 
255
 
256
+ def get_input_embeddings(self): return self.model.embed_tokens
257
+ def get_output_embeddings(self): return self.lm_head
258
 
259
  def forward(
260
  self,
 
285
  return {"input_ids": input_ids}
286
 
287
 
288
+ # ── Loader ────────────────────────────────────────────────────────────────────
289
  def load_smartcoder_moe(model_id="Johnblick187/SmartCoderMoE", dtype=torch.bfloat16):
290
  import os
291
  from huggingface_hub import snapshot_download
 
307
  for f in sf_files:
308
  state_dict.update(load_file(str(f)))
309
 
310
+ # Remap expert keys safetensors has .weight suffix, our params don't
311
+ remapped = {}
312
+ for k, v in state_dict.items():
313
+ if 'experts_fc.weight' in k:
314
+ remapped[k.replace('experts_fc.weight', 'experts_fc')] = v
315
+ elif 'experts_proj.weight' in k:
316
+ remapped[k.replace('experts_proj.weight', 'experts_proj')] = v
317
+ else:
318
+ remapped[k] = v
319
+ state_dict = remapped
320
+
321
  missing, unexpected = model.load_state_dict(state_dict, strict=False)
 
 
 
322
  if missing:
323
+ print(f"Missing: {missing[:3]}{'...' if len(missing)>3 else ''}")
 
 
324
  if unexpected:
325
+ print(f"Unexpected: {unexpected[:3]}{'...' if len(unexpected)>3 else ''}")
 
 
326
 
327
  model = model.to(dtype)
328
+ print(f"Loaded! Params: {sum(p.numel() for p in model.parameters())/1e9:.2f}B")
329
  return model, config
330
 
 
331
  from transformers import AutoConfig, AutoModelForCausalLM
 
332
  AutoConfig.register("smartcoder_moe", SmartCoderMoEConfig)
333
  AutoModelForCausalLM.register(SmartCoderMoEConfig, SmartCoderMoEForCausalLM)