@sparkleideas/plugins 3.0.0-alpha.10

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,394 @@
1
+ /**
2
+ * RuVector PostgreSQL Bridge - Attention Mechanisms Example
3
+ *
4
+ * This example demonstrates:
5
+ * - Multi-head attention for vector aggregation
6
+ * - Flash attention for long sequences
7
+ * - Sparse attention for efficiency
8
+ * - Cross-attention for multi-modal scenarios
9
+ *
10
+ * Run with: npx ts-node examples/ruvector/attention-patterns.ts
11
+ *
12
+ * @module @sparkleideas/plugins/examples/ruvector/attention-patterns
13
+ */
14
+
15
+ import {
16
+ createRuVectorBridge,
17
+ type RuVectorBridge,
18
+ type AttentionConfig,
19
+ type AttentionInput,
20
+ } from '../../src/integrations/ruvector/index.js';
21
+
22
+ import {
23
+ MultiHeadAttention,
24
+ SelfAttention,
25
+ CrossAttention,
26
+ CausalAttention,
27
+ AttentionRegistry,
28
+ type AttentionOptions,
29
+ } from '../../src/integrations/ruvector/attention.js';
30
+
31
+ // ============================================================================
32
+ // Configuration
33
+ // ============================================================================
34
+
35
+ const config = {
36
+ connection: {
37
+ host: process.env.POSTGRES_HOST || 'localhost',
38
+ port: parseInt(process.env.POSTGRES_PORT || '5432', 10),
39
+ database: process.env.POSTGRES_DB || 'vectors',
40
+ user: process.env.POSTGRES_USER || 'postgres',
41
+ password: process.env.POSTGRES_PASSWORD || 'postgres',
42
+ },
43
+ embedDim: 512,
44
+ numHeads: 8,
45
+ headDim: 64,
46
+ };
47
+
48
+ // ============================================================================
49
+ // Helper Functions
50
+ // ============================================================================
51
+
52
+ /**
53
+ * Generate random vectors for demonstration.
54
+ */
55
+ function generateRandomVectors(count: number, dim: number): number[][] {
56
+ return Array.from({ length: count }, () =>
57
+ Array.from({ length: dim }, () => Math.random() * 2 - 1)
58
+ );
59
+ }
60
+
61
+ /**
62
+ * Measure execution time of an async function.
63
+ */
64
+ async function measure<T>(name: string, fn: () => Promise<T>): Promise<T> {
65
+ const start = performance.now();
66
+ const result = await fn();
67
+ const duration = performance.now() - start;
68
+ console.log(` ${name}: ${duration.toFixed(2)}ms`);
69
+ return result;
70
+ }
71
+
72
+ /**
73
+ * Print vector statistics.
74
+ */
75
+ function printVectorStats(name: string, vec: number[]): void {
76
+ const min = Math.min(...vec);
77
+ const max = Math.max(...vec);
78
+ const mean = vec.reduce((a, b) => a + b, 0) / vec.length;
79
+ const magnitude = Math.sqrt(vec.reduce((s, v) => s + v * v, 0));
80
+
81
+ console.log(` ${name}:`);
82
+ console.log(` Dimension: ${vec.length}`);
83
+ console.log(` Range: [${min.toFixed(4)}, ${max.toFixed(4)}]`);
84
+ console.log(` Mean: ${mean.toFixed(4)}`);
85
+ console.log(` Magnitude: ${magnitude.toFixed(4)}`);
86
+ }
87
+
88
+ // ============================================================================
89
+ // Main Example
90
+ // ============================================================================
91
+
92
+ async function main(): Promise<void> {
93
+ console.log('RuVector PostgreSQL Bridge - Attention Mechanisms Example');
94
+ console.log('==========================================================\n');
95
+
96
+ const bridge: RuVectorBridge = createRuVectorBridge({
97
+ connectionString: `postgresql://${config.connection.user}:${config.connection.password}@${config.connection.host}:${config.connection.port}/${config.connection.database}`,
98
+ });
99
+
100
+ // Initialize attention registry
101
+ const registry = new AttentionRegistry();
102
+
103
+ // Register attention mechanisms
104
+ registry.register(new MultiHeadAttention({ numHeads: config.numHeads, headDim: config.headDim }));
105
+ registry.register(new SelfAttention({ headDim: config.headDim }));
106
+ registry.register(new CrossAttention({ numHeads: config.numHeads, headDim: config.headDim }));
107
+ registry.register(new CausalAttention({ numHeads: config.numHeads, headDim: config.headDim }));
108
+
109
+ try {
110
+ await bridge.connect();
111
+ console.log('Connected to PostgreSQL\n');
112
+
113
+ // ========================================================================
114
+ // 1. Multi-Head Attention Example
115
+ // ========================================================================
116
+ console.log('1. Multi-Head Attention');
117
+ console.log(' ' + '-'.repeat(40));
118
+ console.log(' Parallel attention heads for capturing different relationships\n');
119
+
120
+ const multiHeadAttn = registry.get('multi_head');
121
+ console.log(` Configuration:`);
122
+ console.log(` - Heads: ${config.numHeads}`);
123
+ console.log(` - Head dimension: ${config.headDim}`);
124
+ console.log(` - Total dimension: ${config.numHeads * config.headDim}\n`);
125
+
126
+ // Generate sample data
127
+ const sequenceLength = 32;
128
+ const queries = generateRandomVectors(sequenceLength, config.headDim);
129
+ const keys = generateRandomVectors(sequenceLength, config.headDim);
130
+ const values = generateRandomVectors(sequenceLength, config.headDim);
131
+
132
+ // Compute attention for a single query
133
+ const singleOutput = await measure('Single query attention', async () => {
134
+ return multiHeadAttn.compute(queries[0], keys, values);
135
+ });
136
+ printVectorStats('Output vector', singleOutput);
137
+
138
+ // Batch computation
139
+ const batchOutput = await measure('Batch attention (32 queries)', async () => {
140
+ return multiHeadAttn.computeBatch(queries, keys, values);
141
+ });
142
+ console.log(` Batch output shape: [${batchOutput.length}, ${batchOutput[0].length}]\n`);
143
+
144
+ // ========================================================================
145
+ // 2. Self-Attention Example
146
+ // ========================================================================
147
+ console.log('2. Self-Attention');
148
+ console.log(' ' + '-'.repeat(40));
149
+ console.log(' Attention where Q, K, V come from the same sequence\n');
150
+
151
+ const selfAttn = registry.get('self_attention');
152
+
153
+ // Create a sequence where each token attends to all others
154
+ const selfSequence = generateRandomVectors(16, config.headDim);
155
+
156
+ // Self-attention: query = key = value = same sequence
157
+ const selfOutput = await measure('Self-attention (16 tokens)', async () => {
158
+ return selfAttn.computeBatch(selfSequence, selfSequence, selfSequence);
159
+ });
160
+
161
+ console.log(` Input sequence: [${selfSequence.length}, ${selfSequence[0].length}]`);
162
+ console.log(` Output sequence: [${selfOutput.length}, ${selfOutput[0].length}]`);
163
+
164
+ // Show attention pattern (which tokens attend to which)
165
+ console.log('\n Attention pattern visualization (simplified):');
166
+ const attentionPattern = selfSequence.map((q, i) => {
167
+ const scores = selfSequence.map(k =>
168
+ q.reduce((sum, val, j) => sum + val * k[j], 0)
169
+ );
170
+ const maxIdx = scores.indexOf(Math.max(...scores));
171
+ return maxIdx;
172
+ });
173
+ console.log(` Token -> Most attended: [${attentionPattern.join(', ')}]\n`);
174
+
175
+ // ========================================================================
176
+ // 3. Cross-Attention Example (Encoder-Decoder)
177
+ // ========================================================================
178
+ console.log('3. Cross-Attention (Encoder-Decoder)');
179
+ console.log(' ' + '-'.repeat(40));
180
+ console.log(' Decoder attends to encoder outputs\n');
181
+
182
+ const crossAttn = registry.get('cross_attention');
183
+
184
+ // Simulate encoder output (e.g., from processing an image or source text)
185
+ const encoderOutput = generateRandomVectors(64, config.headDim);
186
+
187
+ // Simulate decoder queries (e.g., generating target text)
188
+ const decoderQueries = generateRandomVectors(16, config.headDim);
189
+
190
+ const crossOutput = await measure('Cross-attention (16 decoder queries, 64 encoder outputs)', async () => {
191
+ return crossAttn.computeBatch(decoderQueries, encoderOutput, encoderOutput);
192
+ });
193
+
194
+ console.log(` Encoder sequence: [${encoderOutput.length}, ${encoderOutput[0].length}]`);
195
+ console.log(` Decoder queries: [${decoderQueries.length}, ${decoderQueries[0].length}]`);
196
+ console.log(` Cross-attention output: [${crossOutput.length}, ${crossOutput[0].length}]\n`);
197
+
198
+ // ========================================================================
199
+ // 4. Causal (Masked) Attention Example
200
+ // ========================================================================
201
+ console.log('4. Causal (Masked) Attention');
202
+ console.log(' ' + '-'.repeat(40));
203
+ console.log(' Autoregressive attention - each position only sees previous positions\n');
204
+
205
+ const causalAttn = registry.get('causal');
206
+
207
+ // Simulate autoregressive generation
208
+ const autoregSequence = generateRandomVectors(8, config.headDim);
209
+
210
+ const causalOutput = await measure('Causal attention (8 tokens)', async () => {
211
+ return causalAttn.computeBatch(autoregSequence, autoregSequence, autoregSequence);
212
+ });
213
+
214
+ console.log(' Causal mask pattern (1 = attend, 0 = masked):');
215
+ for (let i = 0; i < 8; i++) {
216
+ const mask = Array.from({ length: 8 }, (_, j) => (j <= i ? '1' : '0')).join(' ');
217
+ console.log(` Token ${i}: [${mask}]`);
218
+ }
219
+ console.log();
220
+
221
+ // ========================================================================
222
+ // 5. Flash Attention Simulation
223
+ // ========================================================================
224
+ console.log('5. Flash Attention (Memory-Efficient)');
225
+ console.log(' ' + '-'.repeat(40));
226
+ console.log(' Tiled computation for long sequences with O(N) memory\n');
227
+
228
+ // Flash attention uses tiling to reduce memory usage
229
+ // Here we simulate the performance characteristics
230
+
231
+ const longSequenceLengths = [128, 256, 512, 1024];
232
+
233
+ console.log(' Sequence length | Standard Attention | Flash Attention (simulated)');
234
+ console.log(' ' + '-'.repeat(65));
235
+
236
+ for (const seqLen of longSequenceLengths) {
237
+ // Standard attention: O(N^2) memory
238
+ const standardMemory = seqLen * seqLen * 4; // float32
239
+
240
+ // Flash attention: O(N) memory with tiling
241
+ const blockSize = 64;
242
+ const flashMemory = 2 * blockSize * seqLen * 4;
243
+
244
+ const memoryRatio = (standardMemory / flashMemory).toFixed(1);
245
+
246
+ console.log(
247
+ ` ${seqLen.toString().padStart(6)} tokens | ` +
248
+ `${(standardMemory / 1024).toFixed(0).padStart(10)} KB | ` +
249
+ `${(flashMemory / 1024).toFixed(0).padStart(10)} KB (${memoryRatio}x less)`
250
+ );
251
+ }
252
+ console.log();
253
+
254
+ // ========================================================================
255
+ // 6. Sparse Attention Patterns
256
+ // ========================================================================
257
+ console.log('6. Sparse Attention Patterns');
258
+ console.log(' ' + '-'.repeat(40));
259
+ console.log(' Reduce computation by attending to subset of tokens\n');
260
+
261
+ // Demonstrate different sparse patterns
262
+ const sparsePatterns = {
263
+ local: 'Each token attends to k nearest neighbors',
264
+ strided: 'Attend every n-th token for global context',
265
+ global: 'Special tokens attend to all, others attend locally',
266
+ random: 'Random subset of tokens (BigBird style)',
267
+ };
268
+
269
+ console.log(' Common sparse attention patterns:');
270
+ Object.entries(sparsePatterns).forEach(([name, desc]) => {
271
+ console.log(` - ${name}: ${desc}`);
272
+ });
273
+
274
+ // Compute complexity comparison
275
+ const N = 1024; // sequence length
276
+ const k = 64; // local window
277
+ const s = 16; // stride
278
+
279
+ console.log(`\n Complexity comparison (N=${N}, k=${k}, s=${s}):`);
280
+ console.log(` - Full attention: O(N^2) = ${N * N} ops`);
281
+ console.log(` - Local attention: O(N*k) = ${N * k} ops (${((N * k) / (N * N) * 100).toFixed(1)}%)`);
282
+ console.log(` - Strided attention: O(N*N/s) = ${Math.floor(N * N / s)} ops (${(100 / s).toFixed(1)}%)`);
283
+ console.log(` - Local + Strided: O(N*(k+N/s)) = ${N * (k + N / s)} ops`);
284
+ console.log();
285
+
286
+ // ========================================================================
287
+ // 7. Attention with KV Cache
288
+ // ========================================================================
289
+ console.log('7. Attention with KV Cache (Inference Optimization)');
290
+ console.log(' ' + '-'.repeat(40));
291
+ console.log(' Cache key-value pairs for autoregressive generation\n');
292
+
293
+ // Simulate KV cache for incremental generation
294
+ interface KVCache {
295
+ keys: number[][];
296
+ values: number[][];
297
+ }
298
+
299
+ const kvCache: KVCache = { keys: [], values: [] };
300
+
301
+ // Simulate generating 8 tokens one by one
302
+ console.log(' Simulating autoregressive generation with KV cache:');
303
+
304
+ const tokenDim = config.headDim;
305
+ let totalWithoutCache = 0;
306
+ let totalWithCache = 0;
307
+
308
+ for (let step = 0; step < 8; step++) {
309
+ // New token embedding
310
+ const newToken = generateRandomVectors(1, tokenDim)[0];
311
+
312
+ // Without cache: recompute all K, V
313
+ const withoutCacheOps = (step + 1) * (step + 1) * tokenDim;
314
+ totalWithoutCache += withoutCacheOps;
315
+
316
+ // With cache: only compute for new token
317
+ const withCacheOps = (step + 1) * tokenDim;
318
+ totalWithCache += withCacheOps;
319
+
320
+ // Update cache
321
+ kvCache.keys.push(newToken);
322
+ kvCache.values.push(newToken);
323
+
324
+ console.log(
325
+ ` Step ${step + 1}: Without cache ${withoutCacheOps.toLocaleString()} ops, ` +
326
+ `With cache ${withCacheOps.toLocaleString()} ops ` +
327
+ `(${((1 - withCacheOps / withoutCacheOps) * 100).toFixed(1)}% reduction)`
328
+ );
329
+ }
330
+
331
+ console.log(`\n Total: Without cache ${totalWithoutCache.toLocaleString()} ops, ` +
332
+ `With cache ${totalWithCache.toLocaleString()} ops`);
333
+ console.log(` Overall speedup: ${(totalWithoutCache / totalWithCache).toFixed(1)}x\n`);
334
+
335
+ // ========================================================================
336
+ // 8. SQL Generation for PostgreSQL
337
+ // ========================================================================
338
+ console.log('8. SQL Generation for PostgreSQL Execution');
339
+ console.log(' ' + '-'.repeat(40));
340
+ console.log(' Generate SQL for executing attention in PostgreSQL\n');
341
+
342
+ const input: AttentionInput = {
343
+ query: new Float32Array([0.1, 0.2, 0.3, 0.4]),
344
+ key: new Float32Array([0.5, 0.6, 0.7, 0.8]),
345
+ value: new Float32Array([0.9, 1.0, 1.1, 1.2]),
346
+ };
347
+
348
+ // Multi-head attention SQL
349
+ const multiHeadSQL = multiHeadAttn.toSQL(input);
350
+ console.log(' Multi-Head Attention SQL:');
351
+ console.log(` ${multiHeadSQL}\n`);
352
+
353
+ // Self-attention SQL
354
+ const selfSQL = selfAttn.toSQL(input);
355
+ console.log(' Self-Attention SQL:');
356
+ console.log(` ${selfSQL}\n`);
357
+
358
+ // Causal attention SQL
359
+ const causalSQL = causalAttn.toSQL(input);
360
+ console.log(' Causal Attention SQL:');
361
+ console.log(` ${causalSQL}\n`);
362
+
363
+ // ========================================================================
364
+ // 9. Available Attention Mechanisms
365
+ // ========================================================================
366
+ console.log('9. Available Attention Mechanisms');
367
+ console.log(' ' + '-'.repeat(40));
368
+
369
+ const available = registry.getAllWithMetadata();
370
+ console.log(` Registered: ${available.length} mechanisms\n`);
371
+
372
+ available.forEach(mech => {
373
+ console.log(` ${mech.name} (${mech.type})`);
374
+ console.log(` Category: ${mech.category}`);
375
+ console.log(` ${mech.description}\n`);
376
+ });
377
+
378
+ // ========================================================================
379
+ // Done
380
+ // ========================================================================
381
+ console.log('='.repeat(60));
382
+ console.log('Attention mechanisms example completed!');
383
+ console.log('='.repeat(60));
384
+
385
+ } catch (error) {
386
+ console.error('Error:', error);
387
+ throw error;
388
+ } finally {
389
+ await bridge.disconnect();
390
+ console.log('\nDisconnected from PostgreSQL.');
391
+ }
392
+ }
393
+
394
+ main().catch(console.error);
@@ -0,0 +1,288 @@
1
+ /**
2
+ * RuVector PostgreSQL Bridge - Basic Usage Example
3
+ *
4
+ * This example demonstrates fundamental operations:
5
+ * - Connecting to PostgreSQL with pgvector
6
+ * - Creating collections and inserting vectors
7
+ * - Performing similarity searches
8
+ * - Updating and deleting vectors
9
+ *
10
+ * Prerequisites:
11
+ * - PostgreSQL 14+ with pgvector extension
12
+ * - Docker: docker compose up -d
13
+ *
14
+ * Run with: npx ts-node examples/ruvector/basic-usage.ts
15
+ *
16
+ * @module @sparkleideas/plugins/examples/ruvector/basic-usage
17
+ */
18
+
19
+ import {
20
+ createRuVectorBridge,
21
+ type RuVectorBridge,
22
+ type VectorRecord,
23
+ type VectorSearchOptions,
24
+ } from '../../src/integrations/ruvector/index.js';
25
+
26
+ // ============================================================================
27
+ // Configuration
28
+ // ============================================================================
29
+
30
+ const config = {
31
+ connection: {
32
+ host: process.env.POSTGRES_HOST || 'localhost',
33
+ port: parseInt(process.env.POSTGRES_PORT || '5432', 10),
34
+ database: process.env.POSTGRES_DB || 'vectors',
35
+ user: process.env.POSTGRES_USER || 'postgres',
36
+ password: process.env.POSTGRES_PASSWORD || 'postgres',
37
+ },
38
+ dimensions: 384, // Common embedding dimension (e.g., sentence-transformers/all-MiniLM-L6-v2)
39
+ };
40
+
41
+ // ============================================================================
42
+ // Helper Functions
43
+ // ============================================================================
44
+
45
+ /**
46
+ * Generate a random embedding vector for demonstration.
47
+ * In production, use a proper embedding model.
48
+ */
49
+ function generateRandomEmbedding(dim: number): number[] {
50
+ const embedding = new Array(dim);
51
+ for (let i = 0; i < dim; i++) {
52
+ embedding[i] = Math.random() * 2 - 1; // Range [-1, 1]
53
+ }
54
+ // Normalize to unit length
55
+ const magnitude = Math.sqrt(embedding.reduce((sum, v) => sum + v * v, 0));
56
+ return embedding.map(v => v / magnitude);
57
+ }
58
+
59
+ /**
60
+ * Print search results in a readable format.
61
+ */
62
+ function printResults(title: string, results: VectorRecord[]): void {
63
+ console.log(`\n${title}`);
64
+ console.log('='.repeat(50));
65
+ results.forEach((result, i) => {
66
+ console.log(`${i + 1}. ID: ${result.id}`);
67
+ console.log(` Distance: ${result.distance?.toFixed(4) ?? 'N/A'}`);
68
+ console.log(` Metadata: ${JSON.stringify(result.metadata)}`);
69
+ });
70
+ }
71
+
72
+ // ============================================================================
73
+ // Main Example
74
+ // ============================================================================
75
+
76
+ async function main(): Promise<void> {
77
+ console.log('RuVector PostgreSQL Bridge - Basic Usage Example');
78
+ console.log('================================================\n');
79
+
80
+ // Create the bridge instance
81
+ const bridge: RuVectorBridge = createRuVectorBridge({
82
+ connectionString: `postgresql://${config.connection.user}:${config.connection.password}@${config.connection.host}:${config.connection.port}/${config.connection.database}`,
83
+ poolSize: 5,
84
+ });
85
+
86
+ try {
87
+ // ========================================================================
88
+ // 1. Connect to PostgreSQL
89
+ // ========================================================================
90
+ console.log('1. Connecting to PostgreSQL...');
91
+ await bridge.connect();
92
+ console.log(' Connected successfully!\n');
93
+
94
+ // ========================================================================
95
+ // 2. Create a Collection
96
+ // ========================================================================
97
+ console.log('2. Creating collection "documents"...');
98
+ await bridge.createCollection('documents', {
99
+ dimensions: config.dimensions,
100
+ distanceMetric: 'cosine',
101
+ indexType: 'hnsw',
102
+ indexParams: {
103
+ m: 16, // Number of connections per layer
104
+ efConstruction: 64, // Size of dynamic candidate list during construction
105
+ },
106
+ });
107
+ console.log(' Collection created!\n');
108
+
109
+ // ========================================================================
110
+ // 3. Insert Vectors
111
+ // ========================================================================
112
+ console.log('3. Inserting vectors...');
113
+
114
+ // Sample documents with embeddings
115
+ const documents = [
116
+ { id: 'doc-1', content: 'Introduction to machine learning', category: 'ML' },
117
+ { id: 'doc-2', content: 'Deep learning fundamentals', category: 'DL' },
118
+ { id: 'doc-3', content: 'Natural language processing', category: 'NLP' },
119
+ { id: 'doc-4', content: 'Computer vision basics', category: 'CV' },
120
+ { id: 'doc-5', content: 'Reinforcement learning guide', category: 'RL' },
121
+ ];
122
+
123
+ // Insert each document with its embedding
124
+ for (const doc of documents) {
125
+ const embedding = generateRandomEmbedding(config.dimensions);
126
+ await bridge.insert('documents', {
127
+ id: doc.id,
128
+ embedding,
129
+ metadata: {
130
+ content: doc.content,
131
+ category: doc.category,
132
+ createdAt: new Date().toISOString(),
133
+ },
134
+ });
135
+ console.log(` Inserted: ${doc.id}`);
136
+ }
137
+ console.log(' All vectors inserted!\n');
138
+
139
+ // ========================================================================
140
+ // 4. Basic Similarity Search
141
+ // ========================================================================
142
+ console.log('4. Performing similarity search...');
143
+
144
+ // Generate a query vector (in production, embed your query text)
145
+ const queryVector = generateRandomEmbedding(config.dimensions);
146
+
147
+ const searchOptions: VectorSearchOptions = {
148
+ k: 3, // Return top 3 results
149
+ includeMetadata: true,
150
+ includeDistance: true,
151
+ };
152
+
153
+ const searchResults = await bridge.search('documents', queryVector, searchOptions);
154
+ printResults('Top 3 Similar Documents', searchResults);
155
+
156
+ // ========================================================================
157
+ // 5. Filtered Search
158
+ // ========================================================================
159
+ console.log('\n5. Performing filtered search (category = "ML")...');
160
+
161
+ const filteredResults = await bridge.search('documents', queryVector, {
162
+ ...searchOptions,
163
+ filter: {
164
+ category: 'ML',
165
+ },
166
+ });
167
+ printResults('Filtered Results (ML category)', filteredResults);
168
+
169
+ // ========================================================================
170
+ // 6. Range Search (by distance threshold)
171
+ // ========================================================================
172
+ console.log('\n6. Performing range search (distance < 0.8)...');
173
+
174
+ const rangeResults = await bridge.search('documents', queryVector, {
175
+ k: 10,
176
+ includeMetadata: true,
177
+ includeDistance: true,
178
+ distanceThreshold: 0.8, // Only return results within this distance
179
+ });
180
+ printResults('Range Search Results', rangeResults);
181
+
182
+ // ========================================================================
183
+ // 7. Update a Vector
184
+ // ========================================================================
185
+ console.log('\n7. Updating vector "doc-1"...');
186
+
187
+ const newEmbedding = generateRandomEmbedding(config.dimensions);
188
+ await bridge.update('documents', 'doc-1', {
189
+ embedding: newEmbedding,
190
+ metadata: {
191
+ content: 'Introduction to machine learning (Updated)',
192
+ category: 'ML',
193
+ updatedAt: new Date().toISOString(),
194
+ },
195
+ });
196
+ console.log(' Vector updated!');
197
+
198
+ // Verify the update
199
+ const updatedDoc = await bridge.get('documents', 'doc-1');
200
+ if (updatedDoc) {
201
+ console.log(` Verified: ${JSON.stringify(updatedDoc.metadata)}`);
202
+ }
203
+
204
+ // ========================================================================
205
+ // 8. Batch Insert
206
+ // ========================================================================
207
+ console.log('\n8. Batch inserting 100 vectors...');
208
+
209
+ const batchRecords: VectorRecord[] = [];
210
+ for (let i = 0; i < 100; i++) {
211
+ batchRecords.push({
212
+ id: `batch-${i}`,
213
+ embedding: generateRandomEmbedding(config.dimensions),
214
+ metadata: {
215
+ batchIndex: i,
216
+ createdAt: new Date().toISOString(),
217
+ },
218
+ });
219
+ }
220
+
221
+ const startTime = performance.now();
222
+ await bridge.insertBatch('documents', batchRecords);
223
+ const duration = performance.now() - startTime;
224
+
225
+ console.log(` Inserted 100 vectors in ${duration.toFixed(2)}ms`);
226
+ console.log(` Throughput: ${(100 / (duration / 1000)).toFixed(0)} vectors/second`);
227
+
228
+ // ========================================================================
229
+ // 9. Get Collection Statistics
230
+ // ========================================================================
231
+ console.log('\n9. Collection statistics...');
232
+
233
+ const stats = await bridge.getCollectionStats('documents');
234
+ console.log(` Total vectors: ${stats.vectorCount}`);
235
+ console.log(` Dimensions: ${stats.dimensions}`);
236
+ console.log(` Index type: ${stats.indexType}`);
237
+ console.log(` Index size: ${(stats.indexSizeBytes / 1024).toFixed(2)} KB`);
238
+
239
+ // ========================================================================
240
+ // 10. Delete Vectors
241
+ // ========================================================================
242
+ console.log('\n10. Deleting vectors...');
243
+
244
+ // Delete a single vector
245
+ await bridge.delete('documents', 'doc-5');
246
+ console.log(' Deleted: doc-5');
247
+
248
+ // Delete multiple vectors
249
+ const idsToDelete = ['batch-0', 'batch-1', 'batch-2'];
250
+ for (const id of idsToDelete) {
251
+ await bridge.delete('documents', id);
252
+ }
253
+ console.log(` Deleted: ${idsToDelete.join(', ')}`);
254
+
255
+ // Verify deletion
256
+ const deletedDoc = await bridge.get('documents', 'doc-5');
257
+ console.log(` Verification - doc-5 exists: ${deletedDoc !== null}`);
258
+
259
+ // ========================================================================
260
+ // 11. Cleanup (Optional)
261
+ // ========================================================================
262
+ console.log('\n11. Cleanup...');
263
+
264
+ // Uncomment to drop the collection when done
265
+ // await bridge.dropCollection('documents');
266
+ // console.log(' Collection dropped!');
267
+
268
+ console.log(' Skipping collection drop (uncomment to enable)');
269
+
270
+ // ========================================================================
271
+ // Done
272
+ // ========================================================================
273
+ console.log('\n' + '='.repeat(50));
274
+ console.log('Basic usage example completed successfully!');
275
+ console.log('='.repeat(50));
276
+
277
+ } catch (error) {
278
+ console.error('Error:', error);
279
+ throw error;
280
+ } finally {
281
+ // Always disconnect
282
+ await bridge.disconnect();
283
+ console.log('\nDisconnected from PostgreSQL.');
284
+ }
285
+ }
286
+
287
+ // Run the example
288
+ main().catch(console.error);