TurkishCodeMan commited on
Commit
ec6ed45
·
verified ·
1 Parent(s): cded0fd

Upload architecture.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. architecture.py +215 -0
architecture.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from typing import Optional, Tuple
3
+ import torch
4
+ import torch.nn as nn
5
+ import torch.nn.functional as F
6
+
7
+
8
+ class RMSNorm(nn.Module):
9
+ """
10
+ Standart Qwen2.5 / LLaMA RMSNorm:
11
+ y = (x / RMS(x)) * weight, weight 1.0 ile başlatılır.
12
+ """
13
+ def __init__(self, dim: int, eps: float = 1e-6, dtype: torch.dtype = torch.float32):
14
+ super().__init__()
15
+ self.eps = eps
16
+ self.weight = nn.Parameter(torch.ones(dim, dtype=dtype))
17
+
18
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
19
+ input_dtype = x.dtype
20
+ x_fp32 = x.to(torch.float32)
21
+ variance = x_fp32.pow(2).mean(-1, keepdim=True)
22
+ normed = x_fp32 * torch.rsqrt(variance + self.eps)
23
+ return (normed * self.weight).to(input_dtype)
24
+
25
+
26
+ def precompute_rope_freqs(
27
+ head_dim: int,
28
+ seq_len: int,
29
+ theta: float = 1000000.0,
30
+ device: str = "cpu"
31
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
32
+ """
33
+ Qwen2.5 RoPE (Rotary Position Embeddings) frekanslarını önceden hesaplar.
34
+ Varsayılan theta: 1,000,000 (Qwen2.5 standardı).
35
+ """
36
+ freqs = 1.0 / (theta ** (torch.arange(0, head_dim, 2, dtype=torch.float32, device=device) / head_dim))
37
+ t = torch.arange(seq_len, dtype=torch.float32, device=device)
38
+ angles = torch.outer(t, freqs)
39
+ cos = torch.cos(angles)
40
+ sin = torch.sin(angles)
41
+ return cos, sin
42
+
43
+
44
+ def apply_rope(
45
+ x: torch.Tensor,
46
+ cos: torch.Tensor,
47
+ sin: torch.Tensor,
48
+ position_ids: Optional[torch.Tensor] = None
49
+ ) -> torch.Tensor:
50
+ """
51
+ Qwen2.5 rotate_half rotasyonunu uygular:
52
+ x shape: (B, num_heads, seq_len, head_dim)
53
+ """
54
+ B, H, S, D = x.shape
55
+ half = D // 2
56
+
57
+ if position_ids is not None:
58
+ cos = cos[position_ids].unsqueeze(1) # (B, 1, S, half)
59
+ sin = sin[position_ids].unsqueeze(1)
60
+ else:
61
+ cos = cos[:S].unsqueeze(0).unsqueeze(1) # (1, 1, S, half)
62
+ sin = sin[:S].unsqueeze(0).unsqueeze(1)
63
+
64
+ x1 = x[..., :half]
65
+ x2 = x[..., half:]
66
+ rotated = torch.cat([x1 * cos - x2 * sin, x2 * cos + x1 * sin], dim=-1)
67
+ return rotated.to(x.dtype)
68
+
69
+
70
+ class MultiHeadAttention(nn.Module):
71
+ """
72
+ Qwen2.5 Grouped Query Attention (GQA) & KV-Cache:
73
+ - q_proj, k_proj, v_proj (bias=True)
74
+ - o_proj (bias=False)
75
+ - RoPE
76
+ - KV-Cache desteği
77
+ """
78
+ def __init__(
79
+ self,
80
+ num_heads: int,
81
+ num_kv_heads: int,
82
+ d_model: int,
83
+ qkv_bias: bool = True,
84
+ dtype: torch.dtype = torch.float32,
85
+ ):
86
+ super().__init__()
87
+ self.num_heads = num_heads
88
+ self.num_kv_heads = num_kv_heads
89
+ self.d_model = d_model
90
+ self.head_dim = d_model // num_heads
91
+ self.kv_dim = num_kv_heads * self.head_dim
92
+
93
+ self.q_proj = nn.Linear(d_model, d_model, bias=qkv_bias, dtype=dtype)
94
+ self.k_proj = nn.Linear(d_model, self.kv_dim, bias=qkv_bias, dtype=dtype)
95
+ self.v_proj = nn.Linear(d_model, self.kv_dim, bias=qkv_bias, dtype=dtype)
96
+ self.out_proj = nn.Linear(d_model, d_model, bias=False, dtype=dtype)
97
+
98
+ def forward(
99
+ self,
100
+ q_input: torch.Tensor,
101
+ kv_input: Optional[torch.Tensor] = None,
102
+ mask: Optional[torch.Tensor] = None,
103
+ rope: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
104
+ position_ids: Optional[torch.Tensor] = None,
105
+ kv_cache: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
106
+ use_cache: bool = False,
107
+ ) -> Tuple[torch.Tensor, Optional[Tuple[torch.Tensor, torch.Tensor]]]:
108
+ if kv_input is None:
109
+ kv_input = q_input
110
+
111
+ B, Sq, _ = q_input.shape
112
+ _, Sk, _ = kv_input.shape
113
+
114
+ q = self.q_proj(q_input).view(B, Sq, self.num_heads, self.head_dim).transpose(1, 2)
115
+ k = self.k_proj(kv_input).view(B, Sk, self.num_kv_heads, self.head_dim).transpose(1, 2)
116
+ v = self.v_proj(kv_input).view(B, Sk, self.num_kv_heads, self.head_dim).transpose(1, 2)
117
+
118
+ # RoPE Rotasyonu
119
+ if rope is not None:
120
+ cos, sin = rope
121
+ cos, sin = cos.to(q.device), sin.to(q.device)
122
+ q = apply_rope(q, cos, sin, position_ids)
123
+ k = apply_rope(k, cos, sin, position_ids)
124
+
125
+ # KV Cache
126
+ new_kv_cache = None
127
+ if kv_cache is not None:
128
+ past_k, past_v = kv_cache
129
+ k = torch.cat([past_k, k], dim=2)
130
+ v = torch.cat([past_v, v], dim=2)
131
+
132
+ if use_cache:
133
+ new_kv_cache = (k, v)
134
+
135
+ # GQA Repeat Interleave
136
+ repeats = self.num_heads // self.num_kv_heads
137
+ if repeats > 1:
138
+ k = k.repeat_interleave(repeats, dim=1)
139
+ v = v.repeat_interleave(repeats, dim=1)
140
+
141
+ scale = 1.0 / math.sqrt(self.head_dim)
142
+ out = F.scaled_dot_product_attention(
143
+ q, k, v,
144
+ attn_mask=mask,
145
+ dropout_p=0.0,
146
+ scale=scale,
147
+ )
148
+ out = out.transpose(1, 2).contiguous().view(B, Sq, self.d_model)
149
+ return self.out_proj(out), new_kv_cache
150
+
151
+
152
+ class FeedForward(nn.Module):
153
+ """
154
+ Qwen2.5 SwiGLU MLP:
155
+ FFN(x) = down_proj(SiLU(gate_proj(x)) * up_proj(x))
156
+ """
157
+ def __init__(self, d_model: int, d_ff: int, dtype: torch.dtype = torch.float32):
158
+ super().__init__()
159
+ self.gate_proj = nn.Linear(d_model, d_ff, bias=False, dtype=dtype)
160
+ self.up_proj = nn.Linear(d_model, d_ff, bias=False, dtype=dtype)
161
+ self.down_proj = nn.Linear(d_ff, d_model, bias=False, dtype=dtype)
162
+
163
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
164
+ return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
165
+
166
+
167
+ class TransformerBlock(nn.Module):
168
+ """
169
+ Qwen2.5 Decoder Layer:
170
+ Pre-norm RMSNorm + GQA Attention + Post-attention RMSNorm + SwiGLU MLP
171
+ """
172
+ def __init__(
173
+ self,
174
+ d_model: int,
175
+ num_heads: int,
176
+ num_kv_heads: int,
177
+ d_ff: int,
178
+ dropout_rate: float = 0.0,
179
+ dtype: torch.dtype = torch.float32,
180
+ ):
181
+ super().__init__()
182
+ self.norm1 = RMSNorm(d_model, dtype=dtype)
183
+ self.self_attn = MultiHeadAttention(num_heads, num_kv_heads, d_model, qkv_bias=True, dtype=dtype)
184
+ self.dropout = nn.Dropout(dropout_rate) if dropout_rate > 0.0 else nn.Identity()
185
+
186
+ self.norm2 = RMSNorm(d_model, dtype=dtype)
187
+ self.ffn = FeedForward(d_model, d_ff, dtype=dtype)
188
+
189
+ def forward(
190
+ self,
191
+ x: torch.Tensor,
192
+ mask: Optional[torch.Tensor] = None,
193
+ rope: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
194
+ position_ids: Optional[torch.Tensor] = None,
195
+ kv_cache: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,
196
+ use_cache: bool = False,
197
+ ) -> Tuple[torch.Tensor, Optional[Tuple[torch.Tensor, torch.Tensor]]]:
198
+ residual = x
199
+ normed = self.norm1(x)
200
+ attn_out, new_kv_cache = self.self_attn(
201
+ normed,
202
+ mask=mask,
203
+ rope=rope,
204
+ position_ids=position_ids,
205
+ kv_cache=kv_cache,
206
+ use_cache=use_cache,
207
+ )
208
+ x = residual + self.dropout(attn_out)
209
+
210
+ residual = x
211
+ normed = self.norm2(x)
212
+ ffn_out = self.ffn(normed)
213
+ x = residual + self.dropout(ffn_out)
214
+
215
+ return x, new_kv_cache