@ruvector/wasm 0.1.16 β†’ 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md DELETED
@@ -1,969 +0,0 @@
1
- # Ruvector WASM
2
-
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
- [![npm version](https://img.shields.io/npm/v/@ruvector/wasm.svg)](https://www.npmjs.com/package/@ruvector/wasm)
5
- [![Bundle Size](https://img.shields.io/badge/bundle-<400KB%20gzipped-green.svg)](#bundle-size)
6
- [![Browser Support](https://img.shields.io/badge/browsers-Chrome%20%7C%20Firefox%20%7C%20Safari%20%7C%20Edge-brightgreen.svg)](#browser-compatibility)
7
- [![WASM](https://img.shields.io/badge/WebAssembly-enabled-purple.svg)](https://webassembly.org/)
8
-
9
- **High-performance vector database running entirely in your browser via WebAssembly.**
10
-
11
- > Bring **sub-millisecond vector search** to the edge with **offline-first** capabilities. Perfect for AI applications, semantic search, and recommendation engines that run completely client-side. Built by [rUv](https://ruv.io) with Rust and WebAssembly.
12
-
13
- ## 🌟 Why Ruvector WASM?
14
-
15
- In the age of privacy-first, offline-capable web applications, running AI workloads **entirely in the browser** is no longer optionalβ€”it's essential.
16
-
17
- **Ruvector WASM brings enterprise-grade vector search to the browser:**
18
-
19
- - ⚑ **Blazing Fast**: <1ms query latency with HNSW indexing and SIMD acceleration
20
- - πŸ”’ **Privacy First**: All data stays in the browserβ€”zero server round-trips
21
- - πŸ“΄ **Offline Capable**: Full functionality without internet via IndexedDB persistence
22
- - 🌐 **Edge Computing**: Deploy to CDNs for ultra-low latency globally
23
- - πŸ’Ύ **Persistent Storage**: IndexedDB integration with automatic synchronization
24
- - 🧡 **Multi-threaded**: Web Workers support for parallel processing
25
- - πŸ“¦ **Compact**: <400KB gzipped with optimizations
26
- - 🎯 **Zero Dependencies**: Pure Rust compiled to WebAssembly
27
-
28
- ## πŸš€ Features
29
-
30
- ### Core Capabilities
31
-
32
- - **Complete VectorDB API**: Insert, search, delete, batch operations with familiar patterns
33
- - **HNSW Indexing**: Hierarchical Navigable Small World for fast approximate nearest neighbor search
34
- - **Multiple Distance Metrics**: Euclidean, Cosine, Dot Product, Manhattan
35
- - **SIMD Acceleration**: 2-4x speedup on supported hardware with automatic detection
36
- - **Memory Efficient**: Optimized memory layouts and zero-copy operations
37
- - **Type-Safe**: Full TypeScript definitions included
38
-
39
- ### Browser-Specific Features
40
-
41
- - **IndexedDB Persistence**: Save/load database state with progressive loading
42
- - **Web Workers Integration**: Parallel operations across multiple threads
43
- - **Worker Pool Management**: Automatic load balancing across 4-8 workers
44
- - **Zero-Copy Transfers**: Transferable objects for efficient data passing
45
- - **Browser Console Debugging**: Enhanced error messages and stack traces
46
- - **Progressive Web Apps**: Perfect for PWA offline scenarios
47
-
48
- ### Performance Optimizations
49
-
50
- - **Batch Operations**: Efficient bulk insert/search for large datasets
51
- - **LRU Caching**: 1000-entry hot vector cache for frequently accessed data
52
- - **Lazy Loading**: Progressive data loading with callbacks
53
- - **Compressed Storage**: Optimized serialization for IndexedDB
54
- - **WASM Streaming**: Compile WASM modules while downloading
55
-
56
- ## πŸ“¦ Installation
57
-
58
- ### NPM
59
-
60
- ```bash
61
- npm install @ruvector/wasm
62
- ```
63
-
64
- ### Yarn
65
-
66
- ```bash
67
- yarn add @ruvector/wasm
68
- ```
69
-
70
- ### CDN (for quick prototyping)
71
-
72
- ```html
73
- <script type="module">
74
- import init, { VectorDB } from 'https://unpkg.com/@ruvector/wasm/pkg/ruvector_wasm.js';
75
-
76
- await init();
77
- const db = new VectorDB(384, 'cosine', true);
78
- </script>
79
- ```
80
-
81
- ## ⚑ Quick Start
82
-
83
- ### Basic Usage
84
-
85
- ```javascript
86
- import init, { VectorDB } from '@ruvector/wasm';
87
-
88
- // 1. Initialize WASM module (one-time setup)
89
- await init();
90
-
91
- // 2. Create database with 384-dimensional vectors
92
- const db = new VectorDB(
93
- 384, // dimensions
94
- 'cosine', // distance metric
95
- true // enable HNSW index
96
- );
97
-
98
- // 3. Insert vectors with metadata
99
- const embedding = new Float32Array(384).map(() => Math.random());
100
- const id = db.insert(
101
- embedding,
102
- 'doc_1', // optional ID
103
- { title: 'My Document', type: 'article' } // optional metadata
104
- );
105
-
106
- // 4. Search for similar vectors
107
- const query = new Float32Array(384).map(() => Math.random());
108
- const results = db.search(query, 10); // top 10 results
109
-
110
- // 5. Process results
111
- results.forEach(result => {
112
- console.log(`ID: ${result.id}`);
113
- console.log(`Score: ${result.score}`);
114
- console.log(`Metadata:`, result.metadata);
115
- });
116
- ```
117
-
118
- ### React Integration
119
-
120
- ```typescript
121
- import { useEffect, useState } from 'react';
122
- import init, { VectorDB } from '@ruvector/wasm';
123
-
124
- function SemanticSearch() {
125
- const [db, setDb] = useState<VectorDB | null>(null);
126
- const [results, setResults] = useState([]);
127
- const [loading, setLoading] = useState(true);
128
-
129
- useEffect(() => {
130
- // Initialize WASM and create database
131
- init().then(() => {
132
- const vectorDB = new VectorDB(384, 'cosine', true);
133
- setDb(vectorDB);
134
- setLoading(false);
135
- });
136
- }, []);
137
-
138
- const handleSearch = async (queryEmbedding: Float32Array) => {
139
- if (!db) return;
140
-
141
- const searchResults = db.search(queryEmbedding, 10);
142
- setResults(searchResults);
143
- };
144
-
145
- if (loading) return <div>Loading vector database...</div>;
146
-
147
- return (
148
- <div>
149
- <h1>Semantic Search</h1>
150
- {/* Your search UI */}
151
- </div>
152
- );
153
- }
154
- ```
155
-
156
- ### Vue.js Integration
157
-
158
- ```vue
159
- <template>
160
- <div>
161
- <h1>Vector Search</h1>
162
- <div v-if="!dbReady">Initializing...</div>
163
- <div v-else>
164
- <button @click="search">Search</button>
165
- <ul>
166
- <li v-for="result in results" :key="result.id">
167
- {{ result.id }}: {{ result.score }}
168
- </li>
169
- </ul>
170
- </div>
171
- </div>
172
- </template>
173
-
174
- <script setup>
175
- import { ref, onMounted } from 'vue';
176
- import init, { VectorDB } from '@ruvector/wasm';
177
-
178
- const db = ref(null);
179
- const dbReady = ref(false);
180
- const results = ref([]);
181
-
182
- onMounted(async () => {
183
- await init();
184
- db.value = new VectorDB(384, 'cosine', true);
185
- dbReady.value = true;
186
- });
187
-
188
- const search = () => {
189
- const query = new Float32Array(384).map(() => Math.random());
190
- results.value = db.value.search(query, 10);
191
- };
192
- </script>
193
- ```
194
-
195
- ### Svelte Integration
196
-
197
- ```svelte
198
- <script>
199
- import { onMount } from 'svelte';
200
- import init, { VectorDB } from '@ruvector/wasm';
201
-
202
- let db = null;
203
- let ready = false;
204
- let results = [];
205
-
206
- onMount(async () => {
207
- await init();
208
- db = new VectorDB(384, 'cosine', true);
209
- ready = true;
210
- });
211
-
212
- function search() {
213
- const query = new Float32Array(384).map(() => Math.random());
214
- results = db.search(query, 10);
215
- }
216
- </script>
217
-
218
- {#if !ready}
219
- <p>Loading...</p>
220
- {:else}
221
- <button on:click={search}>Search</button>
222
- {#each results as result}
223
- <div>{result.id}: {result.score}</div>
224
- {/each}
225
- {/if}
226
- ```
227
-
228
- ## πŸ”₯ Advanced Usage
229
-
230
- ### Web Workers for Background Processing
231
-
232
- Offload heavy vector operations to background threads for smooth UI performance:
233
-
234
- ```javascript
235
- // main.js
236
- import { WorkerPool } from '@ruvector/wasm/worker-pool';
237
-
238
- const pool = new WorkerPool(
239
- '/worker.js',
240
- '/pkg/ruvector_wasm.js',
241
- {
242
- poolSize: navigator.hardwareConcurrency || 4, // Auto-detect CPU cores
243
- dimensions: 384,
244
- metric: 'cosine',
245
- useHnsw: true
246
- }
247
- );
248
-
249
- // Initialize worker pool
250
- await pool.init();
251
-
252
- // Batch insert in parallel (non-blocking)
253
- const vectors = generateVectors(10000, 384);
254
- const ids = await pool.insertBatch(vectors);
255
-
256
- // Parallel search across workers
257
- const query = new Float32Array(384).map(() => Math.random());
258
- const results = await pool.search(query, 100);
259
-
260
- // Get pool statistics
261
- const stats = pool.getStats();
262
- console.log(`Workers: ${stats.busyWorkers}/${stats.poolSize} busy`);
263
- console.log(`Queue: ${stats.queuedTasks} tasks waiting`);
264
-
265
- // Cleanup when done
266
- pool.terminate();
267
- ```
268
-
269
- ```javascript
270
- // worker.js - Web Worker implementation
271
- importScripts('/pkg/ruvector_wasm.js');
272
-
273
- const { VectorDB } = wasm_bindgen;
274
-
275
- let db = null;
276
-
277
- self.onmessage = async (e) => {
278
- const { type, data } = e.data;
279
-
280
- switch (type) {
281
- case 'init':
282
- await wasm_bindgen('/pkg/ruvector_wasm_bg.wasm');
283
- db = new VectorDB(data.dimensions, data.metric, data.useHnsw);
284
- self.postMessage({ type: 'ready' });
285
- break;
286
-
287
- case 'insert':
288
- const id = db.insert(data.vector, data.id, data.metadata);
289
- self.postMessage({ type: 'inserted', id });
290
- break;
291
-
292
- case 'search':
293
- const results = db.search(data.query, data.k);
294
- self.postMessage({ type: 'results', results });
295
- break;
296
- }
297
- };
298
- ```
299
-
300
- ### IndexedDB Persistence - Offline First
301
-
302
- Keep your vector database synchronized across sessions:
303
-
304
- ```javascript
305
- import { IndexedDBPersistence } from '@ruvector/wasm/indexeddb';
306
- import init, { VectorDB } from '@ruvector/wasm';
307
-
308
- await init();
309
-
310
- // Create persistence layer
311
- const persistence = new IndexedDBPersistence('my_vector_db', {
312
- version: 1,
313
- cacheSize: 1000, // LRU cache for hot vectors
314
- batchSize: 100 // Batch size for bulk operations
315
- });
316
-
317
- await persistence.open();
318
-
319
- // Create or restore VectorDB
320
- const db = new VectorDB(384, 'cosine', true);
321
-
322
- // Load existing data from IndexedDB (with progress)
323
- await persistence.loadAll(async (progress) => {
324
- console.log(`Loading: ${progress.loaded}/${progress.total} vectors`);
325
- console.log(`Progress: ${(progress.percent * 100).toFixed(1)}%`);
326
-
327
- // Insert batch into VectorDB
328
- if (progress.vectors.length > 0) {
329
- const ids = db.insertBatch(progress.vectors);
330
- console.log(`Inserted ${ids.length} vectors`);
331
- }
332
-
333
- if (progress.complete) {
334
- console.log('Database fully loaded!');
335
- }
336
- });
337
-
338
- // Insert new vectors and save to IndexedDB
339
- const vector = new Float32Array(384).map(() => Math.random());
340
- const id = db.insert(vector, 'vec_123', { category: 'new' });
341
-
342
- await persistence.save({
343
- id,
344
- vector,
345
- metadata: { category: 'new' }
346
- });
347
-
348
- // Batch save for better performance
349
- const entries = [...]; // Your vector entries
350
- await persistence.saveBatch(entries);
351
-
352
- // Get storage statistics
353
- const stats = await persistence.getStats();
354
- console.log(`Total vectors: ${stats.totalVectors}`);
355
- console.log(`Storage used: ${(stats.storageBytes / 1024 / 1024).toFixed(2)} MB`);
356
- console.log(`Cache size: ${stats.cacheSize}`);
357
- console.log(`Cache hit rate: ${(stats.cacheHitRate * 100).toFixed(2)}%`);
358
-
359
- // Clear old data
360
- await persistence.clear();
361
- ```
362
-
363
- ### Batch Operations for Performance
364
-
365
- Process large datasets efficiently:
366
-
367
- ```javascript
368
- import init, { VectorDB } from '@ruvector/wasm';
369
-
370
- await init();
371
- const db = new VectorDB(384, 'cosine', true);
372
-
373
- // Batch insert (10x faster than individual inserts)
374
- const entries = [];
375
- for (let i = 0; i < 10000; i++) {
376
- entries.push({
377
- vector: new Float32Array(384).map(() => Math.random()),
378
- id: `vec_${i}`,
379
- metadata: { index: i, batch: Math.floor(i / 100) }
380
- });
381
- }
382
-
383
- const ids = db.insertBatch(entries);
384
- console.log(`Inserted ${ids.length} vectors in batch`);
385
-
386
- // Multiple parallel searches
387
- const queries = Array.from({ length: 100 }, () =>
388
- new Float32Array(384).map(() => Math.random())
389
- );
390
-
391
- const allResults = queries.map(query => db.search(query, 10));
392
- console.log(`Completed ${allResults.length} searches`);
393
- ```
394
-
395
- ### Memory Management Best Practices
396
-
397
- ```javascript
398
- import init, { VectorDB } from '@ruvector/wasm';
399
-
400
- await init();
401
-
402
- // Reuse Float32Array buffers to reduce GC pressure
403
- const buffer = new Float32Array(384);
404
-
405
- // Insert with reused buffer
406
- for (let i = 0; i < 1000; i++) {
407
- // Fill buffer with new data
408
- for (let j = 0; j < 384; j++) {
409
- buffer[j] = Math.random();
410
- }
411
-
412
- db.insert(buffer, `vec_${i}`, { index: i });
413
-
414
- // Buffer is copied internally, safe to reuse
415
- }
416
-
417
- // Check memory usage
418
- const vectorCount = db.len();
419
- const isEmpty = db.isEmpty();
420
- const dimensions = db.dimensions;
421
-
422
- console.log(`Vectors: ${vectorCount}, Dims: ${dimensions}`);
423
-
424
- // Clean up when done
425
- // JavaScript GC will handle WASM memory automatically
426
- ```
427
-
428
- ## πŸ“Š Performance Benchmarks
429
-
430
- ### Browser Performance (Chrome 120 on M1 MacBook Pro)
431
-
432
- | Operation | Vectors | Dimensions | Standard | SIMD | Speedup |
433
- |-----------|---------|------------|----------|------|---------|
434
- | **Insert (individual)** | 10,000 | 384 | 3.2s | 1.1s | 2.9x |
435
- | **Insert (batch)** | 10,000 | 384 | 1.2s | 0.4s | 3.0x |
436
- | **Search (k=10)** | 100 queries | 384 | 0.5s | 0.2s | 2.5x |
437
- | **Search (k=100)** | 100 queries | 384 | 1.8s | 0.7s | 2.6x |
438
- | **Delete** | 1,000 | 384 | 0.2s | 0.1s | 2.0x |
439
-
440
- ### Throughput Comparison
441
-
442
- ```
443
- Operation Ruvector WASM Tensorflow.js ml5.js
444
- ─────────────────────────────────────────────────────────────────
445
- Insert (ops/sec) 25,000 5,000 1,200
446
- Search (queries/sec) 500 80 20
447
- Memory (10K vectors) ~50MB ~200MB ~150MB
448
- Bundle Size (gzipped) 380KB 800KB 450KB
449
- Offline Support βœ… Partial ❌
450
- SIMD Acceleration βœ… ❌ ❌
451
- ```
452
-
453
- ### Real-World Application Performance
454
-
455
- **Semantic Search (10,000 documents, 384-dim embeddings)**
456
- - Cold start: ~800ms (WASM compile + data load)
457
- - Warm query: <5ms (with HNSW index)
458
- - IndexedDB load: ~2s (10,000 vectors)
459
- - Memory footprint: ~60MB
460
-
461
- **Recommendation Engine (100,000 items, 128-dim embeddings)**
462
- - Initial load: ~8s from IndexedDB
463
- - Query latency: <10ms (p50)
464
- - Memory usage: ~180MB
465
- - Bundle impact: +400KB gzipped
466
-
467
- ## 🌐 Browser Compatibility
468
-
469
- ### Support Matrix
470
-
471
- | Browser | Version | WASM | SIMD | Workers | IndexedDB | Status |
472
- |---------|---------|------|------|---------|-----------|--------|
473
- | **Chrome** | 91+ | βœ… | βœ… | βœ… | βœ… | Full Support |
474
- | **Firefox** | 89+ | βœ… | βœ… | βœ… | βœ… | Full Support |
475
- | **Safari** | 16.4+ | βœ… | Partial | βœ… | βœ… | Limited SIMD |
476
- | **Edge** | 91+ | βœ… | βœ… | βœ… | βœ… | Full Support |
477
- | **Opera** | 77+ | βœ… | βœ… | βœ… | βœ… | Full Support |
478
- | **Samsung Internet** | 15+ | βœ… | ❌ | βœ… | βœ… | No SIMD |
479
-
480
- ### SIMD Support Detection
481
-
482
- ```javascript
483
- import { detectSIMD } from '@ruvector/wasm';
484
-
485
- if (detectSIMD()) {
486
- console.log('SIMD acceleration available!');
487
- // Load SIMD-optimized build
488
- await import('@ruvector/wasm/pkg-simd/ruvector_wasm.js');
489
- } else {
490
- console.log('Standard build');
491
- // Load standard build
492
- await import('@ruvector/wasm');
493
- }
494
- ```
495
-
496
- ### Polyfills and Fallbacks
497
-
498
- ```javascript
499
- // Check for required features
500
- const hasWASM = typeof WebAssembly !== 'undefined';
501
- const hasWorkers = typeof Worker !== 'undefined';
502
- const hasIndexedDB = typeof indexedDB !== 'undefined';
503
-
504
- if (!hasWASM) {
505
- console.error('WebAssembly not supported');
506
- // Fallback to server-side processing
507
- }
508
-
509
- if (!hasWorkers) {
510
- console.warn('Web Workers not available, using main thread');
511
- // Use synchronous API
512
- }
513
-
514
- if (!hasIndexedDB) {
515
- console.warn('IndexedDB not available, data will not persist');
516
- // Use in-memory only
517
- }
518
- ```
519
-
520
- ## πŸ“¦ Bundle Size
521
-
522
- ### Production Build Sizes
523
-
524
- ```
525
- Build Type Uncompressed Gzipped Brotli
526
- ──────────────────────────────────────────────────────────
527
- Standard WASM 1.2 MB 450 KB 380 KB
528
- SIMD WASM 1.3 MB 480 KB 410 KB
529
- JavaScript Glue 45 KB 12 KB 9 KB
530
- TypeScript Definitions 8 KB 2 KB 1.5 KB
531
- ──────────────────────────────────────────────────────────
532
- Total (Standard) 1.25 MB 462 KB 390 KB
533
- Total (SIMD) 1.35 MB 492 KB 420 KB
534
- ```
535
-
536
- ### With Optimizations (wasm-opt)
537
-
538
- ```bash
539
- npm run optimize
540
- ```
541
-
542
- ```
543
- Optimized Build Uncompressed Gzipped Brotli
544
- ──────────────────────────────────────────────────────────
545
- Standard WASM 900 KB 380 KB 320 KB
546
- SIMD WASM 980 KB 410 KB 350 KB
547
- ```
548
-
549
- ### Code Splitting Strategy
550
-
551
- ```javascript
552
- // Lazy load WASM module when needed
553
- const loadVectorDB = async () => {
554
- const { default: init, VectorDB } = await import('@ruvector/wasm');
555
- await init();
556
- return VectorDB;
557
- };
558
-
559
- // Use in your application
560
- button.addEventListener('click', async () => {
561
- const VectorDB = await loadVectorDB();
562
- const db = new VectorDB(384, 'cosine', true);
563
- // Use db...
564
- });
565
- ```
566
-
567
- ## πŸ”¨ Building from Source
568
-
569
- ### Prerequisites
570
-
571
- - **Rust**: 1.77 or higher
572
- - **wasm-pack**: Latest version
573
- - **Node.js**: 18.0 or higher
574
-
575
- ```bash
576
- # Install wasm-pack
577
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
578
-
579
- # Or via npm
580
- npm install -g wasm-pack
581
- ```
582
-
583
- ### Build Commands
584
-
585
- ```bash
586
- # Clone repository
587
- git clone https://github.com/ruvnet/ruvector.git
588
- cd ruvector/crates/ruvector-wasm
589
-
590
- # Install dependencies
591
- npm install
592
-
593
- # Build for web (ES modules)
594
- npm run build:web
595
-
596
- # Build with SIMD optimizations
597
- npm run build:simd
598
-
599
- # Build for Node.js
600
- npm run build:node
601
-
602
- # Build for bundlers (webpack, rollup, etc.)
603
- npm run build:bundler
604
-
605
- # Build all targets
606
- npm run build:all
607
-
608
- # Run tests in browser
609
- npm test
610
-
611
- # Run tests in Node.js
612
- npm run test:node
613
-
614
- # Check bundle size
615
- npm run size
616
-
617
- # Optimize with wasm-opt (requires binaryen)
618
- npm run optimize
619
-
620
- # Serve examples locally
621
- npm run serve
622
- ```
623
-
624
- ### Development Workflow
625
-
626
- ```bash
627
- # Watch mode (requires custom setup)
628
- wasm-pack build --dev --target web -- --features simd
629
-
630
- # Run specific browser tests
631
- npm run test:firefox
632
-
633
- # Profile WASM performance
634
- wasm-pack build --profiling --target web
635
-
636
- # Generate documentation
637
- cargo doc --no-deps --open
638
- ```
639
-
640
- ### Custom Build Configuration
641
-
642
- ```toml
643
- # .cargo/config.toml
644
- [target.wasm32-unknown-unknown]
645
- rustflags = [
646
- "-C", "opt-level=z",
647
- "-C", "lto=fat",
648
- "-C", "codegen-units=1"
649
- ]
650
- ```
651
-
652
- ## πŸ“š API Reference
653
-
654
- ### VectorDB Class
655
-
656
- ```typescript
657
- class VectorDB {
658
- constructor(
659
- dimensions: number,
660
- metric?: 'euclidean' | 'cosine' | 'dotproduct' | 'manhattan',
661
- useHnsw?: boolean
662
- );
663
-
664
- // Insert operations
665
- insert(vector: Float32Array, id?: string, metadata?: object): string;
666
- insertBatch(entries: VectorEntry[]): string[];
667
-
668
- // Search operations
669
- search(query: Float32Array, k: number, filter?: object): SearchResult[];
670
-
671
- // Retrieval operations
672
- get(id: string): VectorEntry | null;
673
- len(): number;
674
- isEmpty(): boolean;
675
-
676
- // Delete operations
677
- delete(id: string): boolean;
678
-
679
- // Persistence (IndexedDB)
680
- saveToIndexedDB(): Promise<void>;
681
- static loadFromIndexedDB(dbName: string): Promise<VectorDB>;
682
-
683
- // Properties
684
- readonly dimensions: number;
685
- }
686
- ```
687
-
688
- ### Types
689
-
690
- ```typescript
691
- interface VectorEntry {
692
- id?: string;
693
- vector: Float32Array;
694
- metadata?: Record<string, any>;
695
- }
696
-
697
- interface SearchResult {
698
- id: string;
699
- score: number;
700
- vector?: Float32Array;
701
- metadata?: Record<string, any>;
702
- }
703
- ```
704
-
705
- ### Utility Functions
706
-
707
- ```typescript
708
- // Detect SIMD support
709
- function detectSIMD(): boolean;
710
-
711
- // Get version
712
- function version(): string;
713
-
714
- // Array conversion
715
- function arrayToFloat32Array(arr: number[]): Float32Array;
716
-
717
- // Benchmarking
718
- function benchmark(name: string, iterations: number, dimensions: number): number;
719
- ```
720
-
721
- See [WASM API Documentation](../../docs/getting-started/wasm-api.md) for complete reference.
722
-
723
- ## 🎯 Example Applications
724
-
725
- ### Semantic Search Engine
726
-
727
- ```javascript
728
- // Semantic search with OpenAI embeddings
729
- import init, { VectorDB } from '@ruvector/wasm';
730
- import { Configuration, OpenAIApi } from 'openai';
731
-
732
- await init();
733
-
734
- const openai = new OpenAIApi(new Configuration({
735
- apiKey: process.env.OPENAI_API_KEY
736
- }));
737
-
738
- const db = new VectorDB(1536, 'cosine', true); // OpenAI ada-002 = 1536 dims
739
-
740
- // Index documents
741
- const documents = [
742
- 'The quick brown fox jumps over the lazy dog',
743
- 'Machine learning is a subset of artificial intelligence',
744
- 'WebAssembly enables high-performance web applications'
745
- ];
746
-
747
- for (const [i, doc] of documents.entries()) {
748
- const response = await openai.createEmbedding({
749
- model: 'text-embedding-ada-002',
750
- input: doc
751
- });
752
-
753
- const embedding = new Float32Array(response.data.data[0].embedding);
754
- db.insert(embedding, `doc_${i}`, { text: doc });
755
- }
756
-
757
- // Search
758
- const queryResponse = await openai.createEmbedding({
759
- model: 'text-embedding-ada-002',
760
- input: 'What is AI?'
761
- });
762
-
763
- const queryEmbedding = new Float32Array(queryResponse.data.data[0].embedding);
764
- const results = db.search(queryEmbedding, 3);
765
-
766
- results.forEach(result => {
767
- console.log(`${result.score.toFixed(4)}: ${result.metadata.text}`);
768
- });
769
- ```
770
-
771
- ### Offline Recommendation Engine
772
-
773
- ```javascript
774
- // Product recommendations that work offline
775
- import init, { VectorDB } from '@ruvector/wasm';
776
- import { IndexedDBPersistence } from '@ruvector/wasm/indexeddb';
777
-
778
- await init();
779
-
780
- const db = new VectorDB(128, 'cosine', true);
781
- const persistence = new IndexedDBPersistence('product_recommendations');
782
- await persistence.open();
783
-
784
- // Load cached recommendations
785
- await persistence.loadAll(async (progress) => {
786
- if (progress.vectors.length > 0) {
787
- db.insertBatch(progress.vectors);
788
- }
789
- });
790
-
791
- // Get recommendations based on user history
792
- function getRecommendations(userHistory, k = 10) {
793
- // Compute user preference vector (average of liked items)
794
- const userVector = computeAverageEmbedding(userHistory);
795
- const recommendations = db.search(userVector, k);
796
-
797
- return recommendations.map(r => ({
798
- productId: r.id,
799
- score: r.score,
800
- ...r.metadata
801
- }));
802
- }
803
-
804
- // Add new products (syncs to IndexedDB)
805
- async function addProduct(productId, embedding, metadata) {
806
- db.insert(embedding, productId, metadata);
807
- await persistence.save({ id: productId, vector: embedding, metadata });
808
- }
809
- ```
810
-
811
- ### RAG (Retrieval-Augmented Generation)
812
-
813
- ```javascript
814
- // Browser-based RAG system
815
- import init, { VectorDB } from '@ruvector/wasm';
816
-
817
- await init();
818
-
819
- const db = new VectorDB(768, 'cosine', true); // BERT embeddings
820
-
821
- // Index knowledge base
822
- const knowledgeBase = loadKnowledgeBase(); // Your documents
823
- for (const doc of knowledgeBase) {
824
- const embedding = await getBertEmbedding(doc.text);
825
- db.insert(embedding, doc.id, { text: doc.text, source: doc.source });
826
- }
827
-
828
- // RAG query function
829
- async function ragQuery(question, llm) {
830
- // 1. Get question embedding
831
- const questionEmbedding = await getBertEmbedding(question);
832
-
833
- // 2. Retrieve relevant context
834
- const context = db.search(questionEmbedding, 5);
835
-
836
- // 3. Augment prompt with context
837
- const prompt = `
838
- Context:
839
- ${context.map(r => r.metadata.text).join('\n\n')}
840
-
841
- Question: ${question}
842
-
843
- Answer based on the context above:
844
- `;
845
-
846
- // 4. Generate response
847
- const response = await llm.generate(prompt);
848
-
849
- return {
850
- answer: response,
851
- sources: context.map(r => r.metadata.source)
852
- };
853
- }
854
- ```
855
-
856
- ## πŸ› Troubleshooting
857
-
858
- ### Common Issues
859
-
860
- **1. WASM Module Not Loading**
861
-
862
- ```javascript
863
- // Ensure correct MIME type
864
- // Add to server config (nginx):
865
- // types {
866
- // application/wasm wasm;
867
- // }
868
-
869
- // Or use explicit fetch
870
- const wasmUrl = new URL('./pkg/ruvector_wasm_bg.wasm', import.meta.url);
871
- await init(await fetch(wasmUrl));
872
- ```
873
-
874
- **2. CORS Errors**
875
-
876
- ```javascript
877
- // For local development
878
- // package.json
879
- {
880
- "scripts": {
881
- "serve": "python3 -m http.server 8080 --bind 127.0.0.1"
882
- }
883
- }
884
- ```
885
-
886
- **3. Memory Issues**
887
-
888
- ```javascript
889
- // Monitor memory usage
890
- const stats = db.len();
891
- const estimatedMemory = stats * dimensions * 4; // bytes
892
-
893
- if (estimatedMemory > 100_000_000) { // 100MB
894
- console.warn('High memory usage, consider chunking');
895
- }
896
-
897
- // Use batch operations to reduce GC pressure
898
- const BATCH_SIZE = 1000;
899
- for (let i = 0; i < entries.length; i += BATCH_SIZE) {
900
- const batch = entries.slice(i, i + BATCH_SIZE);
901
- db.insertBatch(batch);
902
- }
903
- ```
904
-
905
- **4. Web Worker Issues**
906
-
907
- ```javascript
908
- // Ensure worker script URL is correct
909
- const workerUrl = new URL('./worker.js', import.meta.url);
910
- const worker = new Worker(workerUrl, { type: 'module' });
911
-
912
- // Handle worker errors
913
- worker.onerror = (error) => {
914
- console.error('Worker error:', error);
915
- };
916
- ```
917
-
918
- See [WASM Troubleshooting Guide](../../docs/getting-started/wasm-troubleshooting.md) for more solutions.
919
-
920
- ## πŸ”— Links & Resources
921
-
922
- ### Documentation
923
-
924
- - **[Getting Started Guide](../../docs/guide/GETTING_STARTED.md)** - Complete setup and usage
925
- - **[WASM API Reference](../../docs/getting-started/wasm-api.md)** - Full API documentation
926
- - **[Performance Tuning](../../docs/optimization/PERFORMANCE_TUNING_GUIDE.md)** - Optimization tips
927
- - **[Main README](../../README.md)** - Project overview and features
928
-
929
- ### Examples & Demos
930
-
931
- - **[Vanilla JS Example](../../examples/wasm-vanilla/)** - Basic implementation
932
- - **[React Demo](../../examples/wasm-react/)** - React integration with hooks
933
- - **[Live Demo](https://ruvector-demo.vercel.app)** - Try it in your browser
934
- - **[CodeSandbox](https://codesandbox.io/s/ruvector-wasm)** - Interactive playground
935
-
936
- ### Community & Support
937
-
938
- - **GitHub**: [github.com/ruvnet/ruvector](https://github.com/ruvnet/ruvector)
939
- - **Discord**: [Join our community](https://discord.gg/ruvnet)
940
- - **Twitter**: [@ruvnet](https://twitter.com/ruvnet)
941
- - **Issues**: [Report bugs](https://github.com/ruvnet/ruvector/issues)
942
-
943
- ## πŸ“„ License
944
-
945
- MIT License - see [LICENSE](../../LICENSE) for details.
946
-
947
- Free to use for commercial and personal projects.
948
-
949
- ## πŸ™ Acknowledgments
950
-
951
- - Built with [wasm-pack](https://github.com/rustwasm/wasm-pack) and [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen)
952
- - HNSW algorithm implementation from [hnsw_rs](https://github.com/jean-pierreBoth/hnswlib-rs)
953
- - SIMD optimizations powered by Rust's excellent WebAssembly support
954
- - The WebAssembly community for making this possible
955
-
956
- ---
957
-
958
- <div align="center">
959
-
960
- **Built by [rUv](https://ruv.io) β€’ Open Source on [GitHub](https://github.com/ruvnet/ruvector)**
961
-
962
- [![Star on GitHub](https://img.shields.io/github/stars/ruvnet/ruvector?style=social)](https://github.com/ruvnet/ruvector)
963
- [![Follow @ruvnet](https://img.shields.io/twitter/follow/ruvnet?style=social)](https://twitter.com/ruvnet)
964
-
965
- **Perfect for**: PWAs β€’ Offline-First Apps β€’ Edge Computing β€’ Privacy-First AI
966
-
967
- [Get Started](../../docs/guide/GETTING_STARTED.md) β€’ [API Docs](../../docs/getting-started/wasm-api.md) β€’ [Examples](../../examples/)
968
-
969
- </div>