ruvector 0.2.22 → 0.2.23

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 (108) hide show
  1. package/README.md +2 -2
  2. package/package.json +9 -5
  3. package/dist/analysis/complexity.d.ts +0 -52
  4. package/dist/analysis/complexity.d.ts.map +0 -1
  5. package/dist/analysis/complexity.js +0 -146
  6. package/dist/analysis/index.d.ts +0 -15
  7. package/dist/analysis/index.d.ts.map +0 -1
  8. package/dist/analysis/index.js +0 -38
  9. package/dist/analysis/patterns.d.ts +0 -71
  10. package/dist/analysis/patterns.d.ts.map +0 -1
  11. package/dist/analysis/patterns.js +0 -243
  12. package/dist/analysis/security.d.ts +0 -51
  13. package/dist/analysis/security.d.ts.map +0 -1
  14. package/dist/analysis/security.js +0 -139
  15. package/dist/core/adaptive-embedder.d.ts +0 -156
  16. package/dist/core/adaptive-embedder.d.ts.map +0 -1
  17. package/dist/core/adaptive-embedder.js +0 -838
  18. package/dist/core/agentdb-fast.d.ts +0 -149
  19. package/dist/core/agentdb-fast.d.ts.map +0 -1
  20. package/dist/core/agentdb-fast.js +0 -301
  21. package/dist/core/ast-parser.d.ts +0 -108
  22. package/dist/core/ast-parser.d.ts.map +0 -1
  23. package/dist/core/ast-parser.js +0 -602
  24. package/dist/core/attention-fallbacks.d.ts +0 -321
  25. package/dist/core/attention-fallbacks.d.ts.map +0 -1
  26. package/dist/core/attention-fallbacks.js +0 -552
  27. package/dist/core/cluster-wrapper.d.ts +0 -148
  28. package/dist/core/cluster-wrapper.d.ts.map +0 -1
  29. package/dist/core/cluster-wrapper.js +0 -271
  30. package/dist/core/coverage-router.d.ts +0 -88
  31. package/dist/core/coverage-router.d.ts.map +0 -1
  32. package/dist/core/coverage-router.js +0 -315
  33. package/dist/core/diff-embeddings.d.ts +0 -93
  34. package/dist/core/diff-embeddings.d.ts.map +0 -1
  35. package/dist/core/diff-embeddings.js +0 -334
  36. package/dist/core/gnn-wrapper.d.ts +0 -143
  37. package/dist/core/gnn-wrapper.d.ts.map +0 -1
  38. package/dist/core/gnn-wrapper.js +0 -213
  39. package/dist/core/graph-algorithms.d.ts +0 -83
  40. package/dist/core/graph-algorithms.d.ts.map +0 -1
  41. package/dist/core/graph-algorithms.js +0 -514
  42. package/dist/core/graph-wrapper.d.ts +0 -147
  43. package/dist/core/graph-wrapper.d.ts.map +0 -1
  44. package/dist/core/graph-wrapper.js +0 -299
  45. package/dist/core/index.d.ts +0 -48
  46. package/dist/core/index.d.ts.map +0 -1
  47. package/dist/core/index.js +0 -89
  48. package/dist/core/intelligence-engine.d.ts +0 -258
  49. package/dist/core/intelligence-engine.d.ts.map +0 -1
  50. package/dist/core/intelligence-engine.js +0 -1030
  51. package/dist/core/learning-engine.d.ts +0 -160
  52. package/dist/core/learning-engine.d.ts.map +0 -1
  53. package/dist/core/learning-engine.js +0 -589
  54. package/dist/core/neural-embeddings.d.ts +0 -393
  55. package/dist/core/neural-embeddings.d.ts.map +0 -1
  56. package/dist/core/neural-embeddings.js +0 -1091
  57. package/dist/core/neural-perf.d.ts +0 -331
  58. package/dist/core/neural-perf.d.ts.map +0 -1
  59. package/dist/core/neural-perf.js +0 -704
  60. package/dist/core/onnx/pkg/package.json +0 -3
  61. package/dist/core/onnx-embedder.d.ts +0 -105
  62. package/dist/core/onnx-embedder.d.ts.map +0 -1
  63. package/dist/core/onnx-embedder.js +0 -410
  64. package/dist/core/onnx-optimized.d.ts +0 -109
  65. package/dist/core/onnx-optimized.d.ts.map +0 -1
  66. package/dist/core/onnx-optimized.js +0 -419
  67. package/dist/core/parallel-intelligence.d.ts +0 -109
  68. package/dist/core/parallel-intelligence.d.ts.map +0 -1
  69. package/dist/core/parallel-intelligence.js +0 -340
  70. package/dist/core/parallel-workers.d.ts +0 -177
  71. package/dist/core/parallel-workers.d.ts.map +0 -1
  72. package/dist/core/parallel-workers.js +0 -671
  73. package/dist/core/router-wrapper.d.ts +0 -75
  74. package/dist/core/router-wrapper.d.ts.map +0 -1
  75. package/dist/core/router-wrapper.js +0 -243
  76. package/dist/core/rvf-wrapper.d.ts +0 -86
  77. package/dist/core/rvf-wrapper.d.ts.map +0 -1
  78. package/dist/core/rvf-wrapper.js +0 -102
  79. package/dist/core/sona-wrapper.d.ts +0 -226
  80. package/dist/core/sona-wrapper.d.ts.map +0 -1
  81. package/dist/core/sona-wrapper.js +0 -282
  82. package/dist/core/tensor-compress.d.ts +0 -134
  83. package/dist/core/tensor-compress.d.ts.map +0 -1
  84. package/dist/core/tensor-compress.js +0 -432
  85. package/dist/index.d.ts +0 -105
  86. package/dist/index.d.ts.map +0 -1
  87. package/dist/index.js +0 -221
  88. package/dist/services/embedding-service.d.ts +0 -136
  89. package/dist/services/embedding-service.d.ts.map +0 -1
  90. package/dist/services/embedding-service.js +0 -294
  91. package/dist/services/index.d.ts +0 -6
  92. package/dist/services/index.d.ts.map +0 -1
  93. package/dist/services/index.js +0 -26
  94. package/dist/types.d.ts +0 -145
  95. package/dist/types.d.ts.map +0 -1
  96. package/dist/types.js +0 -2
  97. package/dist/workers/benchmark.d.ts +0 -44
  98. package/dist/workers/benchmark.d.ts.map +0 -1
  99. package/dist/workers/benchmark.js +0 -230
  100. package/dist/workers/index.d.ts +0 -10
  101. package/dist/workers/index.d.ts.map +0 -1
  102. package/dist/workers/index.js +0 -25
  103. package/dist/workers/native-worker.d.ts +0 -76
  104. package/dist/workers/native-worker.d.ts.map +0 -1
  105. package/dist/workers/native-worker.js +0 -490
  106. package/dist/workers/types.d.ts +0 -69
  107. package/dist/workers/types.d.ts.map +0 -1
  108. package/dist/workers/types.js +0 -7
