mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-30 12:13:34 +00:00
* feat(rvf): add RuVector Format universal substrate specification Research and design for RVF — a streaming, progressive, adaptive, quantum-secure binary format for vector intelligence. Covers append-only segment model, two-level tail manifests, temperature tiering, progressive HNSW indexing, epoch-based overlay system, SIMD-optimized query paths, WASM microkernel for Cognitum tiles, domain profiles (RVDNA, RVText, RVGraph, RVVision), and post-quantum cryptography. https://claude.ai/code/session_01DDqjGE51JpsRE3DgUjFyjW * feat(rvf): add deletion, filtered search, concurrency, and operations specs Fill four specification gaps in the RVF format design: - spec/07: Vector deletion lifecycle, JOURNAL_SEG wire format, deletion bitmaps - spec/08: Filtered search with META_SEG, METAIDX_SEG, filter expression language - spec/09: Writer locking, reader-writer coordination, versioning, space reclamation - spec/10: Batch operations API, error codes, network streaming protocol Also fixes the segment header field conflict between spec/01 and wire/binary-layout.md (checksum_algo/compression now u8, adds uncompressed_len at 0x38). https://claude.ai/code/session_01DDqjGE51JpsRE3DgUjFyjW * feat(rvf): add RuVector Format SDK, 40 examples, MCP server, and documentation Complete RVF implementation including: - 12 Rust crates (rvf-types, rvf-wire, rvf-manifest, rvf-index, rvf-quant, rvf-crypto, rvf-runtime, rvf-import, rvf-wasm, rvf-node, rvf-server, plus integration tests) - 40 runnable examples covering core storage, agentic AI, production patterns, vertical domains, exotic capabilities, runtime targets, network/security, POSIX/systems, and network operations - TypeScript SDK (npm/packages/rvf) with RvfDatabase class - MCP server (npm/packages/rvf-mcp-server) with stdio and SSE transports - Node.js N-API bindings (npm/packages/rvf-node) - WASM package (npm/packages/rvf-wasm) - ADR-029 (canonical format), ADR-030 (computational container), ADR-031 (example repository) - DNA-style lineage provenance, computational containers (KERNEL_SEG, EBPF_SEG), witness chains, TEE attestation, domain profiles - Superseded ADR annotations for ADR-001, ADR-005, ADR-006, ADR-018-021 Co-Authored-By: claude-flow <ruv@ruv.net> * feat(rvf): add CLI, WASM store, generate_all, and 46 output .rvf files - Add rvf-cli crate (665 lines, 9 subcommands: create/ingest/query/delete/status/inspect/compact/derive/serve) - Add WASM control plane store (alloc_setup, segment, store modules) for ~46 KB binary - Add generate_all.rs example producing 46 persistent .rvf files in output/ - Add Node.js N-API bindings for lineage, kernel/eBPF, and inspection - Add npm TypeScript backend/database/types for RVF integration - Update READMEs with CLI sections, MCP server docs, and crate map (13 crates) - All 40 examples verified passing Co-Authored-By: claude-flow <ruv@ruv.net> * feat(rvf): add Claude Code appliance, improve Quick Start, fix API docs - Add claude_code_appliance.rs: self-booting RVF with SSH + Claude Code install (curl -fsSL https://claude.ai/install.sh | bash), 3 SSH users, eBPF filter, 20-package manifest, witness chain, lineage snapshot - Improve Quick Start: Install section (crate/CLI/npm/WASM/MCP), WASM browser example, generate_all reference, expanded Rust crate deps - Fix embed_kernel/embed_ebpf API docs to match actual signatures (u8 params with `as u8` cast, 6-param kernel, Option<&[u8]> btf) - Update generate_all.rs: add claude_code_appliance generator (47 files) - Regenerate all 47 output .rvf files Co-Authored-By: claude-flow <ruv@ruv.net> * feat(rvf): add RVCOW branching, real kernel/eBPF/launcher, 795 tests Vector-native copy-on-write branching (ADR-031) with four new segment types (COW_MAP 0x20, REFCOUNT 0x21, MEMBERSHIP 0x22, DELTA 0x23), real Linux microkernel builder, QEMU microVM launcher, real eBPF programs, and 128-byte KernelBinding for tamper-evident kernel-manifest linkage. New crates: - rvf-kernel: Docker-based kernel build, real cpio/newc initramfs builder, SHA3-256 verification, prebuilt kernel support (37 tests) - rvf-launch: QEMU microVM launcher with QMP shutdown, KVM/TCG detection, virtio-blk/net port forwarding, kernel extraction (8 tests) - rvf-ebpf: 3 real BPF C programs (xdp_distance, socket_filter, tc_query_route) with clang compilation support (17 tests) RVCOW runtime: - CowEngine with read/write paths, write coalescing, snapshot-freeze - CowMap (flat-array), MembershipFilter (bitmap), CowCompactor - 3x read performance via pread optimization (1.3us/vector) - Branch creation: 2.6ms for 10K vectors, child = 162 bytes Security: 20-finding audit, 7 fixes applied including division-by-zero guards, integer overflow checks, and KernelBinding::from_bytes_validated(). CLI: 8 new commands (launch, embed-kernel, embed-ebpf, filter, freeze, verify-witness, verify-attestation, rebuild-refcounts), serve wired to real rvf-server. Co-Authored-By: claude-flow <ruv@ruv.net> * feat(rvf): update README, add crate/npm READMEs, publish to crates.io and npm - Rewrite README with cognitive container terminology, grouped features, 4 comparison tables (vs Docker, Vector DBs, Git LFS, SQLite), updated benchmarks, architecture diagram, and 45 examples - Add READMEs for rvf-kernel, rvf-launch, rvf-ebpf, rvf-import crates - Add READMEs for @ruvector/rvf, rvf-node, rvf-wasm, rvf-mcp-server npm packages - Fix Cargo.toml metadata (homepage, readme, categories, keywords) and add version specs to all path dependencies for crates.io publishing - Fix clippy warnings in rvf-kernel/initramfs.rs and rvf-launch/lib.rs - Published to crates.io: rvf-types, rvf-wire, rvf-manifest, rvf-quant, rvf-index, rvf-crypto (remaining crates pending rate limit) - Published to npm: @ruvector/rvf, @ruvector/rvf-node, @ruvector/rvf-wasm, @ruvector/rvf-mcp-server Co-Authored-By: claude-flow <ruv@ruv.net> * chore: add rvf-kernel, rvf-ebpf, rvf-launch, rvf-server, rvf-import, rvf-cli to workspace Include all 15 RVF crates plus integration tests and benchmarks in the root workspace members list so cargo publish can resolve them by name. Co-Authored-By: claude-flow <ruv@ruv.net> * feat(rvf): add published packages, cognitive container branding, grouped capabilities - Add Published Packages section with 13 crates.io + 4 npm tables - Add Platform Support table (Linux, macOS, Windows, WASM, no_std) - Expand capability table from 9 to 15 rows in 4 groups - Rewrite all "How" descriptions in plain language - Update .rvf diagram to show all 20 segment types - Rename ADRs: computational container -> cognitive container - Add emojis to all section headers Co-Authored-By: claude-flow <ruv@ruv.net> * feat: update root README with RVF cognitive containers, expanded capabilities - Update intro: "gets smarter + ships as cognitive container" - Add self-booting microservice row to Pinecone comparison table - Expand capabilities from 34 to 42 features with dedicated RVF section - Update "Think of it as" to include Docker comparison and RVF explanation - Add RVF collapsed group to Ecosystem (13 crates, 4 npm, install commands) - Add RVF to Platform & Edge section with install commands - Add RVF npm packages (4) and Rust crates (13) to package reference - Add RVF rows to feature comparison table (6 new rows) - Add ADR-030/031 to ADR list - Add RVF to Installation table, Project Structure - Update attention mechanisms count from 39 to 40+ - Update npm count to 49+, Rust crates to 83 - Update footer with crates.io and RVF links Co-Authored-By: claude-flow <ruv@ruv.net> * feat: expand comparison table with emojis, cost, audit, branching, single-file Co-Authored-By: claude-flow <ruv@ruv.net> * docs: rewrite comparison table in plain language Co-Authored-By: claude-flow <ruv@ruv.net> * chore: clean up empty code change sections in the changes log --------- Co-authored-by: Claude <noreply@anthropic.com>
285 lines
9.5 KiB
Rust
285 lines
9.5 KiB
Rust
//! Temperature-Tiered Quantization
|
|
//!
|
|
//! Demonstrates all three quantization tiers in the RVF format:
|
|
//! 1. Scalar quantization (Hot tier): fp32 -> u8, 4x compression
|
|
//! 2. Product quantization (Warm tier): fp32 -> PQ codes, 8-16x compression
|
|
//! 3. Binary quantization (Cold tier): fp32 -> 1-bit, 32x compression
|
|
//! 4. Count-Min Sketch: track access patterns, assign temperature tiers
|
|
|
|
use rvf_quant::{
|
|
ScalarQuantizer, ProductQuantizer, CountMinSketch,
|
|
encode_binary, decode_binary, hamming_distance,
|
|
TemperatureTier,
|
|
};
|
|
use rvf_quant::tier::assign_tier;
|
|
use rvf_quant::traits::Quantizer;
|
|
|
|
/// LCG-based pseudo-random vector generator.
|
|
fn random_vectors(n: usize, dim: usize, seed: u64) -> Vec<Vec<f32>> {
|
|
let mut s = seed;
|
|
(0..n)
|
|
.map(|_| {
|
|
(0..dim)
|
|
.map(|_| {
|
|
s = s.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
|
|
((s >> 33) as f32) / (u32::MAX as f32) - 0.5
|
|
})
|
|
.collect()
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
/// Compute mean squared error between original and reconstructed vectors.
|
|
fn mse(original: &[f32], reconstructed: &[f32]) -> f32 {
|
|
assert_eq!(original.len(), reconstructed.len());
|
|
let sum: f32 = original
|
|
.iter()
|
|
.zip(reconstructed.iter())
|
|
.map(|(a, b)| {
|
|
let d = a - b;
|
|
d * d
|
|
})
|
|
.sum();
|
|
sum / original.len() as f32
|
|
}
|
|
|
|
fn main() {
|
|
println!("=== RVF Quantization Example ===\n");
|
|
|
|
let dim = 384;
|
|
let n = 1000;
|
|
|
|
println!("Generating {} random vectors ({} dims)...\n", n, dim);
|
|
let vectors = random_vectors(n, dim, 42);
|
|
let vec_refs: Vec<&[f32]> = vectors.iter().map(|v| v.as_slice()).collect();
|
|
|
|
// ====================================================================
|
|
// 1. Scalar Quantization (Hot tier)
|
|
// ====================================================================
|
|
println!("--- 1. Scalar Quantization (Hot Tier) ---");
|
|
println!(" Compression: fp32 -> u8 (4x)");
|
|
println!(" Training scalar quantizer...");
|
|
|
|
let sq = ScalarQuantizer::train(&vec_refs);
|
|
assert_eq!(sq.tier(), TemperatureTier::Hot);
|
|
assert_eq!(sq.dim(), dim);
|
|
|
|
// Encode and decode a sample vector.
|
|
let sample = &vectors[0];
|
|
let sq_encoded = sq.encode_vec(sample);
|
|
let sq_decoded = sq.decode_vec(&sq_encoded);
|
|
|
|
let sq_error = mse(sample, &sq_decoded);
|
|
let sq_orig_bytes = dim * 4; // fp32
|
|
let sq_comp_bytes = sq_encoded.len(); // u8 per dim
|
|
let sq_ratio = sq_orig_bytes as f32 / sq_comp_bytes as f32;
|
|
|
|
println!(" Encoded size: {} bytes (from {} bytes)", sq_comp_bytes, sq_orig_bytes);
|
|
println!(" Compression ratio: {:.1}x", sq_ratio);
|
|
println!(" Reconstruction MSE: {:.8}", sq_error);
|
|
|
|
// Compute average MSE over all vectors.
|
|
let sq_avg_mse: f32 = vectors
|
|
.iter()
|
|
.map(|v| {
|
|
let codes = sq.encode_vec(v);
|
|
let recon = sq.decode_vec(&codes);
|
|
mse(v, &recon)
|
|
})
|
|
.sum::<f32>()
|
|
/ n as f32;
|
|
println!(" Average MSE (all {} vectors): {:.8}", n, sq_avg_mse);
|
|
|
|
// Quantized distance comparison.
|
|
let a_codes = sq.encode_vec(&vectors[0]);
|
|
let b_codes = sq.encode_vec(&vectors[1]);
|
|
let quant_dist = sq.distance_l2_quantized(&a_codes, &b_codes);
|
|
let exact_dist: f32 = vectors[0]
|
|
.iter()
|
|
.zip(vectors[1].iter())
|
|
.map(|(x, y)| { let d = x - y; d * d })
|
|
.sum();
|
|
println!(
|
|
" Distance (quantized vs exact): {:.4} vs {:.4} (error: {:.4})",
|
|
quant_dist,
|
|
exact_dist,
|
|
(quant_dist - exact_dist).abs()
|
|
);
|
|
|
|
// ====================================================================
|
|
// 2. Product Quantization (Warm tier)
|
|
// ====================================================================
|
|
println!("\n--- 2. Product Quantization (Warm Tier) ---");
|
|
|
|
let pq_m = 48; // Number of subspaces (dim must be divisible by M)
|
|
let pq_k = 64; // Centroids per subspace
|
|
let pq_iters = 20;
|
|
|
|
println!(
|
|
" Config: M={}, K={}, iterations={}, sub_dim={}",
|
|
pq_m,
|
|
pq_k,
|
|
pq_iters,
|
|
dim / pq_m,
|
|
);
|
|
println!(" Training product quantizer...");
|
|
|
|
let pq = ProductQuantizer::train(&vec_refs, pq_m, pq_k, pq_iters);
|
|
assert_eq!(pq.tier(), TemperatureTier::Warm);
|
|
assert_eq!(pq.dim(), dim);
|
|
|
|
let pq_encoded = pq.encode_vec(sample);
|
|
let pq_decoded = pq.decode_vec(&pq_encoded);
|
|
|
|
let pq_error = mse(sample, &pq_decoded);
|
|
let pq_comp_bytes = pq_encoded.len(); // 1 byte per subspace
|
|
let pq_ratio = sq_orig_bytes as f32 / pq_comp_bytes as f32;
|
|
|
|
println!(" Encoded size: {} bytes (from {} bytes)", pq_comp_bytes, sq_orig_bytes);
|
|
println!(" Compression ratio: {:.1}x", pq_ratio);
|
|
println!(" Reconstruction MSE: {:.8}", pq_error);
|
|
|
|
// ADC (Asymmetric Distance Computation) demo.
|
|
let query = &vectors[42];
|
|
let tables = pq.compute_distance_tables(query);
|
|
let target_codes = pq.encode_vec(&vectors[99]);
|
|
let adc_dist = ProductQuantizer::distance_adc(&tables, &target_codes);
|
|
|
|
let exact_dist_pq: f32 = query
|
|
.iter()
|
|
.zip(vectors[99].iter())
|
|
.map(|(x, y)| { let d = x - y; d * d })
|
|
.sum();
|
|
println!(
|
|
" ADC distance (query[42] -> vec[99]): {:.4} (exact: {:.4})",
|
|
adc_dist, exact_dist_pq,
|
|
);
|
|
|
|
// Average MSE.
|
|
let pq_avg_mse: f32 = vectors
|
|
.iter()
|
|
.map(|v| {
|
|
let codes = pq.encode_vec(v);
|
|
let recon = pq.decode_vec(&codes);
|
|
mse(v, &recon)
|
|
})
|
|
.sum::<f32>()
|
|
/ n as f32;
|
|
println!(" Average MSE (all {} vectors): {:.8}", n, pq_avg_mse);
|
|
|
|
// ====================================================================
|
|
// 3. Binary Quantization (Cold tier)
|
|
// ====================================================================
|
|
println!("\n--- 3. Binary Quantization (Cold Tier) ---");
|
|
println!(" Compression: fp32 -> 1-bit (32x)");
|
|
|
|
let bin_encoded = encode_binary(sample);
|
|
let bin_decoded = decode_binary(&bin_encoded, dim);
|
|
|
|
let bin_error = mse(sample, &bin_decoded);
|
|
let bin_comp_bytes = bin_encoded.len();
|
|
let bin_ratio = sq_orig_bytes as f32 / bin_comp_bytes as f32;
|
|
|
|
println!(" Encoded size: {} bytes (from {} bytes)", bin_comp_bytes, sq_orig_bytes);
|
|
println!(" Compression ratio: {:.1}x", bin_ratio);
|
|
println!(" Reconstruction MSE: {:.8}", bin_error);
|
|
|
|
// Hamming distance demo.
|
|
let bin_a = encode_binary(&vectors[0]);
|
|
let bin_b = encode_binary(&vectors[1]);
|
|
let ham_dist = hamming_distance(&bin_a, &bin_b);
|
|
println!(
|
|
" Hamming distance (vec[0] vs vec[1]): {} / {} bits",
|
|
ham_dist, dim,
|
|
);
|
|
|
|
// ====================================================================
|
|
// 4. Count-Min Sketch: Temperature Assignment
|
|
// ====================================================================
|
|
println!("\n--- 4. Count-Min Sketch: Temperature Tracking ---");
|
|
|
|
let mut sketch = CountMinSketch::default_sketch();
|
|
println!(
|
|
" Sketch size: {} bytes (width={}, depth={})",
|
|
sketch.memory_bytes(),
|
|
sketch.width,
|
|
sketch.depth,
|
|
);
|
|
|
|
// Demonstrate access patterns:
|
|
// - Block 0: very hot (200 accesses)
|
|
// - Block 1: warm (50 accesses)
|
|
// - Block 2: cold (5 accesses)
|
|
// - Block 3: never accessed
|
|
let access_patterns = [(0u64, 200u32), (1, 50), (2, 5)];
|
|
|
|
for &(block_id, count) in &access_patterns {
|
|
for _ in 0..count {
|
|
sketch.increment(block_id);
|
|
}
|
|
}
|
|
|
|
println!("\n Access patterns:");
|
|
println!(" {:>8} {:>10} {:>10} {:>8}", "Block", "Accesses", "Estimate", "Tier");
|
|
println!(" {:->8} {:->10} {:->10} {:->8}", "", "", "", "");
|
|
|
|
for &(block_id, true_count) in &access_patterns {
|
|
let estimate = sketch.estimate(block_id);
|
|
let tier = assign_tier(estimate);
|
|
println!(
|
|
" {:>8} {:>10} {:>10} {:>8?}",
|
|
block_id, true_count, estimate, tier,
|
|
);
|
|
}
|
|
|
|
// Unseen block.
|
|
let unseen_est = sketch.estimate(3);
|
|
let unseen_tier = assign_tier(unseen_est);
|
|
println!(
|
|
" {:>8} {:>10} {:>10} {:>8?}",
|
|
3, 0, unseen_est, unseen_tier,
|
|
);
|
|
|
|
// Show aging effect.
|
|
println!("\n After aging (halving all counters):");
|
|
sketch.age();
|
|
for &(block_id, _) in &access_patterns {
|
|
let estimate = sketch.estimate(block_id);
|
|
let tier = assign_tier(estimate);
|
|
println!(
|
|
" Block {}: estimate={}, tier={:?}",
|
|
block_id, estimate, tier,
|
|
);
|
|
}
|
|
|
|
// ====================================================================
|
|
// Summary Table
|
|
// ====================================================================
|
|
println!("\n=== Quantization Comparison Summary ===\n");
|
|
println!(
|
|
" {:>12} {:>12} {:>18} {:>14}",
|
|
"Tier", "Compression", "Avg MSE", "Bytes/Vector"
|
|
);
|
|
println!(
|
|
" {:->12} {:->12} {:->18} {:->14}",
|
|
"", "", "", ""
|
|
);
|
|
println!(
|
|
" {:>12} {:>11.1}x {:>18.8} {:>14}",
|
|
"Hot (SQ)", sq_ratio, sq_avg_mse, sq_comp_bytes
|
|
);
|
|
println!(
|
|
" {:>12} {:>11.1}x {:>18.8} {:>14}",
|
|
"Warm (PQ)", pq_ratio, pq_avg_mse, pq_comp_bytes
|
|
);
|
|
println!(
|
|
" {:>12} {:>11.1}x {:>18.8} {:>14}",
|
|
"Cold (Bin)", bin_ratio, bin_error, bin_comp_bytes
|
|
);
|
|
println!(
|
|
" {:>12} {:>11.1}x {:>18} {:>14}",
|
|
"Raw fp32", 1.0, "0.00000000", sq_orig_bytes
|
|
);
|
|
|
|
println!("\nDone.");
|
|
}
|