persadian commited on
Commit
0ab4683
·
verified ·
1 Parent(s): 297841c

Upload PersadianNanoV4Model.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. PersadianNanoV4Model.py +56 -74
PersadianNanoV4Model.py CHANGED
@@ -1,11 +1,10 @@
1
- # persadian_nano_v4/PersadianNanoV4Model.py
2
- # Stable GPU-ready implementation with Hugging Face compatibility
3
 
4
  import math
5
  import torch
6
  import torch.nn as nn
7
  import torch.nn.functional as F
8
- from transformers import PreTrainedModel, PretrainedConfig
9
  from transformers.modeling_outputs import CausalLMOutputWithPast
10
 
11
  # ============================================================
@@ -14,51 +13,28 @@ from transformers.modeling_outputs import CausalLMOutputWithPast
14
 
15
  class PersadianNanoV4Config:
16
  def __init__(self):
17
- # Core architecture (MATCH CHECKPOINT)
18
  self.hidden_size = 512
19
  self.intermediate_size = 1024
20
  self.num_hidden_layers = 12
21
-
22
- # Attention
23
  self.num_attention_heads = 8
24
  self.num_key_value_heads = 4
25
-
26
- # MoE
27
  self.num_experts = 4
28
  self.num_experts_per_tok = 2
29
-
30
- # Progressive experts
31
  self.progressive_experts = True
32
  self.min_experts = 1
33
  self.max_experts = 2
34
-
35
- # Hyper connections
36
  self.use_hyper_connection = True
37
-
38
- # Compression
39
  self.use_compressed_attention = True
40
  self.compress_ratio = 4
41
-
42
- # Context
43
- self.max_position_embeddings = 2048
44
-
45
- # Tokenizer
46
  self.vocab_size = 50257
 
47
  self.bos_token_id = 50256
48
  self.eos_token_id = 50256
49
-
50
- # RoPE
51
  self.rope_theta = 10000.0
52
-
53
- # Regularization
54
  self.dropout = 0.1
55
  self.layer_norm_eps = 1e-5
56
-
57
- # Attention
58
  self.attention_dropout = 0.0
59
  self.use_flash_attention = True
60
-
61
- # Precision
62
  self.torch_dtype = "float16"
63
 
64
  # ============================================================
@@ -127,7 +103,6 @@ class CompressedSparseAttention(nn.Module):
127
 
128
  def forward(self, hidden_states, attention_mask=None, position_ids=None):
129
  batch_size, seq_len, _ = hidden_states.shape
130
-
131
  q = self.q_proj(hidden_states).view(batch_size, seq_len, self.num_heads, self.head_dim)
132
 
133
  if self.config.use_compressed_attention and seq_len > 512:
@@ -172,7 +147,6 @@ class MixtureOfExperts(nn.Module):
172
  super().__init__()
173
  self.config = config
174
  self.num_experts = config.num_experts
175
-
176
  self.experts = nn.ModuleList([
177
  nn.Sequential(
178
  nn.Linear(config.hidden_size, config.intermediate_size),
@@ -181,7 +155,6 @@ class MixtureOfExperts(nn.Module):
181
  nn.Dropout(config.dropout)
182
  ) for _ in range(config.num_experts)
183
  ])
184
-
185
  self.router = nn.Linear(config.hidden_size, config.num_experts, bias=False)
186
  self.aux_loss_coef = 0.01
187
 
@@ -211,7 +184,6 @@ class MixtureOfExperts(nn.Module):
211
 
212
  router_probs = routing_weights.mean(dim=0)
213
  aux_loss = torch.var(router_probs)
214
-
215
  return final_hidden.view(batch_size, seq_len, hidden_size), aux_loss * self.aux_loss_coef
216
 
217
  # ============================================================
@@ -226,7 +198,6 @@ class PersadianNanoV4DecoderLayer(nn.Module):
226
  self.self_attn = CompressedSparseAttention(config)
227
  self.post_attention_layernorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
228
  self.moe = MixtureOfExperts(config)
229
-
230
  if config.use_hyper_connection:
231
  self.hc_attention = AdaptiveHyperConnection(config.hidden_size)
232
  self.hc_moe = AdaptiveHyperConnection(config.hidden_size)
@@ -253,7 +224,7 @@ class PersadianNanoV4DecoderLayer(nn.Module):
253
  return hidden_states, aux_loss
254
 
255
  # ============================================================
256
- # MAIN MODEL (Original)
257
  # ============================================================
258
 
259
  class PersadianNanoV4Model(nn.Module):
@@ -301,7 +272,9 @@ class PersadianNanoV4Model(nn.Module):
301
  if top_k > 0:
302
  values, _ = torch.topk(next_token_logits, top_k)
303
  min_values = values[:, -1].unsqueeze(-1)
304
- next_token_logits = torch.where(next_token_logits < min_values, torch.full_like(next_token_logits, float("-inf")), next_token_logits)
 
 
305
  probs = F.softmax(next_token_logits, dim=-1)
