git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
133 lines
5.0 KiB
Markdown
133 lines
5.0 KiB
Markdown
# rvf-wasm
|
|
|
|
WASM microkernel and control plane for running RuVector Format operations in the browser and at the edge.
|
|
|
|
## Overview
|
|
|
|
`rvf-wasm` compiles the core RVF runtime to WebAssembly for use in browsers, Cloudflare Workers, and other WASM environments:
|
|
|
|
- **Compact binary** -- optimized with `opt-level = "z"` and LTO
|
|
- **No-std compatible** -- runs with a lightweight `dlmalloc` allocator
|
|
- **Browser-ready** -- works with `wasm-bindgen` or standalone instantiation
|
|
- **Full control plane** -- create, query, modify, and export `.rvf` stores entirely in-memory
|
|
|
|
## Build
|
|
|
|
```bash
|
|
cargo build --target wasm32-unknown-unknown --release -p rvf-wasm
|
|
```
|
|
|
|
## API
|
|
|
|
### Tile Compute (14 exports)
|
|
|
|
Low-level distance computation, quantization, and HNSW navigation for the Cognitum tile architecture:
|
|
|
|
| Export | Description |
|
|
|--------|-------------|
|
|
| `rvf_init` | Initialize tile with configuration |
|
|
| `rvf_load_query` | Load query vector into scratch |
|
|
| `rvf_load_block` | Load vector block into SIMD scratch |
|
|
| `rvf_distances` | Compute distances (L2, IP, cosine, hamming) |
|
|
| `rvf_topk_merge` | Merge distances into top-K heap |
|
|
| `rvf_topk_read` | Read sorted top-K results |
|
|
| `rvf_load_sq_params` | Load scalar quantization parameters |
|
|
| `rvf_dequant_i8` | Dequantize int8 to fp16 |
|
|
| `rvf_load_pq_codebook` | Load PQ codebook for asymmetric distance |
|
|
| `rvf_pq_distances` | Compute PQ distances |
|
|
| `rvf_load_neighbors` | Load HNSW neighbor list |
|
|
| `rvf_greedy_step` | HNSW greedy search step |
|
|
| `rvf_verify_header` | Verify segment header magic/version |
|
|
| `rvf_crc32c` | Compute CRC32C checksum |
|
|
|
|
### Control Plane (10 exports)
|
|
|
|
In-memory store operations for creating and querying `.rvf` data without filesystem access:
|
|
|
|
| Export | Description |
|
|
|--------|-------------|
|
|
| `rvf_store_create(dim, metric) -> handle` | Create in-memory store |
|
|
| `rvf_store_open(buf_ptr, buf_len) -> handle` | Parse `.rvf` bytes into queryable store |
|
|
| `rvf_store_ingest(handle, vecs, ids, count)` | Add vectors |
|
|
| `rvf_store_query(handle, query, k, metric, out)` | k-NN search |
|
|
| `rvf_store_delete(handle, ids, count)` | Soft-delete by ID |
|
|
| `rvf_store_count(handle)` | Live vector count |
|
|
| `rvf_store_dimension(handle)` | Get dimensionality |
|
|
| `rvf_store_status(handle, out)` | Write 20-byte status |
|
|
| `rvf_store_export(handle, out, len)` | Serialize to `.rvf` bytes |
|
|
| `rvf_store_close(handle)` | Free store |
|
|
|
|
### Segment Inspection (4 exports)
|
|
|
|
Parse and inspect `.rvf` file structure from raw bytes:
|
|
|
|
| Export | Description |
|
|
|--------|-------------|
|
|
| `rvf_parse_header(buf, len, out)` | Parse a 64-byte segment header |
|
|
| `rvf_segment_count(buf, len)` | Count segments in buffer |
|
|
| `rvf_segment_info(buf, len, idx, out)` | Get segment details by index |
|
|
| `rvf_verify_checksum(buf, len)` | Verify CRC32C integrity |
|
|
|
|
### Witness Chain Verification (2 exports)
|
|
|
|
Verify SHAKE-256 witness chains from WITNESS_SEG payloads:
|
|
|
|
| Export | Description |
|
|
|--------|-------------|
|
|
| `rvf_witness_verify(chain_ptr, chain_len) -> i32` | Verify full chain integrity; returns entry count or negative error (-2 = truncated, -3 = hash mismatch) |
|
|
| `rvf_witness_count(chain_len) -> i32` | Count entries without full verification (chain_len / 73) |
|
|
|
|
These exports enable browser-side verification of acceptance test artifacts and audit trails without any backend. See [ADR-037](../../docs/adr/ADR-037-publishable-rvf-acceptance-test.md).
|
|
|
|
### Memory Management (2 exports)
|
|
|
|
| Export | Description |
|
|
|--------|-------------|
|
|
| `rvf_alloc(size) -> ptr` | Allocate memory for JS interop |
|
|
| `rvf_free(ptr, size)` | Free allocated memory |
|
|
|
|
## Usage from JavaScript
|
|
|
|
```javascript
|
|
const wasm = await WebAssembly.instantiate(wasmBytes);
|
|
const { rvf_store_create, rvf_store_ingest, rvf_store_query,
|
|
rvf_store_export, rvf_store_close, rvf_alloc, rvf_free } = wasm.instance.exports;
|
|
|
|
// Create a 4-dimensional store with L2 metric
|
|
const handle = rvf_store_create(4, 0);
|
|
|
|
// Allocate and copy vectors into WASM memory
|
|
const vecs = new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0]);
|
|
const ids = new BigUint64Array([0n, 1n, 2n]);
|
|
const vecPtr = rvf_alloc(vecs.byteLength);
|
|
const idPtr = rvf_alloc(ids.byteLength);
|
|
new Uint8Array(wasm.instance.exports.memory.buffer, vecPtr, vecs.byteLength)
|
|
.set(new Uint8Array(vecs.buffer));
|
|
new Uint8Array(wasm.instance.exports.memory.buffer, idPtr, ids.byteLength)
|
|
.set(new Uint8Array(ids.buffer));
|
|
|
|
// Ingest
|
|
rvf_store_ingest(handle, vecPtr, idPtr, 3);
|
|
rvf_free(vecPtr, vecs.byteLength);
|
|
rvf_free(idPtr, ids.byteLength);
|
|
|
|
// Query
|
|
const queryVec = new Float32Array([1,0,0,0]);
|
|
const qPtr = rvf_alloc(16);
|
|
new Uint8Array(wasm.instance.exports.memory.buffer, qPtr, 16)
|
|
.set(new Uint8Array(queryVec.buffer));
|
|
const outPtr = rvf_alloc(12 * 3); // 3 results * (8 bytes id + 4 bytes dist)
|
|
const count = rvf_store_query(handle, qPtr, 3, 0, outPtr);
|
|
|
|
// Export to .rvf bytes
|
|
const exportBuf = rvf_alloc(65536);
|
|
const written = rvf_store_export(handle, exportBuf, 65536);
|
|
const rvfBytes = new Uint8Array(wasm.instance.exports.memory.buffer, exportBuf, written);
|
|
|
|
rvf_store_close(handle);
|
|
```
|
|
|
|
## License
|
|
|
|
MIT OR Apache-2.0
|