Hoglet-33 commited on
Commit
7233995
·
verified ·
1 Parent(s): 6cdea3e

Create modeling_pebble.py

Browse files
Files changed (1) hide show
  1. modeling_pebble.py +147 -0
modeling_pebble.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ from transformers import PreTrainedModel
5
+ from transformers.modeling_outputs import CausalLMOutputWithPast
6
+
7
+ try:
8
+ from mamba_ssm import Mamba2
9
+ except ImportError:
10
+ raise ImportError("mamba-ssm is required. pip install mamba-ssm causal-conv1d")
11
+
12
+ from .configuration_pebble import PebbleConfig
13
+
14
+ class RMSNorm(nn.Module):
15
+ def __init__(self, dim, eps=1e-6):
16
+ super().__init__()
17
+ self.eps = eps
18
+ self.weight = nn.Parameter(torch.ones(dim))
19
+
20
+ def forward(self, x):
21
+ dt = x.dtype
22
+ xf = x.float()
23
+ xf = xf * torch.rsqrt(xf.pow(2).mean(-1, keepdim=True) + self.eps)
24
+ return self.weight * xf.to(dt)
25
+
26
+ class AttentionBlock(nn.Module):
27
+ def __init__(self, config):
28
+ super().__init__()
29
+ dim = config.hidden_size
30
+ n_heads = config.num_attention_heads
31
+ hidden = config.intermediate_size
32
+ assert dim % n_heads == 0
33
+ self.nh, self.hd = n_heads, dim // n_heads
34
+ self.wqkv = nn.Linear(dim, 3 * dim, bias=False)
35
+ self.wo = nn.Linear(dim, dim, bias=False)
36
+ self.fc1 = nn.Linear(dim, hidden, bias=False)
37
+ self.fc2 = nn.Linear(hidden, dim, bias=False)
38
+ self.ln1 = RMSNorm(dim, eps=config.rms_norm_eps)
39
+ self.ln2 = RMSNorm(dim, eps=config.rms_norm_eps)
40
+ self.rope_theta = config.attention.get("rope_theta", 10000.0)
41
+
42
+ def forward(self, x):
43
+ B, T, C = x.shape
44
+ h = self.ln1(x)
45
+
46
+ qkv = self.wqkv(h).view(B, T, 3, self.nh, self.hd) \
47
+ .permute(2, 0, 3, 1, 4)
48
+ q, k, v = qkv[0].float(), qkv[1].float(), qkv[2]
49
+
50
+ half = self.hd // 2
51
+ invf = 1.0 / (self.rope_theta ** (
52
+ torch.arange(0, half, device=x.device, dtype=torch.float32)
53
+ * 2.0 / self.hd))
54
+ ang = torch.outer(
55
+ torch.arange(T, device=x.device, dtype=torch.float32), invf)
56
+ cos, sin = ang.cos()[None, None], ang.sin()[None, None]
57
+
58
+ q1, q2 = q[..., :half], q[..., half:]
59
+ k1, k2 = k[..., :half], k[..., half:]
60
+ q = torch.cat([q1 * cos - q2 * sin,
61
+ q1 * sin + q2 * cos], dim=-1).to(v.dtype)
62
+ k = torch.cat([k1 * cos - k2 * sin,
63
+ k1 * sin + k2 * cos], dim=-1).to(v.dtype)
64
+
65
+ y = F.scaled_dot_product_attention(q, k, v, is_causal=True)
66
+ y = y.transpose(1, 2).reshape(B, T, C)
67
+
68
+ x = x + self.wo(y)
69
+ x = x + self.fc2(F.gelu(self.fc1(self.ln2(x))))
70
+ return x
71
+
72
+ class MambaBlock(nn.Module):
73
+ def __init__(self, config):
74
+ super().__init__()
75
+ self.ln = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
76
+ mamba_cfg = config.mamba2
77
+ self.mixer = Mamba2(
78
+ d_model=config.hidden_size,
79
+ d_state=mamba_cfg.get("d_state", 128),
80
+ d_conv=mamba_cfg.get("d_conv", 4),
81
+ expand=mamba_cfg.get("expand", 2),
82
+ headdim=mamba_cfg.get("headdim", 96),
83
+ use_mem_eff_path=mamba_cfg.get("use_mem_eff_path", True),
84
+ )
85
+
86
+ def forward(self, x):
87
+ return x + self.mixer(self.ln(x))
88
+
89
+ class PebbleForCausalLM(PreTrainedModel):
90
+ config_class = PebbleConfig
91
+ supports_gradient_checkpointing = False
92
+ _no_split_modules = ["MambaBlock", "AttentionBlock"]
93
+
94
+ def __init__(self, config):
95
+ super().__init__(config)
96
+ self.config = config
97
+
98
+ self.wte = nn.Embedding(config.vocab_size, config.hidden_size)
99
+
100
+ # 3:1 Mamba:Attention ratio layout
101
+ self.blocks = nn.ModuleList([
102
+ MambaBlock(config) if i % 4 < 3
103
+ else AttentionBlock(config)
104
+ for i in range(config.num_hidden_layers)
105
+ ])
106
+
107
+ self.lnf = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
108
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
109
+
110
+ # Tie weights
111
+ self.tie_weights()
112
+
113
+ def tie_weights(self):
114
+ if self.config.tie_word_embeddings:
115
+ self.lm_head.weight = self.wte.weight
116
+
117
+ def forward(self, input_ids=None, attention_mask=None, labels=None, past_key_values=None, **kwargs):
118
+ x = self.wte(input_ids)
119
+
120
+ for blk in self.blocks:
121
+ x = blk(x)
122
+
123
+ logits = self.lm_head(self.lnf(x))
124
+
125
+ loss = None
126
+ if labels is not None:
127
+ # Shift so that tokens < n predict n+1
128
+ shift_logits = logits[..., :-1, :].contiguous()
129
+ shift_labels = labels[..., 1:].contiguous()
130
+ loss = F.cross_entropy(
131
+ shift_logits.view(-1, shift_logits.size(-1)),
132
+ shift_labels.view(-1)
133
+ )
134
+
135
+ return CausalLMOutputWithPast(
136
+ loss=loss,
137
+ logits=logits,
138
+ past_key_values=past_key_values,
139
+ )
140
+
141
+ def prepare_inputs_for_generation(self, input_ids, past_key_values=None, **kwargs):
142
+ # Mamba handles state internally in the mixer, so we don't use past_key_values
143
+ # at the model level for now (standard HF generation will still work for greedy/beam).
144
+ return {
145
+ "input_ids": input_ids,
146
+ "past_key_values": past_key_values,
147
+ }