@mineproness/tensorloop 1.5.2 → 1.5.4
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 +0 -2
- package/package.json +5 -3
- package/readme.md +8 -12
- package/src/FFN/index.js +1 -0
- package/src/GPU.js +167 -0
- package/src/Linear/index.js +6 -19
- package/src/Tokenizer/index.js +1 -2
- package/src/Tokenizer/vocabs.json +9 -1
- package/src/TransformerBlock/index.js +2 -7
- package/src/tools/index.d.ts +0 -3
- package/src/tools/index.js +0 -5
package/index.js
CHANGED
|
@@ -3,7 +3,6 @@ import { Embedding as embeddding2 } from "./src/Embedding/index.js";
|
|
|
3
3
|
import { Linear as li2 } from "./src/Linear/index.js";
|
|
4
4
|
import { Softmax as softmax2 } from "./src/Softmax/index.js";
|
|
5
5
|
import { crossEntropy } from "./src/crossEntropy/index.js";
|
|
6
|
-
import {tools} from './src/tools/index.js'
|
|
7
6
|
import {ReLU} from './src/ReLU/index.js'
|
|
8
7
|
import {PositionEmbedding as PE} from './src/PositionEmbedding/index.js'
|
|
9
8
|
import {SelfAttention as ST} from './src/SelfAttention/index.js'
|
|
@@ -15,7 +14,6 @@ export const Embedding = embeddding2
|
|
|
15
14
|
export const Linear = li2
|
|
16
15
|
export const Softmax = softmax2
|
|
17
16
|
export const CrossEntropy = crossEntropy
|
|
18
|
-
export const Tools = tools
|
|
19
17
|
export const ReLu = ReLU
|
|
20
18
|
export const PositionEmbedding = PE
|
|
21
19
|
export const SelfAttention = ST
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mineproness/tensorloop",
|
|
3
|
-
"version": "1.5.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.4",
|
|
4
|
+
"description": "Raw-JAVASCRIPT Based Matirx and AI LLM Package called Tensorloop.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
7
7
|
"llm",
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
21
|
"url": "https://github.com/mineproness-org/tensorloop.git"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"gpu.js": "^2.24.0"
|
|
22
25
|
}
|
|
23
|
-
|
|
24
26
|
}
|
package/readme.md
CHANGED
|
@@ -14,7 +14,7 @@ A high-performance JavaScript library that provides essential AI and Large Langu
|
|
|
14
14
|
- **Attention & Positioning**: Built-in **Self-Attention** and **Positional Embedding** matrices.
|
|
15
15
|
- **Text Processing**: Built-in **Tokenizer** to convert raw text into token IDs and back.
|
|
16
16
|
- **Special Tokens**: Native support for `<PAD>` and `<EOS>`.
|
|
17
|
-
|
|
17
|
+
- **FFN BLOCK**: It add a layer to understand Complex Patterns.
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
## 🏗 Core Architecture
|
|
@@ -93,7 +93,7 @@ const text = "Hello, Welcome to My Channel."
|
|
|
93
93
|
|
|
94
94
|
// Encode text to token IDs
|
|
95
95
|
const { tokenIDs } = tokenizer.encoder(text)
|
|
96
|
-
console.log(tokenIDs) // Output example: ["hello", "
|
|
96
|
+
console.log(tokenIDs) // Output example: ["hello", "$12", "well", "come", "$130"...]
|
|
97
97
|
|
|
98
98
|
// Decode token IDs back to text
|
|
99
99
|
const decoded = tokenizer.decoder(tokenIDs)
|
|
@@ -107,19 +107,15 @@ console.log(decoded) // Output: "Hello, Welcome to My Channel."
|
|
|
107
107
|
### 1. Use TypeScript
|
|
108
108
|
We highly recommend using **TypeScript** with TensorLoop to enforce type safety and leverage IDE autocomplete features for all active classes and methods.
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
Maximize efficiency by processing your layers with our built-in `Tools` utility suite:
|
|
112
|
-
|
|
113
|
-
```javascript
|
|
114
|
-
import { Tools } from '@mineproness/tensorloop'
|
|
115
|
-
|
|
116
|
-
const tools = new Tools()
|
|
110
|
+
---
|
|
117
111
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```
|
|
112
|
+
### 2. Always use NodeJS 20 Higher
|
|
113
|
+
This Package optimized for node js 20 or higher. If you use older version it Maybe Break Easliy.
|
|
121
114
|
|
|
122
115
|
---
|
|
116
|
+
### 3. Use GELU Always.
|
|
117
|
+
|
|
118
|
+
Gelu is Better Activation because it is not turn a gradient 0 so it is so smoothly works.
|
|
123
119
|
|
|
124
120
|
## ⭐ Support the Project
|
|
125
121
|
|
package/src/FFN/index.js
CHANGED
package/src/GPU.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { GPU } from "gpu.js";
|
|
2
|
+
|
|
3
|
+
const gpu = new GPU({
|
|
4
|
+
mode: "gpu"
|
|
5
|
+
})
|
|
6
|
+
const kernel = gpu.createKernel(function () {
|
|
7
|
+
return 1
|
|
8
|
+
}).setOutput([1])
|
|
9
|
+
|
|
10
|
+
kernel()
|
|
11
|
+
const gl = kernel.context
|
|
12
|
+
|
|
13
|
+
export function splitMatrix(matrix, chunksSizes = gl.getParameter(gl.MAX_TEXTURE_SIZE)) {
|
|
14
|
+
const chunks = []
|
|
15
|
+
for (let a = 0; a < matrix.length; a += chunksSizes) {
|
|
16
|
+
chunks.push(matrix.slice(a, a + chunksSizes))
|
|
17
|
+
}
|
|
18
|
+
return { split: true, data: chunks }
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const cacheLF = []
|
|
23
|
+
const cacheLBIas = []
|
|
24
|
+
const cacheLBWeights = []
|
|
25
|
+
const cacheLBInputGradent = []
|
|
26
|
+
export function InitKernel(weights, size) {
|
|
27
|
+
const splitedWeights = splitMatrix(weights)
|
|
28
|
+
for (let a = 0; a < splitedWeights.data.length; a++) {
|
|
29
|
+
cacheLF[a] = gpu.createKernel(function (input, bias, weights) {
|
|
30
|
+
let sum = bias[this.thread.x]
|
|
31
|
+
for (let a = 0; a < this.constants.inputLength; a++) {
|
|
32
|
+
sum += input[a] * weights[this.thread.x][a]
|
|
33
|
+
}
|
|
34
|
+
return sum
|
|
35
|
+
}).setConstants({
|
|
36
|
+
inputLength: splitedWeights.data[a].length
|
|
37
|
+
}).setOutput([splitedWeights.data[a].length])
|
|
38
|
+
cacheLBIas[a] = gpu.createKernel(function (
|
|
39
|
+
bias,
|
|
40
|
+
outputGradient,
|
|
41
|
+
learningRate
|
|
42
|
+
) {
|
|
43
|
+
const grad = Math.max(
|
|
44
|
+
-1,
|
|
45
|
+
Math.min(1, outputGradient[this.thread.x])
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return bias[this.thread.x] - learningRate * grad
|
|
49
|
+
})
|
|
50
|
+
.setOutput([splitedWeights.data[a].length])
|
|
51
|
+
cacheLBInputGradent[a] = gpu.createKernel(function (
|
|
52
|
+
weights,
|
|
53
|
+
outputGradient
|
|
54
|
+
) {
|
|
55
|
+
let sum = 0
|
|
56
|
+
|
|
57
|
+
for (let a = 0; a < this.constants.outputSize; a++) {
|
|
58
|
+
const grad = Math.max(
|
|
59
|
+
-1,
|
|
60
|
+
Math.min(1, outputGradient[a])
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
sum += grad * weights[a][this.thread.x]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return sum
|
|
67
|
+
})
|
|
68
|
+
.setConstants({
|
|
69
|
+
outputSize: splitedWeights.data[a].length
|
|
70
|
+
})
|
|
71
|
+
.setOutput([size])
|
|
72
|
+
cacheLBWeights[a] = gpu.createKernel(function (
|
|
73
|
+
weights,
|
|
74
|
+
outputGradient,
|
|
75
|
+
input,
|
|
76
|
+
learningRate
|
|
77
|
+
) {
|
|
78
|
+
const grad = Math.max(
|
|
79
|
+
-1,
|
|
80
|
+
Math.min(1, outputGradient[this.thread.y])
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return weights[this.thread.y][this.thread.x]
|
|
84
|
+
- learningRate * input[this.thread.x] * grad
|
|
85
|
+
})
|
|
86
|
+
.setOutput([size, splitedWeights.data[a].length])
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
export function CalculateLinearForward(weights, bias, input) {
|
|
92
|
+
const splitedBias = splitMatrix(bias)
|
|
93
|
+
const splitedWeights = splitMatrix(weights)
|
|
94
|
+
const result = new Float32Array(weights.length)
|
|
95
|
+
let offset = 0;
|
|
96
|
+
for (let a = 0; a < splitedBias.data.length; a++) {
|
|
97
|
+
const output = cacheLF[a](input, splitedBias.data[a], splitedWeights.data[a])
|
|
98
|
+
result.set(output, offset)
|
|
99
|
+
offset += output.length
|
|
100
|
+
}
|
|
101
|
+
return result
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function CalculateBackward(weights, bias, out, learningRate, input) {
|
|
105
|
+
const splitedBias = splitMatrix(bias)
|
|
106
|
+
const splitedWeights = splitMatrix(weights)
|
|
107
|
+
const inputGradient = new Float32Array(input.length)
|
|
108
|
+
const biasOut = new Float32Array(bias.length)
|
|
109
|
+
const weightsOut = []
|
|
110
|
+
let offsetBias = 0
|
|
111
|
+
let offsetWeights = 0
|
|
112
|
+
let gradientOffset = 0
|
|
113
|
+
|
|
114
|
+
for (let a = 0; a < splitedWeights.data.length; a++) {
|
|
115
|
+
const weightChunk = splitedWeights.data[a]
|
|
116
|
+
const biasChunk = splitedBias.data[a]
|
|
117
|
+
|
|
118
|
+
const chunkOutputSize = weightChunk.length
|
|
119
|
+
|
|
120
|
+
// Gradient belonging to this output/weight chunk
|
|
121
|
+
const gradientChunk = out.slice(
|
|
122
|
+
gradientOffset,
|
|
123
|
+
gradientOffset + chunkOutputSize
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
gradientOffset += chunkOutputSize
|
|
127
|
+
|
|
128
|
+
// Bias update
|
|
129
|
+
const newBias = cacheLBIas[a](
|
|
130
|
+
biasChunk,
|
|
131
|
+
gradientChunk,
|
|
132
|
+
learningRate
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
biasOut.set(newBias, offsetBias)
|
|
136
|
+
offsetBias += newBias.length
|
|
137
|
+
|
|
138
|
+
// Input gradient
|
|
139
|
+
const outputGra = cacheLBInputGradent[a](
|
|
140
|
+
weightChunk,
|
|
141
|
+
gradientChunk
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
// ADD this chunk's gradient to the same input gradient
|
|
145
|
+
for (let i = 0; i < outputGra.length; i++) {
|
|
146
|
+
inputGradient[i] += outputGra[i]
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Weight update
|
|
150
|
+
const newWeights = cacheLBWeights[a](
|
|
151
|
+
weightChunk,
|
|
152
|
+
gradientChunk,
|
|
153
|
+
input,
|
|
154
|
+
learningRate
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
// Copy chunk into final Float32Array
|
|
158
|
+
weightsOut.push(...newWeights)
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
inputGradient,
|
|
164
|
+
biasOut,
|
|
165
|
+
weightsOut
|
|
166
|
+
}
|
|
167
|
+
}
|
package/src/Linear/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LoadBias, LoadVectors, SaveBias, SaveVectors } from '../GetConfigs.js'
|
|
2
2
|
import { existsSync } from 'fs'
|
|
3
|
+
import { CalculateBackward, CalculateLinearForward, InitKernel } from '../GPU.js'
|
|
3
4
|
function GenerateWeightsBias(embeddingSize, vocabSize) {
|
|
4
5
|
const vectors = []
|
|
5
6
|
const Bias = new Float32Array(vocabSize)
|
|
@@ -38,6 +39,7 @@ export class Linear {
|
|
|
38
39
|
this.Weights = vectors;
|
|
39
40
|
this.Bias = Bias;
|
|
40
41
|
}
|
|
42
|
+
InitKernel(this.Weights, embeddingSize)
|
|
41
43
|
}
|
|
42
44
|
Save() {
|
|
43
45
|
SaveVectors(this.Weights, this.configs.save.filename[0])
|
|
@@ -45,29 +47,14 @@ export class Linear {
|
|
|
45
47
|
}
|
|
46
48
|
forward(input) {
|
|
47
49
|
this.input.push(input)
|
|
48
|
-
|
|
49
|
-
for (let a = 0; a < this.Weights.length; a++) {
|
|
50
|
-
let sum = this.Bias[a]
|
|
51
|
-
for (let t = 0; t < input.length; t++) {
|
|
52
|
-
sum += input[t] * this.Weights[a][t]
|
|
53
|
-
}
|
|
54
|
-
output[a] = sum
|
|
55
|
-
}
|
|
56
|
-
return output
|
|
50
|
+
return CalculateLinearForward(this.Weights, this.Bias, input)
|
|
57
51
|
}
|
|
58
52
|
backward(outputGradient, learningRate, idx) {
|
|
59
53
|
const input = this.input[idx];
|
|
60
54
|
const weights = this.Weights
|
|
61
|
-
const inputGradient =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const w = weights[a]
|
|
65
|
-
for (let at = 0; at < input.length; at++) {
|
|
66
|
-
inputGradient[at] += gran * w[at]
|
|
67
|
-
w[at] -= learningRate * input[at] * gran
|
|
68
|
-
}
|
|
69
|
-
this.Bias[a] -= learningRate * gran
|
|
70
|
-
}
|
|
55
|
+
const {biasOut,inputGradient, weightsOut} = CalculateBackward(weights, this.Bias, outputGradient, learningRate, input)
|
|
56
|
+
this.Weights = weightsOut;
|
|
57
|
+
this.Bias = biasOut
|
|
71
58
|
return inputGradient
|
|
72
59
|
}
|
|
73
60
|
ClearInputCache(){
|
package/src/Tokenizer/index.js
CHANGED
|
@@ -70,7 +70,7 @@ export class Tokenizer {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
return Validate(output.filter(e=> e.trim().length > 0)).join(" ").replaceAll(/\s+([,.;'{}
|
|
73
|
+
return Validate(output.filter(e=> e.trim().length > 0)).join(" ").replaceAll(/\s+([,.;'{}`!~\"?])/g, "$1")
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -86,7 +86,6 @@ function Validate(output = ["hello", "guys"]) {
|
|
|
86
86
|
bestOutput[idx] = e[0].toLocaleUpperCase() + e.slice(1, e.length)
|
|
87
87
|
} else {
|
|
88
88
|
bestOutput[idx] = e
|
|
89
|
-
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
91
|
|
|
@@ -19606,5 +19606,13 @@
|
|
|
19606
19606
|
"?",
|
|
19607
19607
|
"!",
|
|
19608
19608
|
"@",
|
|
19609
|
-
"$"
|
|
19609
|
+
"$",
|
|
19610
|
+
":",
|
|
19611
|
+
"/",
|
|
19612
|
+
"+",
|
|
19613
|
+
"-",
|
|
19614
|
+
"=",
|
|
19615
|
+
"%",
|
|
19616
|
+
"*",
|
|
19617
|
+
"@"
|
|
19610
19618
|
]
|
|
@@ -12,13 +12,8 @@ export class TransformerBlock {
|
|
|
12
12
|
return this.ffn.forward(attention)
|
|
13
13
|
}
|
|
14
14
|
backward(dOutput, learningRate) {
|
|
15
|
-
const dAttention =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return this.selfAttention.backward(
|
|
19
|
-
dAttention,
|
|
20
|
-
learningRate
|
|
21
|
-
)
|
|
15
|
+
const dAttention = this.ffn.backward(dOutput, learningRate)
|
|
16
|
+
return this.selfAttention.backward(dAttention, learningRate)
|
|
22
17
|
}
|
|
23
18
|
clearInputCache() {
|
|
24
19
|
this.ffn.ClearInputCache()
|
package/src/tools/index.d.ts
DELETED