Robotics
multilingual
ternary
multimodal
pretraining
jirack
ternarytransformer
kgrabko commited on
Commit
9516dab
·
verified ·
1 Parent(s): 7143161

Create JiRackNative_3b.py

Browse files
Files changed (1) hide show
  1. JiRackNative_3b.py +193 -0
JiRackNative_3b.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =============================================================================
2
+ # COPYRIGHT © 2025-2026 Konstantin Vladimirovich Grabko. ALL RIGHTS RESERVED.
3
+ # CMS Manhattan JiRack Technology — PATENT PENDING
4
+ #
5
+ # This code is proprietary.
6
+ # Personal and non-commercial research use is allowed.
7
+ # Any commercial use, derivative works for profit, or distribution
8
+ # requires a paid license and 5% royalty.
9
+ #
10
+ # Unauthorized commercial use is strictly prohibited.
11
+ # Contact: grabko@cmsmanhattan.com
12
+ # =============================================================================
13
+ #
14
+ # CHANGE LOG (this revision) — two correctness fixes, no behaviour change to
15
+ # the rest of the architecture:
16
+ # FIX 1: RMSNorm now reduces the mean-of-squares in float32 and casts back.
17
+ # Prevents bf16 precision loss that can cause loss/perplexity spikes.
18
+ # FIX 2: BitLinear activation quantization no longer subtracts the mean
19
+ # (per-token absmax, matching BitNet b1.58) and uses a symmetric
20
+ # [-127, 127] clamp. Removes the double-centering vs. RMSNorm and the
21
+ # forward/STE mismatch.
22
+ # =============================================================================
23
+ import torch
24
+ import torch.nn as nn
25
+ import torch.nn.functional as F
26
+ from torch.utils.checkpoint import checkpoint
27
+
28
+ # --- JIRACK 3B CONSTANTS ---
29
+ VOCAB_SIZE = 128256
30
+ HIDDEN_SIZE = 3072
31
+ NUM_LAYERS = 20
32
+ NUM_HEADS = 24
33
+ NUM_KV_HEADS = 8
34
+ # NOTE: with INTERMEDIATE_SIZE = 4096 the model is ~2.05B params, not 3B.
35
+ # Restore 8192 for a true ~2.8-3B model (wider SwiGLU FFN). Your call.
36
+ #INTERMEDIATE_SIZE = 8192
37
+ INTERMEDIATE_SIZE = 4096
38
+ MAX_SEQ_LEN = 4096
39
+ RMS_EPS = 1e-6
40
+ STABILITY_EPS = 1e-9
41
+ INT8_SCALE_TARGET = 127.0
42
+ TERNARY = False
43
+
44
+ class TernaryConfig:
45
+ def __init__(self):
46
+ self.vocab_size = VOCAB_SIZE
47
+ self.hidden_size = HIDDEN_SIZE
48
+ self.num_hidden_layers = NUM_LAYERS
49
+ self.num_attention_heads = NUM_HEADS
50
+ self.num_key_value_heads = NUM_KV_HEADS
51
+ self.intermediate_size = INTERMEDIATE_SIZE
52
+ self.max_position_embeddings = MAX_SEQ_LEN
53
+ self.rms_norm_eps = RMS_EPS
54
+ self.tie_word_embeddings = False
55
+ self.model_type = "jirack_ternary"
56
+ self.ternary = TERNARY # Флаг теперь внутри конфига
57
+
58
+ def get(self, key, default=None):
59
+ return getattr(self, key, default)
60
+
61
+ def __getitem__(self, key):
62
+ return getattr(self, key)
63
+
64
+ class BitLinear(nn.Linear):
65
+ def __init__(self, in_features, out_features, bias=False, ternary=False):
66
+ super().__init__(in_features, out_features, bias)
67
+ self.ternary = ternary
68
+
69
+ def forward(self, x):
70
+ if not self.ternary:
71
+ return F.linear(x, self.weight, self.bias)
72
+ # Weight Quantization (ternary {-1,0,+1}, absmean scale) — unchanged
73
+ w = self.weight
74
+ gamma = w.abs().mean().clamp(min=STABILITY_EPS)
75
+ w_quant = torch.clamp(torch.round(w / gamma), -1, 1)
76
+ w_final = w + (w_quant * gamma - w).detach()
77
+
78
+ # Activation Quantization (per-token absmax, BitNet b1.58 style)
79
+ # FIX 2: no mean-centering (there is already an RMSNorm before this
80
+ # projection), and symmetric [-127, 127] clamp to match INT8_SCALE_TARGET.
81
+ x_max = x.abs().amax(dim=-1, keepdim=True).clamp(min=STABILITY_EPS)
82
+ scale = INT8_SCALE_TARGET / x_max
83
+ x_quant = (x * scale).round().clamp(-INT8_SCALE_TARGET, INT8_SCALE_TARGET) / scale
84
+ x_final = x + (x_quant - x).detach()
85
+
86
+ return F.linear(x_final, w_final, self.bias)
87
+
88
+ class RMSNorm(nn.Module):
89
+ def __init__(self, dim, eps=RMS_EPS):
90
+ super().__init__()
91
+ self.eps = eps
92
+ self.weight = nn.Parameter(torch.ones(dim))
93
+ def forward(self, x):
94
+ # FIX 1: reduce in float32 then cast back (bf16-safe, prevents spikes)
95
+ dtype = x.dtype
96
+ x = x.float()
97
+ x = x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
98
+ return (x * self.weight.float()).to(dtype)
99
+
100
+ def precompute_freqs_cis(dim, seq_len, theta=500000.0):
101
+ freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))
102
+ t = torch.arange(seq_len).float()
103
+ freqs = torch.outer(t, freqs)
104
+ return torch.cos(freqs), torch.sin(freqs)
105
+
106
+ def apply_rotary_emb(xq, xk, freqs_cos, freqs_sin):
107
+ def rotate_half(x):
108
+ x1, x2 = x[..., : x.shape[-1] // 2], x[..., x.shape[-1] // 2 :]
109
+ return torch.cat((-x2, x1), dim=-1)
110
+ T = xq.shape[2]
111
+ f_cos = freqs_cos[:T].to(device=xq.device, dtype=xq.dtype).view(1, 1, T, -1).repeat(1, 1, 1, 2)
112
+ f_sin = freqs_sin[:T].to(device=xq.device, dtype=xq.dtype).view(1, 1, T, -1).repeat(1, 1, 1, 2)
113
+ return (xq * f_cos) + (rotate_half(xq) * f_sin), (xk * f_cos) + (rotate_half(xk) * f_sin)
114
+
115
+ class TransformerBlock(nn.Module):
116
+ def __init__(self, config):
117
+ super().__init__()
118
+ self.n_heads = config.num_attention_heads
119
+ self.n_kv_heads = config.num_key_value_heads
120
+ self.n_rep = self.n_heads // self.n_kv_heads
121
+ self.head_dim = config.hidden_size // self.n_heads
122
+ # Передаем параметр ternary из конфигурации
123
+ self.q_proj = BitLinear(config.hidden_size, config.hidden_size, ternary=config.ternary)
124
+ self.k_proj = BitLinear(config.hidden_size, self.n_kv_heads * self.head_dim, ternary=config.ternary)
125
+ self.v_proj = BitLinear(config.hidden_size, self.n_kv_heads * self.head_dim, ternary=config.ternary)
126
+ self.out_proj = BitLinear(config.hidden_size, config.hidden_size, ternary=config.ternary)
127
+
128
+ self.ffn_w1 = BitLinear(config.hidden_size, config.intermediate_size, ternary=config.ternary)
129
+ self.ffn_w3 = BitLinear(config.hidden_size, config.intermediate_size, ternary=config.ternary)
130
+ self.ffn_w2 = BitLinear(config.intermediate_size, config.hidden_size, ternary=config.ternary)
131
+
132
+ self.norm1, self.norm2 = RMSNorm(config.hidden_size), RMSNorm(config.hidden_size)
133
+
134
+ def forward(self, x, freqs_cos, freqs_sin):
135
+ h = self.norm1(x)
136
+ B, T, D = x.shape
137
+
138
+ q = self.q_proj(h).view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
139
+ k = self.k_proj(h).view(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2)
140
+ v = self.v_proj(h).view(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2)
141
+
142
+ q, k = apply_rotary_emb(q, k, freqs_cos, freqs_sin)
143
+
144
+ if self.n_rep > 1:
145
+ k = k[:, :, None, :, :].expand(B, self.n_kv_heads, self.n_rep, T, self.head_dim).reshape(B, self.n_heads, T, self.head_dim)
146
+ v = v[:, :, None, :, :].expand(B, self.n_kv_heads, self.n_rep, T, self.head_dim).reshape(B, self.n_heads, T, self.head_dim)
147
+
148
+ # Полностью автоматический выбор кернела силами PyTorch
149
+ attn_out = F.scaled_dot_product_attention(q, k, v, is_causal=True)
150
+
151
+ x = x + self.out_proj(attn_out.transpose(1, 2).reshape(B, T, D))
152
+ m = self.norm2(x)
153
+ x = x + self.ffn_w2(F.silu(self.ffn_w1(m)) * self.ffn_w3(m))
154
+ return x
155
+
156
+ class TernaryTransformer3B(nn.Module):
157
+ def __init__(self, config):
158
+ super().__init__()
159
+ self.config = config
160
+ self.token_emb = nn.Embedding(config.vocab_size, config.hidden_size)
161
+ self.blocks = nn.ModuleList([TransformerBlock(config) for _ in range(config.num_hidden_layers)])
162
+ self.ln_f = RMSNorm(config.hidden_size)
163
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
164
+
165
+ self.head_dim = config.hidden_size // config.num_attention_heads
166
+ self.gradient_checkpointing = False
167
+ self._set_rope_cache(config.max_position_embeddings)
168
+ print(f"Ternary={config.ternary} | Native Auto-SDPA Activated")
169
+
170
+ def gradient_checkpointing_enable(self, **kwargs):
171
+ self.gradient_checkpointing = True
172
+
173
+ def _set_rope_cache(self, seq_len):
174
+ cos, sin = precompute_freqs_cis(self.head_dim, seq_len)
175
+ self.register_buffer("freqs_cos", cos, persistent=False)
176
+ self.register_buffer("freqs_sin", sin, persistent=False)
177
+
178
+ def forward(self, input_ids):
179
+ input_ids = input_ids.to(torch.long)
180
+ T = input_ids.shape[1]
181
+ if T > self.freqs_cos.shape[0]:
182
+ self._set_rope_cache(T)
183
+
184
+ x = self.token_emb(input_ids)
185
+
186
+ for block in self.blocks:
187
+ if self.gradient_checkpointing and self.training:
188
+ x = checkpoint(block, x, self.freqs_cos, self.freqs_sin, use_reentrant=False)
189
+ else:
190
+ x = block(x, self.freqs_cos, self.freqs_sin)
191
+
192
+ logits = self.lm_head(self.ln_f(x))
193
+ return logits, None