@aleph-ai/tinyaleph 1.5.7 → 1.6.1
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/core/alexander-module.js +1469 -0
- package/core/arithmetic-link-kernel.js +1338 -0
- package/core/emotion.js +565 -0
- package/core/gravity.js +714 -0
- package/core/hilbert.js +506 -3
- package/core/index.js +132 -4
- package/core/nonlocal.js +744 -0
- package/core/oracle.js +662 -0
- package/examples/01-hello-world.js +69 -0
- package/examples/02-basic-hash.js +90 -0
- package/examples/02-observer-stack.js +385 -0
- package/examples/03-quantum-coin.js +136 -0
- package/examples/05-symbolic-resonance.js +146 -0
- package/examples/06-symbol-database.js +150 -0
- package/examples/07-semantic-inference.js +223 -0
- package/examples/08-compound-symbols.js +219 -0
- package/examples/README.md +170 -0
- package/examples/ai/01-embeddings.js +155 -0
- package/examples/ai/02-semantic-memory.js +243 -0
- package/examples/ai/03-reasoning.js +243 -0
- package/examples/ai/04-knowledge-graph.js +279 -0
- package/examples/ai/05-llm-integration.js +333 -0
- package/examples/ai/06-agent.js +294 -0
- package/examples/ai/07-hybrid-ai.js +223 -0
- package/examples/ai/08-entropy-reasoning.js +259 -0
- package/examples/ai/09-concept-learning.js +271 -0
- package/examples/ai/10-prompt-primes.js +312 -0
- package/examples/ai/11-rag.js +332 -0
- package/examples/ai/12-neuro-symbolic.js +321 -0
- package/examples/ai/README.md +80 -0
- package/examples/arithmetic-topology/01-legendre-symbol.js +78 -0
- package/examples/arithmetic-topology/02-redei-symbol.js +126 -0
- package/examples/arithmetic-topology/03-alk-kuramoto.js +138 -0
- package/examples/arithmetic-topology/04-alexander-module.js +117 -0
- package/examples/arithmetic-topology/05-signature-memory.js +118 -0
- package/examples/arithmetic-topology/README.md +291 -0
- package/examples/bioinformatics/01-dna-encoding.js +108 -0
- package/examples/bioinformatics/02-central-dogma.js +162 -0
- package/examples/bioinformatics/03-protein-folding.js +206 -0
- package/examples/bioinformatics/04-dna-computing.js +192 -0
- package/examples/bioinformatics/05-molecular-binding.js +209 -0
- package/examples/book-operators-demo.js +155 -0
- package/examples/chat.js +105 -0
- package/examples/crt-homology/01-residue-encoding.js +87 -0
- package/examples/crt-homology/02-birkhoff-attention.js +100 -0
- package/examples/crt-homology/03-homology-loss.js +132 -0
- package/examples/crt-homology/04-crt-resoformer.js +132 -0
- package/examples/crt-homology/README.md +67 -0
- package/examples/crypto/01-password-hash.js +210 -0
- package/examples/crypto/02-key-derivation.js +210 -0
- package/examples/crypto/03-hmac.js +229 -0
- package/examples/crypto/04-file-integrity.js +263 -0
- package/examples/crypto/05-content-hash.js +263 -0
- package/examples/crypto/README.md +99 -0
- package/examples/demo-modular.js +223 -0
- package/examples/demo-two-layer.js +196 -0
- package/examples/discrete/01-integer-sine-table.js +120 -0
- package/examples/discrete/02-codebook-tunneling.js +118 -0
- package/examples/discrete/03-canonical-fusion.js +135 -0
- package/examples/discrete/04-tick-gate.js +139 -0
- package/examples/discrete/README.md +142 -0
- package/examples/emotion-demo.js +200 -0
- package/examples/formal-semantics/01-typed-terms.js +156 -0
- package/examples/formal-semantics/02-reduction.js +202 -0
- package/examples/formal-semantics/03-lambda-translation.js +206 -0
- package/examples/formal-semantics/04-enochian-language.js +257 -0
- package/examples/formal-semantics/README.md +98 -0
- package/examples/gravity-demo.js +190 -0
- package/examples/math/01-quaternions.js +237 -0
- package/examples/math/02-octonions.js +192 -0
- package/examples/math/03-prime-factorization.js +215 -0
- package/examples/math/04-vector-spaces.js +210 -0
- package/examples/math/05-gaussian-primes.js +234 -0
- package/examples/math/README.md +93 -0
- package/examples/nonlocal-demo.js +237 -0
- package/examples/oracle-demo.js +204 -0
- package/examples/physics/01-oscillator.js +177 -0
- package/examples/physics/02-lyapunov.js +201 -0
- package/examples/physics/03-collapse.js +183 -0
- package/examples/physics/04-kuramoto.js +212 -0
- package/examples/physics/05-entropy.js +226 -0
- package/examples/physics/05-sync-models.js +298 -0
- package/examples/physics/06-primeon-ladder.js +233 -0
- package/examples/physics/07-kuramoto-coupled-ladder.js +298 -0
- package/examples/physics/README.md +126 -0
- package/examples/quantum/01-prime-hunter.js +79 -0
- package/examples/quantum/02-entanglement-demo.js +79 -0
- package/examples/quantum/03-wave-analysis.js +63 -0
- package/examples/resonance/01-prime-hilbert-space.js +140 -0
- package/examples/resonance/02-prime-resonance-network.js +221 -0
- package/examples/resonance/03-resoformer.js +349 -0
- package/examples/resonance/04-resoformer-training.js +329 -0
- package/examples/resonance/05-language-model.js +484 -0
- package/examples/resonance/README.md +238 -0
- package/examples/run-examples.js +427 -0
- package/examples/scientific/01-single-qubit.js +185 -0
- package/examples/scientific/02-two-qubit.js +209 -0
- package/examples/scientific/03-quantum-circuits.js +270 -0
- package/examples/scientific/04-measurement.js +229 -0
- package/examples/scientific/05-algorithms.js +245 -0
- package/examples/scientific/06-random.js +225 -0
- package/examples/scientific/07-wavefunction.js +192 -0
- package/examples/scientific/README.md +118 -0
- package/examples/semantic/01-vocabulary.js +186 -0
- package/examples/semantic/02-similarity.js +263 -0
- package/examples/semantic/03-word-algebra.js +295 -0
- package/examples/semantic/04-clustering.js +348 -0
- package/examples/semantic/05-classification.js +386 -0
- package/examples/semantic/06-dna-encoding.js +228 -0
- package/examples/semantic/07-search.js +304 -0
- package/examples/semantic/08-qa-system.js +278 -0
- package/examples/semantic/README.md +116 -0
- package/examples/topology/01-108-invariant.js +81 -0
- package/examples/topology/02-trefoil-constants.js +112 -0
- package/examples/topology/03-gauge-symmetry.js +112 -0
- package/examples/topology/04-free-energy-dynamics.js +124 -0
- package/examples/topology/README.md +129 -0
- package/index.js +32 -0
- package/modular.js +63 -2
- package/package.json +8 -3
- package/physics/alk-kuramoto.js +817 -0
- package/physics/index.js +23 -2
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example 05: ResoFormer Language Model
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates training a ResoFormer on actual language:
|
|
5
|
+
* - Character-level language model
|
|
6
|
+
* - Trains on sample text corpus
|
|
7
|
+
* - Generates new text using the trained model
|
|
8
|
+
*
|
|
9
|
+
* Run with: node examples/resonance/05-language-model.js
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const tf = require('@tensorflow/tfjs-node');
|
|
13
|
+
const {
|
|
14
|
+
ResoFormerBlock
|
|
15
|
+
} = require('../../core/rformer-tf');
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// SAMPLE TEXT CORPUS - More text for better training
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
const SAMPLE_TEXT = `
|
|
22
|
+
To be, or not to be, that is the question:
|
|
23
|
+
Whether 'tis nobler in the mind to suffer
|
|
24
|
+
The slings and arrows of outrageous fortune,
|
|
25
|
+
Or to take arms against a sea of troubles
|
|
26
|
+
And by opposing end them. To die, to sleep,
|
|
27
|
+
No more; and by a sleep to say we end
|
|
28
|
+
The heart-ache and the thousand natural shocks
|
|
29
|
+
That flesh is heir to. To die, to sleep;
|
|
30
|
+
To sleep, perchance to dream. For in that sleep of death
|
|
31
|
+
what dreams may come when we have shuffled off this mortal coil,
|
|
32
|
+
Must give us pause. There is the respect
|
|
33
|
+
That makes calamity of so long life.
|
|
34
|
+
|
|
35
|
+
All the world is a stage,
|
|
36
|
+
And all the men and women merely players;
|
|
37
|
+
They have their exits and their entrances,
|
|
38
|
+
And one man in his time plays many parts,
|
|
39
|
+
His acts being seven ages. At first, the infant,
|
|
40
|
+
Then the whining schoolboy, with his satchel
|
|
41
|
+
And shining morning face, creeping like snail
|
|
42
|
+
Unwillingly to school. And then the lover,
|
|
43
|
+
Sighing like furnace, with a woeful ballad
|
|
44
|
+
Made to his mistress. Then a soldier,
|
|
45
|
+
Full of strange oaths and bearded like the pard,
|
|
46
|
+
Jealous in honour, sudden and quick in quarrel,
|
|
47
|
+
Seeking the bubble reputation
|
|
48
|
+
Even in the cannon mouth.
|
|
49
|
+
|
|
50
|
+
Now is the winter of our discontent
|
|
51
|
+
Made glorious summer by this sun of York;
|
|
52
|
+
And all the clouds that lowered upon our house
|
|
53
|
+
In the deep bosom of the ocean buried.
|
|
54
|
+
Now are our brows bound with victorious wreaths;
|
|
55
|
+
Our bruised arms hung up for monuments;
|
|
56
|
+
Our stern alarums changed to merry meetings,
|
|
57
|
+
Our dreadful marches to delightful measures.
|
|
58
|
+
|
|
59
|
+
The quality of mercy is not strained,
|
|
60
|
+
It droppeth as the gentle rain from heaven
|
|
61
|
+
Upon the place beneath. It is twice blest;
|
|
62
|
+
It blesseth him that gives and him that takes.
|
|
63
|
+
It is mightiest in the mightiest. It becomes
|
|
64
|
+
The throned monarch better than his crown;
|
|
65
|
+
His sceptre shows the force of temporal power,
|
|
66
|
+
The attribute to awe and majesty,
|
|
67
|
+
Wherein doth sit the dread and fear of kings;
|
|
68
|
+
But mercy is above this sceptred sway;
|
|
69
|
+
It is enthroned in the hearts of kings,
|
|
70
|
+
It is an attribute to God himself.
|
|
71
|
+
|
|
72
|
+
Friends, Romans, countrymen, lend me your ears;
|
|
73
|
+
I come to bury Caesar, not to praise him.
|
|
74
|
+
The evil that men do lives after them;
|
|
75
|
+
The good is oft interred with their bones;
|
|
76
|
+
So let it be with Caesar. The noble Brutus
|
|
77
|
+
Hath told you Caesar was ambitious.
|
|
78
|
+
If it were so, it was a grievous fault,
|
|
79
|
+
And grievously hath Caesar answered it.
|
|
80
|
+
|
|
81
|
+
Tomorrow, and tomorrow, and tomorrow,
|
|
82
|
+
Creeps in this petty pace from day to day,
|
|
83
|
+
To the last syllable of recorded time;
|
|
84
|
+
And all our yesterdays have lighted fools
|
|
85
|
+
The way to dusty death. Out, out, brief candle!
|
|
86
|
+
Life is but a walking shadow, a poor player,
|
|
87
|
+
That struts and frets his hour upon the stage,
|
|
88
|
+
And then is heard no more. It is a tale
|
|
89
|
+
Told by an idiot, full of sound and fury,
|
|
90
|
+
Signifying nothing.
|
|
91
|
+
|
|
92
|
+
We are such stuff as dreams are made on,
|
|
93
|
+
and our little life is rounded with a sleep.
|
|
94
|
+
|
|
95
|
+
Now is the winter of our discontent
|
|
96
|
+
made glorious summer by this son of York;
|
|
97
|
+
and all the clouds that lowered upon our house
|
|
98
|
+
in the deep bosom of the ocean buried.
|
|
99
|
+
|
|
100
|
+
The quality of mercy is not strained.
|
|
101
|
+
It droppeth as the gentle rain from heaven
|
|
102
|
+
upon the place beneath. It is twice blessed.
|
|
103
|
+
It blesseth him that gives and him that takes.
|
|
104
|
+
|
|
105
|
+
Is this a dagger which I see before me,
|
|
106
|
+
The handle toward my hand? Come, let me clutch thee.
|
|
107
|
+
I have thee not, and yet I see thee still.
|
|
108
|
+
Art thou not, fatal vision, sensible
|
|
109
|
+
To feeling as to sight? or art thou but
|
|
110
|
+
A dagger of the mind, a false creation,
|
|
111
|
+
Proceeding from the heat-oppressed brain?
|
|
112
|
+
|
|
113
|
+
If music be the food of love, play on;
|
|
114
|
+
Give me excess of it, that, surfeiting,
|
|
115
|
+
The appetite may sicken, and so die.
|
|
116
|
+
That strain again! it had a dying fall:
|
|
117
|
+
O, it came over my ear like the sweet sound.
|
|
118
|
+
|
|
119
|
+
Shall I compare thee to a summer day?
|
|
120
|
+
Thou art more lovely and more temperate.
|
|
121
|
+
Rough winds do shake the darling buds of May,
|
|
122
|
+
And summer lease hath all too short a date.
|
|
123
|
+
|
|
124
|
+
Now is the time for all good men to come to the aid.
|
|
125
|
+
The quick brown fox jumps over the lazy dog.
|
|
126
|
+
A stitch in time saves nine.
|
|
127
|
+
To be or not to be that is the question.
|
|
128
|
+
All that glitters is not gold.
|
|
129
|
+
Actions speak louder than words.
|
|
130
|
+
`.trim().toLowerCase();
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// TOKENIZATION
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
class CharTokenizer {
|
|
137
|
+
constructor() {
|
|
138
|
+
this.charToId = new Map();
|
|
139
|
+
this.idToChar = new Map();
|
|
140
|
+
this.vocabSize = 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fit(text) {
|
|
144
|
+
const chars = [...new Set(text)].sort();
|
|
145
|
+
|
|
146
|
+
this.charToId.set('<pad>', 0);
|
|
147
|
+
this.idToChar.set(0, '');
|
|
148
|
+
|
|
149
|
+
let id = 1;
|
|
150
|
+
for (const char of chars) {
|
|
151
|
+
this.charToId.set(char, id);
|
|
152
|
+
this.idToChar.set(id, char);
|
|
153
|
+
id++;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.vocabSize = id;
|
|
157
|
+
console.log(`Vocabulary: ${this.vocabSize} tokens (${chars.length} unique chars)`);
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
encode(text) {
|
|
162
|
+
return [...text].map(c => this.charToId.get(c) || 0);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
decode(ids) {
|
|
166
|
+
return ids.map(id => this.idToChar.get(id) || '').join('');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ============================================================================
|
|
171
|
+
// DATA PREPARATION
|
|
172
|
+
// ============================================================================
|
|
173
|
+
|
|
174
|
+
function createTrainingData(text, tokenizer, seqLen = 32, stride = 4) {
|
|
175
|
+
const encoded = tokenizer.encode(text);
|
|
176
|
+
const sequences = [];
|
|
177
|
+
const targets = [];
|
|
178
|
+
|
|
179
|
+
// Create more overlapping sequences
|
|
180
|
+
for (let i = 0; i < encoded.length - seqLen; i += stride) {
|
|
181
|
+
const seq = encoded.slice(i, i + seqLen);
|
|
182
|
+
const target = encoded.slice(i + 1, i + seqLen + 1);
|
|
183
|
+
sequences.push(seq);
|
|
184
|
+
targets.push(target);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
console.log(`Created ${sequences.length} training sequences (stride=${stride})`);
|
|
188
|
+
|
|
189
|
+
const x = tf.tensor2d(sequences, [sequences.length, seqLen], 'int32');
|
|
190
|
+
const y = tf.tensor3d(
|
|
191
|
+
targets.map(t => t.map(id => {
|
|
192
|
+
const oneHot = new Array(tokenizer.vocabSize).fill(0);
|
|
193
|
+
oneHot[id] = 1;
|
|
194
|
+
return oneHot;
|
|
195
|
+
})),
|
|
196
|
+
[targets.length, seqLen, tokenizer.vocabSize]
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return { x, y };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// SIMPLER MODEL (for better convergence)
|
|
204
|
+
// ============================================================================
|
|
205
|
+
|
|
206
|
+
function createSimpleLanguageModel(config = {}) {
|
|
207
|
+
const {
|
|
208
|
+
vocabSize,
|
|
209
|
+
seqLen = 32,
|
|
210
|
+
dim = 256,
|
|
211
|
+
numHeads = 8,
|
|
212
|
+
ffnDim = 512,
|
|
213
|
+
dropout = 0.1
|
|
214
|
+
} = config;
|
|
215
|
+
|
|
216
|
+
const input = tf.input({ shape: [seqLen], dtype: 'int32', name: 'input_ids' });
|
|
217
|
+
|
|
218
|
+
// Token + position embedding
|
|
219
|
+
let x = tf.layers.embedding({
|
|
220
|
+
inputDim: vocabSize,
|
|
221
|
+
outputDim: dim,
|
|
222
|
+
name: 'token_embedding'
|
|
223
|
+
}).apply(input);
|
|
224
|
+
|
|
225
|
+
// Simple transformer-style blocks
|
|
226
|
+
for (let i = 0; i < 3; i++) {
|
|
227
|
+
// Pre-norm
|
|
228
|
+
const normed = tf.layers.layerNormalization({ name: `ln1_${i}` }).apply(x);
|
|
229
|
+
|
|
230
|
+
// Self-attention (using dense projections)
|
|
231
|
+
const q = tf.layers.dense({ units: dim, name: `q_${i}` }).apply(normed);
|
|
232
|
+
const k = tf.layers.dense({ units: dim, name: `k_${i}` }).apply(normed);
|
|
233
|
+
const v = tf.layers.dense({ units: dim, name: `v_${i}` }).apply(normed);
|
|
234
|
+
|
|
235
|
+
// Simple attention: softmax(QK^T / sqrt(d)) V
|
|
236
|
+
// Use dot product attention
|
|
237
|
+
let attn = tf.layers.dot({ axes: -1, name: `attn_dot_${i}` }).apply([q, k]);
|
|
238
|
+
attn = tf.layers.activation({ activation: 'softmax', name: `attn_softmax_${i}` }).apply(attn);
|
|
239
|
+
attn = tf.layers.dot({ axes: [2, 1], name: `attn_v_${i}` }).apply([attn, v]);
|
|
240
|
+
|
|
241
|
+
// Residual
|
|
242
|
+
x = tf.layers.add({ name: `res1_${i}` }).apply([x, attn]);
|
|
243
|
+
|
|
244
|
+
// FFN
|
|
245
|
+
const normed2 = tf.layers.layerNormalization({ name: `ln2_${i}` }).apply(x);
|
|
246
|
+
let ffn = tf.layers.dense({ units: ffnDim, activation: 'relu', name: `ffn1_${i}` }).apply(normed2);
|
|
247
|
+
ffn = tf.layers.dense({ units: dim, name: `ffn2_${i}` }).apply(ffn);
|
|
248
|
+
|
|
249
|
+
x = tf.layers.add({ name: `res2_${i}` }).apply([x, ffn]);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Final norm and output
|
|
253
|
+
x = tf.layers.layerNormalization({ name: 'final_ln' }).apply(x);
|
|
254
|
+
const output = tf.layers.dense({
|
|
255
|
+
units: vocabSize,
|
|
256
|
+
activation: 'softmax',
|
|
257
|
+
name: 'lm_head'
|
|
258
|
+
}).apply(x);
|
|
259
|
+
|
|
260
|
+
return tf.model({
|
|
261
|
+
inputs: input,
|
|
262
|
+
outputs: output,
|
|
263
|
+
name: 'SimpleLM'
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// ResoFormer-based Language Model
|
|
269
|
+
// ============================================================================
|
|
270
|
+
|
|
271
|
+
function createResoFormerLM(config = {}) {
|
|
272
|
+
const {
|
|
273
|
+
vocabSize,
|
|
274
|
+
seqLen = 32,
|
|
275
|
+
dim = 256,
|
|
276
|
+
numLayers = 3,
|
|
277
|
+
numHeads = 8,
|
|
278
|
+
ffnDim = 512,
|
|
279
|
+
dropout = 0.1
|
|
280
|
+
} = config;
|
|
281
|
+
|
|
282
|
+
const input = tf.input({ shape: [seqLen], dtype: 'int32', name: 'input_ids' });
|
|
283
|
+
|
|
284
|
+
// Token embedding
|
|
285
|
+
let x = tf.layers.embedding({
|
|
286
|
+
inputDim: vocabSize,
|
|
287
|
+
outputDim: dim,
|
|
288
|
+
name: 'token_embedding'
|
|
289
|
+
}).apply(input);
|
|
290
|
+
|
|
291
|
+
// Stack of ResoFormer blocks
|
|
292
|
+
for (let i = 0; i < numLayers; i++) {
|
|
293
|
+
const block = new ResoFormerBlock({
|
|
294
|
+
dim,
|
|
295
|
+
numHeads,
|
|
296
|
+
ffnDim,
|
|
297
|
+
dropout,
|
|
298
|
+
useCollapse: i === numLayers - 1,
|
|
299
|
+
name: `resoformer_block_${i}`
|
|
300
|
+
});
|
|
301
|
+
x = block.apply(x);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Final norm
|
|
305
|
+
x = tf.layers.layerNormalization({ name: 'final_ln' }).apply(x);
|
|
306
|
+
|
|
307
|
+
// LM head
|
|
308
|
+
const output = tf.layers.dense({
|
|
309
|
+
units: vocabSize,
|
|
310
|
+
activation: 'softmax',
|
|
311
|
+
name: 'lm_head'
|
|
312
|
+
}).apply(x);
|
|
313
|
+
|
|
314
|
+
return tf.model({
|
|
315
|
+
inputs: input,
|
|
316
|
+
outputs: output,
|
|
317
|
+
name: 'ResoFormerLM'
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// ============================================================================
|
|
322
|
+
// TEXT GENERATION
|
|
323
|
+
// ============================================================================
|
|
324
|
+
|
|
325
|
+
async function generateText(model, tokenizer, prompt, maxLen = 100, temperature = 0.8) {
|
|
326
|
+
const seqLen = model.inputs[0].shape[1];
|
|
327
|
+
let context = tokenizer.encode(prompt);
|
|
328
|
+
|
|
329
|
+
if (context.length > seqLen) {
|
|
330
|
+
context = context.slice(-seqLen);
|
|
331
|
+
} else if (context.length < seqLen) {
|
|
332
|
+
context = new Array(seqLen - context.length).fill(0).concat(context);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
let generated = prompt;
|
|
336
|
+
|
|
337
|
+
for (let i = 0; i < maxLen; i++) {
|
|
338
|
+
const inputTensor = tf.tensor2d([context], [1, seqLen], 'int32');
|
|
339
|
+
const logits = model.predict(inputTensor);
|
|
340
|
+
const lastLogits = logits.slice([0, seqLen - 1, 0], [1, 1, -1]).squeeze();
|
|
341
|
+
|
|
342
|
+
// Temperature scaling
|
|
343
|
+
const scaled = lastLogits.div(temperature);
|
|
344
|
+
const probs = tf.softmax(scaled);
|
|
345
|
+
|
|
346
|
+
// Sample
|
|
347
|
+
const nextTokenId = tf.multinomial(probs.expandDims(0), 1).dataSync()[0];
|
|
348
|
+
const nextChar = tokenizer.decode([nextTokenId]);
|
|
349
|
+
generated += nextChar;
|
|
350
|
+
|
|
351
|
+
// Shift context
|
|
352
|
+
context = context.slice(1).concat([nextTokenId]);
|
|
353
|
+
|
|
354
|
+
inputTensor.dispose();
|
|
355
|
+
logits.dispose();
|
|
356
|
+
lastLogits.dispose();
|
|
357
|
+
scaled.dispose();
|
|
358
|
+
probs.dispose();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return generated;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ============================================================================
|
|
365
|
+
// MAIN
|
|
366
|
+
// ============================================================================
|
|
367
|
+
|
|
368
|
+
async function main() {
|
|
369
|
+
console.log('='.repeat(70));
|
|
370
|
+
console.log('ResoFormer Language Model - Shakespeare');
|
|
371
|
+
console.log('='.repeat(70));
|
|
372
|
+
console.log(`TensorFlow.js: ${tf.version.tfjs} (${tf.getBackend()})\n`);
|
|
373
|
+
|
|
374
|
+
// Tokenize
|
|
375
|
+
const tokenizer = new CharTokenizer();
|
|
376
|
+
tokenizer.fit(SAMPLE_TEXT);
|
|
377
|
+
|
|
378
|
+
// Create training data with more overlap
|
|
379
|
+
const seqLen = 48;
|
|
380
|
+
const { x, y } = createTrainingData(SAMPLE_TEXT, tokenizer, seqLen, 2);
|
|
381
|
+
console.log(`Training data: ${x.shape[0]} sequences × ${seqLen} chars`);
|
|
382
|
+
console.log(`Total chars: ${SAMPLE_TEXT.length}`);
|
|
383
|
+
|
|
384
|
+
// Create model
|
|
385
|
+
console.log('\nCreating ResoFormer Language Model...');
|
|
386
|
+
const model = createResoFormerLM({
|
|
387
|
+
vocabSize: tokenizer.vocabSize,
|
|
388
|
+
seqLen,
|
|
389
|
+
dim: 256,
|
|
390
|
+
numLayers: 3,
|
|
391
|
+
numHeads: 8,
|
|
392
|
+
ffnDim: 512,
|
|
393
|
+
dropout: 0.1
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Count params
|
|
397
|
+
let totalParams = 0;
|
|
398
|
+
model.layers.forEach(layer => totalParams += layer.countParams());
|
|
399
|
+
console.log(`Parameters: ${totalParams.toLocaleString()}`);
|
|
400
|
+
|
|
401
|
+
// Compile with lower learning rate
|
|
402
|
+
model.compile({
|
|
403
|
+
optimizer: tf.train.adam(0.0005),
|
|
404
|
+
loss: 'categoricalCrossentropy',
|
|
405
|
+
metrics: ['accuracy']
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Train
|
|
409
|
+
const epochs = 50;
|
|
410
|
+
const batchSize = 32;
|
|
411
|
+
|
|
412
|
+
console.log(`\nTraining for ${epochs} epochs (batch size ${batchSize})...`);
|
|
413
|
+
console.log('-'.repeat(60));
|
|
414
|
+
|
|
415
|
+
let bestLoss = Infinity;
|
|
416
|
+
|
|
417
|
+
await model.fit(x, y, {
|
|
418
|
+
epochs,
|
|
419
|
+
batchSize,
|
|
420
|
+
validationSplit: 0.1,
|
|
421
|
+
shuffle: true,
|
|
422
|
+
callbacks: {
|
|
423
|
+
onEpochEnd: async (epoch, logs) => {
|
|
424
|
+
if (logs.loss < bestLoss) {
|
|
425
|
+
bestLoss = logs.loss;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if ((epoch + 1) % 10 === 0 || epoch === 0) {
|
|
429
|
+
const acc = (logs.acc * 100).toFixed(1);
|
|
430
|
+
const valAcc = (logs.val_acc * 100).toFixed(1);
|
|
431
|
+
console.log(`Epoch ${epoch + 1}/${epochs} | loss: ${logs.loss.toFixed(3)} | acc: ${acc}% | val_acc: ${valAcc}%`);
|
|
432
|
+
|
|
433
|
+
// Quick generation check
|
|
434
|
+
if ((epoch + 1) % 20 === 0) {
|
|
435
|
+
const sample = await generateText(model, tokenizer, 'to be ', 40, 0.7);
|
|
436
|
+
console.log(` Sample: "${sample}"`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// Final generation
|
|
444
|
+
console.log('\n' + '='.repeat(70));
|
|
445
|
+
console.log('TEXT GENERATION');
|
|
446
|
+
console.log('='.repeat(70));
|
|
447
|
+
|
|
448
|
+
const prompts = [
|
|
449
|
+
'to be or not',
|
|
450
|
+
'the quality',
|
|
451
|
+
'all the world',
|
|
452
|
+
'now is the'
|
|
453
|
+
];
|
|
454
|
+
|
|
455
|
+
for (const prompt of prompts) {
|
|
456
|
+
console.log(`\nPrompt: "${prompt}"`);
|
|
457
|
+
|
|
458
|
+
// Low temperature (more focused)
|
|
459
|
+
const text1 = await generateText(model, tokenizer, prompt, 80, 0.5);
|
|
460
|
+
console.log(`T=0.5: ${text1}`);
|
|
461
|
+
|
|
462
|
+
// Higher temperature (more creative)
|
|
463
|
+
const text2 = await generateText(model, tokenizer, prompt, 80, 0.9);
|
|
464
|
+
console.log(`T=0.9: ${text2}`);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Novel prompt
|
|
468
|
+
console.log('\n--- Novel prompt ---');
|
|
469
|
+
const novel = await generateText(model, tokenizer, 'in the beginning ', 120, 0.7);
|
|
470
|
+
console.log(`T=0.7: ${novel}`);
|
|
471
|
+
|
|
472
|
+
// Cleanup
|
|
473
|
+
x.dispose();
|
|
474
|
+
y.dispose();
|
|
475
|
+
|
|
476
|
+
console.log('\n' + '='.repeat(70));
|
|
477
|
+
console.log('Training complete!');
|
|
478
|
+
console.log('='.repeat(70));
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
main().catch(err => {
|
|
482
|
+
console.error('Error:', err.message);
|
|
483
|
+
console.error(err.stack);
|
|
484
|
+
});
|