@sparkleideas/neural 3.5.2-patch.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/README.md +260 -0
- package/__tests__/README.md +235 -0
- package/__tests__/algorithms.test.ts +582 -0
- package/__tests__/patterns.test.ts +549 -0
- package/__tests__/sona.test.ts +445 -0
- package/docs/SONA_INTEGRATION.md +460 -0
- package/docs/SONA_QUICKSTART.md +168 -0
- package/examples/sona-usage.ts +318 -0
- package/package.json +23 -0
- package/src/algorithms/a2c.d.ts +86 -0
- package/src/algorithms/a2c.d.ts.map +1 -0
- package/src/algorithms/a2c.js +361 -0
- package/src/algorithms/a2c.js.map +1 -0
- package/src/algorithms/a2c.ts +478 -0
- package/src/algorithms/curiosity.d.ts +82 -0
- package/src/algorithms/curiosity.d.ts.map +1 -0
- package/src/algorithms/curiosity.js +392 -0
- package/src/algorithms/curiosity.js.map +1 -0
- package/src/algorithms/curiosity.ts +509 -0
- package/src/algorithms/decision-transformer.d.ts +82 -0
- package/src/algorithms/decision-transformer.d.ts.map +1 -0
- package/src/algorithms/decision-transformer.js +415 -0
- package/src/algorithms/decision-transformer.js.map +1 -0
- package/src/algorithms/decision-transformer.ts +521 -0
- package/src/algorithms/dqn.d.ts +72 -0
- package/src/algorithms/dqn.d.ts.map +1 -0
- package/src/algorithms/dqn.js +303 -0
- package/src/algorithms/dqn.js.map +1 -0
- package/src/algorithms/dqn.ts +382 -0
- package/src/algorithms/index.d.ts +32 -0
- package/src/algorithms/index.d.ts.map +1 -0
- package/src/algorithms/index.js +74 -0
- package/src/algorithms/index.js.map +1 -0
- package/src/algorithms/index.ts +122 -0
- package/src/algorithms/ppo.d.ts +72 -0
- package/src/algorithms/ppo.d.ts.map +1 -0
- package/src/algorithms/ppo.js +331 -0
- package/src/algorithms/ppo.js.map +1 -0
- package/src/algorithms/ppo.ts +429 -0
- package/src/algorithms/q-learning.d.ts +77 -0
- package/src/algorithms/q-learning.d.ts.map +1 -0
- package/src/algorithms/q-learning.js +259 -0
- package/src/algorithms/q-learning.js.map +1 -0
- package/src/algorithms/q-learning.ts +333 -0
- package/src/algorithms/sarsa.d.ts +82 -0
- package/src/algorithms/sarsa.d.ts.map +1 -0
- package/src/algorithms/sarsa.js +297 -0
- package/src/algorithms/sarsa.js.map +1 -0
- package/src/algorithms/sarsa.ts +383 -0
- package/src/algorithms/tmp.json +0 -0
- package/src/application/index.ts +11 -0
- package/src/application/services/neural-application-service.ts +217 -0
- package/src/domain/entities/pattern.ts +169 -0
- package/src/domain/index.ts +18 -0
- package/src/domain/services/learning-service.ts +256 -0
- package/src/index.d.ts +118 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +201 -0
- package/src/index.js.map +1 -0
- package/src/index.ts +363 -0
- package/src/modes/balanced.d.ts +60 -0
- package/src/modes/balanced.d.ts.map +1 -0
- package/src/modes/balanced.js +234 -0
- package/src/modes/balanced.js.map +1 -0
- package/src/modes/balanced.ts +299 -0
- package/src/modes/base.ts +163 -0
- package/src/modes/batch.d.ts +82 -0
- package/src/modes/batch.d.ts.map +1 -0
- package/src/modes/batch.js +316 -0
- package/src/modes/batch.js.map +1 -0
- package/src/modes/batch.ts +434 -0
- package/src/modes/edge.d.ts +85 -0
- package/src/modes/edge.d.ts.map +1 -0
- package/src/modes/edge.js +310 -0
- package/src/modes/edge.js.map +1 -0
- package/src/modes/edge.ts +409 -0
- package/src/modes/index.d.ts +55 -0
- package/src/modes/index.d.ts.map +1 -0
- package/src/modes/index.js +83 -0
- package/src/modes/index.js.map +1 -0
- package/src/modes/index.ts +16 -0
- package/src/modes/real-time.d.ts +58 -0
- package/src/modes/real-time.d.ts.map +1 -0
- package/src/modes/real-time.js +196 -0
- package/src/modes/real-time.js.map +1 -0
- package/src/modes/real-time.ts +257 -0
- package/src/modes/research.d.ts +79 -0
- package/src/modes/research.d.ts.map +1 -0
- package/src/modes/research.js +389 -0
- package/src/modes/research.js.map +1 -0
- package/src/modes/research.ts +486 -0
- package/src/modes/tmp.json +0 -0
- package/src/pattern-learner.d.ts +117 -0
- package/src/pattern-learner.d.ts.map +1 -0
- package/src/pattern-learner.js +603 -0
- package/src/pattern-learner.js.map +1 -0
- package/src/pattern-learner.ts +757 -0
- package/src/reasoning-bank.d.ts +259 -0
- package/src/reasoning-bank.d.ts.map +1 -0
- package/src/reasoning-bank.js +993 -0
- package/src/reasoning-bank.js.map +1 -0
- package/src/reasoning-bank.ts +1279 -0
- package/src/reasoningbank-adapter.ts +697 -0
- package/src/sona-integration.d.ts +168 -0
- package/src/sona-integration.d.ts.map +1 -0
- package/src/sona-integration.js +316 -0
- package/src/sona-integration.js.map +1 -0
- package/src/sona-integration.ts +432 -0
- package/src/sona-manager.d.ts +147 -0
- package/src/sona-manager.d.ts.map +1 -0
- package/src/sona-manager.js +695 -0
- package/src/sona-manager.js.map +1 -0
- package/src/sona-manager.ts +835 -0
- package/src/tmp.json +0 -0
- package/src/types.d.ts +431 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.js +11 -0
- package/src/types.js.map +1 -0
- package/src/types.ts +590 -0
- package/tmp.json +0 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +19 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research Mode Implementation
|
|
3
|
+
*
|
|
4
|
+
* Optimized for maximum quality with:
|
|
5
|
+
* - +55% quality improvement target
|
|
6
|
+
* - Learning rate 0.002 (sweet spot)
|
|
7
|
+
* - Rank-16 LoRA
|
|
8
|
+
* - Gradient checkpointing
|
|
9
|
+
* - Full learning pipeline
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
SONAModeConfig,
|
|
14
|
+
ModeOptimizations,
|
|
15
|
+
Trajectory,
|
|
16
|
+
Pattern,
|
|
17
|
+
PatternMatch,
|
|
18
|
+
LoRAWeights,
|
|
19
|
+
EWCState,
|
|
20
|
+
} from '../types.js';
|
|
21
|
+
import { BaseModeImplementation } from './base.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Research mode for maximum quality learning
|
|
25
|
+
*/
|
|
26
|
+
export class ResearchMode extends BaseModeImplementation {
|
|
27
|
+
readonly mode = 'research';
|
|
28
|
+
|
|
29
|
+
// Extended pattern storage
|
|
30
|
+
private patternIndex: Map<string, number> = new Map();
|
|
31
|
+
private clusterCentroids: Float32Array[] = [];
|
|
32
|
+
|
|
33
|
+
// Learning state with checkpointing
|
|
34
|
+
private gradientHistory: Array<Map<string, Float32Array>> = [];
|
|
35
|
+
private checkpoints: Array<{ iteration: number; state: Map<string, Float32Array> }> = [];
|
|
36
|
+
|
|
37
|
+
// Adam optimizer state
|
|
38
|
+
private adamM: Map<string, Float32Array> = new Map();
|
|
39
|
+
private adamV: Map<string, Float32Array> = new Map();
|
|
40
|
+
private adamStep = 0;
|
|
41
|
+
|
|
42
|
+
// Stats
|
|
43
|
+
private totalPatternMatches = 0;
|
|
44
|
+
private totalPatternTime = 0;
|
|
45
|
+
private totalLearnTime = 0;
|
|
46
|
+
private learnIterations = 0;
|
|
47
|
+
private qualityHistory: number[] = [];
|
|
48
|
+
private explorationRewards: number[] = [];
|
|
49
|
+
|
|
50
|
+
async initialize(): Promise<void> {
|
|
51
|
+
await super.initialize();
|
|
52
|
+
this.patternIndex.clear();
|
|
53
|
+
this.clusterCentroids = [];
|
|
54
|
+
this.gradientHistory = [];
|
|
55
|
+
this.checkpoints = [];
|
|
56
|
+
this.adamM.clear();
|
|
57
|
+
this.adamV.clear();
|
|
58
|
+
this.adamStep = 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async cleanup(): Promise<void> {
|
|
62
|
+
this.patternIndex.clear();
|
|
63
|
+
this.clusterCentroids = [];
|
|
64
|
+
this.gradientHistory = [];
|
|
65
|
+
this.checkpoints = [];
|
|
66
|
+
this.adamM.clear();
|
|
67
|
+
this.adamV.clear();
|
|
68
|
+
await super.cleanup();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Find patterns using cluster-based search
|
|
73
|
+
*/
|
|
74
|
+
async findPatterns(
|
|
75
|
+
embedding: Float32Array,
|
|
76
|
+
k: number,
|
|
77
|
+
patterns: Pattern[]
|
|
78
|
+
): Promise<PatternMatch[]> {
|
|
79
|
+
const startTime = performance.now();
|
|
80
|
+
|
|
81
|
+
// Update clusters if needed
|
|
82
|
+
if (this.clusterCentroids.length !== this.config.patternClusters) {
|
|
83
|
+
await this.rebuildClusters(patterns);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Find nearest cluster
|
|
87
|
+
let bestCluster = 0;
|
|
88
|
+
let bestSim = -1;
|
|
89
|
+
for (let c = 0; c < this.clusterCentroids.length; c++) {
|
|
90
|
+
const sim = this.cosineSimilarity(embedding, this.clusterCentroids[c]);
|
|
91
|
+
if (sim > bestSim) {
|
|
92
|
+
bestSim = sim;
|
|
93
|
+
bestCluster = c;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Search within cluster + nearby clusters
|
|
98
|
+
const clustersToSearch = this.getNearestClusters(embedding, 3);
|
|
99
|
+
const candidates: PatternMatch[] = [];
|
|
100
|
+
|
|
101
|
+
for (const pattern of patterns) {
|
|
102
|
+
const patternCluster = this.patternIndex.get(pattern.patternId);
|
|
103
|
+
if (patternCluster !== undefined && clustersToSearch.includes(patternCluster)) {
|
|
104
|
+
const similarity = this.cosineSimilarity(embedding, pattern.embedding);
|
|
105
|
+
candidates.push({
|
|
106
|
+
pattern,
|
|
107
|
+
similarity,
|
|
108
|
+
confidence: this.computeConfidence(pattern, similarity),
|
|
109
|
+
latencyMs: 0,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// If not enough candidates, search all patterns
|
|
115
|
+
if (candidates.length < k) {
|
|
116
|
+
for (const pattern of patterns) {
|
|
117
|
+
if (!candidates.find(c => c.pattern.patternId === pattern.patternId)) {
|
|
118
|
+
const similarity = this.cosineSimilarity(embedding, pattern.embedding);
|
|
119
|
+
candidates.push({
|
|
120
|
+
pattern,
|
|
121
|
+
similarity,
|
|
122
|
+
confidence: this.computeConfidence(pattern, similarity),
|
|
123
|
+
latencyMs: 0,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Sort and return top-k
|
|
130
|
+
candidates.sort((a, b) => b.similarity - a.similarity);
|
|
131
|
+
|
|
132
|
+
this.totalPatternTime += performance.now() - startTime;
|
|
133
|
+
this.totalPatternMatches++;
|
|
134
|
+
|
|
135
|
+
return candidates.slice(0, k);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Learn using full Adam optimizer with gradient checkpointing
|
|
140
|
+
*/
|
|
141
|
+
async learn(
|
|
142
|
+
trajectories: Trajectory[],
|
|
143
|
+
config: SONAModeConfig,
|
|
144
|
+
ewcState: EWCState
|
|
145
|
+
): Promise<number> {
|
|
146
|
+
const startTime = performance.now();
|
|
147
|
+
|
|
148
|
+
if (trajectories.length === 0) return 0;
|
|
149
|
+
|
|
150
|
+
// Research mode uses low threshold to learn from all data
|
|
151
|
+
const learningRate = config.learningRate; // 0.002 sweet spot
|
|
152
|
+
const batchSize = config.batchSize;
|
|
153
|
+
|
|
154
|
+
// Sort trajectories by quality
|
|
155
|
+
const sortedTrajectories = [...trajectories].sort((a, b) => b.qualityScore - a.qualityScore);
|
|
156
|
+
|
|
157
|
+
// Create checkpoint before learning
|
|
158
|
+
if (this.learnIterations % 10 === 0) {
|
|
159
|
+
this.createCheckpoint();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let totalLoss = 0;
|
|
163
|
+
let batchCount = 0;
|
|
164
|
+
|
|
165
|
+
// Process in mini-batches
|
|
166
|
+
for (let i = 0; i < sortedTrajectories.length; i += batchSize) {
|
|
167
|
+
const batch = sortedTrajectories.slice(i, i + batchSize);
|
|
168
|
+
const batchLoss = await this.processBatch(batch, learningRate, ewcState, config.ewcLambda);
|
|
169
|
+
totalLoss += batchLoss;
|
|
170
|
+
batchCount++;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Track quality
|
|
174
|
+
const avgQuality = sortedTrajectories.reduce((s, t) => s + t.qualityScore, 0) / sortedTrajectories.length;
|
|
175
|
+
this.qualityHistory.push(avgQuality);
|
|
176
|
+
if (this.qualityHistory.length > 1000) {
|
|
177
|
+
this.qualityHistory = this.qualityHistory.slice(-1000);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Compute improvement
|
|
181
|
+
const recentAvg = this.qualityHistory.slice(-10).reduce((a, b) => a + b, 0) / Math.min(10, this.qualityHistory.length);
|
|
182
|
+
const oldAvg = this.qualityHistory.slice(0, Math.max(1, this.qualityHistory.length - 10)).reduce((a, b) => a + b, 0) / Math.max(1, this.qualityHistory.length - 10);
|
|
183
|
+
const improvementDelta = recentAvg - oldAvg;
|
|
184
|
+
|
|
185
|
+
this.totalLearnTime += performance.now() - startTime;
|
|
186
|
+
this.learnIterations++;
|
|
187
|
+
|
|
188
|
+
return Math.max(0, improvementDelta * 2); // Scale for research mode
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Apply LoRA with rank-16 for maximum expressivity
|
|
193
|
+
*/
|
|
194
|
+
async applyLoRA(
|
|
195
|
+
input: Float32Array,
|
|
196
|
+
weights?: LoRAWeights
|
|
197
|
+
): Promise<Float32Array> {
|
|
198
|
+
if (!weights) {
|
|
199
|
+
return input;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const output = new Float32Array(input.length);
|
|
203
|
+
output.set(input);
|
|
204
|
+
|
|
205
|
+
const rank = this.config.loraRank; // 16 for research mode
|
|
206
|
+
|
|
207
|
+
// Apply to all modules with higher blending
|
|
208
|
+
for (const module of ['q_proj', 'v_proj', 'k_proj', 'o_proj']) {
|
|
209
|
+
const A = weights.A.get(module);
|
|
210
|
+
const B = weights.B.get(module);
|
|
211
|
+
|
|
212
|
+
if (A && B) {
|
|
213
|
+
const adapted = this.applyLoRATransform(input, A, B, rank);
|
|
214
|
+
const alpha = 0.3; // Higher blending for research
|
|
215
|
+
for (let i = 0; i < output.length; i++) {
|
|
216
|
+
output[i] = output[i] * (1 - alpha) + adapted[i] * alpha;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return output;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
getStats(): Record<string, number> {
|
|
225
|
+
const avgQuality = this.qualityHistory.length > 0
|
|
226
|
+
? this.qualityHistory.reduce((a, b) => a + b, 0) / this.qualityHistory.length
|
|
227
|
+
: 0;
|
|
228
|
+
|
|
229
|
+
const recentQuality = this.qualityHistory.slice(-10).reduce((a, b) => a + b, 0) / Math.min(10, this.qualityHistory.length) || 0;
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
avgPatternMatchMs: this.totalPatternMatches > 0
|
|
233
|
+
? this.totalPatternTime / this.totalPatternMatches
|
|
234
|
+
: 0,
|
|
235
|
+
avgLearnMs: this.learnIterations > 0
|
|
236
|
+
? this.totalLearnTime / this.learnIterations
|
|
237
|
+
: 0,
|
|
238
|
+
avgQuality,
|
|
239
|
+
recentQuality,
|
|
240
|
+
qualityImprovement: recentQuality - avgQuality,
|
|
241
|
+
clusterCount: this.clusterCentroids.length,
|
|
242
|
+
checkpointCount: this.checkpoints.length,
|
|
243
|
+
adamStep: this.adamStep,
|
|
244
|
+
learnIterations: this.learnIterations,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Rebuild cluster centroids using k-means
|
|
250
|
+
*/
|
|
251
|
+
private async rebuildClusters(patterns: Pattern[]): Promise<void> {
|
|
252
|
+
if (patterns.length === 0) return;
|
|
253
|
+
|
|
254
|
+
const k = Math.min(this.config.patternClusters, patterns.length);
|
|
255
|
+
const dim = patterns[0].embedding.length;
|
|
256
|
+
|
|
257
|
+
// Initialize centroids randomly
|
|
258
|
+
this.clusterCentroids = [];
|
|
259
|
+
const indices = new Set<number>();
|
|
260
|
+
while (indices.size < k) {
|
|
261
|
+
indices.add(Math.floor(Math.random() * patterns.length));
|
|
262
|
+
}
|
|
263
|
+
for (const idx of indices) {
|
|
264
|
+
this.clusterCentroids.push(new Float32Array(patterns[idx].embedding));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Run k-means iterations
|
|
268
|
+
for (let iter = 0; iter < 10; iter++) {
|
|
269
|
+
// Assign patterns to clusters
|
|
270
|
+
const clusterAssignments: number[][] = Array.from({ length: k }, () => []);
|
|
271
|
+
|
|
272
|
+
for (let p = 0; p < patterns.length; p++) {
|
|
273
|
+
let bestCluster = 0;
|
|
274
|
+
let bestSim = -1;
|
|
275
|
+
for (let c = 0; c < k; c++) {
|
|
276
|
+
const sim = this.cosineSimilarity(patterns[p].embedding, this.clusterCentroids[c]);
|
|
277
|
+
if (sim > bestSim) {
|
|
278
|
+
bestSim = sim;
|
|
279
|
+
bestCluster = c;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
clusterAssignments[bestCluster].push(p);
|
|
283
|
+
this.patternIndex.set(patterns[p].patternId, bestCluster);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Update centroids
|
|
287
|
+
for (let c = 0; c < k; c++) {
|
|
288
|
+
if (clusterAssignments[c].length > 0) {
|
|
289
|
+
const newCentroid = new Float32Array(dim);
|
|
290
|
+
for (const p of clusterAssignments[c]) {
|
|
291
|
+
for (let d = 0; d < dim; d++) {
|
|
292
|
+
newCentroid[d] += patterns[p].embedding[d];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
for (let d = 0; d < dim; d++) {
|
|
296
|
+
newCentroid[d] /= clusterAssignments[c].length;
|
|
297
|
+
}
|
|
298
|
+
this.clusterCentroids[c] = newCentroid;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get nearest clusters to embedding
|
|
306
|
+
*/
|
|
307
|
+
private getNearestClusters(embedding: Float32Array, n: number): number[] {
|
|
308
|
+
const similarities: Array<{ cluster: number; sim: number }> = [];
|
|
309
|
+
for (let c = 0; c < this.clusterCentroids.length; c++) {
|
|
310
|
+
similarities.push({ cluster: c, sim: this.cosineSimilarity(embedding, this.clusterCentroids[c]) });
|
|
311
|
+
}
|
|
312
|
+
similarities.sort((a, b) => b.sim - a.sim);
|
|
313
|
+
return similarities.slice(0, n).map(s => s.cluster);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Compute confidence for pattern match
|
|
318
|
+
*/
|
|
319
|
+
private computeConfidence(pattern: Pattern, similarity: number): number {
|
|
320
|
+
// Combine similarity with pattern history
|
|
321
|
+
const historyWeight = Math.min(pattern.usageCount / 10, 1);
|
|
322
|
+
return similarity * (1 - historyWeight * 0.3) + pattern.successRate * historyWeight * 0.3;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Create learning checkpoint
|
|
327
|
+
*/
|
|
328
|
+
private createCheckpoint(): void {
|
|
329
|
+
const state = new Map<string, Float32Array>();
|
|
330
|
+
for (const [key, value] of this.adamM) {
|
|
331
|
+
state.set(`m_${key}`, new Float32Array(value));
|
|
332
|
+
}
|
|
333
|
+
for (const [key, value] of this.adamV) {
|
|
334
|
+
state.set(`v_${key}`, new Float32Array(value));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
this.checkpoints.push({ iteration: this.learnIterations, state });
|
|
338
|
+
|
|
339
|
+
// Keep only last 10 checkpoints
|
|
340
|
+
if (this.checkpoints.length > 10) {
|
|
341
|
+
this.checkpoints = this.checkpoints.slice(-10);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Process a mini-batch with Adam optimizer
|
|
347
|
+
*/
|
|
348
|
+
private async processBatch(
|
|
349
|
+
batch: Trajectory[],
|
|
350
|
+
learningRate: number,
|
|
351
|
+
ewcState: EWCState,
|
|
352
|
+
ewcLambda: number
|
|
353
|
+
): Promise<number> {
|
|
354
|
+
const beta1 = 0.9;
|
|
355
|
+
const beta2 = 0.999;
|
|
356
|
+
const epsilon = 1e-8;
|
|
357
|
+
|
|
358
|
+
this.adamStep++;
|
|
359
|
+
|
|
360
|
+
let totalLoss = 0;
|
|
361
|
+
|
|
362
|
+
for (const trajectory of batch) {
|
|
363
|
+
if (trajectory.steps.length === 0) continue;
|
|
364
|
+
|
|
365
|
+
// Compute gradient from trajectory
|
|
366
|
+
const gradient = this.computeTrajectoryGradient(trajectory);
|
|
367
|
+
|
|
368
|
+
for (const [key, grad] of gradient) {
|
|
369
|
+
// Get or initialize Adam state
|
|
370
|
+
let m = this.adamM.get(key);
|
|
371
|
+
let v = this.adamV.get(key);
|
|
372
|
+
|
|
373
|
+
if (!m) {
|
|
374
|
+
m = new Float32Array(grad.length);
|
|
375
|
+
this.adamM.set(key, m);
|
|
376
|
+
}
|
|
377
|
+
if (!v) {
|
|
378
|
+
v = new Float32Array(grad.length);
|
|
379
|
+
this.adamV.set(key, v);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Update biased first moment estimate
|
|
383
|
+
for (let i = 0; i < grad.length; i++) {
|
|
384
|
+
m[i] = beta1 * m[i] + (1 - beta1) * grad[i];
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Update biased second moment estimate
|
|
388
|
+
for (let i = 0; i < grad.length; i++) {
|
|
389
|
+
v[i] = beta2 * v[i] + (1 - beta2) * grad[i] * grad[i];
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Bias correction
|
|
393
|
+
const mHat = new Float32Array(grad.length);
|
|
394
|
+
const vHat = new Float32Array(grad.length);
|
|
395
|
+
for (let i = 0; i < grad.length; i++) {
|
|
396
|
+
mHat[i] = m[i] / (1 - Math.pow(beta1, this.adamStep));
|
|
397
|
+
vHat[i] = v[i] / (1 - Math.pow(beta2, this.adamStep));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Compute loss contribution
|
|
401
|
+
for (let i = 0; i < grad.length; i++) {
|
|
402
|
+
totalLoss += grad[i] * grad[i];
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Add EWC penalty
|
|
408
|
+
const ewcPenalty = this.computeEWCLoss(ewcState, ewcLambda);
|
|
409
|
+
totalLoss += ewcPenalty;
|
|
410
|
+
|
|
411
|
+
return totalLoss / batch.length;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Compute gradient from trajectory
|
|
416
|
+
*/
|
|
417
|
+
private computeTrajectoryGradient(trajectory: Trajectory): Map<string, Float32Array> {
|
|
418
|
+
const gradient = new Map<string, Float32Array>();
|
|
419
|
+
|
|
420
|
+
if (trajectory.steps.length < 2) return gradient;
|
|
421
|
+
|
|
422
|
+
// Use advantage estimation
|
|
423
|
+
const rewards = trajectory.steps.map(s => s.reward);
|
|
424
|
+
const advantages = this.computeAdvantages(rewards);
|
|
425
|
+
|
|
426
|
+
for (let i = 0; i < trajectory.steps.length; i++) {
|
|
427
|
+
const step = trajectory.steps[i];
|
|
428
|
+
const advantage = advantages[i];
|
|
429
|
+
|
|
430
|
+
// Policy gradient: grad = advantage * grad_log_pi
|
|
431
|
+
const stateGrad = new Float32Array(step.stateAfter.length);
|
|
432
|
+
for (let j = 0; j < stateGrad.length; j++) {
|
|
433
|
+
stateGrad[j] = step.stateAfter[j] * advantage;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
gradient.set(`step_${i}`, stateGrad);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return gradient;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Compute advantages using GAE
|
|
444
|
+
*/
|
|
445
|
+
private computeAdvantages(rewards: number[]): number[] {
|
|
446
|
+
const gamma = 0.99;
|
|
447
|
+
const lambda = 0.95;
|
|
448
|
+
|
|
449
|
+
const advantages = new Array(rewards.length).fill(0);
|
|
450
|
+
let lastGae = 0;
|
|
451
|
+
|
|
452
|
+
for (let t = rewards.length - 1; t >= 0; t--) {
|
|
453
|
+
const nextValue = t < rewards.length - 1 ? rewards[t + 1] : 0;
|
|
454
|
+
const delta = rewards[t] + gamma * nextValue - rewards[t];
|
|
455
|
+
lastGae = delta + gamma * lambda * lastGae;
|
|
456
|
+
advantages[t] = lastGae;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Normalize advantages
|
|
460
|
+
const mean = advantages.reduce((a, b) => a + b, 0) / advantages.length;
|
|
461
|
+
const std = Math.sqrt(advantages.reduce((a, b) => a + (b - mean) ** 2, 0) / advantages.length) + 1e-8;
|
|
462
|
+
|
|
463
|
+
return advantages.map(a => (a - mean) / std);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Compute EWC loss for continual learning
|
|
468
|
+
*/
|
|
469
|
+
private computeEWCLoss(ewcState: EWCState, lambda: number): number {
|
|
470
|
+
let loss = 0;
|
|
471
|
+
|
|
472
|
+
for (const [key, fisher] of ewcState.fisher) {
|
|
473
|
+
const means = ewcState.means.get(key);
|
|
474
|
+
const current = this.adamM.get(key);
|
|
475
|
+
|
|
476
|
+
if (means && current) {
|
|
477
|
+
for (let i = 0; i < Math.min(fisher.length, means.length, current.length); i++) {
|
|
478
|
+
const diff = current[i] - means[i];
|
|
479
|
+
loss += fisher[i] * diff * diff;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return lambda * loss * 0.5;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Learner
|
|
3
|
+
*
|
|
4
|
+
* Implements pattern extraction, matching, and evolution for
|
|
5
|
+
* continuous learning from agent experiences.
|
|
6
|
+
*
|
|
7
|
+
* Performance Targets:
|
|
8
|
+
* - Pattern matching: <1ms
|
|
9
|
+
* - Pattern extraction: <5ms
|
|
10
|
+
* - Evolution step: <2ms
|
|
11
|
+
*/
|
|
12
|
+
import type { Pattern, PatternMatch, Trajectory, DistilledMemory, NeuralEventListener } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for Pattern Learner
|
|
15
|
+
*/
|
|
16
|
+
export interface PatternLearnerConfig {
|
|
17
|
+
/** Maximum number of patterns to store */
|
|
18
|
+
maxPatterns: number;
|
|
19
|
+
/** Similarity threshold for matching */
|
|
20
|
+
matchThreshold: number;
|
|
21
|
+
/** Minimum usages before pattern is stable */
|
|
22
|
+
minUsagesForStable: number;
|
|
23
|
+
/** Quality threshold for pattern inclusion */
|
|
24
|
+
qualityThreshold: number;
|
|
25
|
+
/** Enable pattern clustering */
|
|
26
|
+
enableClustering: boolean;
|
|
27
|
+
/** Number of clusters (if clustering enabled) */
|
|
28
|
+
numClusters: number;
|
|
29
|
+
/** Evolution learning rate */
|
|
30
|
+
evolutionLearningRate: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Pattern Learner - Manages pattern extraction, matching, and evolution
|
|
34
|
+
*/
|
|
35
|
+
export declare class PatternLearner {
|
|
36
|
+
private config;
|
|
37
|
+
private patterns;
|
|
38
|
+
private clusters;
|
|
39
|
+
private patternToCluster;
|
|
40
|
+
private matchCount;
|
|
41
|
+
private totalMatchTime;
|
|
42
|
+
private extractionCount;
|
|
43
|
+
private totalExtractionTime;
|
|
44
|
+
private evolutionCount;
|
|
45
|
+
private totalEvolutionTime;
|
|
46
|
+
private eventListeners;
|
|
47
|
+
constructor(config?: Partial<PatternLearnerConfig>);
|
|
48
|
+
/**
|
|
49
|
+
* Find matching patterns for a query embedding
|
|
50
|
+
* Target: <1ms
|
|
51
|
+
*/
|
|
52
|
+
findMatches(queryEmbedding: Float32Array, k?: number): PatternMatch[];
|
|
53
|
+
/**
|
|
54
|
+
* Find best single match
|
|
55
|
+
*/
|
|
56
|
+
findBestMatch(queryEmbedding: Float32Array): PatternMatch | null;
|
|
57
|
+
/**
|
|
58
|
+
* Extract a pattern from a trajectory
|
|
59
|
+
* Target: <5ms
|
|
60
|
+
*/
|
|
61
|
+
extractPattern(trajectory: Trajectory, memory?: DistilledMemory): Pattern | null;
|
|
62
|
+
/**
|
|
63
|
+
* Extract patterns from multiple trajectories in batch
|
|
64
|
+
*/
|
|
65
|
+
extractPatternsBatch(trajectories: Trajectory[]): Pattern[];
|
|
66
|
+
/**
|
|
67
|
+
* Evolve a pattern based on new experience
|
|
68
|
+
* Target: <2ms
|
|
69
|
+
*/
|
|
70
|
+
evolvePattern(patternId: string, quality: number, context?: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Merge two similar patterns
|
|
73
|
+
*/
|
|
74
|
+
mergePatterns(patternId1: string, patternId2: string): Pattern | null;
|
|
75
|
+
/**
|
|
76
|
+
* Split a pattern into more specific sub-patterns
|
|
77
|
+
*/
|
|
78
|
+
splitPattern(patternId: string, numSplits?: number): Pattern[];
|
|
79
|
+
/**
|
|
80
|
+
* Get all patterns
|
|
81
|
+
*/
|
|
82
|
+
getPatterns(): Pattern[];
|
|
83
|
+
/**
|
|
84
|
+
* Get pattern by ID
|
|
85
|
+
*/
|
|
86
|
+
getPattern(patternId: string): Pattern | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Get patterns by domain
|
|
89
|
+
*/
|
|
90
|
+
getPatternsByDomain(domain: string): Pattern[];
|
|
91
|
+
/**
|
|
92
|
+
* Get stable patterns (sufficient usage)
|
|
93
|
+
*/
|
|
94
|
+
getStablePatterns(): Pattern[];
|
|
95
|
+
getStats(): Record<string, number>;
|
|
96
|
+
addEventListener(listener: NeuralEventListener): void;
|
|
97
|
+
removeEventListener(listener: NeuralEventListener): void;
|
|
98
|
+
private emitEvent;
|
|
99
|
+
private cosineSimilarity;
|
|
100
|
+
private computeMatchConfidence;
|
|
101
|
+
private getCandidatesFromClusters;
|
|
102
|
+
private findSimilarPattern;
|
|
103
|
+
private updatePatternFromTrajectory;
|
|
104
|
+
private computePatternEmbedding;
|
|
105
|
+
private generatePatternName;
|
|
106
|
+
private extractStrategy;
|
|
107
|
+
private assignToCluster;
|
|
108
|
+
private updateClusterCentroid;
|
|
109
|
+
private rebuildClusters;
|
|
110
|
+
private prunePatterns;
|
|
111
|
+
private determineEvolutionType;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Factory function for creating PatternLearner
|
|
115
|
+
*/
|
|
116
|
+
export declare function createPatternLearner(config?: Partial<PatternLearnerConfig>): PatternLearner;
|
|
117
|
+
//# sourceMappingURL=pattern-learner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-learner.d.ts","sourceRoot":"","sources":["pattern-learner.ts"],"names":[],"mappings":"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"}
|