@@ -1,838 +0,0 @@
1
- "use strict";
2
- /**
3
- * AdaptiveEmbedder - Micro-LoRA Style Optimization for ONNX Embeddings
4
- *
5
- * Applies continual learning techniques to frozen ONNX embeddings:
6
- *
7
- * 1. MICRO-LORA ADAPTERS
8
- * - Low-rank projection layers (rank 2-8) on top of frozen embeddings
9
- * - Domain-specific fine-tuning with minimal parameters
10
- * - ~0.1% of base model parameters
11
- *
12
- * 2. CONTRASTIVE LEARNING
13
- * - Files edited together → embeddings closer
14
- * - Semantic clustering from trajectories
15
- * - Online learning from user behavior
16
- *
17
- * 3. EWC++ (Elastic Weight Consolidation)
18
- * - Prevents catastrophic forgetting
19
- * - Consolidates important adaptations
20
- * - Fisher information regularization
21
- *
22
- * 4. MEMORY-AUGMENTED RETRIEVAL
23
- * - Episodic memory for context-aware embeddings
24
- * - Attention over past similar embeddings
25
- * - Domain prototype learning
26
- *
27
- * Architecture:
28
- * ONNX(text) → [frozen 384d] → LoRA_A → LoRA_B → [adapted 384d]
29
- * (384×r) (r×384)
30
- */
31
- Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.AdaptiveEmbedder = void 0;
33
- exports.getAdaptiveEmbedder = getAdaptiveEmbedder;
34
- exports.initAdaptiveEmbedder = initAdaptiveEmbedder;
35
- const onnx_embedder_1 = require("./onnx-embedder");
36
- // ============================================================================
37
- // Optimized Micro-LoRA Layer with Float32Array and Caching
38
- // ============================================================================
39
- /**
40
- * Low-rank adaptation layer for embeddings (OPTIMIZED)
41
- * Implements: output = input + scale * (input @ A @ B)
42
- *
43
- * Optimizations:
44
- * - Float32Array for 2-3x faster math operations
45
- * - Flattened matrices for cache-friendly access
46
- * - Pre-allocated buffers to avoid GC pressure
47
- * - LRU embedding cache for repeated inputs
48
- */
49
- class MicroLoRA {
50
- constructor(dim, rank, scale = 0.1) {
51
- // EWC Fisher information (importance weights)
52
- this.fisherA = null;
53
- this.fisherB = null;
54
- this.savedA = null;
55
- this.savedB = null;
56
- // LRU cache for repeated embeddings (key: hash, value: output)
57
- this.cache = new Map();
58
- this.cacheMaxSize = 256;
59
- this.dim = dim;
60
- this.rank = rank;
61
- this.scale = scale;
62
- // Initialize A with small random values (Xavier-like)
63
- // Initialize B to EXACTLY ZERO so untrained LoRA is identity
64
- // This preserves semantic signal until training occurs
65
- const stdA = Math.sqrt(2 / (dim + rank));
66
- this.A = this.initFlatMatrix(dim, rank, stdA);
67
- this.B = new Float32Array(rank * dim); // Zero-initialized (identity)
68
- // Pre-allocate buffers
69
- this.hiddenBuffer = new Float32Array(rank);
70
- this.outputBuffer = new Float32Array(dim);
71
- }
72
- initFlatMatrix(rows, cols, std) {
73
- const arr = new Float32Array(rows * cols);
74
- for (let i = 0; i < arr.length; i++) {
75
- arr[i] = (Math.random() - 0.5) * 2 * std;
76
- }
77
- return arr;
78
- }
79
- /**
80
- * Fast hash for cache key (FNV-1a variant)
81
- */
82
- hashInput(input) {
83
- let h = 2166136261;
84
- const len = Math.min(input.length, 32); // Sample first 32 for speed
85
- for (let i = 0; i < len; i++) {
86
- h ^= Math.floor(input[i] * 10000);
87
- h = Math.imul(h, 16777619);
88
- }
89
- return h.toString(36);
90
- }
91
- /**
92
- * Forward pass: input + scale * (input @ A @ B)
93
- * OPTIMIZED with Float32Array and loop unrolling
94
- */
95
- forward(input) {
96
- // Check cache first
97
- const cacheKey = this.hashInput(input);
98
- const cached = this.cache.get(cacheKey);
99
- if (cached) {
100
- return Array.from(cached);
101
- }
102
- // Zero the hidden buffer
103
- this.hiddenBuffer.fill(0);
104
- // Compute input @ A (dim → rank) - SIMD-friendly loop
105
- // Unroll by 4 for better pipelining
106
- const dim4 = this.dim - (this.dim % 4);
107
- for (let r = 0; r < this.rank; r++) {
108
- let sum = 0;
109
- const rOffset = r;
110
- // Unrolled loop
111
- for (let d = 0; d < dim4; d += 4) {
112
- const aIdx = d * this.rank + rOffset;
113
- sum += input[d] * this.A[aIdx];
114
- sum += input[d + 1] * this.A[aIdx + this.rank];
115
- sum += input[d + 2] * this.A[aIdx + 2 * this.rank];
116
- sum += input[d + 3] * this.A[aIdx + 3 * this.rank];
117
- }
118
- // Remainder
119
- for (let d = dim4; d < this.dim; d++) {
120
- sum += input[d] * this.A[d * this.rank + rOffset];
121
- }
122
- this.hiddenBuffer[r] = sum;
123
- }
124
- // Compute hidden @ B (rank → dim) and add residual
125
- // Copy input to output buffer first
126
- for (let d = 0; d < this.dim; d++) {
127
- this.outputBuffer[d] = input[d];
128
- }
129
- // Add scaled LoRA contribution
130
- for (let d = 0; d < this.dim; d++) {
131
- let delta = 0;
132
- for (let r = 0; r < this.rank; r++) {
133
- delta += this.hiddenBuffer[r] * this.B[r * this.dim + d];
134
- }
135
- this.outputBuffer[d] += this.scale * delta;
136
- }
137
- // Cache result (LRU eviction if full)
138
- if (this.cache.size >= this.cacheMaxSize) {
139
- const firstKey = this.cache.keys().next().value;
140
- if (firstKey)
141
- this.cache.delete(firstKey);
142
- }
143
- this.cache.set(cacheKey, new Float32Array(this.outputBuffer));
144
- return Array.from(this.outputBuffer);
145
- }
146
- /**
147
- * Clear cache (call after weight updates)
148
- */
149
- clearCache() {
150
- this.cache.clear();
151
- }
152
- /**
153
- * Backward pass with contrastive loss
154
- * Pulls positive pairs closer, pushes negatives apart
155
- * OPTIMIZED: Uses Float32Array buffers
156
- */
157
- backward(anchor, positive, negatives, lr, ewcLambda = 0) {
158
- if (!positive && negatives.length === 0)
159
- return 0;
160
- // Clear cache since weights will change
161
- this.clearCache();
162
- // Compute adapted embeddings
163
- const anchorOut = this.forward(anchor);
164
- const positiveOut = positive ? this.forward(positive) : null;
165
- const negativeOuts = negatives.map(n => this.forward(n));
166
- // Contrastive loss with temperature scaling
167
- const temp = 0.07;
168
- let loss = 0;
169
- if (positiveOut) {
170
- // Positive similarity
171
- const posSim = this.cosineSimilarity(anchorOut, positiveOut) / temp;
172
- // Negative similarities
173
- const negSims = negativeOuts.map(n => this.cosineSimilarity(anchorOut, n) / temp);
174
- // InfoNCE loss
175
- const maxSim = Math.max(posSim, ...negSims);
176
- const expPos = Math.exp(posSim - maxSim);
177
- const expNegs = negSims.reduce((sum, s) => sum + Math.exp(s - maxSim), 0);
178
- loss = -Math.log(expPos / (expPos + expNegs) + 1e-8);
179
- // Compute gradients (simplified)
180
- const gradScale = lr * this.scale;
181
- // Update A based on gradient direction (flattened access)
182
- for (let d = 0; d < this.dim; d++) {
183
- for (let r = 0; r < this.rank; r++) {
184
- const idx = d * this.rank + r;
185
- // Gradient from positive (pull closer)
186
- const pOutR = r < positiveOut.length ? positiveOut[r] : 0;
187
- const aOutR = r < anchorOut.length ? anchorOut[r] : 0;
188
- const gradA = anchor[d] * (pOutR - aOutR) * gradScale;
189
- this.A[idx] += gradA;
190
- // EWC regularization
191
- if (ewcLambda > 0 && this.fisherA && this.savedA) {
192
- this.A[idx] -= ewcLambda * this.fisherA[idx] * (this.A[idx] - this.savedA[idx]);
193
- }
194
- }
195
- }
196
- // Update B (flattened access)
197
- for (let r = 0; r < this.rank; r++) {
198
- const anchorR = r < anchor.length ? anchor[r] : 0;
199
- for (let d = 0; d < this.dim; d++) {
200
- const idx = r * this.dim + d;
201
- const gradB = anchorR * (positiveOut[d] - anchorOut[d]) * gradScale * 0.1;
202
- this.B[idx] += gradB;
203
- if (ewcLambda > 0 && this.fisherB && this.savedB) {
204
- this.B[idx] -= ewcLambda * this.fisherB[idx] * (this.B[idx] - this.savedB[idx]);
205
- }
206
- }
207
- }
208
- }
209
- return loss;
210
- }
211
- /**
212
- * EWC consolidation - save current weights and compute Fisher information
213
- * OPTIMIZED: Uses Float32Array
214
- */
215
- consolidate(embeddings) {
216
- // Save current weights
217
- this.savedA = new Float32Array(this.A);
218
- this.savedB = new Float32Array(this.B);
219
- // Estimate Fisher information (diagonal approximation)
220
- this.fisherA = new Float32Array(this.dim * this.rank);
221
- this.fisherB = new Float32Array(this.rank * this.dim);
222
- const numEmb = embeddings.length;
223
- for (const emb of embeddings) {
224
- // Accumulate squared gradients as Fisher estimate
225
- for (let d = 0; d < this.dim; d++) {
226
- const embD = emb[d] * emb[d] / numEmb;
227
- for (let r = 0; r < this.rank; r++) {
228
- this.fisherA[d * this.rank + r] += embD;
229
- }
230
- }
231
- }
232
- // Clear cache after consolidation
233
- this.clearCache();
234
- }
235
- /**
236
- * Optimized cosine similarity with early termination
237
- */
238
- cosineSimilarity(a, b) {
239
- let dot = 0, normA = 0, normB = 0;
240
- const len = Math.min(a.length, b.length);
241
- // Unrolled loop for speed
242
- const len4 = len - (len % 4);
243
- for (let i = 0; i < len4; i += 4) {
244
- dot += a[i] * b[i] + a[i + 1] * b[i + 1] + a[i + 2] * b[i + 2] + a[i + 3] * b[i + 3];
245
- normA += a[i] * a[i] + a[i + 1] * a[i + 1] + a[i + 2] * a[i + 2] + a[i + 3] * a[i + 3];
246
- normB += b[i] * b[i] + b[i + 1] * b[i + 1] + b[i + 2] * b[i + 2] + b[i + 3] * b[i + 3];
247
- }
248
- // Remainder
249
- for (let i = len4; i < len; i++) {
250
- dot += a[i] * b[i];
251
- normA += a[i] * a[i];
252
- normB += b[i] * b[i];
253
- }
254
- return dot / (Math.sqrt(normA * normB) + 1e-8);
255
- }
256
- getParams() {
257
- return this.dim * this.rank + this.rank * this.dim;
258
- }
259
- getCacheStats() {
260
- return {
261
- size: this.cache.size,
262
- maxSize: this.cacheMaxSize,
263
- hitRate: 0, // Would need hit counter for accurate tracking
264
- };
265
- }
266
- /**
267
- * Export weights as 2D arrays for serialization
268
- */
269
- export() {
270
- // Convert flattened Float32Array back to 2D number[][]
271
- const A = [];
272
- for (let d = 0; d < this.dim; d++) {
273
- const row = [];
274
- for (let r = 0; r < this.rank; r++) {
275
- row.push(this.A[d * this.rank + r]);
276
- }
277
- A.push(row);
278
- }
279
- const B = [];
280
- for (let r = 0; r < this.rank; r++) {
281
- const row = [];
282
- for (let d = 0; d < this.dim; d++) {
283
- row.push(this.B[r * this.dim + d]);
284
- }
285
- B.push(row);
286
- }
287
- return { A, B };
288
- }
289
- /**
290
- * Import weights from 2D arrays
291
- */
292
- import(weights) {
293
- // Convert 2D number[][] to flattened Float32Array
294
- for (let d = 0; d < this.dim && d < weights.A.length; d++) {
295
- for (let r = 0; r < this.rank && r < weights.A[d].length; r++) {
296
- this.A[d * this.rank + r] = weights.A[d][r];
297
- }
298
- }
299
- for (let r = 0; r < this.rank && r < weights.B.length; r++) {
300
- for (let d = 0; d < this.dim && d < weights.B[r].length; d++) {
301
- this.B[r * this.dim + d] = weights.B[r][d];
302
- }
303
- }
304
- // Clear cache after import
305
- this.clearCache();
306
- }
307
- }
308
- // ============================================================================
309
- // Domain Prototype Learning (OPTIMIZED with Float32Array)
310
- // ============================================================================
311
- class PrototypeMemory {
312
- constructor(maxPrototypes = 50, dimension = 384) {
313
- this.prototypes = new Map();
314
- this.maxPrototypes = maxPrototypes;
315
- this.scratchBuffer = new Float32Array(dimension);
316
- }
317
- /**
318
- * Update prototype with new embedding (online mean update)
319
- * OPTIMIZED: Uses Float32Array internally
320
- */
321
- update(domain, embedding) {
322
- const existing = this.prototypes.get(domain);
323
- if (existing) {
324
- // Online mean update: new_mean = old_mean + (x - old_mean) / n
325
- const n = existing.count + 1;
326
- const invN = 1 / n;
327
- // Unrolled update loop
328
- const len = Math.min(embedding.length, existing.centroid.length);
329
- const len4 = len - (len % 4);
330
- for (let i = 0; i < len4; i += 4) {
331
- const d0 = embedding[i] - existing.centroid[i];
332
- const d1 = embedding[i + 1] - existing.centroid[i + 1];
333
- const d2 = embedding[i + 2] - existing.centroid[i + 2];
334
- const d3 = embedding[i + 3] - existing.centroid[i + 3];
335
- existing.centroid[i] += d0 * invN;
336
- existing.centroid[i + 1] += d1 * invN;
337
- existing.centroid[i + 2] += d2 * invN;
338
- existing.centroid[i + 3] += d3 * invN;
339
- existing.variance += d0 * (embedding[i] - existing.centroid[i]);
340
- existing.variance += d1 * (embedding[i + 1] - existing.centroid[i + 1]);
341
- existing.variance += d2 * (embedding[i + 2] - existing.centroid[i + 2]);
342
- existing.variance += d3 * (embedding[i + 3] - existing.centroid[i + 3]);
343
- }
344
- for (let i = len4; i < len; i++) {
345
- const delta = embedding[i] - existing.centroid[i];
346
- existing.centroid[i] += delta * invN;
347
- existing.variance += delta * (embedding[i] - existing.centroid[i]);
348
- }
349
- existing.count = n;
350
- }
351
- else {
352
- // Create new prototype
353
- if (this.prototypes.size >= this.maxPrototypes) {
354
- // Remove least used prototype
355
- let minCount = Infinity;
356
- let minKey = '';
357
- for (const [key, proto] of this.prototypes) {
358
- if (proto.count < minCount) {
359
- minCount = proto.count;
360
- minKey = key;
361
- }
362
- }
363
- this.prototypes.delete(minKey);
364
- }
365
- this.prototypes.set(domain, {
366
- domain,
367
- centroid: Array.from(embedding),
368
- count: 1,
369
- variance: 0,
370
- });
371
- }
372
- }
373
- /**
374
- * Find closest prototype and return domain-adjusted embedding
375
- * OPTIMIZED: Single-pass similarity with early exit
376
- */
377
- adjust(embedding) {
378
- if (this.prototypes.size === 0) {
379
- return { adjusted: Array.from(embedding), domain: null, confidence: 0 };
380
- }
381
- let bestSim = -Infinity;
382
- let bestProto = null;
383
- for (const proto of this.prototypes.values()) {
384
- const sim = this.cosineSimilarityFast(embedding, proto.centroid);
385
- if (sim > bestSim) {
386
- bestSim = sim;
387
- bestProto = proto;
388
- }
389
- }
390
- if (!bestProto || bestSim < 0.5) {
391
- return { adjusted: Array.from(embedding), domain: null, confidence: 0 };
392
- }
393
- // Adjust embedding toward prototype (soft assignment)
394
- const alpha = 0.1 * bestSim;
395
- const oneMinusAlpha = 1 - alpha;
396
- const adjusted = new Array(embedding.length);
397
- // Unrolled adjustment
398
- const len = embedding.length;
399
- const len4 = len - (len % 4);
400
- for (let i = 0; i < len4; i += 4) {
401
- adjusted[i] = embedding[i] * oneMinusAlpha + bestProto.centroid[i] * alpha;
402
- adjusted[i + 1] = embedding[i + 1] * oneMinusAlpha + bestProto.centroid[i + 1] * alpha;
403
- adjusted[i + 2] = embedding[i + 2] * oneMinusAlpha + bestProto.centroid[i + 2] * alpha;
404
- adjusted[i + 3] = embedding[i + 3] * oneMinusAlpha + bestProto.centroid[i + 3] * alpha;
405
- }
406
- for (let i = len4; i < len; i++) {
407
- adjusted[i] = embedding[i] * oneMinusAlpha + bestProto.centroid[i] * alpha;
408
- }
409
- return {
410
- adjusted,
411
- domain: bestProto.domain,
412
- confidence: bestSim,
413
- };
414
- }
415
- /**
416
- * Fast cosine similarity with loop unrolling
417
- */
418
- cosineSimilarityFast(a, b) {
419
- let dot = 0, normA = 0, normB = 0;
420
- const len = Math.min(a.length, b.length);
421
- const len4 = len - (len % 4);
422
- for (let i = 0; i < len4; i += 4) {
423
- dot += a[i] * b[i] + a[i + 1] * b[i + 1] + a[i + 2] * b[i + 2] + a[i + 3] * b[i + 3];
424
- normA += a[i] * a[i] + a[i + 1] * a[i + 1] + a[i + 2] * a[i + 2] + a[i + 3] * a[i + 3];
425
- normB += b[i] * b[i] + b[i + 1] * b[i + 1] + b[i + 2] * b[i + 2] + b[i + 3] * b[i + 3];
426
- }
427
- for (let i = len4; i < len; i++) {
428
- dot += a[i] * b[i];
429
- normA += a[i] * a[i];
430
- normB += b[i] * b[i];
431
- }
432
- return dot / (Math.sqrt(normA * normB) + 1e-8);
433
- }
434
- getPrototypes() {
435
- return Array.from(this.prototypes.values());
436
- }
437
- export() {
438
- return this.getPrototypes();
439
- }
440
- import(prototypes) {
441
- this.prototypes.clear();
442
- for (const p of prototypes) {
443
- this.prototypes.set(p.domain, p);
444
- }
445
- }
446
- }
447
- class EpisodicMemory {
448
- constructor(capacity = 1000, dimension = 384) {
449
- this.entries = [];
450
- this.capacity = capacity;
451
- this.dimension = dimension;
452
- this.augmentBuffer = new Float32Array(dimension);
453
- this.weightsBuffer = new Float32Array(Math.min(capacity, 16)); // Max k
454
- }
455
- add(embedding, context) {
456
- if (this.entries.length >= this.capacity) {
457
- // Find and remove least used entry (O(n) but infrequent)
458
- let minIdx = 0;
459
- let minCount = this.entries[0].useCount;
460
- for (let i = 1; i < this.entries.length; i++) {
461
- if (this.entries[i].useCount < minCount) {
462
- minCount = this.entries[i].useCount;
463
- minIdx = i;
464
- }
465
- }
466
- this.entries.splice(minIdx, 1);
467
- }
468
- // Convert to Float32Array and pre-compute norm
469
- const emb = embedding instanceof Float32Array
470
- ? new Float32Array(embedding)
471
- : new Float32Array(embedding);
472
- let normSq = 0;
473
- for (let i = 0; i < emb.length; i++) {
474
- normSq += emb[i] * emb[i];
475
- }
476
- this.entries.push({
477
- embedding: emb,
478
- context,
479
- timestamp: Date.now(),
480
- useCount: 0,
481
- normSquared: normSq,
482
- });
483
- }
484
- /**
485
- * Retrieve similar past embeddings for context augmentation
486
- * OPTIMIZED: Uses pre-computed norms for fast similarity
487
- */
488
- retrieve(query, k = 5) {
489
- if (this.entries.length === 0)
490
- return [];
491
- // Pre-compute query norm
492
- let queryNormSq = 0;
493
- for (let i = 0; i < query.length; i++) {
494
- queryNormSq += query[i] * query[i];
495
- }
496
- const queryNorm = Math.sqrt(queryNormSq);
497
- // Score all entries
498
- const scored = [];
499
- for (const entry of this.entries) {
500
- // Fast dot product with loop unrolling
501
- let dot = 0;
502
- const len = Math.min(query.length, entry.embedding.length);
503
- const len4 = len - (len % 4);
504
- for (let i = 0; i < len4; i += 4) {
505
- dot += query[i] * entry.embedding[i];
506
- dot += query[i + 1] * entry.embedding[i + 1];
507
- dot += query[i + 2] * entry.embedding[i + 2];
508
- dot += query[i + 3] * entry.embedding[i + 3];
509
- }
510
- for (let i = len4; i < len; i++) {
511
- dot += query[i] * entry.embedding[i];
512
- }
513
- const similarity = dot / (queryNorm * Math.sqrt(entry.normSquared) + 1e-8);
514
- scored.push({ entry, similarity });
515
- }
516
- // Partial sort for top-k (faster than full sort for large arrays)
517
- if (scored.length <= k) {
518
- scored.sort((a, b) => b.similarity - a.similarity);
519
- for (const s of scored)
520
- s.entry.useCount++;
521
- return scored.map(s => s.entry);
522
- }
523
- // Quick select for top-k
524
- scored.sort((a, b) => b.similarity - a.similarity);
525
- const topK = scored.slice(0, k);
526
- for (const s of topK)
527
- s.entry.useCount++;
528
- return topK.map(s => s.entry);
529
- }
530
- /**
531
- * Augment embedding with episodic memory (attention-like)
532
- * OPTIMIZED: Uses pre-allocated buffers
533
- */
534
- augment(embedding, k = 3) {
535
- const similar = this.retrieve(embedding, k);
536
- if (similar.length === 0)
537
- return Array.from(embedding);
538
- // Pre-compute query norm
539
- let queryNormSq = 0;
540
- for (let i = 0; i < embedding.length; i++) {
541
- queryNormSq += embedding[i] * embedding[i];
542
- }
543
- const queryNorm = Math.sqrt(queryNormSq);
544
- // Compute weights
545
- let sumWeights = 1; // Start with 1 for query
546
- for (let j = 0; j < similar.length; j++) {
547
- // Fast dot product for similarity
548
- let dot = 0;
549
- const emb = similar[j].embedding;
550
- const len = Math.min(embedding.length, emb.length);
551
- for (let i = 0; i < len; i++) {
552
- dot += embedding[i] * emb[i];
553
- }
554
- const sim = dot / (queryNorm * Math.sqrt(similar[j].normSquared) + 1e-8);
555
- const weight = Math.exp(sim / 0.1);
556
- this.weightsBuffer[j] = weight;
557
- sumWeights += weight;
558
- }
559
- const invSumWeights = 1 / sumWeights;
560
- // Weighted average
561
- const dim = embedding.length;
562
- for (let i = 0; i < dim; i++) {
563
- let sum = embedding[i]; // Query contribution
564
- for (let j = 0; j < similar.length; j++) {
565
- sum += this.weightsBuffer[j] * similar[j].embedding[i];
566
- }
567
- this.augmentBuffer[i] = sum * invSumWeights;
568
- }
569
- return Array.from(this.augmentBuffer.subarray(0, dim));
570
- }
571
- size() {
572
- return this.entries.length;
573
- }
574
- clear() {
575
- this.entries = [];
576
- }
577
- }
578
- // ============================================================================
579
- // Adaptive Embedder (Main Class)
580
- // ============================================================================
581
- class AdaptiveEmbedder {
582
- constructor(config = {}) {
583
- this.onnxReady = false;
584
- this.dimension = 384;
585
- // Stats
586
- this.adaptationCount = 0;
587
- this.ewcCount = 0;
588
- this.contrastiveCount = 0;
589
- // Co-edit buffer for contrastive learning
590
- this.coEditBuffer = [];
591
- this.config = {
592
- loraRank: config.loraRank ?? 4,
593
- learningRate: config.learningRate ?? 0.01,
594
- ewcLambda: config.ewcLambda ?? 0.1,
595
- numPrototypes: config.numPrototypes ?? 50,
596
- contrastiveLearning: config.contrastiveLearning ?? true,
597
- contrastiveTemp: config.contrastiveTemp ?? 0.07,
598
- memoryCapacity: config.memoryCapacity ?? 1000,
599
- };
600
- // Pass dimension for pre-allocation of Float32Array buffers
601
- this.lora = new MicroLoRA(this.dimension, this.config.loraRank);
602
- this.prototypes = new PrototypeMemory(this.config.numPrototypes, this.dimension);
603
- this.episodic = new EpisodicMemory(this.config.memoryCapacity, this.dimension);
604
- }
605
- /**
606
- * Initialize ONNX backend
607
- */
608
- async init() {
609
- if ((0, onnx_embedder_1.isOnnxAvailable)()) {
610
- await (0, onnx_embedder_1.initOnnxEmbedder)();
611
- this.onnxReady = true;
612
- }
613
- }
614
- /**
615
- * Generate adaptive embedding
616
- * Pipeline: ONNX → LoRA → Prototype Adjustment → Episodic Augmentation
617
- */
618
- async embed(text, options) {
619
- // Step 1: Get base ONNX embedding
620
- let baseEmb;
621
- if (this.onnxReady) {
622
- const result = await (0, onnx_embedder_1.embed)(text);
623
- baseEmb = result.embedding;
624
- }
625
- else {
626
- // Fallback to hash embedding
627
- baseEmb = this.hashEmbed(text);
628
- }
629
- // Step 2: Apply LoRA adaptation
630
- let adapted = this.lora.forward(baseEmb);
631
- // Step 3: Prototype adjustment (if domain specified)
632
- if (options?.domain) {
633
- this.prototypes.update(options.domain, adapted);
634
- }
635
- const { adjusted, domain } = this.prototypes.adjust(adapted);
636
- adapted = adjusted;
637
- // Step 4: Episodic memory augmentation
638
- if (options?.useEpisodic !== false) {
639
- adapted = this.episodic.augment(adapted);
640
- }
641
- // Step 5: Store in episodic memory
642
- if (options?.storeInMemory !== false) {
643
- this.episodic.add(adapted, text.slice(0, 100));
644
- }
645
- // Normalize
646
- return this.normalize(adapted);
647
- }
648
- /**
649
- * Batch embed with adaptation
650
- */
651
- async embedBatch(texts, options) {
652
- const results = [];
653
- if (this.onnxReady) {
654
- const baseResults = await (0, onnx_embedder_1.embedBatch)(texts);
655
- for (let i = 0; i < baseResults.length; i++) {
656
- let adapted = this.lora.forward(baseResults[i].embedding);
657
- if (options?.domain) {
658
- this.prototypes.update(options.domain, adapted);
659
- }
660
- const { adjusted } = this.prototypes.adjust(adapted);
661
- results.push(this.normalize(adjusted));
662
- }
663
- }
664
- else {
665
- for (const text of texts) {
666
- results.push(await this.embed(text, options));
667
- }
668
- }
669
- return results;
670
- }
671
- /**
672
- * Learn from co-edit pattern (contrastive learning)
673
- * Files edited together should have similar embeddings
674
- */
675
- async learnCoEdit(file1, content1, file2, content2) {
676
- if (!this.config.contrastiveLearning)
677
- return 0;
678
- // Get embeddings
679
- const emb1 = await this.embed(content1.slice(0, 512), { storeInMemory: false });
680
- const emb2 = await this.embed(content2.slice(0, 512), { storeInMemory: false });
681
- // Store in buffer for batch learning
682
- this.coEditBuffer.push({ file1, emb1, file2, emb2 });
683
- // Process batch when buffer is full
684
- if (this.coEditBuffer.length >= 16) {
685
- return this.processCoEditBatch();
686
- }
687
- return 0;
688
- }
689
- /**
690
- * Process co-edit batch with contrastive loss
691
- */
692
- processCoEditBatch() {
693
- if (this.coEditBuffer.length < 2)
694
- return 0;
695
- let totalLoss = 0;
696
- for (const { emb1, emb2 } of this.coEditBuffer) {
697
- // Use other pairs as negatives
698
- const negatives = this.coEditBuffer
699
- .filter(p => p.emb1 !== emb1)
700
- .slice(0, 4)
701
- .map(p => p.emb1);
702
- // Backward pass with contrastive loss
703
- const loss = this.lora.backward(emb1, emb2, negatives, this.config.learningRate, this.config.ewcLambda);
704
- totalLoss += loss;
705
- this.contrastiveCount++;
706
- }
707
- this.coEditBuffer = [];
708
- this.adaptationCount++;
709
- return totalLoss / this.coEditBuffer.length;
710
- }
711
- /**
712
- * Learn from trajectory outcome (reinforcement-like)
713
- */
714
- async learnFromOutcome(context, action, success, quality = 0.5) {
715
- const contextEmb = await this.embed(context, { storeInMemory: false });
716
- const actionEmb = await this.embed(action, { storeInMemory: false });
717
- if (success && quality > 0.7) {
718
- // Positive outcome - pull embeddings closer
719
- this.lora.backward(contextEmb, actionEmb, [], this.config.learningRate * quality, this.config.ewcLambda);
720
- this.adaptationCount++;
721
- }
722
- }
723
- /**
724
- * EWC consolidation - prevent forgetting important adaptations
725
- * OPTIMIZED: Works with Float32Array episodic entries
726
- */
727
- async consolidate() {
728
- // Collect current episodic memories for Fisher estimation
729
- const embeddings = [];
730
- const entries = this.episodic.entries || [];
731
- // Get last 100 entries for Fisher estimation
732
- const recentEntries = entries.slice(-100);
733
- for (const entry of recentEntries) {
734
- if (entry.embedding instanceof Float32Array) {
735
- embeddings.push(entry.embedding);
736
- }
737
- }
738
- if (embeddings.length > 10) {
739
- this.lora.consolidate(embeddings);
740
- this.ewcCount++;
741
- }
742
- }
743
- /**
744
- * Fallback hash embedding
745
- */
746
- hashEmbed(text) {
747
- const embedding = new Array(this.dimension).fill(0);
748
- const tokens = text.toLowerCase().split(/\s+/);
749
- for (let t = 0; t < tokens.length; t++) {
750
- const token = tokens[t];
751
- const posWeight = 1 / (1 + t * 0.1);
752
- for (let i = 0; i < token.length; i++) {
753
- const code = token.charCodeAt(i);
754
- const h1 = (code * 31 + i * 17 + t * 7) % this.dimension;
755
- const h2 = (code * 37 + i * 23 + t * 11) % this.dimension;
756
- embedding[h1] += posWeight;
757
- embedding[h2] += posWeight * 0.5;
758
- }
759
- }
760
- return this.normalize(embedding);
761
- }
762
- normalize(v) {
763
- const norm = Math.sqrt(v.reduce((a, b) => a + b * b, 0));
764
- return norm > 0 ? v.map(x => x / norm) : v;
765
- }
766
- /**
767
- * Get statistics
768
- */
769
- getStats() {
770
- return {
771
- baseModel: 'all-MiniLM-L6-v2',
772
- dimension: this.dimension,
773
- loraRank: this.config.loraRank,
774
- loraParams: this.lora.getParams(),
775
- adaptations: this.adaptationCount,
776
- prototypes: this.prototypes.getPrototypes().length,
777
- memorySize: this.episodic.size(),
778
- ewcConsolidations: this.ewcCount,
779
- contrastiveUpdates: this.contrastiveCount,
780
- };
781
- }
782
- /**
783
- * Export learned weights
784
- */
785
- export() {
786
- return {
787
- lora: this.lora.export(),
788
- prototypes: this.prototypes.export(),
789
- stats: this.getStats(),
790
- };
791
- }
792
- /**
793
- * Import learned weights
794
- */
795
- import(data) {
796
- if (data.lora) {
797
- this.lora.import(data.lora);
798
- }
799
- if (data.prototypes) {
800
- this.prototypes.import(data.prototypes);
801
- }
802
- }
803
- /**
804
- * Reset adaptations
805
- */
806
- reset() {
807
- this.lora = new MicroLoRA(this.dimension, this.config.loraRank);
808
- this.prototypes = new PrototypeMemory(this.config.numPrototypes, this.dimension);
809
- this.episodic.clear();
810
- this.adaptationCount = 0;
811
- this.ewcCount = 0;
812
- this.contrastiveCount = 0;
813
- this.coEditBuffer = [];
814
- }
815
- /**
816
- * Get LoRA cache statistics
817
- */
818
- getCacheStats() {
819
- return this.lora.getCacheStats?.() ?? { size: 0, maxSize: 256 };
820
- }
821
- }
822
- exports.AdaptiveEmbedder = AdaptiveEmbedder;
823
- // ============================================================================
824
- // Factory & Singleton
825
- // ============================================================================
826
- let instance = null;
827
- function getAdaptiveEmbedder(config) {
828
- if (!instance) {
829
- instance = new AdaptiveEmbedder(config);
830
- }
831
- return instance;
832
- }
833
- async function initAdaptiveEmbedder(config) {
834
- const embedder = getAdaptiveEmbedder(config);
835
- await embedder.init();
836
- return embedder;
837
- }
838
- exports.default = AdaptiveEmbedder;