@sparkleideas/plugins 3.0.0-alpha.8

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 (80) hide show
  1. package/README.md +401 -0
  2. package/__tests__/collection-manager.test.ts +332 -0
  3. package/__tests__/dependency-graph.test.ts +434 -0
  4. package/__tests__/enhanced-plugin-registry.test.ts +488 -0
  5. package/__tests__/plugin-registry.test.ts +368 -0
  6. package/__tests__/ruvector-bridge.test.ts +2429 -0
  7. package/__tests__/ruvector-integration.test.ts +1602 -0
  8. package/__tests__/ruvector-migrations.test.ts +1099 -0
  9. package/__tests__/ruvector-quantization.test.ts +846 -0
  10. package/__tests__/ruvector-streaming.test.ts +1088 -0
  11. package/__tests__/sdk.test.ts +325 -0
  12. package/__tests__/security.test.ts +348 -0
  13. package/__tests__/utils/ruvector-test-utils.ts +860 -0
  14. package/examples/plugin-creator/index.ts +636 -0
  15. package/examples/plugin-creator/plugin-creator.test.ts +312 -0
  16. package/examples/ruvector/README.md +288 -0
  17. package/examples/ruvector/attention-patterns.ts +394 -0
  18. package/examples/ruvector/basic-usage.ts +288 -0
  19. package/examples/ruvector/docker-compose.yml +75 -0
  20. package/examples/ruvector/gnn-analysis.ts +501 -0
  21. package/examples/ruvector/hyperbolic-hierarchies.ts +557 -0
  22. package/examples/ruvector/init-db.sql +119 -0
  23. package/examples/ruvector/quantization.ts +680 -0
  24. package/examples/ruvector/self-learning.ts +447 -0
  25. package/examples/ruvector/semantic-search.ts +576 -0
  26. package/examples/ruvector/streaming-large-data.ts +507 -0
  27. package/examples/ruvector/transactions.ts +594 -0
  28. package/examples/ruvector-plugins/hook-pattern-library.ts +486 -0
  29. package/examples/ruvector-plugins/index.ts +79 -0
  30. package/examples/ruvector-plugins/intent-router.ts +354 -0
  31. package/examples/ruvector-plugins/mcp-tool-optimizer.ts +424 -0
  32. package/examples/ruvector-plugins/reasoning-bank.ts +657 -0
  33. package/examples/ruvector-plugins/ruvector-plugins.test.ts +518 -0
  34. package/examples/ruvector-plugins/semantic-code-search.ts +498 -0
  35. package/examples/ruvector-plugins/shared/index.ts +20 -0
  36. package/examples/ruvector-plugins/shared/vector-utils.ts +257 -0
  37. package/examples/ruvector-plugins/sona-learning.ts +445 -0
  38. package/package.json +97 -0
  39. package/src/collections/collection-manager.ts +661 -0
  40. package/src/collections/index.ts +56 -0
  41. package/src/collections/official/index.ts +1040 -0
  42. package/src/core/base-plugin.ts +416 -0
  43. package/src/core/plugin-interface.ts +215 -0
  44. package/src/hooks/index.ts +685 -0
  45. package/src/index.ts +378 -0
  46. package/src/integrations/agentic-flow.ts +743 -0
  47. package/src/integrations/index.ts +88 -0
  48. package/src/integrations/ruvector/ARCHITECTURE.md +1245 -0
  49. package/src/integrations/ruvector/attention-advanced.ts +1040 -0
  50. package/src/integrations/ruvector/attention-executor.ts +782 -0
  51. package/src/integrations/ruvector/attention-mechanisms.ts +757 -0
  52. package/src/integrations/ruvector/attention.ts +1063 -0
  53. package/src/integrations/ruvector/gnn.ts +3050 -0
  54. package/src/integrations/ruvector/hyperbolic.ts +1948 -0
  55. package/src/integrations/ruvector/index.ts +394 -0
  56. package/src/integrations/ruvector/migrations/001_create_extension.sql +135 -0
  57. package/src/integrations/ruvector/migrations/002_create_vector_tables.sql +259 -0
  58. package/src/integrations/ruvector/migrations/003_create_indices.sql +328 -0
  59. package/src/integrations/ruvector/migrations/004_create_functions.sql +598 -0
  60. package/src/integrations/ruvector/migrations/005_create_attention_functions.sql +654 -0
  61. package/src/integrations/ruvector/migrations/006_create_gnn_functions.sql +728 -0
  62. package/src/integrations/ruvector/migrations/007_create_hyperbolic_functions.sql +762 -0
  63. package/src/integrations/ruvector/migrations/index.ts +35 -0
  64. package/src/integrations/ruvector/migrations/migrations.ts +647 -0
  65. package/src/integrations/ruvector/quantization.ts +2036 -0
  66. package/src/integrations/ruvector/ruvector-bridge.ts +2000 -0
  67. package/src/integrations/ruvector/self-learning.ts +2376 -0
  68. package/src/integrations/ruvector/streaming.ts +1737 -0
  69. package/src/integrations/ruvector/types.ts +1945 -0
  70. package/src/providers/index.ts +643 -0
  71. package/src/registry/dependency-graph.ts +568 -0
  72. package/src/registry/enhanced-plugin-registry.ts +994 -0
  73. package/src/registry/plugin-registry.ts +604 -0
  74. package/src/sdk/index.ts +563 -0
  75. package/src/security/index.ts +594 -0
  76. package/src/types/index.ts +446 -0
  77. package/src/workers/index.ts +700 -0
  78. package/tmp.json +0 -0
  79. package/tsconfig.json +25 -0
  80. package/vitest.config.ts +23 -0
