@imaduddin/fastbrain 0.0.0-stage → 1.0.0

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.
Files changed (57) hide show
  1. package/index.js +20 -0
  2. package/package.json +29 -6
  3. package/readme.md +959 -0
  4. package/src/Embedding/index.d.ts +21 -0
  5. package/src/Embedding/index.js +141 -0
  6. package/src/FFN/index.d.ts +23 -0
  7. package/src/FFN/index.js +45 -0
  8. package/src/Linear/index.d.ts +31 -0
  9. package/src/Linear/index.js +198 -0
  10. package/src/OperationManager.js +169 -0
  11. package/src/PositionEmbedding/index.d.ts +30 -0
  12. package/src/PositionEmbedding/index.js +65 -0
  13. package/src/RMSNorm/index.d.ts +30 -0
  14. package/src/RMSNorm/index.js +96 -0
  15. package/src/Relu/index.d.ts +25 -0
  16. package/src/Relu/index.js +110 -0
  17. package/src/SelfAttention/index.d.ts +28 -0
  18. package/src/SelfAttention/index.js +138 -0
  19. package/src/Softmax/index.d.ts +26 -0
  20. package/src/Softmax/index.js +225 -0
  21. package/src/Tokenizer/index.d.ts +12 -0
  22. package/src/Tokenizer/index.js +164 -0
  23. package/src/Tokenizer/vocabs.json +19618 -0
  24. package/src/TransformerBlock/index.d.ts +28 -0
  25. package/src/TransformerBlock/index.js +78 -0
  26. package/src/getVec.js +30 -0
  27. package/src/gpu.js +0 -0
  28. package/src/residualConnection/index.js +32 -0
  29. package/src/shaders/CalculateAcc.wgsl +50 -0
  30. package/src/shaders/CalculateLoss.wgsl +30 -0
  31. package/src/shaders/ComputeDInput.wgsl +32 -0
  32. package/src/shaders/EB.wgsl +33 -0
  33. package/src/shaders/EF.wgsl +25 -0
  34. package/src/shaders/LB.wgsl +75 -0
  35. package/src/shaders/LF.wgsl +60 -0
  36. package/src/shaders/Norm/rmsBackward.wgsl +65 -0
  37. package/src/shaders/Norm/rmsForward.wgsl +30 -0
  38. package/src/shaders/Norm/sumSquare.wgsl +38 -0
  39. package/src/shaders/Norm/updateGamma.wgsl +52 -0
  40. package/src/shaders/PB.wgsl +25 -0
  41. package/src/shaders/PF.wgsl +19 -0
  42. package/src/shaders/RB.wgsl +37 -0
  43. package/src/shaders/RF.wgsl +33 -0
  44. package/src/shaders/ReductionFunction.wgsl +28 -0
  45. package/src/shaders/SB.wgsl +36 -0
  46. package/src/shaders/SF.wgsl +75 -0
  47. package/src/shaders/SoftmaxBackward.wgsl +31 -0
  48. package/src/shaders/add.wgsl +30 -0
  49. package/src/shaders/attentionShader/CompueFinalForwardOutput.wgsl +29 -0
  50. package/src/shaders/attentionShader/ComputeDA.wgsl +30 -0
  51. package/src/shaders/attentionShader/ComputeDV.wgsl +37 -0
  52. package/src/shaders/attentionShader/ComputeK.wgsl +30 -0
  53. package/src/shaders/attentionShader/ComputedQ.wgsl +31 -0
  54. package/src/shaders/attentionShader/attentionSocres.wgsl +40 -0
  55. package/src/shaders/attentionShader/sumGradient.wgsl +24 -0
  56. package/src/shaders/calculateTotal.wgsl +26 -0
  57. package/README.md +0 -3
