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

Update modeling_smartcoder_moe.py

Browse files
Files changed (1) hide show
  1. modeling_smartcoder_moe.py +90 -50
modeling_smartcoder_moe.py CHANGED
@@ -13,6 +13,17 @@ 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
 
18
  import math
@@ -71,18 +82,23 @@ class SmartCoderMoEConfig(PretrainedConfig):
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,20 +121,32 @@ class LayerNormWithBias(nn.Module):
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,15 +163,17 @@ class SmartCoderAttention(nn.Module):
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,26 +186,27 @@ class SmartCoderAttention(nn.Module):
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,13 +214,16 @@ class SmartCoderMoEMLP(nn.Module):
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,10 +233,10 @@ class SmartCoderMoEMLP(nn.Module):
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,8 +257,10 @@ class SmartCoderMoEModel(nn.Module):
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,20 +277,25 @@ class SmartCoderMoEForCausalLM(PreTrainedModel, GenerationMixin):
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,7 +326,7 @@ class SmartCoderMoEForCausalLM(PreTrainedModel, GenerationMixin):
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,27 +348,26 @@ def load_smartcoder_moe(model_id="Johnblick187/SmartCoderMoE", dtype=torch.bfloa
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)
 
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
 
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
  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
  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
  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
  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
  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
  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
 
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
  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
  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)