@@ -0,0 +1,1063 @@
1
+ /**
2
+ * RuVector PostgreSQL Bridge - Attention Mechanisms Module
3
+ *
4
+ * Comprehensive implementation of all 39 attention mechanisms for the
5
+ * RuVector PostgreSQL vector database integration.
6
+ *
7
+ * @module @sparkleideas/plugins/integrations/ruvector/attention
8
+ * @version 1.0.0
9
+ */
10
+
11
+ import type {
12
+ AttentionMechanism,
13
+ AttentionConfig,
14
+ AttentionInput,
15
+ AttentionOutput,
16
+ AttentionParams,
17
+ AttentionStats,
18
+ KVCache,
19
+ } from './types.js';
20
+
21
+ // ============================================================================
22
+ // Attention Mechanism Interface
23
+ // ============================================================================
24
+
25
+ /**
26
+ * Options for configuring attention computation.
27
+ */
28
+ export interface AttentionOptions {
29
+ /** Number of attention heads */
30
+ numHeads?: number;
31
+ /** Dimension per head */
32
+ headDim?: number;
33
+ /** Dropout rate */
34
+ dropout?: number;
35
+ /** Whether to use causal masking */
36
+ causal?: boolean;
37
+ /** Scale factor for attention scores */
38
+ scale?: number;
39
+ /** Maximum sequence length */
40
+ maxSeqLen?: number;
41
+ /** Mechanism-specific parameters */
42
+ params?: AttentionParams;
43
+ }
44
+
45
+ /**
46
+ * Interface for attention mechanism implementations.
47
+ */
48
+ export interface IAttentionMechanism {
49
+ /** Attention mechanism type */
50
+ readonly type: AttentionMechanism;
51
+ /** Human-readable name */
52
+ readonly name: string;
53
+ /** Description of the mechanism */
54
+ readonly description: string;
55
+ /** Category of the mechanism */
56
+ readonly category: AttentionCategory;
57
+
58
+ /**
59
+ * Compute attention output from query, keys, and values.
60
+ */
61
+ compute(
62
+ query: number[],
63
+ keys: number[][],
64
+ values: number[][]
65
+ ): Promise<number[]>;
66
+
67
+ /**
68
+ * Compute batched attention.
69
+ */
70
+ computeBatch(
71
+ queries: number[][],
72
+ keys: number[][],
73
+ values: number[][]
74
+ ): Promise<number[][]>;
75
+
76
+ /**
77
+ * Configure the attention mechanism with options.
78
+ */
79
+ configure(options: AttentionOptions): void;
80
+
81
+ /**
82
+ * Generate SQL query for PostgreSQL execution.
83
+ */
84
+ toSQL(input: AttentionInput): string;
85
+
86
+ /**
87
+ * Get current configuration.
88
+ */
89
+ getConfig(): AttentionConfig;
90
+ }
91
+
92
+ /**
93
+ * Categories of attention mechanisms.
94
+ */
95
+ export type AttentionCategory =
96
+ | 'core'
97
+ | 'efficient'
98
+ | 'positional'
99
+ | 'sparse'
100
+ | 'linear'
101
+ | 'graph'
102
+ | 'temporal'
103
+ | 'multimodal'
104
+ | 'retrieval';
105
+
106
+ // ============================================================================
107
+ // Attention Registry
108
+ // ============================================================================
109
+
110
+ /**
111
+ * Registry for managing attention mechanism implementations.
112
+ */
113
+ export class AttentionRegistry {
114
+ private mechanisms: Map<AttentionMechanism, IAttentionMechanism> = new Map();
115
+ private categoryIndex: Map<AttentionCategory, Set<AttentionMechanism>> = new Map();
116
+
117
+ constructor() {
118
+ // Initialize category index
119
+ const categories: AttentionCategory[] = [
120
+ 'core', 'efficient', 'positional', 'sparse',
121
+ 'linear', 'graph', 'temporal', 'multimodal', 'retrieval'
122
+ ];
123
+ categories.forEach(cat => this.categoryIndex.set(cat, new Set()));
124
+ }
125
+
126
+ /**
127
+ * Register an attention mechanism implementation.
128
+ */
129
+ register(impl: IAttentionMechanism): void {
130
+ this.mechanisms.set(impl.type, impl);
131
+ this.categoryIndex.get(impl.category)?.add(impl.type);
132
+ }
133
+
134
+ /**
135
+ * Get an attention mechanism by type.
136
+ */
137
+ get(type: AttentionMechanism): IAttentionMechanism {
138
+ const mechanism = this.mechanisms.get(type);
139
+ if (!mechanism) {
140
+ throw new Error(`Attention mechanism '${type}' not registered`);
141
+ }
142
+ return mechanism;
143
+ }
144
+
145
+ /**
146
+ * Check if a mechanism is registered.
147
+ */
148
+ has(type: AttentionMechanism): boolean {
149
+ return this.mechanisms.has(type);
150
+ }
151
+
152
+ /**
153
+ * List all registered attention mechanisms.
154
+ */
155
+ listAvailable(): AttentionMechanism[] {
156
+ return Array.from(this.mechanisms.keys());
157
+ }
158
+
159
+ /**
160
+ * List mechanisms by category.
161
+ */
162
+ listByCategory(category: AttentionCategory): AttentionMechanism[] {
163
+ return Array.from(this.categoryIndex.get(category) || []);
164
+ }
165
+
166
+ /**
167
+ * Get all mechanisms with metadata.
168
+ */
169
+ getAllWithMetadata(): Array<{
170
+ type: AttentionMechanism;
171
+ name: string;
172
+ description: string;
173
+ category: AttentionCategory;
174
+ }> {
175
+ return Array.from(this.mechanisms.values()).map(m => ({
176
+ type: m.type,
177
+ name: m.name,
178
+ description: m.description,
179
+ category: m.category,
180
+ }));
181
+ }
182
+
183
+ /**
184
+ * Unregister a mechanism.
185
+ */
186
+ unregister(type: AttentionMechanism): boolean {
187
+ const mechanism = this.mechanisms.get(type);
188
+ if (mechanism) {
189
+ this.categoryIndex.get(mechanism.category)?.delete(type);
190
+ return this.mechanisms.delete(type);
191
+ }
192
+ return false;
193
+ }
194
+
195
+ /**
196
+ * Clear all registered mechanisms.
197
+ */
198
+ clear(): void {
199
+ this.mechanisms.clear();
200
+ this.categoryIndex.forEach(set => set.clear());
201
+ }
202
+ }
203
+
204
+ // ============================================================================
205
+ // Base Attention Implementation
206
+ // ============================================================================
207
+
208
+ /**
209
+ * Base class for attention mechanism implementations.
210
+ */
211
+ export abstract class BaseAttentionMechanism implements IAttentionMechanism {
212
+ abstract readonly type: AttentionMechanism;
213
+ abstract readonly name: string;
214
+ abstract readonly description: string;
215
+ abstract readonly category: AttentionCategory;
216
+
217
+ protected config: AttentionConfig;
218
+
219
+ constructor(config?: Partial<AttentionConfig>) {
220
+ // Note: mechanism will be set correctly via getConfig() which uses this.type
221
+ this.config = {
222
+ mechanism: 'multi_head' as AttentionMechanism, // Placeholder, overridden by getConfig
223
+ numHeads: config?.numHeads ?? 8,
224
+ headDim: config?.headDim ?? 64,
225
+ embedDim: config?.embedDim ?? 512,
226
+ dropout: config?.dropout ?? 0.0,
227
+ useBias: config?.useBias ?? true,
228
+ scale: config?.scale,
229
+ causal: config?.causal ?? false,
230
+ maxSeqLen: config?.maxSeqLen ?? 2048,
231
+ params: config?.params,
232
+ };
233
+ }
234
+
235
+ configure(options: AttentionOptions): void {
236
+ if (options.numHeads !== undefined) this.config = { ...this.config, numHeads: options.numHeads };
237
+ if (options.headDim !== undefined) this.config = { ...this.config, headDim: options.headDim };
238
+ if (options.dropout !== undefined) this.config = { ...this.config, dropout: options.dropout };
239
+ if (options.causal !== undefined) this.config = { ...this.config, causal: options.causal };
240
+ if (options.scale !== undefined) this.config = { ...this.config, scale: options.scale };
241
+ if (options.maxSeqLen !== undefined) this.config = { ...this.config, maxSeqLen: options.maxSeqLen };
242
+ if (options.params !== undefined) this.config = { ...this.config, params: { ...this.config.params, ...options.params } };
243
+ }
244
+
245
+ getConfig(): AttentionConfig {
246
+ return { ...this.config, mechanism: this.type };
247
+ }
248
+
249
+ abstract compute(query: number[], keys: number[][], values: number[][]): Promise<number[]>;
250
+ abstract computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]>;
251
+ abstract toSQL(input: AttentionInput): string;
252
+
253
+ /**
254
+ * Compute attention scale factor.
255
+ */
256
+ protected getScale(): number {
257
+ return this.config.scale ?? Math.sqrt(this.config.headDim);
258
+ }
259
+
260
+ /**
261
+ * Format vector for SQL.
262
+ */
263
+ protected formatVector(v: number[] | Float32Array): string {
264
+ const arr = Array.isArray(v) ? v : Array.from(v);
265
+ return `'[${arr.join(',')}]'::vector`;
266
+ }
267
+
268
+ /**
269
+ * Format matrix for SQL.
270
+ */
271
+ protected formatMatrix(m: number[][] | Float32Array[]): string {
272
+ const rows = m.map(row => {
273
+ const arr = Array.isArray(row) ? row : Array.from(row);
274
+ return `'[${arr.join(',')}]'::vector`;
275
+ });
276
+ return `ARRAY[${rows.join(',')}]`;
277
+ }
278
+ }
279
+
280
+ // ============================================================================
281
+ // Core Attention Implementations
282
+ // ============================================================================
283
+
284
+ /**
285
+ * Multi-Head Attention (Transformer standard).
286
+ */
287
+ export class MultiHeadAttention extends BaseAttentionMechanism {
288
+ readonly type: AttentionMechanism = 'multi_head';
289
+ readonly name = 'Multi-Head Attention';
290
+ readonly description = 'Standard Transformer multi-head attention with parallel attention heads';
291
+ readonly category: AttentionCategory = 'core';
292
+
293
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
294
+ // Compute attention scores
295
+ const scale = this.getScale();
296
+ const scores = keys.map(k => this.dotProduct(query, k) / scale);
297
+ const weights = this.softmax(scores);
298
+ return this.weightedSum(values, weights);
299
+ }
300
+
301
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
302
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
303
+ }
304
+
305
+ toSQL(input: AttentionInput): string {
306
+ const q = this.formatMatrix(input.query);
307
+ const k = this.formatMatrix(input.key);
308
+ const v = this.formatMatrix(input.value);
309
+ return `SELECT ruvector.multi_head_attention(${q}, ${k}, ${v}, ${this.config.numHeads}, ${this.getScale()}, ${this.config.causal})`;
310
+ }
311
+
312
+ private dotProduct(a: number[], b: number[]): number {
313
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
314
+ }
315
+
316
+ private softmax(x: number[]): number[] {
317
+ const max = Math.max(...x);
318
+ const exp = x.map(v => Math.exp(v - max));
319
+ const sum = exp.reduce((a, b) => a + b, 0);
320
+ return exp.map(v => v / sum);
321
+ }
322
+
323
+ private weightedSum(values: number[][], weights: number[]): number[] {
324
+ const dim = values[0].length;
325
+ const result = new Array(dim).fill(0);
326
+ for (let i = 0; i < values.length; i++) {
327
+ for (let j = 0; j < dim; j++) {
328
+ result[j] += weights[i] * values[i][j];
329
+ }
330
+ }
331
+ return result;
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Self-Attention mechanism.
337
+ */
338
+ export class SelfAttention extends BaseAttentionMechanism {
339
+ readonly type: AttentionMechanism = 'self_attention';
340
+ readonly name = 'Self-Attention';
341
+ readonly description = 'Self-attention where queries, keys, and values come from the same sequence';
342
+ readonly category: AttentionCategory = 'core';
343
+
344
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
345
+ const scale = this.getScale();
346
+ const scores = keys.map(k => this.dotProduct(query, k) / scale);
347
+ const weights = this.softmax(scores);
348
+ return this.weightedSum(values, weights);
349
+ }
350
+
351
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
352
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
353
+ }
354
+
355
+ toSQL(input: AttentionInput): string {
356
+ const q = this.formatMatrix(input.query);
357
+ const k = this.formatMatrix(input.key);
358
+ const v = this.formatMatrix(input.value);
359
+ return `SELECT ruvector.self_attention(${q}, ${k}, ${v}, ${this.getScale()}, ${this.config.causal})`;
360
+ }
361
+
362
+ private dotProduct(a: number[], b: number[]): number {
363
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
364
+ }
365
+
366
+ private softmax(x: number[]): number[] {
367
+ const max = Math.max(...x);
368
+ const exp = x.map(v => Math.exp(v - max));
369
+ const sum = exp.reduce((a, b) => a + b, 0);
370
+ return exp.map(v => v / sum);
371
+ }
372
+
373
+ private weightedSum(values: number[][], weights: number[]): number[] {
374
+ const dim = values[0].length;
375
+ const result = new Array(dim).fill(0);
376
+ for (let i = 0; i < values.length; i++) {
377
+ for (let j = 0; j < dim; j++) {
378
+ result[j] += weights[i] * values[i][j];
379
+ }
380
+ }
381
+ return result;
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Cross-Attention mechanism.
387
+ */
388
+ export class CrossAttention extends BaseAttentionMechanism {
389
+ readonly type: AttentionMechanism = 'cross_attention';
390
+ readonly name = 'Cross-Attention';
391
+ readonly description = 'Cross-attention between two different sequences (encoder-decoder)';
392
+ readonly category: AttentionCategory = 'core';
393
+
394
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
395
+ const scale = this.getScale();
396
+ const scores = keys.map(k => this.dotProduct(query, k) / scale);
397
+ const weights = this.softmax(scores);
398
+ return this.weightedSum(values, weights);
399
+ }
400
+
401
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
402
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
403
+ }
404
+
405
+ toSQL(input: AttentionInput): string {
406
+ const q = this.formatMatrix(input.query);
407
+ const k = this.formatMatrix(input.key);
408
+ const v = this.formatMatrix(input.value);
409
+ return `SELECT ruvector.cross_attention(${q}, ${k}, ${v}, ${this.config.numHeads}, ${this.getScale()})`;
410
+ }
411
+
412
+ private dotProduct(a: number[], b: number[]): number {
413
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
414
+ }
415
+
416
+ private softmax(x: number[]): number[] {
417
+ const max = Math.max(...x);
418
+ const exp = x.map(v => Math.exp(v - max));
419
+ const sum = exp.reduce((a, b) => a + b, 0);
420
+ return exp.map(v => v / sum);
421
+ }
422
+
423
+ private weightedSum(values: number[][], weights: number[]): number[] {
424
+ const dim = values[0].length;
425
+ const result = new Array(dim).fill(0);
426
+ for (let i = 0; i < values.length; i++) {
427
+ for (let j = 0; j < dim; j++) {
428
+ result[j] += weights[i] * values[i][j];
429
+ }
430
+ }
431
+ return result;
432
+ }
433
+ }
434
+
435
+ /**
436
+ * Causal (Masked) Attention for autoregressive models.
437
+ */
438
+ export class CausalAttention extends BaseAttentionMechanism {
439
+ readonly type: AttentionMechanism = 'causal';
440
+ readonly name = 'Causal Attention';
441
+ readonly description = 'Causal/masked attention for autoregressive generation (GPT-style)';
442
+ readonly category: AttentionCategory = 'core';
443
+
444
+ constructor(config?: Partial<AttentionConfig>) {
445
+ super({ ...config, causal: true });
446
+ }
447
+
448
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
449
+ const scale = this.getScale();
450
+ const queryIdx = keys.length - 1; // Assume query is for last position
451
+ const scores = keys.map((k, i) => {
452
+ if (i > queryIdx) return -Infinity; // Mask future tokens
453
+ return this.dotProduct(query, k) / scale;
454
+ });
455
+ const weights = this.softmax(scores);
456
+ return this.weightedSum(values, weights);
457
+ }
458
+
459
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
460
+ const results: number[][] = [];
461
+ for (let i = 0; i < queries.length; i++) {
462
+ const maskedKeys = keys.slice(0, i + 1);
463
+ const maskedValues = values.slice(0, i + 1);
464
+ results.push(await this.compute(queries[i], maskedKeys, maskedValues));
465
+ }
466
+ return results;
467
+ }
468
+
469
+ toSQL(input: AttentionInput): string {
470
+ const q = this.formatMatrix(input.query);
471
+ const k = this.formatMatrix(input.key);
472
+ const v = this.formatMatrix(input.value);
473
+ return `SELECT ruvector.causal_attention(${q}, ${k}, ${v}, ${this.config.numHeads}, ${this.getScale()})`;
474
+ }
475
+
476
+ private dotProduct(a: number[], b: number[]): number {
477
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
478
+ }
479
+
480
+ private softmax(x: number[]): number[] {
481
+ const filtered = x.filter(v => v !== -Infinity);
482
+ if (filtered.length === 0) return x.map(() => 0);
483
+ const max = Math.max(...filtered);
484
+ const exp = x.map(v => v === -Infinity ? 0 : Math.exp(v - max));
485
+ const sum = exp.reduce((a, b) => a + b, 0);
486
+ return sum > 0 ? exp.map(v => v / sum) : exp;
487
+ }
488
+
489
+ private weightedSum(values: number[][], weights: number[]): number[] {
490
+ const dim = values[0].length;
491
+ const result = new Array(dim).fill(0);
492
+ for (let i = 0; i < values.length; i++) {
493
+ for (let j = 0; j < dim; j++) {
494
+ result[j] += weights[i] * values[i][j];
495
+ }
496
+ }
497
+ return result;
498
+ }
499
+ }
500
+
501
+ /**
502
+ * Bidirectional Attention (BERT-style).
503
+ */
504
+ export class BidirectionalAttention extends BaseAttentionMechanism {
505
+ readonly type: AttentionMechanism = 'bidirectional';
506
+ readonly name = 'Bidirectional Attention';
507
+ readonly description = 'Bidirectional attention attending to all tokens (BERT-style)';
508
+ readonly category: AttentionCategory = 'core';
509
+
510
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
511
+ const scale = this.getScale();
512
+ const scores = keys.map(k => this.dotProduct(query, k) / scale);
513
+ const weights = this.softmax(scores);
514
+ return this.weightedSum(values, weights);
515
+ }
516
+
517
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
518
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
519
+ }
520
+
521
+ toSQL(input: AttentionInput): string {
522
+ const q = this.formatMatrix(input.query);
523
+ const k = this.formatMatrix(input.key);
524
+ const v = this.formatMatrix(input.value);
525
+ return `SELECT ruvector.bidirectional_attention(${q}, ${k}, ${v}, ${this.config.numHeads}, ${this.getScale()})`;
526
+ }
527
+
528
+ private dotProduct(a: number[], b: number[]): number {
529
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
530
+ }
531
+
532
+ private softmax(x: number[]): number[] {
533
+ const max = Math.max(...x);
534
+ const exp = x.map(v => Math.exp(v - max));
535
+ const sum = exp.reduce((a, b) => a + b, 0);
536
+ return exp.map(v => v / sum);
537
+ }
538
+
539
+ private weightedSum(values: number[][], weights: number[]): number[] {
540
+ const dim = values[0].length;
541
+ const result = new Array(dim).fill(0);
542
+ for (let i = 0; i < values.length; i++) {
543
+ for (let j = 0; j < dim; j++) {
544
+ result[j] += weights[i] * values[i][j];
545
+ }
546
+ }
547
+ return result;
548
+ }
549
+ }
550
+
551
+ /**
552
+ * Local Attention with sliding window.
553
+ */
554
+ export class LocalAttention extends BaseAttentionMechanism {
555
+ readonly type: AttentionMechanism = 'local_attention';
556
+ readonly name = 'Local Attention';
557
+ readonly description = 'Local attention with fixed window size around each position';
558
+ readonly category: AttentionCategory = 'core';
559
+
560
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
561
+ const windowSize = this.config.params?.windowSize ?? 256;
562
+ const scale = this.getScale();
563
+ const queryIdx = keys.length - 1;
564
+ const start = Math.max(0, queryIdx - Math.floor(windowSize / 2));
565
+ const end = Math.min(keys.length, queryIdx + Math.floor(windowSize / 2) + 1);
566
+
567
+ const scores = keys.map((k, i) => {
568
+ if (i < start || i >= end) return -Infinity;
569
+ return this.dotProduct(query, k) / scale;
570
+ });
571
+ const weights = this.softmax(scores);
572
+ return this.weightedSum(values, weights);
573
+ }
574
+
575
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
576
+ return Promise.all(queries.map((q, i) => {
577
+ const windowSize = this.config.params?.windowSize ?? 256;
578
+ const start = Math.max(0, i - Math.floor(windowSize / 2));
579
+ const end = Math.min(keys.length, i + Math.floor(windowSize / 2) + 1);
580
+ return this.compute(q, keys.slice(start, end), values.slice(start, end));
581
+ }));
582
+ }
583
+
584
+ toSQL(input: AttentionInput): string {
585
+ const q = this.formatMatrix(input.query);
586
+ const k = this.formatMatrix(input.key);
587
+ const v = this.formatMatrix(input.value);
588
+ const windowSize = this.config.params?.windowSize ?? 256;
589
+ return `SELECT ruvector.local_attention(${q}, ${k}, ${v}, ${windowSize}, ${this.getScale()})`;
590
+ }
591
+
592
+ private dotProduct(a: number[], b: number[]): number {
593
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
594
+ }
595
+
596
+ private softmax(x: number[]): number[] {
597
+ const filtered = x.filter(v => v !== -Infinity);
598
+ if (filtered.length === 0) return x.map(() => 0);
599
+ const max = Math.max(...filtered);
600
+ const exp = x.map(v => v === -Infinity ? 0 : Math.exp(v - max));
601
+ const sum = exp.reduce((a, b) => a + b, 0);
602
+ return sum > 0 ? exp.map(v => v / sum) : exp;
603
+ }
604
+
605
+ private weightedSum(values: number[][], weights: number[]): number[] {
606
+ const dim = values[0].length;
607
+ const result = new Array(dim).fill(0);
608
+ for (let i = 0; i < values.length; i++) {
609
+ for (let j = 0; j < dim; j++) {
610
+ result[j] += weights[i] * values[i][j];
611
+ }
612
+ }
613
+ return result;
614
+ }
615
+ }
616
+
617
+ /**
618
+ * Global Attention with special global tokens.
619
+ */
620
+ export class GlobalAttention extends BaseAttentionMechanism {
621
+ readonly type: AttentionMechanism = 'global_attention';
622
+ readonly name = 'Global Attention';
623
+ readonly description = 'Global attention tokens that attend to and are attended by all positions';
624
+ readonly category: AttentionCategory = 'core';
625
+
626
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
627
+ const scale = this.getScale();
628
+ const scores = keys.map(k => this.dotProduct(query, k) / scale);
629
+ const weights = this.softmax(scores);
630
+ return this.weightedSum(values, weights);
631
+ }
632
+
633
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
634
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
635
+ }
636
+
637
+ toSQL(input: AttentionInput): string {
638
+ const q = this.formatMatrix(input.query);
639
+ const k = this.formatMatrix(input.key);
640
+ const v = this.formatMatrix(input.value);
641
+ const numGlobal = this.config.params?.numGlobalTokens ?? 1;
642
+ return `SELECT ruvector.global_attention(${q}, ${k}, ${v}, ${numGlobal}, ${this.getScale()})`;
643
+ }
644
+
645
+ private dotProduct(a: number[], b: number[]): number {
646
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
647
+ }
648
+
649
+ private softmax(x: number[]): number[] {
650
+ const max = Math.max(...x);
651
+ const exp = x.map(v => Math.exp(v - max));
652
+ const sum = exp.reduce((a, b) => a + b, 0);
653
+ return exp.map(v => v / sum);
654
+ }
655
+
656
+ private weightedSum(values: number[][], weights: number[]): number[] {
657
+ const dim = values[0].length;
658
+ const result = new Array(dim).fill(0);
659
+ for (let i = 0; i < values.length; i++) {
660
+ for (let j = 0; j < dim; j++) {
661
+ result[j] += weights[i] * values[i][j];
662
+ }
663
+ }
664
+ return result;
665
+ }
666
+ }
667
+
668
+ // ============================================================================
669
+ // Efficient Attention Implementations
670
+ // ============================================================================
671
+
672
+ /**
673
+ * Flash Attention - memory efficient O(N) attention.
674
+ */
675
+ export class FlashAttention extends BaseAttentionMechanism {
676
+ readonly type: AttentionMechanism = 'flash_attention';
677
+ readonly name = 'Flash Attention';
678
+ readonly description = 'Memory-efficient attention using tiling and recomputation';
679
+ readonly category: AttentionCategory = 'efficient';
680
+
681
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
682
+ const blockSize = this.config.params?.flashBlockSize ?? 64;
683
+ const scale = this.getScale();
684
+ const seqLen = keys.length;
685
+ const dim = values[0].length;
686
+
687
+ let output = new Array(dim).fill(0);
688
+ let maxScore = -Infinity;
689
+ let sumExp = 0;
690
+
691
+ // Process in blocks for memory efficiency
692
+ for (let blockStart = 0; blockStart < seqLen; blockStart += blockSize) {
693
+ const blockEnd = Math.min(blockStart + blockSize, seqLen);
694
+
695
+ // Compute scores for this block
696
+ const blockScores: number[] = [];
697
+ for (let i = blockStart; i < blockEnd; i++) {
698
+ blockScores.push(this.dotProduct(query, keys[i]) / scale);
699
+ }
700
+
701
+ // Update running max and sum
702
+ const blockMax = Math.max(...blockScores);
703
+ if (blockMax > maxScore) {
704
+ const correction = Math.exp(maxScore - blockMax);
705
+ output = output.map(v => v * correction);
706
+ sumExp *= correction;
707
+ maxScore = blockMax;
708
+ }
709
+
710
+ // Accumulate weighted values
711
+ for (let i = 0; i < blockScores.length; i++) {
712
+ const weight = Math.exp(blockScores[i] - maxScore);
713
+ sumExp += weight;
714
+ for (let j = 0; j < dim; j++) {
715
+ output[j] += weight * values[blockStart + i][j];
716
+ }
717
+ }
718
+ }
719
+
720
+ // Normalize
721
+ return output.map(v => v / sumExp);
722
+ }
723
+
724
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
725
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
726
+ }
727
+
728
+ toSQL(input: AttentionInput): string {
729
+ const q = this.formatMatrix(input.query);
730
+ const k = this.formatMatrix(input.key);
731
+ const v = this.formatMatrix(input.value);
732
+ const blockSize = this.config.params?.flashBlockSize ?? 64;
733
+ return `SELECT ruvector.flash_attention(${q}, ${k}, ${v}, ${blockSize}, ${this.getScale()}, ${this.config.causal})`;
734
+ }
735
+
736
+ private dotProduct(a: number[], b: number[]): number {
737
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
738
+ }
739
+ }
740
+
741
+ /**
742
+ * Flash Attention V2 - improved memory efficiency.
743
+ */
744
+ export class FlashAttentionV2 extends BaseAttentionMechanism {
745
+ readonly type: AttentionMechanism = 'flash_attention_v2';
746
+ readonly name = 'Flash Attention V2';
747
+ readonly description = 'Improved Flash Attention with better parallelism and reduced memory';
748
+ readonly category: AttentionCategory = 'efficient';
749
+
750
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
751
+ // Similar to Flash Attention but with improved block scheduling
752
+ const blockSize = this.config.params?.flashBlockSize ?? 128;
753
+ const scale = this.getScale();
754
+ const seqLen = keys.length;
755
+ const dim = values[0].length;
756
+
757
+ let output = new Array(dim).fill(0);
758
+ let maxScore = -Infinity;
759
+ let sumExp = 0;
760
+
761
+ for (let blockStart = 0; blockStart < seqLen; blockStart += blockSize) {
762
+ const blockEnd = Math.min(blockStart + blockSize, seqLen);
763
+
764
+ const blockScores: number[] = [];
765
+ for (let i = blockStart; i < blockEnd; i++) {
766
+ blockScores.push(this.dotProduct(query, keys[i]) / scale);
767
+ }
768
+
769
+ const blockMax = Math.max(...blockScores);
770
+ if (blockMax > maxScore) {
771
+ const correction = Math.exp(maxScore - blockMax);
772
+ output = output.map(v => v * correction);
773
+ sumExp *= correction;
774
+ maxScore = blockMax;
775
+ }
776
+
777
+ for (let i = 0; i < blockScores.length; i++) {
778
+ const weight = Math.exp(blockScores[i] - maxScore);
779
+ sumExp += weight;
780
+ for (let j = 0; j < dim; j++) {
781
+ output[j] += weight * values[blockStart + i][j];
782
+ }
783
+ }
784
+ }
785
+
786
+ return output.map(v => v / sumExp);
787
+ }
788
+
789
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
790
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
791
+ }
792
+
793
+ toSQL(input: AttentionInput): string {
794
+ const q = this.formatMatrix(input.query);
795
+ const k = this.formatMatrix(input.key);
796
+ const v = this.formatMatrix(input.value);
797
+ const blockSize = this.config.params?.flashBlockSize ?? 128;
798
+ return `SELECT ruvector.flash_attention_v2(${q}, ${k}, ${v}, ${blockSize}, ${this.getScale()}, ${this.config.causal})`;
799
+ }
800
+
801
+ private dotProduct(a: number[], b: number[]): number {
802
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
803
+ }
804
+ }
805
+
806
+ /**
807
+ * Memory Efficient Attention.
808
+ */
809
+ export class MemoryEfficientAttention extends BaseAttentionMechanism {
810
+ readonly type: AttentionMechanism = 'memory_efficient';
811
+ readonly name = 'Memory Efficient Attention';
812
+ readonly description = 'Attention optimized for reduced memory footprint';
813
+ readonly category: AttentionCategory = 'efficient';
814
+
815
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
816
+ const scale = this.getScale();
817
+ const scores = keys.map(k => this.dotProduct(query, k) / scale);
818
+ const weights = this.softmax(scores);
819
+ return this.weightedSum(values, weights);
820
+ }
821
+
822
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
823
+ // Process one at a time to minimize memory
824
+ const results: number[][] = [];
825
+ for (const q of queries) {
826
+ results.push(await this.compute(q, keys, values));
827
+ }
828
+ return results;
829
+ }
830
+
831
+ toSQL(input: AttentionInput): string {
832
+ const q = this.formatMatrix(input.query);
833
+ const k = this.formatMatrix(input.key);
834
+ const v = this.formatMatrix(input.value);
835
+ return `SELECT ruvector.memory_efficient_attention(${q}, ${k}, ${v}, ${this.getScale()}, ${this.config.params?.checkpointing ?? false})`;
836
+ }
837
+
838
+ private dotProduct(a: number[], b: number[]): number {
839
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
840
+ }
841
+
842
+ private softmax(x: number[]): number[] {
843
+ const max = Math.max(...x);
844
+ const exp = x.map(v => Math.exp(v - max));
845
+ const sum = exp.reduce((a, b) => a + b, 0);
846
+ return exp.map(v => v / sum);
847
+ }
848
+
849
+ private weightedSum(values: number[][], weights: number[]): number[] {
850
+ const dim = values[0].length;
851
+ const result = new Array(dim).fill(0);
852
+ for (let i = 0; i < values.length; i++) {
853
+ for (let j = 0; j < dim; j++) {
854
+ result[j] += weights[i] * values[i][j];
855
+ }
856
+ }
857
+ return result;
858
+ }
859
+ }
860
+
861
+ /**
862
+ * Chunk Attention - process in chunks.
863
+ */
864
+ export class ChunkAttention extends BaseAttentionMechanism {
865
+ readonly type: AttentionMechanism = 'chunk_attention';
866
+ readonly name = 'Chunk Attention';
867
+ readonly description = 'Chunked attention processing for very long sequences';
868
+ readonly category: AttentionCategory = 'efficient';
869
+
870
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
871
+ const chunkSize = this.config.params?.blockSize ?? 512;
872
+ const scale = this.getScale();
873
+ const dim = values[0].length;
874
+
875
+ const outputs: number[][] = [];
876
+ const chunkWeights: number[] = [];
877
+
878
+ for (let i = 0; i < keys.length; i += chunkSize) {
879
+ const chunkKeys = keys.slice(i, i + chunkSize);
880
+ const chunkValues = values.slice(i, i + chunkSize);
881
+ const scores = chunkKeys.map(k => this.dotProduct(query, k) / scale);
882
+ const weights = this.softmax(scores);
883
+ const chunkOutput = this.weightedSum(chunkValues, weights);
884
+ outputs.push(chunkOutput);
885
+ chunkWeights.push(weights.reduce((a, b) => a + b, 0));
886
+ }
887
+
888
+ // Combine chunk outputs
889
+ const totalWeight = chunkWeights.reduce((a, b) => a + b, 0);
890
+ const result = new Array(dim).fill(0);
891
+ for (let c = 0; c < outputs.length; c++) {
892
+ const w = chunkWeights[c] / totalWeight;
893
+ for (let j = 0; j < dim; j++) {
894
+ result[j] += w * outputs[c][j];
895
+ }
896
+ }
897
+ return result;
898
+ }
899
+
900
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
901
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
902
+ }
903
+
904
+ toSQL(input: AttentionInput): string {
905
+ const q = this.formatMatrix(input.query);
906
+ const k = this.formatMatrix(input.key);
907
+ const v = this.formatMatrix(input.value);
908
+ const chunkSize = this.config.params?.blockSize ?? 512;
909
+ return `SELECT ruvector.chunk_attention(${q}, ${k}, ${v}, ${chunkSize}, ${this.getScale()})`;
910
+ }
911
+
912
+ private dotProduct(a: number[], b: number[]): number {
913
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
914
+ }
915
+
916
+ private softmax(x: number[]): number[] {
917
+ const max = Math.max(...x);
918
+ const exp = x.map(v => Math.exp(v - max));
919
+ const sum = exp.reduce((a, b) => a + b, 0);
920
+ return exp.map(v => v / sum);
921
+ }
922
+
923
+ private weightedSum(values: number[][], weights: number[]): number[] {
924
+ const dim = values[0].length;
925
+ const result = new Array(dim).fill(0);
926
+ for (let i = 0; i < values.length; i++) {
927
+ for (let j = 0; j < dim; j++) {
928
+ result[j] += weights[i] * values[i][j];
929
+ }
930
+ }
931
+ return result;
932
+ }
933
+ }
934
+
935
+ /**
936
+ * Sliding Window Attention.
937
+ */
938
+ export class SlidingWindowAttention extends BaseAttentionMechanism {
939
+ readonly type: AttentionMechanism = 'sliding_window';
940
+ readonly name = 'Sliding Window Attention';
941
+ readonly description = 'Attention with a sliding window for each position';
942
+ readonly category: AttentionCategory = 'efficient';
943
+
944
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
945
+ const windowSize = this.config.params?.windowSize ?? 256;
946
+ const scale = this.getScale();
947
+ const queryIdx = keys.length - 1;
948
+ const halfWindow = Math.floor(windowSize / 2);
949
+
950
+ const scores = keys.map((k, i) => {
951
+ if (Math.abs(i - queryIdx) > halfWindow) return -Infinity;
952
+ return this.dotProduct(query, k) / scale;
953
+ });
954
+
955
+ const weights = this.softmax(scores);
956
+ return this.weightedSum(values, weights);
957
+ }
958
+
959
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
960
+ const windowSize = this.config.params?.windowSize ?? 256;
961
+ const halfWindow = Math.floor(windowSize / 2);
962
+
963
+ return Promise.all(queries.map((q, idx) => {
964
+ const start = Math.max(0, idx - halfWindow);
965
+ const end = Math.min(keys.length, idx + halfWindow + 1);
966
+ const windowKeys = keys.slice(start, end);
967
+ const windowValues = values.slice(start, end);
968
+ return this.compute(q, windowKeys, windowValues);
969
+ }));
970
+ }
971
+
972
+ toSQL(input: AttentionInput): string {
973
+ const q = this.formatMatrix(input.query);
974
+ const k = this.formatMatrix(input.key);
975
+ const v = this.formatMatrix(input.value);
976
+ const windowSize = this.config.params?.windowSize ?? 256;
977
+ return `SELECT ruvector.sliding_window_attention(${q}, ${k}, ${v}, ${windowSize}, ${this.getScale()})`;
978
+ }
979
+
980
+ private dotProduct(a: number[], b: number[]): number {
981
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
982
+ }
983
+
984
+ private softmax(x: number[]): number[] {
985
+ const filtered = x.filter(v => v !== -Infinity);
986
+ if (filtered.length === 0) return x.map(() => 0);
987
+ const max = Math.max(...filtered);
988
+ const exp = x.map(v => v === -Infinity ? 0 : Math.exp(v - max));
989
+ const sum = exp.reduce((a, b) => a + b, 0);
990
+ return sum > 0 ? exp.map(v => v / sum) : exp;
991
+ }
992
+
993
+ private weightedSum(values: number[][], weights: number[]): number[] {
994
+ const dim = values[0].length;
995
+ const result = new Array(dim).fill(0);
996
+ for (let i = 0; i < values.length; i++) {
997
+ for (let j = 0; j < dim; j++) {
998
+ result[j] += weights[i] * values[i][j];
999
+ }
1000
+ }
1001
+ return result;
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * Dilated Attention with strided access.
1007
+ */
1008
+ export class DilatedAttention extends BaseAttentionMechanism {
1009
+ readonly type: AttentionMechanism = 'dilated_attention';
1010
+ readonly name = 'Dilated Attention';
1011
+ readonly description = 'Dilated/strided attention for capturing long-range dependencies';
1012
+ readonly category: AttentionCategory = 'efficient';
1013
+
1014
+ async compute(query: number[], keys: number[][], values: number[][]): Promise<number[]> {
1015
+ const dilationRate = this.config.params?.dilationRate ?? 2;
1016
+ const scale = this.getScale();
1017
+
1018
+ const scores = keys.map((k, i) => {
1019
+ if (i % dilationRate !== 0) return -Infinity;
1020
+ return this.dotProduct(query, k) / scale;
1021
+ });
1022
+
1023
+ const weights = this.softmax(scores);
1024
+ return this.weightedSum(values, weights);
1025
+ }
1026
+
1027
+ async computeBatch(queries: number[][], keys: number[][], values: number[][]): Promise<number[][]> {
1028
+ return Promise.all(queries.map(q => this.compute(q, keys, values)));
1029
+ }
1030
+
1031
+ toSQL(input: AttentionInput): string {
1032
+ const q = this.formatMatrix(input.query);
1033
+ const k = this.formatMatrix(input.key);
1034
+ const v = this.formatMatrix(input.value);
1035
+ const dilationRate = this.config.params?.dilationRate ?? 2;
1036
+ return `SELECT ruvector.dilated_attention(${q}, ${k}, ${v}, ${dilationRate}, ${this.getScale()})`;
1037
+ }
1038
+
1039
+ private dotProduct(a: number[], b: number[]): number {
1040
+ return a.reduce((sum, val, i) => sum + val * b[i], 0);
1041
+ }
1042
+
1043
+ private softmax(x: number[]): number[] {
1044
+ const filtered = x.filter(v => v !== -Infinity);
1045
+ if (filtered.length === 0) return x.map(() => 0);
1046
+ const max = Math.max(...filtered);
1047
+ const exp = x.map(v => v === -Infinity ? 0 : Math.exp(v - max));
1048
+ const sum = exp.reduce((a, b) => a + b, 0);
1049
+ return sum > 0 ? exp.map(v => v / sum) : exp;
1050
+ }
1051
+
1052
+ private weightedSum(values: number[][], weights: number[]): number[] {
1053
+ const dim = values[0].length;
1054
+ const result = new Array(dim).fill(0);
1055
+ for (let i = 0; i < values.length; i++) {
1056
+ for (let j = 0; j < dim; j++) {
1057
+ result[j] += weights[i] * values[i][j];
1058
+ }
1059
+ }
1060
+ return result;
1061
+ }
1062
+ }
1063
+