cogforge-engine 1.1.0__tar.gz → 2.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/PKG-INFO +1 -1
- cogforge_engine-2.0.1/TODO +7 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/cogforge/app.py +118 -1
- cogforge_engine-2.0.1/cogforge/models.py +254 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/pyproject.toml +1 -1
- cogforge_engine-1.1.0/cogforge/models.py +0 -114
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/.github/workflows/release.yml +0 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/.gitignore +0 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/LICENSE +0 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/README.md +0 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/cogforge/__init__.py +0 -0
- {cogforge_engine-1.1.0 → cogforge_engine-2.0.1}/cogforge/backend.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cogforge-engine
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1
|
|
4
4
|
Summary: A custom autograd engine and Transformer block built from scratch.
|
|
5
5
|
Project-URL: Homepage, https://github.com/avikmjd2/cogforge
|
|
6
6
|
Author-email: Avik Majumder <avikmjd2@gmail.com>
|
|
@@ -55,7 +55,9 @@ class Tensor:
|
|
|
55
55
|
self.typed = typed
|
|
56
56
|
|
|
57
57
|
def __getitem__(self, key):
|
|
58
|
-
out_data = self.data[key]
|
|
58
|
+
out_data = backend.np.asarray(self.data[key]) # force a real ndarray
|
|
59
|
+
if backend.NO_GRAD:
|
|
60
|
+
return Tensor(out_data)
|
|
59
61
|
|
|
60
62
|
out = Tensor(out_data,children=(self,))
|
|
61
63
|
|
|
@@ -455,6 +457,42 @@ class Tensor:
|
|
|
455
457
|
loss._backwards = _backward
|
|
456
458
|
return loss
|
|
457
459
|
|
|
460
|
+
@classmethod
|
|
461
|
+
def sparse_softmax_cross_entropy_index(cls, scores, labels, mask):
|
|
462
|
+
"""
|
|
463
|
+
scores: Tensor (N, V) logits
|
|
464
|
+
labels: (N,) int correct class id per row
|
|
465
|
+
mask: (N,) {0,1} 1 = real token, 0 = padding
|
|
466
|
+
Same loss/gradient as the one-hot masked version, no (N, V) target built.
|
|
467
|
+
"""
|
|
468
|
+
z = scores.data
|
|
469
|
+
z = z - z.max(axis=1, keepdims=True)
|
|
470
|
+
e = backend.np.exp(z)
|
|
471
|
+
p = e / e.sum(axis=1, keepdims=True) # (N, V)
|
|
472
|
+
|
|
473
|
+
labels = backend.np.asarray(labels).reshape(-1) # (N,)
|
|
474
|
+
mask = backend.np.asarray(mask).reshape(-1) # (N,)
|
|
475
|
+
N = p.shape[0]
|
|
476
|
+
rows = backend.np.arange(N)
|
|
477
|
+
|
|
478
|
+
n_real = mask.sum()
|
|
479
|
+
n_real = n_real if n_real > 0 else 1.0
|
|
480
|
+
|
|
481
|
+
logp_correct = backend.np.log(backend.np.clip(p[rows, labels], 1e-15, 1.0))
|
|
482
|
+
loss_data = -backend.np.sum(mask * logp_correct) / n_real
|
|
483
|
+
|
|
484
|
+
if backend.NO_GRAD:
|
|
485
|
+
return cls(loss_data)
|
|
486
|
+
|
|
487
|
+
loss = cls(loss_data, children=(scores,))
|
|
488
|
+
def _backward():
|
|
489
|
+
grad = p.copy()
|
|
490
|
+
grad[rows, labels] -= 1.0
|
|
491
|
+
grad *= (mask / n_real)[:, None]
|
|
492
|
+
scores.grad += grad * loss.grad
|
|
493
|
+
loss._backwards = _backward
|
|
494
|
+
return loss
|
|
495
|
+
|
|
458
496
|
#Legacy
|
|
459
497
|
@classmethod
|
|
460
498
|
def softmax_cross_entropy_old(cls, scores, targets):
|
|
@@ -981,6 +1019,47 @@ class MultiHeadAttention:
|
|
|
981
1019
|
def parameters(self):
|
|
982
1020
|
return (self.q.parameters() + self.k.parameters()
|
|
983
1021
|
+ self.v.parameters() + self.o.parameters())
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
class CrossAttention:
|
|
1026
|
+
def __init__(self, dim_dec, dim_enc,d_out, dec_rope = None, enc_rope = None,d_k=None, h=None, d_model = None):
|
|
1027
|
+
assert (d_k and h) or (d_model and h), "Model Parameters not defined"
|
|
1028
|
+
self.d_model = d_model if d_model is not None else h*d_k
|
|
1029
|
+
self.q = Linear(nin=dim_dec, nout=self.d_model)
|
|
1030
|
+
self.k = Linear(nin=dim_enc, nout=self.d_model)
|
|
1031
|
+
self.v = Linear(nin=dim_enc, nout=self.d_model)
|
|
1032
|
+
self.d_out = d_out
|
|
1033
|
+
self.o = Linear(nin=self.d_model, nout=d_out)
|
|
1034
|
+
self.dk = d_k if d_k is not None else d_model//h
|
|
1035
|
+
self.h = h
|
|
1036
|
+
self.dec_rope = dec_rope
|
|
1037
|
+
self.enc_rope = enc_rope
|
|
1038
|
+
self.attention = Attention(self.dk)
|
|
1039
|
+
|
|
1040
|
+
def split(self,x:Tensor):
|
|
1041
|
+
B,T,_ = x.data.shape
|
|
1042
|
+
return x.view((B,T,self.h,self.dk)).transpose((0,2,1,3)) #(B, h, T, d_k)
|
|
1043
|
+
|
|
1044
|
+
def merge(self,x:Tensor):
|
|
1045
|
+
B, h, T, d_k = x.data.shape
|
|
1046
|
+
return x.transpose((0, 2, 1, 3)).view((B, T, h * d_k))
|
|
1047
|
+
|
|
1048
|
+
def __call__(self, x_decod,x_encod, mask=None):
|
|
1049
|
+
Q = self.split(self.q(x_decod))
|
|
1050
|
+
K = self.split(self.k(x_encod))
|
|
1051
|
+
V = self.split(self.v(x_encod))
|
|
1052
|
+
if self.dec_rope is not None:
|
|
1053
|
+
Q = self.dec_rope(Q)
|
|
1054
|
+
if self.enc_rope is not None:
|
|
1055
|
+
K = self.enc_rope(K)
|
|
1056
|
+
|
|
1057
|
+
out = self.attention(Q=Q,K=K,V=V,mask=mask)
|
|
1058
|
+
return self.o(self.merge(out))
|
|
1059
|
+
|
|
1060
|
+
def parameters(self):
|
|
1061
|
+
return (self.q.parameters() + self.k.parameters()
|
|
1062
|
+
+ self.v.parameters() + self.o.parameters())
|
|
984
1063
|
|
|
985
1064
|
|
|
986
1065
|
class LayerNorm:
|
|
@@ -1057,6 +1136,44 @@ class Transformer:
|
|
|
1057
1136
|
return (self.ln1.parameters() + self.attn.parameters()
|
|
1058
1137
|
+ self.ln2.parameters() + self.ff.parameters())
|
|
1059
1138
|
|
|
1139
|
+
|
|
1140
|
+
class Decoder:
|
|
1141
|
+
"""The decoder block has no bridge. So demb = dmodel"""
|
|
1142
|
+
def __init__(self, d_model, n_heads, d_ff=None, is_training=False,dec_in_rope=None,enc_rope=None,dec_rope=None):
|
|
1143
|
+
self.ln1 = LayerNorm(d_model)
|
|
1144
|
+
self.self_attn = MultiHeadAttention(dinp=d_model,dmodel=d_model,dout=d_model,n=n_heads,rope=dec_in_rope)
|
|
1145
|
+
|
|
1146
|
+
self.ln2 = LayerNorm(d_model)
|
|
1147
|
+
self.cross_attn = CrossAttention(dim_dec=d_model,dim_enc=d_model,d_out=d_model,dec_rope=dec_rope,enc_rope=enc_rope,h=n_heads,d_k=d_model//n_heads)
|
|
1148
|
+
|
|
1149
|
+
self.ln3 = LayerNorm(d_model)
|
|
1150
|
+
self.ff = FeedForward(dmodel=d_model, dff=d_ff)
|
|
1151
|
+
|
|
1152
|
+
self.is_training = is_training
|
|
1153
|
+
|
|
1154
|
+
def __call__(self, x_dec, x_enc, mask=None,cross_mask=None):
|
|
1155
|
+
a = self.ln1(x_dec)
|
|
1156
|
+
x_dec = x_dec + self.self_attn(a,a,a,mask=mask)
|
|
1157
|
+
|
|
1158
|
+
c = self.ln2(x_dec)
|
|
1159
|
+
x_dec = x_dec + self.cross_attn(x_decod=c,x_encod=x_enc,mask=cross_mask)
|
|
1160
|
+
|
|
1161
|
+
f = self.ln3(x_dec)
|
|
1162
|
+
x_dec = x_dec + self.ff(f,self.is_training)
|
|
1163
|
+
|
|
1164
|
+
return x_dec
|
|
1165
|
+
|
|
1166
|
+
def train(self, enabled = True):
|
|
1167
|
+
self.is_training = enabled
|
|
1168
|
+
def infer(self, enabled = True):
|
|
1169
|
+
self.is_training = not enabled
|
|
1170
|
+
|
|
1171
|
+
def parameters(self):
|
|
1172
|
+
return (self.ln1.parameters() + self.self_attn.parameters() +
|
|
1173
|
+
self.ln2.parameters() + self.cross_attn.parameters() +
|
|
1174
|
+
self.ln3.parameters() + self.ff.parameters())
|
|
1175
|
+
|
|
1176
|
+
|
|
1060
1177
|
|
|
1061
1178
|
class PositionalEncoding:
|
|
1062
1179
|
def __init__(self,max_len,dmodel):
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
from . import backend
|
|
2
|
+
from .app import Embedding, PositionalEncoding,Transformer,LayerNorm,Linear,RotatoryPositionalEncoding,to_cpu,needGradientHence,Decoder,Tensor
|
|
3
|
+
import numpy
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GPTV1:
|
|
7
|
+
def __init__(self, vocab, d_model, n_heads, n_layers, max_len, d_ff=None):
|
|
8
|
+
self.tok = Embedding(vocab, d_model)
|
|
9
|
+
self.pos = PositionalEncoding(max_len, d_model)
|
|
10
|
+
self.blocks = [Transformer(dmodel=d_model,n=n_heads,dff=d_ff) for _ in range(n_layers)]
|
|
11
|
+
self.ln_f = LayerNorm(d_model)
|
|
12
|
+
self.head = Linear(d_model, vocab)
|
|
13
|
+
self.max_len = max_len
|
|
14
|
+
|
|
15
|
+
def __call__(self, idx):
|
|
16
|
+
T = idx.shape[1]
|
|
17
|
+
casual = backend.np.triu((backend.np.ones((T,T))),k=1).astype(bool)
|
|
18
|
+
x = self.pos(self.tok(idx))
|
|
19
|
+
for block in self.blocks:
|
|
20
|
+
x = block(x,mask=casual)
|
|
21
|
+
|
|
22
|
+
x = self.ln_f(x)
|
|
23
|
+
return self.head(x)
|
|
24
|
+
|
|
25
|
+
def parameters(self):
|
|
26
|
+
ps = self.tok.parameters() + self.ln_f.parameters() + self.head.parameters()
|
|
27
|
+
for b in self.blocks: ps += b.parameters()
|
|
28
|
+
return ps
|
|
29
|
+
|
|
30
|
+
def generate(self, idx, n_new, temperature=1.0, top_k=None):
|
|
31
|
+
idx = numpy.asarray(idx)
|
|
32
|
+
original_grad_state = not backend.NO_GRAD
|
|
33
|
+
needGradientHence(False)
|
|
34
|
+
try:
|
|
35
|
+
for _ in range(n_new):
|
|
36
|
+
cond = idx[:, -self.max_len:]
|
|
37
|
+
logits = to_cpu(self(cond).data)[:, -1, :] / temperature
|
|
38
|
+
if top_k is not None:
|
|
39
|
+
kth = numpy.sort(logits, axis=-1)[:, -top_k][:, None]
|
|
40
|
+
logits = numpy.where(logits < kth, -1e9, logits)
|
|
41
|
+
z = logits - logits.max(-1, keepdims=True)
|
|
42
|
+
p = numpy.exp(z).astype(numpy.float64); p /= p.sum(-1, keepdims=True)
|
|
43
|
+
nxt = numpy.array([[numpy.random.choice(len(pr), p=pr)] for pr in p])
|
|
44
|
+
idx = numpy.concatenate([idx, nxt], axis=1)
|
|
45
|
+
return idx
|
|
46
|
+
finally:
|
|
47
|
+
needGradientHence(original_grad_state)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class GPT2:
|
|
53
|
+
def __init__(self, vocab, d_model, n_heads, n_layers, max_len, d_ff=None, base=10000.0,training = False):
|
|
54
|
+
assert d_model % n_heads == 0
|
|
55
|
+
self.tok = Embedding(vocab, d_model)
|
|
56
|
+
self.rope = RotatoryPositionalEncoding(max_len, d_model // n_heads, base) # dim = d_k
|
|
57
|
+
self.blocks = [Transformer(d_model, n_heads, dff=d_ff, rope=self.rope,is_training=training)
|
|
58
|
+
for _ in range(n_layers)]
|
|
59
|
+
self.ln_f = LayerNorm(d_model)
|
|
60
|
+
self.head = Linear(d_model, vocab)
|
|
61
|
+
self.max_len = max_len
|
|
62
|
+
self.is_training = training
|
|
63
|
+
|
|
64
|
+
def train(self, enabled = True):
|
|
65
|
+
self.is_training = enabled
|
|
66
|
+
for block in self.blocks:
|
|
67
|
+
block.train(enabled=enabled)
|
|
68
|
+
def infer(self, enabled = True):
|
|
69
|
+
self.is_training = not enabled
|
|
70
|
+
for block in self.blocks:
|
|
71
|
+
block.infer(enabled=enabled)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def __call__(self, idx):
|
|
75
|
+
T = idx.shape[1]
|
|
76
|
+
causal = backend.np.triu(backend.np.ones((T, T)), k=1).astype(bool)
|
|
77
|
+
x = self.tok(idx) # straight from token embedding
|
|
78
|
+
for block in self.blocks:
|
|
79
|
+
x = block(x, mask=causal)
|
|
80
|
+
return self.head(self.ln_f(x))
|
|
81
|
+
|
|
82
|
+
def parameters(self):
|
|
83
|
+
ps = self.tok.parameters() + self.ln_f.parameters() + self.head.parameters()
|
|
84
|
+
for b in self.blocks: ps += b.parameters()
|
|
85
|
+
return ps
|
|
86
|
+
|
|
87
|
+
def generate(self, idx, n_new, temperature=1.0, top_k=None):
|
|
88
|
+
idx = numpy.asarray(idx)
|
|
89
|
+
was_training = self.is_training
|
|
90
|
+
self.infer()
|
|
91
|
+
original_grad_state = not backend.NO_GRAD
|
|
92
|
+
needGradientHence(False)
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
for _ in range(n_new):
|
|
96
|
+
cond = idx[:, -self.max_len:]
|
|
97
|
+
logits = to_cpu(self(cond).data)[:, -1, :] / temperature
|
|
98
|
+
if top_k is not None:
|
|
99
|
+
kth = numpy.sort(logits, axis=-1)[:, -top_k][:, None]
|
|
100
|
+
logits = numpy.where(logits < kth, -1e9, logits)
|
|
101
|
+
z = logits - logits.max(-1, keepdims=True)
|
|
102
|
+
p = numpy.exp(z).astype(numpy.float64); p /= p.sum(-1, keepdims=True)
|
|
103
|
+
nxt = numpy.array([[numpy.random.choice(len(pr), p=pr)] for pr in p])
|
|
104
|
+
idx = numpy.concatenate([idx, nxt], axis=1)
|
|
105
|
+
# backend._cp.get_default_memory_pool().free_all_blocks() if backend.USE_GPU else None
|
|
106
|
+
return idx
|
|
107
|
+
finally:
|
|
108
|
+
if was_training:
|
|
109
|
+
self.train()
|
|
110
|
+
needGradientHence(original_grad_state)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Seq2Seq:
|
|
116
|
+
def __init__(self, enc_vocab, dec_vocab, d_model, n_heads, num_enc_layers, num_dec_layers, max_len, d_ff=None, training=False,shared_tok = False,pad_id=0,encoder_rope = None,dec_in_rope = None, dec_rope = None, enc_rope=None):
|
|
117
|
+
if enc_vocab==dec_vocab and shared_tok:
|
|
118
|
+
self.shared_tok = Embedding(enc_vocab, d_model)
|
|
119
|
+
self.shared_tok.weights.data *= (1.0 / backend.np.sqrt(d_model))
|
|
120
|
+
self.emb_scale = backend.np.sqrt(d_model)
|
|
121
|
+
|
|
122
|
+
self.enc_tok = self.dec_tok = self.shared_tok
|
|
123
|
+
self.tie_weights = True
|
|
124
|
+
self.head_b = Tensor(backend.np.zeros((dec_vocab,)))
|
|
125
|
+
else:
|
|
126
|
+
self.enc_tok = Embedding(enc_vocab, d_model)
|
|
127
|
+
self.dec_tok = Embedding(dec_vocab, d_model)
|
|
128
|
+
|
|
129
|
+
self.head = Linear(d_model, dec_vocab)
|
|
130
|
+
self.tie_weights = False
|
|
131
|
+
self.emb_scale = 1.0
|
|
132
|
+
|
|
133
|
+
self.pad_id = pad_id
|
|
134
|
+
|
|
135
|
+
self.rope = RotatoryPositionalEncoding(max_len, d_model // n_heads) if (dec_in_rope or dec_rope or enc_rope or encoder_rope) is not None else None
|
|
136
|
+
self.dec_in_rope = self.rope if dec_in_rope is not None else None
|
|
137
|
+
self.dec_rope = self.rope if dec_rope is not None else None
|
|
138
|
+
self.enc_rope = self.rope if enc_rope is not None else None
|
|
139
|
+
self.encoder_rope = self.rope if encoder_rope is not None else None
|
|
140
|
+
|
|
141
|
+
self.encoders = [Transformer(dmodel=d_model, n=n_heads, dff=d_ff, is_training=training, rope=self.encoder_rope) for _ in range(num_enc_layers)]
|
|
142
|
+
self.decoders = [
|
|
143
|
+
Decoder(d_model=d_model, n_heads=n_heads, d_ff=d_ff, is_training=training, dec_in_rope=self.dec_in_rope,dec_rope=self.dec_rope,enc_rope=self.enc_rope)
|
|
144
|
+
for _ in range(num_dec_layers)
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
self.ln_f = LayerNorm(d_model)
|
|
148
|
+
self.enc_ln = LayerNorm(d_model)
|
|
149
|
+
|
|
150
|
+
self.max_len = max_len
|
|
151
|
+
self.is_training = training
|
|
152
|
+
|
|
153
|
+
def train(self, enabled=True):
|
|
154
|
+
self.is_training = enabled
|
|
155
|
+
for block in self.encoders: block.train(enabled)
|
|
156
|
+
for block in self.decoders: block.train(enabled)
|
|
157
|
+
|
|
158
|
+
def infer(self, enabled=True):
|
|
159
|
+
self.is_training = not enabled
|
|
160
|
+
for block in self.encoders: block.infer(enabled)
|
|
161
|
+
for block in self.decoders: block.infer(enabled)
|
|
162
|
+
|
|
163
|
+
@staticmethod
|
|
164
|
+
def make_pad_mask(idx, pad_id):
|
|
165
|
+
# idx: (B, T) int -> (B, 1, 1, T) bool, True where padding
|
|
166
|
+
m = (backend.np.asarray(idx) == pad_id)
|
|
167
|
+
return m[:, None, None, :]
|
|
168
|
+
|
|
169
|
+
def __call__(self, enc_idx, dec_idx):
|
|
170
|
+
"""
|
|
171
|
+
enc_idx: Scrambled words, shape (B, T_enc)
|
|
172
|
+
dec_idx: Shifted target sentence starting with <SOS>, shape (B, T_dec)
|
|
173
|
+
"""
|
|
174
|
+
enc_pad = self.make_pad_mask(enc_idx, self.pad_id)
|
|
175
|
+
x_enc = self.enc_tok(enc_idx) * self.emb_scale
|
|
176
|
+
for block in self.encoders:
|
|
177
|
+
x_enc = block(x_enc, mask=enc_pad)
|
|
178
|
+
|
|
179
|
+
x_enc = self.enc_ln(x_enc)
|
|
180
|
+
|
|
181
|
+
T_dec = dec_idx.shape[1]
|
|
182
|
+
causal_mask = backend.np.triu(backend.np.ones((T_dec, T_dec)), k=1).astype(bool)
|
|
183
|
+
|
|
184
|
+
x_dec = self.dec_tok(dec_idx) * self.emb_scale
|
|
185
|
+
for block in self.decoders:
|
|
186
|
+
x_dec = block(x_dec=x_dec, x_enc=x_enc, mask=causal_mask,cross_mask=enc_pad)
|
|
187
|
+
|
|
188
|
+
x = self.ln_f(x_dec)
|
|
189
|
+
if self.tie_weights:
|
|
190
|
+
logits = x @ self.shared_tok.weights.transpose((1, 0)) + self.head_b
|
|
191
|
+
else:
|
|
192
|
+
logits = self.head(x)
|
|
193
|
+
return logits
|
|
194
|
+
|
|
195
|
+
def parameters(self):
|
|
196
|
+
seen, ps = set(), []
|
|
197
|
+
def add(lst):
|
|
198
|
+
for p in lst:
|
|
199
|
+
if id(p) not in seen:
|
|
200
|
+
seen.add(id(p)); ps.append(p)
|
|
201
|
+
add(self.enc_tok.parameters()); add(self.dec_tok.parameters())
|
|
202
|
+
add(self.ln_f.parameters()); add(self.enc_ln.parameters())
|
|
203
|
+
add([self.head_b] if self.tie_weights else self.head.parameters())
|
|
204
|
+
for b in self.encoders: add(b.parameters())
|
|
205
|
+
for b in self.decoders: add(b.parameters())
|
|
206
|
+
return ps
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def encode(self, enc_idx):
|
|
210
|
+
enc_pad = self.make_pad_mask(enc_idx, self.pad_id)
|
|
211
|
+
x_enc = self.enc_tok(enc_idx) * self.emb_scale
|
|
212
|
+
for block in self.encoders:
|
|
213
|
+
x_enc = block(x_enc, mask=enc_pad)
|
|
214
|
+
x_enc = self.enc_ln(x_enc)
|
|
215
|
+
return x_enc, enc_pad
|
|
216
|
+
|
|
217
|
+
def decode_step(self, dec_idx, x_enc, enc_pad):
|
|
218
|
+
T_dec = dec_idx.shape[1]
|
|
219
|
+
causal = backend.np.triu(backend.np.ones((T_dec, T_dec)), k=1).astype(bool)
|
|
220
|
+
x_dec = self.dec_tok(dec_idx) * self.emb_scale
|
|
221
|
+
for block in self.decoders:
|
|
222
|
+
x_dec = block(x_dec=x_dec, x_enc=x_enc, mask=causal, cross_mask=enc_pad)
|
|
223
|
+
x = self.ln_f(x_dec)
|
|
224
|
+
if self.tie_weights:
|
|
225
|
+
return x @ self.shared_tok.weights.transpose((1, 0)) + self.head_b
|
|
226
|
+
return self.head(x)
|
|
227
|
+
|
|
228
|
+
def generate(self, enc_idx, sos_id, eos_id=None, max_new=50, temperature=1.0, top_k=None):
|
|
229
|
+
enc_idx = numpy.asarray(enc_idx)
|
|
230
|
+
B = enc_idx.shape[0]
|
|
231
|
+
was_training = self.is_training
|
|
232
|
+
self.infer()
|
|
233
|
+
original_grad_state = not backend.NO_GRAD
|
|
234
|
+
needGradientHence(False)
|
|
235
|
+
try:
|
|
236
|
+
x_enc, enc_pad = self.encode(enc_idx) # encode once
|
|
237
|
+
dec_idx = numpy.full((B, 1), sos_id, dtype=numpy.int64)
|
|
238
|
+
for _ in range(max_new):
|
|
239
|
+
logits = to_cpu(self.decode_step(dec_idx, x_enc, enc_pad).data)[:, -1, :] / temperature
|
|
240
|
+
if top_k is not None:
|
|
241
|
+
kth = numpy.sort(logits, axis=-1)[:, -top_k][:, None]
|
|
242
|
+
logits = numpy.where(logits < kth, -1e9, logits)
|
|
243
|
+
z = logits - logits.max(-1, keepdims=True)
|
|
244
|
+
p = numpy.exp(z).astype(numpy.float64); p /= p.sum(-1, keepdims=True)
|
|
245
|
+
nxt = numpy.array([[numpy.random.choice(len(pr), p=pr)] for pr in p])
|
|
246
|
+
dec_idx = numpy.concatenate([dec_idx, nxt], axis=1)
|
|
247
|
+
if eos_id is not None and bool((nxt[:, 0] == eos_id).all()):
|
|
248
|
+
break
|
|
249
|
+
return dec_idx
|
|
250
|
+
finally:
|
|
251
|
+
if was_training:
|
|
252
|
+
self.train()
|
|
253
|
+
needGradientHence(original_grad_state)
|
|
254
|
+
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
from . import backend
|
|
2
|
-
from .app import Embedding, PositionalEncoding,Transformer,LayerNorm,Linear,RotatoryPositionalEncoding,to_cpu,needGradientHence
|
|
3
|
-
import numpy
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class GPTV1:
|
|
7
|
-
def __init__(self, vocab, d_model, n_heads, n_layers, max_len, d_ff=None):
|
|
8
|
-
self.tok = Embedding(vocab, d_model)
|
|
9
|
-
self.pos = PositionalEncoding(max_len, d_model)
|
|
10
|
-
self.blocks = [Transformer(dmodel=d_model,n=n_heads,dff=d_ff) for _ in range(n_layers)]
|
|
11
|
-
self.ln_f = LayerNorm(d_model)
|
|
12
|
-
self.head = Linear(d_model, vocab)
|
|
13
|
-
self.max_len = max_len
|
|
14
|
-
|
|
15
|
-
def __call__(self, idx):
|
|
16
|
-
T = idx.shape[1]
|
|
17
|
-
casual = backend.np.triu((backend.np.ones((T,T))),k=1).astype(bool)
|
|
18
|
-
x = self.pos(self.tok(idx))
|
|
19
|
-
for block in self.blocks:
|
|
20
|
-
x = block(x,mask=casual)
|
|
21
|
-
|
|
22
|
-
x = self.ln_f(x)
|
|
23
|
-
return self.head(x)
|
|
24
|
-
|
|
25
|
-
def parameters(self):
|
|
26
|
-
ps = self.tok.parameters() + self.ln_f.parameters() + self.head.parameters()
|
|
27
|
-
for b in self.blocks: ps += b.parameters()
|
|
28
|
-
return ps
|
|
29
|
-
|
|
30
|
-
def generate(self, idx, n_new, temperature=1.0, top_k=None):
|
|
31
|
-
idx = numpy.asarray(idx)
|
|
32
|
-
original_grad_state = not backend.NO_GRAD
|
|
33
|
-
needGradientHence(False)
|
|
34
|
-
try:
|
|
35
|
-
for _ in range(n_new):
|
|
36
|
-
cond = idx[:, -self.max_len:]
|
|
37
|
-
logits = to_cpu(self(cond).data)[:, -1, :] / temperature
|
|
38
|
-
if top_k is not None:
|
|
39
|
-
kth = numpy.sort(logits, axis=-1)[:, -top_k][:, None]
|
|
40
|
-
logits = numpy.where(logits < kth, -1e9, logits)
|
|
41
|
-
z = logits - logits.max(-1, keepdims=True)
|
|
42
|
-
p = numpy.exp(z).astype(numpy.float64); p /= p.sum(-1, keepdims=True)
|
|
43
|
-
nxt = numpy.array([[numpy.random.choice(len(pr), p=pr)] for pr in p])
|
|
44
|
-
idx = numpy.concatenate([idx, nxt], axis=1)
|
|
45
|
-
return idx
|
|
46
|
-
finally:
|
|
47
|
-
needGradientHence(original_grad_state)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class GPT2:
|
|
53
|
-
def __init__(self, vocab, d_model, n_heads, n_layers, max_len, d_ff=None, base=10000.0,training = False):
|
|
54
|
-
assert d_model % n_heads == 0
|
|
55
|
-
self.tok = Embedding(vocab, d_model)
|
|
56
|
-
self.rope = RotatoryPositionalEncoding(max_len, d_model // n_heads, base) # dim = d_k
|
|
57
|
-
self.blocks = [Transformer(d_model, n_heads, dff=d_ff, rope=self.rope,is_training=training)
|
|
58
|
-
for _ in range(n_layers)]
|
|
59
|
-
self.ln_f = LayerNorm(d_model)
|
|
60
|
-
self.head = Linear(d_model, vocab)
|
|
61
|
-
self.max_len = max_len
|
|
62
|
-
self.is_training = training
|
|
63
|
-
|
|
64
|
-
def train(self, enabled = True):
|
|
65
|
-
self.is_training = enabled
|
|
66
|
-
for block in self.blocks:
|
|
67
|
-
block.train(enabled=enabled)
|
|
68
|
-
def infer(self, enabled = True):
|
|
69
|
-
self.is_training = not enabled
|
|
70
|
-
for block in self.blocks:
|
|
71
|
-
block.infer(enabled=enabled)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def __call__(self, idx):
|
|
75
|
-
T = idx.shape[1]
|
|
76
|
-
causal = backend.np.triu(backend.np.ones((T, T)), k=1).astype(bool)
|
|
77
|
-
x = self.tok(idx) # straight from token embedding
|
|
78
|
-
for block in self.blocks:
|
|
79
|
-
x = block(x, mask=causal)
|
|
80
|
-
return self.head(self.ln_f(x))
|
|
81
|
-
|
|
82
|
-
def parameters(self):
|
|
83
|
-
ps = self.tok.parameters() + self.ln_f.parameters() + self.head.parameters()
|
|
84
|
-
for b in self.blocks: ps += b.parameters()
|
|
85
|
-
return ps
|
|
86
|
-
|
|
87
|
-
def generate(self, idx, n_new, temperature=1.0, top_k=None):
|
|
88
|
-
idx = numpy.asarray(idx)
|
|
89
|
-
was_training = self.is_training
|
|
90
|
-
self.infer()
|
|
91
|
-
original_grad_state = not backend.NO_GRAD
|
|
92
|
-
needGradientHence(False)
|
|
93
|
-
|
|
94
|
-
try:
|
|
95
|
-
for _ in range(n_new):
|
|
96
|
-
cond = idx[:, -self.max_len:]
|
|
97
|
-
logits = to_cpu(self(cond).data)[:, -1, :] / temperature
|
|
98
|
-
if top_k is not None:
|
|
99
|
-
kth = numpy.sort(logits, axis=-1)[:, -top_k][:, None]
|
|
100
|
-
logits = numpy.where(logits < kth, -1e9, logits)
|
|
101
|
-
z = logits - logits.max(-1, keepdims=True)
|
|
102
|
-
p = numpy.exp(z).astype(numpy.float64); p /= p.sum(-1, keepdims=True)
|
|
103
|
-
nxt = numpy.array([[numpy.random.choice(len(pr), p=pr)] for pr in p])
|
|
104
|
-
idx = numpy.concatenate([idx, nxt], axis=1)
|
|
105
|
-
# backend._cp.get_default_memory_pool().free_all_blocks() if backend.USE_GPU else None
|
|
106
|
-
return idx
|
|
107
|
-
finally:
|
|
108
|
-
if was_training:
|
|
109
|
-
self.train()
|
|
110
|
-
needGradientHence(original_grad_state)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|