mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-26 16:04:02 +00:00
* docs: Add comprehensive GNN v2 implementation plans Add 22 detailed planning documents for 19 advanced GNN features: Tier 1 (Immediate - 3-6 months): - GNN-Guided HNSW Routing (+25% QPS) - Incremental Graph Learning/ATLAS (10-100x faster updates) - Neuro-Symbolic Query Execution (hybrid neural + logical) Tier 2 (Medium-Term - 6-12 months): - Hyperbolic Embeddings (Poincaré ball model) - Degree-Aware Adaptive Precision (2-4x memory reduction) - Continuous-Time Dynamic GNN (concept drift detection) Tier 3 (Research - 12+ months): - Graph Condensation (10-100x smaller graphs) - Native Sparse Attention (8-15x GPU speedup) - Quantum-Inspired Attention (long-range dependencies) Novel Innovations (10 experimental features): - Gravitational Embedding Fields, Causal Attention Networks - Topology-Aware Gradient Routing, Embedding Crystallization - Semantic Holography, Entangled Subspace Attention - Predictive Prefetch Attention, Morphological Attention - Adversarial Robustness Layer, Consensus Attention Includes comprehensive regression prevention strategy with: - Feature flag system for safe rollout - Performance baseline (186 tests + 6 search_v2 tests) - Automated rollback mechanisms Related to #38 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat(micro-hnsw-wasm): Add neuromorphic HNSW v2.3 with SNN integration ## New Crate: micro-hnsw-wasm v2.3.0 - Published to crates.io: https://crates.io/crates/micro-hnsw-wasm - 11.8KB WASM binary with 58 exported functions - Neuromorphic vector search combining HNSW + Spiking Neural Networks ### Core Features - HNSW graph-based approximate nearest neighbor search - Multi-distance metrics: L2, Cosine, Dot product - GNN extensions: typed nodes, edge weights, neighbor aggregation - Multi-core sharding: 256 cores × 32 vectors = 8K total ### Spiking Neural Network (SNN) - LIF (Leaky Integrate-and-Fire) neurons with membrane dynamics - STDP (Spike-Timing Dependent Plasticity) learning - Spike propagation through graph topology - HNSW→SNN bridge for similarity-driven neural activation ### Novel Neuromorphic Features (v2.3) - Spike-Timing Vector Encoding (rate-to-time conversion) - Homeostatic Plasticity (self-stabilizing thresholds) - Oscillatory Resonance (40Hz gamma synchronization) - Winner-Take-All Circuits (competitive selection) - Dendritic Computation (nonlinear branch integration) - Temporal Pattern Recognition (spike history matching) - Combined Neuromorphic Search pipeline ### Performance Optimizations - 5.5x faster SNN tick (2,726ns → 499ns) - 18% faster STDP learning - Pre-computed reciprocal constants - Division elimination in hot paths ### Documentation & Organization - Reorganized docs into subdirectories (gnn/, implementation/, publishing/, status/) - Added comprehensive README with badges, SEO, citations - Added benchmark.js and test_wasm.js test suites - Added DEEP_REVIEW.md with performance analysis - Added Verilog RTL for ASIC synthesis 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
178 lines
6.9 KiB
Rust
178 lines
6.9 KiB
Rust
//! Integration test for ruvector-attention crate from crates.io
|
|
//!
|
|
//! This tests all attention mechanisms from the published crate
|
|
|
|
use ruvector_attention::{
|
|
attention::{ScaledDotProductAttention, MultiHeadAttention},
|
|
sparse::{LocalGlobalAttention, LinearAttention, FlashAttention},
|
|
hyperbolic::{HyperbolicAttention, HyperbolicAttentionConfig},
|
|
moe::{MoEAttention, MoEConfig},
|
|
graph::{GraphAttention, GraphAttentionConfig},
|
|
traits::Attention,
|
|
};
|
|
|
|
fn main() {
|
|
println!("=== ruvector-attention Crate Integration Tests ===\n");
|
|
|
|
test_scaled_dot_product_attention();
|
|
test_multi_head_attention();
|
|
test_hyperbolic_attention();
|
|
test_linear_attention();
|
|
test_flash_attention();
|
|
test_local_global_attention();
|
|
test_moe_attention();
|
|
test_graph_attention();
|
|
|
|
println!("\n✅ All Rust crate tests passed!\n");
|
|
}
|
|
|
|
fn test_scaled_dot_product_attention() {
|
|
let dim = 64;
|
|
let attention = ScaledDotProductAttention::new(dim);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..3).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..3).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Scaled dot-product attention works correctly");
|
|
}
|
|
|
|
fn test_multi_head_attention() {
|
|
let dim = 64;
|
|
let num_heads = 8;
|
|
let attention = MultiHeadAttention::new(dim, num_heads);
|
|
|
|
assert_eq!(attention.dim(), dim);
|
|
assert_eq!(attention.num_heads(), num_heads);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Multi-head attention works correctly");
|
|
}
|
|
|
|
fn test_hyperbolic_attention() {
|
|
let dim = 64;
|
|
let config = HyperbolicAttentionConfig {
|
|
dim,
|
|
curvature: 1.0,
|
|
..Default::default()
|
|
};
|
|
let attention = HyperbolicAttention::new(config);
|
|
|
|
let query: Vec<f32> = vec![0.1; dim];
|
|
let keys: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>() * 0.1).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Hyperbolic attention works correctly");
|
|
}
|
|
|
|
fn test_linear_attention() {
|
|
let dim = 64;
|
|
let num_features = 128;
|
|
let attention = LinearAttention::new(dim, num_features);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Linear attention works correctly");
|
|
}
|
|
|
|
fn test_flash_attention() {
|
|
let dim = 64;
|
|
let block_size = 16;
|
|
let attention = FlashAttention::new(dim, block_size);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Flash attention works correctly");
|
|
}
|
|
|
|
fn test_local_global_attention() {
|
|
let dim = 64;
|
|
let local_window = 4;
|
|
let global_tokens = 2;
|
|
let attention = LocalGlobalAttention::new(dim, local_window, global_tokens);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..4).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..4).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Local-global attention works correctly");
|
|
}
|
|
|
|
fn test_moe_attention() {
|
|
let dim = 64;
|
|
let config = MoEConfig::builder()
|
|
.dim(dim)
|
|
.num_experts(4)
|
|
.top_k(2)
|
|
.build();
|
|
let attention = MoEAttention::new(config);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..2).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ MoE attention works correctly");
|
|
}
|
|
|
|
fn test_graph_attention() {
|
|
let dim = 64;
|
|
let config = GraphAttentionConfig {
|
|
dim,
|
|
num_heads: 4,
|
|
..Default::default()
|
|
};
|
|
let attention = GraphAttention::new(config);
|
|
|
|
let query: Vec<f32> = vec![0.5; dim];
|
|
let keys: Vec<Vec<f32>> = (0..3).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
let values: Vec<Vec<f32>> = (0..3).map(|_| (0..dim).map(|_| rand::random::<f32>()).collect()).collect();
|
|
|
|
let keys_refs: Vec<&[f32]> = keys.iter().map(|k| k.as_slice()).collect();
|
|
let values_refs: Vec<&[f32]> = values.iter().map(|v| v.as_slice()).collect();
|
|
|
|
let result = attention.compute(&query, &keys_refs, &values_refs).unwrap();
|
|
assert_eq!(result.len(), dim);
|
|
println!(" ✓ Graph attention works correctly");
|
|
}
|