Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

ruvector-learning-wasm

Ultra-fast MicroLoRA adaptation for WASM - rank-2 LoRA with <100us latency for per-operator learning.

Installation

npm install ruvector-learning-wasm

Overview

This package provides Low-Rank Adaptation (LoRA) matrices optimized for WebAssembly execution. It enables real-time per-operator-type learning in query optimization systems with minimal latency overhead.

Key Features

  • Rank-2 LoRA: Minimal parameter count (2d parameters per adapter)
  • Per-Operator Scoping: Separate adapters for 17 different operator types
  • <100us Adaptation: Instant weight updates for real-time learning
  • WASM-Optimized: Compiled to WebAssembly for near-native performance
  • Zero-Allocation Hot Paths: Pre-allocated buffers for performance-critical operations

JavaScript API

WasmMicroLoRA

The main LoRA engine for single-adapter use cases.

import init, { WasmMicroLoRA } from 'ruvector-learning-wasm';

// Initialize WASM module
await init();

// Create a new MicroLoRA engine
const lora = new WasmMicroLoRA(
  256,    // dim: Embedding dimension (max 256)
  0.1,    // alpha: Scaling factor
  0.01    // learning_rate: Learning rate for adaptation
);

// Forward pass with typed array
const input = new Float32Array(256).fill(1.0);
const output = lora.forward_array(input);

// Adapt with gradient
const gradient = new Float32Array(256).fill(0.1);
lora.adapt_array(gradient);

// Get statistics
console.log('Forward count:', lora.forward_count());
console.log('Adapt count:', lora.adapt_count());
console.log('Delta norm:', lora.delta_norm());
console.log('Parameter count:', lora.param_count());

// Reset engine
lora.reset();

Zero-Allocation API

For performance-critical loops, use the buffer-based API:

const lora = new WasmMicroLoRA(256, 0.1, 0.01);

// Get buffer pointers
const inputPtr = lora.get_input_ptr();
const outputPtr = lora.get_output_ptr();
const dim = lora.dim();

// Create views into WASM memory
const memory = new Float32Array(lora.memory.buffer);
const inputView = new Float32Array(memory.buffer, inputPtr, dim);
const outputView = new Float32Array(memory.buffer, outputPtr, dim);

// Write input directly
inputView.set(myInputData);

// Forward pass (zero allocation)
lora.forward();

// Read output directly
const result = outputView.slice();

// Adapt using input buffer as gradient
lora.adapt();

// Adapt with reward (for RL)
lora.adapt_with_reward(0.5); // improvement ratio

WasmScopedLoRA

Per-operator-type LoRA manager with 17 specialized adapters plus category fallback.

import init, { WasmScopedLoRA } from 'ruvector-learning-wasm';

await init();

const scopedLora = new WasmScopedLoRA(
  256,    // dim
  0.1,    // alpha
  0.01    // learning_rate
);

// Operator types (0-16)
const HNSW_SCAN = 2;
const HASH_JOIN = 5;
const FILTER = 9;

// Forward for specific operator
const input = new Float32Array(256).fill(1.0);
const output = scopedLora.forward_array(HNSW_SCAN, input);

// Adapt for specific operator
const gradient = new Float32Array(256).fill(0.1);
scopedLora.adapt_array(FILTER, gradient);

// Per-operator statistics
console.log('HNSW forward count:', scopedLora.forward_count(HNSW_SCAN));
console.log('Filter adapt count:', scopedLora.adapt_count(FILTER));
console.log('Filter delta norm:', scopedLora.delta_norm(FILTER));

// Total statistics
console.log('Total forwards:', scopedLora.total_forward_count());
console.log('Total adapts:', scopedLora.total_adapt_count());

// Get operator name
console.log(WasmScopedLoRA.scope_name(HNSW_SCAN)); // "HnswScan"

// Enable/disable category fallback (default: enabled)
scopedLora.set_category_fallback(true);

// Reset specific operator or all
scopedLora.reset_scope(FILTER);
scopedLora.reset_all();

Operator Types

Value Name Category
0 SeqScan Scan
1 IndexScan Scan
2 HnswScan Scan
3 IvfFlatScan Scan
4 NestedLoopJoin Join
5 HashJoin Join
6 MergeJoin Join
7 Aggregate Aggregation
8 GroupBy Aggregation
9 Filter Transform
10 Project Transform
11 Sort Order
12 Limit Order
13 VectorDistance Vector
14 Rerank Vector
15 Materialize Utility
16 Result Utility