@@ -0,0 +1,225 @@
1
+ import { log } from 'console';
2
+ import { OperationManager } from '../OperationManager.js'
3
+
4
+ export class Softmax {
5
+ device;
6
+ vocabSize;
7
+ forwardPipline;
8
+ embeddingSize;
9
+ gpu;
10
+ paramsForward;
11
+ oldParam;
12
+ bp;
13
+ totalLoss;
14
+ totalAcc;
15
+ totalCalculate;
16
+ constructor(device, embeddingSize, vocabSize) {
17
+ this.vocabSize = vocabSize;
18
+ this.device = device;
19
+ this.embeddingSize = embeddingSize;
20
+ this.gpu = new OperationManager(device);
21
+ this.forwardPipline = this.gpu.getShaderPipline("./src/shaders/SF.wgsl")
22
+ this.backwardPipline = this.gpu.getShaderPipline("./src/shaders/SB.wgsl")
23
+ this.lossPipline = this.gpu.getShaderPipline("./src/shaders/CalculateLoss.wgsl")
24
+ this.accPipline = this.gpu.getShaderPipline("./src/shaders/CalculateAcc.wgsl")
25
+ this.battention = this.gpu.getShaderPipline("./src/shaders/SoftmaxBackward.wgsl")
26
+ this.reduceFn = this.gpu.getShaderPipline("./src/shaders/ReductionFunction.wgsl")
27
+ this.totalCalculate = this.gpu.getShaderPipline('./src/shaders/calculateTotal.wgsl')
28
+ }
29
+ async forward(logits, encoderCPU) {
30
+ const encoder = encoderCPU ? encoderCPU : this.device.createCommandEncoder()
31
+ const tokenCount = logits.size / (this.vocabSize * 4)
32
+ if (!this.paramsForward) {
33
+ this.paramsForward = await this.gpu.createUniFormBuffer(4 * 3)
34
+ }
35
+ if (!this.oldParam) {
36
+ this.oldParam = new Uint32Array([this.vocabSize, 0, 0])
37
+ }
38
+
39
+ if (this.oldParam[1] !== tokenCount) { await this.gpu.WriteBuffer(this.paramsForward, new Uint32Array([this.vocabSize, tokenCount, 0])); this.oldParam = new Uint32Array([this.vocabSize, tokenCount, 0]); }
40
+ if (!this.output) this.output = await this.gpu.ManageBuffer(logits.size);
41
+ if (this.output.size !== 4 * tokenCount * this.vocabSize || this.output.isDestroyed()) {
42
+ this.output.destroy()
43
+ this.output = await this.gpu.ManageBuffer(logits.size)
44
+ }
45
+ await this.output.count()
46
+ const bind = await this.device.createBindGroup({
47
+ layout: await this.forwardPipline.getBindGroupLayout(0),
48
+ entries: [
49
+ {
50
+ binding: 0,
51
+ resource: {
52
+ buffer: logits.mainBuffer
53
+ }
54
+ },
55
+ {
56
+ binding: 1,
57
+ resource: {
58
+ buffer: this.output.mainBuffer
59
+ }
60
+ }, {
61
+ binding: 2,
62
+ resource: {
63
+ buffer: this.paramsForward
64
+ }
65
+ }
66
+ ]
67
+ })
68
+ await this.gpu.RunPipline(encoder, this.forwardPipline, bind, tokenCount)
69
+ if (!encoderCPU) {
70
+ await this.device.queue.submit([encoder.finish()])
71
+ }
72
+ return this.output
73
+ }
74
+ async backward(probs, target, encoderMain) {
75
+ const encoder = encoderMain ? encoderMain : this.device.createCommandEncoder()
76
+ const tokenCount = probs.size / (this.vocabSize * 4)
77
+ if (!this.paramsForward) {
78
+ this.paramsForward = await this.gpu.createUniFormBuffer(4 * 3)
79
+ }
80
+ if (!this.oldParam) {
81
+ this.oldParam = new Uint32Array([this.vocabSize, 0, 0])
82
+ }
83
+ if (this.oldParam[1] !== tokenCount) {
84
+ await this.gpu.WriteBuffer(this.paramsForward, new Uint32Array([this.vocabSize, tokenCount, 0]));
85
+ this.oldParam = new Uint32Array([this.vocabSize, tokenCount, 0]);
86
+ }
87
+ if (!this.targetBuffer) this.targetBuffer = await this.gpu.createBuffer(target.length * Float32Array.BYTES_PER_ELEMENT);
88
+ if (this.targetBuffer.size !== target.length * 4) {
89
+ this.targetBuffer.destroy()
90
+ this.targetBuffer = await this.gpu.createBuffer(target.length * Float32Array.BYTES_PER_ELEMENT)
91
+ }
92
+ await this.gpu.WriteBuffer(this.targetBuffer, new Float32Array(target))
93
+ const bind = await this.device.createBindGroup({
94
+ layout: await this.backwardPipline.getBindGroupLayout(0),
95
+ entries: [
96
+ {
97
+ binding: 0,
98
+ resource: {
99
+ buffer: probs.mainBuffer
100
+ }
101
+ }, {
102
+ binding: 2,
103
+ resource: {
104
+ buffer: this.targetBuffer
105
+ }
106
+ }, {
107
+ binding: 3,
108
+ resource: {
109
+ buffer: this.paramsForward
110
+ }
111
+ }
112
+ ]
113
+ })
114
+ await this.gpu.RunPipline(encoder, this.backwardPipline, bind, Math.ceil((tokenCount * this.vocabSize) / 256))
115
+ if (!encoderMain) this.device.queue.submit([encoder.finish()])
116
+ return probs
117
+ }
118
+ async crossEntropy(probs, target, encoderMain) {
119
+ const encoder = encoderMain ? encoderMain : this.device.createCommandEncoder();
120
+ const tokenCount = probs.size / (this.vocabSize * Float32Array.BYTES_PER_ELEMENT);
121
+ if (!Number.isInteger(tokenCount) || tokenCount <= 0) {
122
+ throw new Error("Invalid probability buffer size or vocabulary size");
123
+ }
124
+ const targetBytes = target.length * Uint32Array.BYTES_PER_ELEMENT;
125
+
126
+ if (!this.targetBuffer || this.targetBuffer.size < targetBytes) {
127
+ this.targetBuffer =
128
+ await this.gpu.createBuffer(targetBytes);
129
+ }
130
+
131
+ if (!this.loss || this.loss.size < tokenCount * 4) {
132
+ this.loss = await this.gpu.createBuffer(tokenCount * 4);
133
+ }
134
+
135
+ if (!this.acc) {
136
+ this.acc = await this.gpu.createBuffer(4);
137
+ }
138
+
139
+ if (!this.totalAcc) {
140
+ this.totalAcc = await this.gpu.createBuffer(4);
141
+ await this.gpu.WriteBuffer(
142
+ this.totalAcc,
143
+ new Float32Array([0])
144
+ );
145
+ }
146
+
147
+ if (!this.totalLoss) {
148
+ this.totalLoss = await this.gpu.createBuffer(4);
149
+ await this.gpu.WriteBuffer(
150
+ this.totalLoss,
151
+ new Float32Array([0])
152
+ );
153
+ }
154
+
155
+ await this.gpu.WriteBuffer(
156
+ this.targetBuffer,
157
+ new Uint32Array(target)
158
+ );
159
+
160
+ const bindGroup1 = await this.gpu.createBindGroup(
161
+ this.lossPipline,
162
+ 0,
163
+ [probs.mainBuffer, this.targetBuffer, this.loss, this.paramsForward]
164
+ );
165
+
166
+ const bindGroup2 = await this.gpu.createBindGroup(
167
+ this.accPipline,
168
+ 0,
169
+ [this.paramsForward, probs.mainBuffer, this.acc, this.targetBuffer]
170
+ );
171
+
172
+ const bindGroup3 = await this.gpu.createBindGroup(
173
+ this.totalCalculate,
174
+ 0,
175
+ [this.loss, this.acc, this.totalLoss, this.totalAcc]
176
+ );
177
+
178
+ await this.gpu.RunPipline(
179
+ encoder,
180
+ this.lossPipline,
181
+ bindGroup1,
182
+ Math.ceil(tokenCount / 4)
183
+ );
184
+
185
+ await this.gpu.RunPipline(
186
+ encoder,
187
+ this.accPipline,
188
+ bindGroup2,
189
+ 1
190
+ );
191
+
192
+ await this.gpu.RunPipline(
193
+ encoder,
194
+ this.totalCalculate,
195
+ bindGroup3,
196
+ 1
197
+ );
198
+
199
+ if (!encoderMain) {
200
+ await this.gpu.submitQueue(encoder);
201
+ }
202
+
203
+ return {
204
+ loss: async () =>
205
+ (await this.gpu.readBuffer(4, this.totalLoss))[0],
206
+
207
+ acc: async () =>
208
+ (await this.gpu.readBuffer(4, this.totalAcc))[0],
209
+
210
+ clear: async () => {
211
+ await this.gpu.WriteBuffer(
212
+ this.totalLoss,
213
+ new Float32Array([0])
214
+ );
215
+
216
+ await this.gpu.WriteBuffer(
217
+ this.totalAcc,
218
+ new Float32Array([0])
219
+ );
220
+ }
221
+ };
222
+ }
223
+
224
+ }
225
+
@@ -0,0 +1,12 @@
1
+ export class Tokenizer{
2
+ vocabs : string[]
3
+ vocabSize: number
4
+ IdtoWord : Record<string, string>
5
+ WordtoID : Record<string , number>
6
+ encoder(text: string) : {
7
+ tokens: string[]
8
+ tokenIDs: number[]
9
+ }
10
+ decoder(tokens: number[] | number[][]) : string
11
+ trainTokenizer(text: string, mergeSize: number, filename: string) : void
12
+ }
@@ -0,0 +1,164 @@
1
+ import fs, { existsSync, readFileSync } from 'fs'
2
+ import { join, dirname, format } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url))
6
+ export class Tokenizer {
7
+ vocabs = [];
8
+ vocabSize = 0;
9
+ IdtoWord = {};
10
+ WordtoID = {};
11
+ EOSToken = 2
12
+ constructor(filename = "") {
13
+ if (fs.existsSync(filename)) {
14
+ console.log("Warning: Tokenizer is loaded with a Custom Vocab File!")
15
+ console.log("")
16
+ this.vocabs = JSON.parse(readFileSync(filename, "utf-8"))
17
+ } else {
18
+ this.vocabs = JSON.parse(readFileSync(join(__dirname, "vocabs.json"), "utf-8"))
19
+ }
20
+ this.vocabSize = this.vocabs.length
21
+ this.IdtoWord = Object.fromEntries(this.vocabs.map((e, idx) => [idx, e]))
22
+ this.WordtoID = Object.fromEntries(this.vocabs.map((e, idx) => [e, idx]))
23
+ }
24
+ encoder(text = "") {
25
+ const AddSpaces = text.replaceAll(/<EOS>/gi, " <EOS> ").toLocaleLowerCase().replaceAll(/<eos>/g, " <EOS> ").replaceAll(/([,.;'{}!`~|":?])/g, " $1 ");
26
+ const splitedWords = AddSpaces.split(/\s+/).filter(e => e.length > 0)
27
+ const output = []
28
+ for (let a = 0; a < splitedWords.length; a++) {
29
+ const word = splitedWords[a]
30
+ if (typeof this.WordtoID[word] !== "undefined") {
31
+ output.push(word)
32
+ } else {
33
+ let max = word.length
34
+ output.push("$12")
35
+ while (true) {
36
+ const regPatten = new RegExp(`.{0,${max}}`, "g")
37
+ const wordsliced = word.match(regPatten).filter((e) => e.length > 0)
38
+ const matched = wordsliced.flatMap(e => {
39
+ if (this.WordtoID[e] !== undefined) {
40
+ return true
41
+ }
42
+ return false
43
+
44
+ }).reduce((prev, curr) => prev && curr, true)
45
+ if (wordsliced.length == 0) output.push("<unk>")
46
+ if (matched) {
47
+ wordsliced.map((e) => output.push(e))
48
+ output.push("$130")
49
+ break
50
+ } else {
51
+ max -= 1
52
+ // break
53
+ }
54
+
55
+ }
56
+ }
57
+ }
58
+ return { tokens: output, tokenIDs: output.map((e) => this.WordtoID[e]) }
59
+ }
60
+ decoder(tokens = [1, 2, 3]) {
61
+ const output = []
62
+ let isSpace = false
63
+ // let index = 0
64
+ for (let token of tokens) {
65
+ const formated = this.IdtoWord[String(token)]
66
+ if (formated == "$12") {
67
+ output[output.length] = ""
68
+ isSpace = true
69
+ } else if (formated == "$130") {
70
+ isSpace = false
71
+ } else {
72
+ if (isSpace) {
73
+ output[output.length - 1] += formated
74
+ } else {
75
+ output.push(formated)
76
+ }
77
+ }
78
+ }
79
+ return output.filter(e => e.trim().length > 0).join(" ").replaceAll(/\s+([,.;'{}`!~\"?])/g, "$1")
80
+ }
81
+ trainTokenizer(text = "ejrnienieijr", mergeLength = 5, vocabFileName) {
82
+ console.log("Training The Tokenizer....")
83
+ const arrText = text.toLowerCase().replace(/\r\n|\n|\r/g, " <EOS> ").toLocaleLowerCase().replaceAll(/<eos>/g, " <EOS> ").replace(/([,.;'{}!`~|":><?])/g, " $1 ").split(/\s+/).map(e => e.trim()).filter(e => e.length > 0)
84
+ const reg = new RegExp(`.{0,${mergeLength}}`, "g")
85
+ const prevVocab = existsSync(vocabFileName) ? JSON.parse(readFileSync(vocabFileName, "utf-8")) : [];
86
+ const specal = ["<unk>",
87
+ "<PAD>",
88
+ "<EOS>",
89
+ "$12",
90
+ "$130",
91
+ "😀",
92
+ "😃",
93
+ "😄",
94
+ "😁",
95
+ "😆",
96
+ "😅",
97
+ "😂",
98
+ "🤣",
99
+ "😊",
100
+ "😎",
101
+ "❤️",
102
+ "👍",
103
+ "👎",
104
+ "🔥",
105
+ "💯",
106
+ "🎉",
107
+ "🚀",
108
+ "⭐",
109
+ "😭",
110
+ "😍",
111
+ "🥰",
112
+ "😡",
113
+ "🤔",
114
+ "😢",
115
+ "😮",
116
+ "👋",
117
+ "🙏",
118
+ "💀",
119
+ "🤖",
120
+ "👀",
121
+ "💕",
122
+ "💔",
123
+ "😂😂",
124
+ "😂😭",
125
+ "🔥🔥",
126
+ "❤️❤️",
127
+ "👍👍",
128
+ "<",
129
+ ">",
130
+ ".",
131
+ "{",
132
+ "}",
133
+ "?",
134
+ "!",
135
+ "@",
136
+ "$",
137
+ ":",
138
+ "/",
139
+ "+",
140
+ "-",
141
+ "=",
142
+ "%",
143
+ "*",
144
+ "@"
145
+ ]
146
+ const uniArr = [...new Set([...arrText, ...specal, ...prevVocab])];
147
+ const output = []
148
+ for (let a = 0; a < uniArr.length; a++) {
149
+ let text = uniArr[a].match(reg).filter((e) => e.length > 0);
150
+ output.push(...text)
151
+ }
152
+ let finalOutput = [...new Set([...output])]
153
+ fs.writeFileSync(vocabFileName, JSON.stringify(finalOutput, null, 2), "utf-8");
154
+ console.log("_________________________________")
155
+ console.log(`New VocabSize : ${finalOutput.length - prevVocab.length}`);
156
+ console.log("_________________________________")
157
+ console.log("Operation Completed!")
158
+ this.vocabs = finalOutput;
159
+ this.vocabSize = finalOutput.length;
160
+ this.IdtoWord = Object.fromEntries(this.vocabs.map((e, idx) => [idx, e]))
161
+ this.WordtoID = Object.fromEntries(this.vocabs.map((e, idx) => [e, idx]))
162
+
163
+ }
164
+ }