306
  next_token = torch.multinomial(probs, num_samples=1)
307
  input_ids = torch.cat([input_ids, next_token], dim=1)
@@ -310,11 +283,10 @@ class PersadianNanoV4Model(nn.Module):
310
  return input_ids
311
 
312
  # ============================================================
313
- # HF CONFIG WRAPPER
314
  # ============================================================
315
 
316
  class PersadianNanoV4ConfigHF(PretrainedConfig):
317
- """HF-compatible config class"""
318
  model_type = "persadian_nano_v4"
319
 
320
  def __init__(self, **kwargs):
@@ -322,59 +294,69 @@ class PersadianNanoV4ConfigHF(PretrainedConfig):
322
  for key, value in kwargs.items():
323
  setattr(self, key, value)
324
 
325
- # ============================================================
326
- # HF MODEL WRAPPER (FIXED)
327
- # ============================================================
328
-
329
- class PersadianNanoV4ForCausalLM(PreTrainedModel):
330
- """HF-compatible model class"""
331
  config_class = PersadianNanoV4ConfigHF
332
 
333
- # Add required attributes for modern Transformers
334
- _tied_weights_keys = ["lm_head.weight"]
335
- _no_split_modules = ["PersadianNanoV4DecoderLayer"]
336
-
337
  def __init__(self, config):
338
- super().__init__(config)
339
- # Create the original config object
340
  original_config = PersadianNanoV4Config()
341
-
342
- # Copy all attributes from HF config to original config
343
  for key, value in config.__dict__.items():
344
  if hasattr(original_config, key):
345
  setattr(original_config, key, value)
346
-
347
  self.model = PersadianNanoV4Model(original_config)
348
- self.post_init()
349
 
350
- def _init_weights(self, module):
351
- """Initialize the weights"""
352
- if isinstance(module, nn.Linear):
353
- module.weight.data.normal_(mean=0.0, std=self.config.initializer_range if hasattr(self.config, 'initializer_range') else 0.02)
354
- if module.bias is not None:
355
- module.bias.data.zero_()
356
- elif isinstance(module, nn.Embedding):
357
- module.weight.data.normal_(mean=0.0, std=self.config.initializer_range if hasattr(self.config, 'initializer_range') else 0.02)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
- def forward(self, input_ids, attention_mask=None, labels=None, **kwargs):
360
  logits, aux_loss = self.model(input_ids, attention_mask)
361
-
362
  loss = None
363
  if labels is not None:
364
  shift_logits = logits[..., :-1, :].contiguous()
365
  shift_labels = labels[..., 1:].contiguous()
366
- loss = F.cross_entropy(
367
- shift_logits.view(-1, shift_logits.size(-1)),
368
- shift_labels.view(-1)
369
- )
370
-
371
- return CausalLMOutputWithPast(
372
- loss=loss,
373
- logits=logits,
374
- )
375
-
376
- def prepare_inputs_for_generation(self, input_ids, **kwargs):
377
- return {"input_ids": input_ids}
378
 
379
  def generate(self, input_ids, **kwargs):
380
  return self.model.generate(input_ids, **kwargs)
 
 
 
 
 
 
 
 
 
1
+ # Simple Hugging Face compatible wrapper without complex inheritance
 
2
 
3
  import math
4
  import torch
5
  import torch.nn as nn
6
  import torch.nn.functional as F
7
+ from transformers import PretrainedConfig
8
  from transformers.modeling_outputs import CausalLMOutputWithPast
9
 
10
  # ============================================================
 
13
 
14
  class PersadianNanoV4Config:
15
  def __init__(self):
 
16
  self.hidden_size = 512
17
  self.intermediate_size = 1024
18
  self.num_hidden_layers = 12
 
 
19
  self.num_attention_heads = 8
20
  self.num_key_value_heads = 4
 
 
21
  self.num_experts = 4
22
  self.num_experts_per_tok = 2
 
 
23
  self.progressive_experts = True
24
  self.min_experts = 1
25
  self.max_experts = 2
 
 
26
  self.use_hyper_connection = True
 
 
27
  self.use_compressed_attention = True
28
  self.compress_ratio = 4
 
 
 
 
 
29
  self.vocab_size = 50257
30
+ self.max_position_embeddings = 2048
31
  self.bos_token_id = 50256
32
  self.eos_token_id = 50256
 
 
33
  self.rope_theta = 10000.0
 
 
34
  self.dropout = 0.1
35
  self.layer_norm_eps = 1e-5
 
 
36
  self.attention_dropout = 0.0
37
  self.use_flash_attention = True
 
 
38
  self.torch_dtype = "float16"
39
 
40
  # ============================================================
 
103
 
104
  def forward(self, hidden_states, attention_mask=None, position_ids=None):
105
  batch_size, seq_len, _ = hidden_states.shape
 
106
  q = self.q_proj(hidden_states).view(batch_size, seq_len, self.num_heads, self.head_dim)
107
 
108
  if self.config.use_compressed_attention and seq_len > 512:
 