WasmTrajectoryBuffer

Trajectory recording for reinforcement learning and pattern analysis.

import init, { WasmTrajectoryBuffer } from 'ruvector-learning-wasm';

await init();

const buffer = new WasmTrajectoryBuffer(
  1000,   // capacity: max trajectories to store
  256     // embedding_dim
);

// Record a trajectory
const embedding = new Float32Array(256).fill(1.0);
buffer.record(
  embedding,
  2,        // op_type: HnswScan
  0,        // attention_type
  100.0,    // execution_ms
  150.0     // baseline_ms (improvement = 150/100 - 1 = 0.5)
);

// Get statistics
console.log('Total count:', buffer.total_count());
console.log('Buffer length:', buffer.len());
console.log('Mean improvement:', buffer.mean_improvement());
console.log('Best improvement:', buffer.best_improvement());
console.log('Success rate:', buffer.success_rate());
console.log('Best attention type:', buffer.best_attention());
console.log('Variance:', buffer.variance());

// Filter by quality
console.log('High quality count:', buffer.high_quality_count(0.5));

// Filter by operator
console.log('HnswScan trajectories:', buffer.count_by_operator(2));

// Reset buffer
buffer.reset();

Architecture

Input Embedding (d-dim)
       |
       v
  +---------+
  | A: d x 2 |  Down projection
  +---------+
       |
       v
  +---------+
  | B: 2 x d |  Up projection (initialized to zero)
  +---------+
       |
       v
Delta W = alpha * (A @ B)
       |
       v
Output = Input + Delta W

Category Fallback

When an operator has fewer than 10 adaptations, the output is blended with the category adapter based on relative experience:

weight = min(operator_adapt_count / 10, 1.0)
output = operator_output * weight + category_output * (1 - weight)

This enables transfer learning between similar operators (e.g., all scan types share Scan category knowledge).

Performance

  • Forward pass: ~50us for 256-dim embeddings
  • Adaptation: ~30us for gradient update
  • Memory: ~2KB per LoRA pair (A + B matrices)
  • WASM size: ~39KB (release build)

TypeScript Types

Full TypeScript definitions are included in the package:

export class WasmMicroLoRA {
  constructor(dim?: number, alpha?: number, learning_rate?: number);
  get_input_ptr(): number;
  get_output_ptr(): number;
  dim(): number;
  forward(): void;
  forward_array(input: Float32Array): Float32Array;
  adapt(): void;
  adapt_array(gradient: Float32Array): void;
  adapt_with_reward(improvement: number): void;
  reset(): void;
  forward_count(): bigint;
  adapt_count(): bigint;
  delta_norm(): number;
  param_count(): number;
}

export class WasmScopedLoRA {
  constructor(dim?: number, alpha?: number, learning_rate?: number);
  get_input_ptr(): number;
  get_output_ptr(): number;
  forward(op_type: number): void;
  forward_array(op_type: number, input: Float32Array): Float32Array;
  adapt(op_type: number): void;
  adapt_array(op_type: number, gradient: Float32Array): void;
  adapt_with_reward(op_type: number, improvement: number): void;
  reset_scope(op_type: number): void;
  reset_all(): void;
  forward_count(op_type: number): bigint;
  adapt_count(op_type: number): bigint;
  delta_norm(op_type: number): number;
  total_forward_count(): bigint;
  total_adapt_count(): bigint;
  set_category_fallback(enabled: boolean): void;
  static scope_name(op_type: number): string;
}

export class WasmTrajectoryBuffer {
  constructor(capacity?: number, embedding_dim?: number);
  record(
    embedding: Float32Array,
    op_type: number,
    attention_type: number,
    execution_ms: number,
    baseline_ms: number
  ): void;
  total_count(): bigint;
  len(): number;
  is_empty(): boolean;
  mean_improvement(): number;
  best_improvement(): number;
  success_rate(): number;
  best_attention(): number;
  variance(): number;
  reset(): void;
  high_quality_count(threshold: number): number;
  count_by_operator(op_type: number): number;
}

License

MIT OR Apache-2.0