@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.
- package/index.js +20 -0
- package/package.json +29 -6
- package/readme.md +959 -0
- package/src/Embedding/index.d.ts +21 -0
- package/src/Embedding/index.js +141 -0
- package/src/FFN/index.d.ts +23 -0
- package/src/FFN/index.js +45 -0
- package/src/Linear/index.d.ts +31 -0
- package/src/Linear/index.js +198 -0
- package/src/OperationManager.js +169 -0
- package/src/PositionEmbedding/index.d.ts +30 -0
- package/src/PositionEmbedding/index.js +65 -0
- package/src/RMSNorm/index.d.ts +30 -0
- package/src/RMSNorm/index.js +96 -0
- package/src/Relu/index.d.ts +25 -0
- package/src/Relu/index.js +110 -0
- package/src/SelfAttention/index.d.ts +28 -0
- package/src/SelfAttention/index.js +138 -0
- package/src/Softmax/index.d.ts +26 -0
- package/src/Softmax/index.js +225 -0
- package/src/Tokenizer/index.d.ts +12 -0
- package/src/Tokenizer/index.js +164 -0
- package/src/Tokenizer/vocabs.json +19618 -0
- package/src/TransformerBlock/index.d.ts +28 -0
- package/src/TransformerBlock/index.js +78 -0
- package/src/getVec.js +30 -0
- package/src/gpu.js +0 -0
- package/src/residualConnection/index.js +32 -0
- package/src/shaders/CalculateAcc.wgsl +50 -0
- package/src/shaders/CalculateLoss.wgsl +30 -0
- package/src/shaders/ComputeDInput.wgsl +32 -0
- package/src/shaders/EB.wgsl +33 -0
- package/src/shaders/EF.wgsl +25 -0
- package/src/shaders/LB.wgsl +75 -0
- package/src/shaders/LF.wgsl +60 -0
- package/src/shaders/Norm/rmsBackward.wgsl +65 -0
- package/src/shaders/Norm/rmsForward.wgsl +30 -0
- package/src/shaders/Norm/sumSquare.wgsl +38 -0
- package/src/shaders/Norm/updateGamma.wgsl +52 -0
- package/src/shaders/PB.wgsl +25 -0
- package/src/shaders/PF.wgsl +19 -0
- package/src/shaders/RB.wgsl +37 -0
- package/src/shaders/RF.wgsl +33 -0
- package/src/shaders/ReductionFunction.wgsl +28 -0
- package/src/shaders/SB.wgsl +36 -0
- package/src/shaders/SF.wgsl +75 -0
- package/src/shaders/SoftmaxBackward.wgsl +31 -0
- package/src/shaders/add.wgsl +30 -0
- package/src/shaders/attentionShader/CompueFinalForwardOutput.wgsl +29 -0
- package/src/shaders/attentionShader/ComputeDA.wgsl +30 -0
- package/src/shaders/attentionShader/ComputeDV.wgsl +37 -0
- package/src/shaders/attentionShader/ComputeK.wgsl +30 -0
- package/src/shaders/attentionShader/ComputedQ.wgsl +31 -0
- package/src/shaders/attentionShader/attentionSocres.wgsl +40 -0
- package/src/shaders/attentionShader/sumGradient.wgsl +24 -0
- package/src/shaders/calculateTotal.wgsl +26 -0
- 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
|
+
}
|