anpaurehf commited on
Commit
bbbd4d1
·
verified ·
1 Parent(s): dd58bce

Upload v6_model.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. v6_model.py +256 -0
v6_model.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+
6
+ class RMSNorm(nn.Module):
7
+ def __init__(self, dim: int, eps: float = 1e-5):
8
+ super().__init__()
9
+ self.eps = eps
10
+ self.weight = nn.Parameter(torch.ones(dim))
11
+
12
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
13
+ norm = x.norm(dim=-1, keepdim=True) * (1.0 / (x.size(-1) ** 0.5))
14
+ return self.weight * x / (norm + self.eps)
15
+
16
+
17
+ def _rotate_half(x: torch.Tensor) -> torch.Tensor:
18
+ x1 = x[..., ::2]
19
+ x2 = x[..., 1::2]
20
+ return torch.stack((-x2, x1), dim=-1).flatten(-2)
21
+
22
+
23
+ def _build_rope_cache(
24
+ seq_len: int,
25
+ dim: int,
26
+ device: torch.device,
27
+ dtype: torch.dtype,
28
+ theta: float,
29
+ ) -> tuple[torch.Tensor, torch.Tensor]:
30
+ positions = torch.arange(seq_len, device=device, dtype=torch.float32)
31
+ freq_seq = torch.arange(0, dim, 2, device=device, dtype=torch.float32)
32
+ inv_freq = theta ** (-freq_seq / dim)
33
+ angles = torch.outer(positions, inv_freq)
34
+ cos = torch.repeat_interleave(torch.cos(angles), 2, dim=-1).to(dtype=dtype)
35
+ sin = torch.repeat_interleave(torch.sin(angles), 2, dim=-1).to(dtype=dtype)
36
+ return cos[None, None, :, :], sin[None, None, :, :]
37
+
38
+
39
+ def _apply_rope(
40
+ q: torch.Tensor,
41
+ k: torch.Tensor,
42
+ cos: torch.Tensor,
43
+ sin: torch.Tensor,
44
+ ) -> tuple[torch.Tensor, torch.Tensor]:
45
+ q_out = (q * cos) + (_rotate_half(q) * sin)
46
+ k_out = (k * cos) + (_rotate_half(k) * sin)
47
+ return q_out, k_out
48
+
49
+
50
+ class ExpertEncoderMultiHot(nn.Module):
51
+ def __init__(
52
+ self,
53
+ num_experts: int,
54
+ num_layers: int,
55
+ d_model: int,
56
+ layer_hidden: int,
57
+ layer_proj: int,
58
+ dropout: float,
59
+ layer_gating: bool,
60
+ ):
61
+ super().__init__()
62
+ self.num_experts = num_experts
63
+ self.num_layers = num_layers
64
+ self.layer_gating = layer_gating
65
+ if layer_gating:
66
+ self.layer_gate = nn.Parameter(torch.zeros(num_layers))
67
+ self.layer_norm = nn.LayerNorm(num_experts)
68
+ self.layer_mlp = nn.Sequential(
69
+ nn.Linear(num_experts, layer_hidden),
70
+ nn.ReLU(),
71
+ nn.Linear(layer_hidden, layer_proj),
72
+ )
73
+ self.proj = nn.Linear(num_layers * layer_proj, d_model)
74
+ self.dropout = nn.Dropout(dropout)
75
+
76
+ def forward(self, expert_idx: torch.Tensor) -> torch.Tensor:
77
+ bsz, seq_len, num_layers, _topk = expert_idx.shape
78
+ multihot = torch.zeros(
79
+ (bsz, seq_len, num_layers, self.num_experts),
80
+ device=expert_idx.device,
81
+ dtype=torch.float32,
82
+ )
83
+ multihot.scatter_(-1, expert_idx, 1.0)
84
+ if self.layer_gating:
85
+ gate = torch.sigmoid(self.layer_gate).view(1, 1, num_layers, 1)
86
+ multihot = multihot * gate
87
+ multihot = self.layer_norm(multihot)
88
+ layer_repr = self.layer_mlp(multihot)
89
+ flat = layer_repr.reshape(bsz, seq_len, num_layers * layer_repr.size(-1))
90
+ return self.dropout(self.proj(flat))
91
+
92
+
93
+ class EncoderBlock(nn.Module):
94
+ def __init__(
95
+ self,
96
+ d_model: int,
97
+ n_head: int,
98
+ d_ff: int,
99
+ dropout: float,
100
+ position_type: str,
101
+ rope_theta: float,
102
+ qk_norm: bool,
103
+ qk_norm_eps: float,
104
+ ):
105
+ super().__init__()
106
+ if d_model % n_head != 0:
107
+ raise ValueError(f"d_model={d_model} must be divisible by n_head={n_head}")
108
+ self.n_head = n_head
109
+ self.d_model = d_model
110
+ self.d_head = d_model // n_head
111
+ if self.d_head % 2 != 0:
112
+ raise ValueError(f"Rotary head dimension must be even, got {self.d_head}")
113
+ self.position_type = position_type
114
+ self.rope_theta = rope_theta
115
+ self.qk_norm = qk_norm
116
+ self.attn_norm = RMSNorm(d_model)
117
+ self.mlp_norm = RMSNorm(d_model)
118
+ self.attn = nn.Linear(d_model, 3 * d_model)
119
+ self.proj = nn.Linear(d_model, d_model)
120
+ self.dropout = nn.Dropout(dropout)
121
+ self.fc = nn.Linear(d_model, d_ff)
122
+ self.fc_out = nn.Linear(d_ff, d_model)
123
+ if self.qk_norm:
124
+ self.q_norm = RMSNorm(self.d_head, eps=qk_norm_eps)
125
+ self.k_norm = RMSNorm(self.d_head, eps=qk_norm_eps)
126
+ else:
127
+ self.q_norm = None
128
+ self.k_norm = None
129
+
130
+ def forward(self, x: torch.Tensor, attention_mask: torch.Tensor | None) -> torch.Tensor:
131
+ bsz, seq_len, d_model = x.shape
132
+ mask = None
133
+ if attention_mask is not None:
134
+ attention_mask = attention_mask.to(torch.bool)
135
+ mask = attention_mask.unsqueeze(-1).to(x.dtype)
136
+ x = x * mask
137
+
138
+ qkv = self.attn(self.attn_norm(x))
139
+ q, k, v = qkv.split(d_model, dim=-1)
140
+ q = q.view(bsz, seq_len, self.n_head, self.d_head).transpose(1, 2)
141
+ k = k.view(bsz, seq_len, self.n_head, self.d_head).transpose(1, 2)
142
+ v = v.view(bsz, seq_len, self.n_head, self.d_head).transpose(1, 2)
143
+
144
+ if self.qk_norm:
145
+ q = self.q_norm(q)
146
+ k = self.k_norm(k)
147
+
148
+ if self.position_type == "rope":
149
+ cos, sin = _build_rope_cache(
150
+ seq_len=seq_len,
151
+ dim=self.d_head,
152
+ device=q.device,
153
+ dtype=q.dtype,
154
+ theta=self.rope_theta,
155
+ )
156
+ q, k = _apply_rope(q, k, cos, sin)
157
+
158
+ attn = F.scaled_dot_product_attention(
159
+ q,
160
+ k,
161
+ v,
162
+ attn_mask=attention_mask[:, None, None, :] if attention_mask is not None else None,
163
+ dropout_p=0.0,
164
+ is_causal=False,
165
+ )
166
+ attn = attn.transpose(1, 2).contiguous().view(bsz, seq_len, d_model)
167
+ x = x + self.dropout(self.proj(attn))
168
+ mlp = self.fc(self.mlp_norm(x))
169
+ mlp = torch.relu(mlp).pow(2)
170
+ x = x + self.dropout(self.fc_out(mlp))
171
+ if mask is not None:
172
+ x = x * mask
173
+ return x
174
+
175
+
176
+ class EncoderOnlyModel(nn.Module):
177
+ def __init__(
178
+ self,
179
+ vocab_size: int,
180
+ num_experts: int,
181
+ num_layers: int,
182
+ topk: int,
183
+ d_model: int,
184
+ n_head: int,
185
+ d_ff: int,
186
+ n_layer: int,
187
+ dropout: float,
188
+ max_len: int,
189
+ layer_gating: bool,
190
+ logit_softcap: float,
191
+ layer_hidden: int,
192
+ layer_proj: int,
193
+ position_type: str = "learned",
194
+ rope_theta: float = 10000.0,
195
+ qk_norm: bool = True,
196
+ qk_norm_eps: float = 1e-5,
197
+ ):
198
+ super().__init__()
199
+ if position_type not in {"learned", "rope"}:
200
+ raise ValueError(f"Unsupported position_type: {position_type}")
201
+ self.encoder_in = ExpertEncoderMultiHot(
202
+ num_experts=num_experts,
203
+ num_layers=num_layers,
204
+ d_model=d_model,
205
+ layer_hidden=layer_hidden,
206
+ layer_proj=layer_proj,
207
+ dropout=dropout,
208
+ layer_gating=layer_gating,
209
+ )
210
+ self.position_type = position_type
211
+ self.rope_theta = rope_theta
212
+ self.qk_norm = qk_norm
213
+ self.qk_norm_eps = qk_norm_eps
214
+ self.max_len = max_len
215
+ if self.position_type == "learned":
216
+ self.pos_emb = nn.Embedding(max_len, d_model)
217
+ else:
218
+ self.pos_emb = None
219
+ self.blocks = nn.ModuleList(
220
+ [
221
+ EncoderBlock(
222
+ d_model=d_model,
223
+ n_head=n_head,
224
+ d_ff=d_ff,
225
+ dropout=dropout,
226
+ position_type=position_type,
227
+ rope_theta=rope_theta,
228
+ qk_norm=qk_norm,
229
+ qk_norm_eps=qk_norm_eps,
230
+ )
231
+ for _ in range(n_layer)
232
+ ]
233
+ )
234
+ self.norm = RMSNorm(d_model)
235
+ self.head = nn.Linear(d_model, vocab_size, bias=False)
236
+ self.logit_softcap = logit_softcap
237
+ self.topk = topk
238
+
239
+ def forward(self, expert_idx: torch.Tensor, attention_mask: torch.Tensor | None) -> torch.Tensor:
240
+ bsz, seq_len = expert_idx.shape[:2]
241
+ if seq_len > self.max_len:
242
+ raise ValueError(f"seq_len={seq_len} exceeds configured max_len={self.max_len}")
243
+ x = self.encoder_in(expert_idx)
244
+ if self.position_type == "learned":
245
+ pos_ids = torch.arange(seq_len, device=expert_idx.device)
246
+ pos_ids = pos_ids.unsqueeze(0).expand(bsz, -1)
247
+ x = x + self.pos_emb(pos_ids)
248
+ if attention_mask is not None:
249
+ x = x * attention_mask.unsqueeze(-1).to(x.dtype)
250
+ for block in self.blocks:
251
+ x = block(x, attention_mask)
252
+ x = self.norm(x)
253
+ logits = self.head(x)
254
+ if self.logit_softcap and self.logit_softcap > 0:
255
+ logits = self.logit_softcap * torch.tanh(logits / self.logit_softcap)
256
+ return logits