147
  super().__init__()
148
  self.config = config
149
  self.num_experts = config.num_experts
 
150
  self.experts = nn.ModuleList([
151
  nn.Sequential(
152
  nn.Linear(config.hidden_size, config.intermediate_size),
 
155
  nn.Dropout(config.dropout)
156
  ) for _ in range(config.num_experts)
157
  ])
 
158
  self.router = nn.Linear(config.hidden_size, config.num_experts, bias=False)
159
  self.aux_loss_coef = 0.01
160
 
 
184
 
185
  router_probs = routing_weights.mean(dim=0)
186
  aux_loss = torch.var(router_probs)
 
187
  return final_hidden.view(batch_size, seq_len, hidden_size), aux_loss * self.aux_loss_coef
188
 
189
  # ============================================================
 
198
  self.self_attn = CompressedSparseAttention(config)
199
  self.post_attention_layernorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
200
  self.moe = MixtureOfExperts(config)
 
201
  if config.use_hyper_connection:
202
  self.hc_attention = AdaptiveHyperConnection(config.hidden_size)
203
  self.hc_moe = AdaptiveHyperConnection(config.hidden_size)
 
224
  return hidden_states, aux_loss
225
 
226
  # ============================================================
227
+ # MAIN MODEL
228
  # ============================================================
229
 
230
  class PersadianNanoV4Model(nn.Module):
 
272
  if top_k > 0:
273
  values, _ = torch.topk(next_token_logits, top_k)
274
  min_values = values[:, -1].unsqueeze(-1)
275
+ next_token_logits = torch.where(next_token_logits < min_values,
276
+ torch.full_like(next_token_logits, float("-inf")),
277
+ next_token_logits)
278
  probs = F.softmax(next_token_logits, dim=-1)
279
  next_token = torch.multinomial(probs, num_samples=1)
280
  input_ids = torch.cat([input_ids, next_token], dim=1)
 
283
  return input_ids
284
 
285
  # ============================================================
286
+ # HF COMPATIBLE WRAPPER (SIMPLE VERSION)
287
  # ============================================================
288
 
289
  class PersadianNanoV4ConfigHF(PretrainedConfig):
 
290
  model_type = "persadian_nano_v4"
291
 
292
  def __init__(self, **kwargs):
 
294
  for key, value in kwargs.items():
295
  setattr(self, key, value)
296
 
297
+ class PersadianNanoV4ForCausalLM(nn.Module):
298
+ """Simple HF-compatible wrapper - no complex inheritance"""
 
 
 
 
299
  config_class = PersadianNanoV4ConfigHF
300
 
 
 
 
 
301
  def __init__(self, config):
302
+ super().__init__()
303
+ # Create original config
304
  original_config = PersadianNanoV4Config()
 
 
305
  for key, value in config.__dict__.items():
306
  if hasattr(original_config, key):
307
  setattr(original_config, key, value)
308
+ self.config = original_config
309
  self.model = PersadianNanoV4Model(original_config)
 
310
 
311
+ @classmethod
312
+ def from_pretrained(cls, pretrained_model_name_or_path, **kwargs):
313
+ """Load model from Hugging Face hub"""
314
+ from transformers import AutoConfig
315
+ import torch
316
+
317
+ # Load config
318
+ config = AutoConfig.from_pretrained(pretrained_model_name_or_path, trust_remote_code=True)
319
+
320
+ # Create model
321
+ model = cls(config)
322
+
323
+ # Load weights
324
+ import os
325
+ from safetensors.torch import load_file
326
+
327
+ # Try to load weights
328
+ weight_files = [
329
+ f"{pretrained_model_name_or_path}/pytorch_model.bin",
330
+ f"{pretrained_model_name_or_path}/model.safetensors"
331
+ ]
332
+
333
+ for weight_file in weight_files:
334
+ if os.path.exists(weight_file):
335
+ if weight_file.endswith('.safetensors'):
336
+ state_dict = load_file(weight_file)
337
+ else:
338
+ state_dict = torch.load(weight_file, map_location='cpu')
339
+ model.load_state_dict(state_dict, strict=False)
340
+ break
341
+
342
+ return model
343
 
344
+ def forward(self, input_ids, attention_mask=None, labels=None):
345
  logits, aux_loss = self.model(input_ids, attention_mask)
 
346
  loss = None
347
  if labels is not None:
348
  shift_logits = logits[..., :-1, :].contiguous()
349
  shift_labels = labels[..., 1:].contiguous()
350
+ loss = F.cross_entropy(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
351
+ return CausalLMOutputWithPast(loss=loss, logits=logits)
 
 
 
 
 
 
 
 
 
 
352
 
353
  def generate(self, input_ids, **kwargs):
354
  return self.model.generate(input_ids, **kwargs)
355
+
356
+ def eval(self):
357
+ self.model.eval()
358
+ return self
359
+
360
+ def to(self, device):
361
+ self.model = self.model.to(device)
362
+ return self