docs: Add Cypher reference, include Tiny Dancer, fix WASM build

- Create docs/api/CYPHER_REFERENCE.md with complete Cypher query guide
- Update README to highlight all capabilities in core npx ruvector package
- Add Tiny Dancer (AI agent routing) to features and comparison table
- Fix ruvector-wasm insertBatch to use js_sys::Array instead of serde
This commit is contained in:
Claude 2025-11-26 12:54:04 +00:00
parent 3972374eff
commit ed2bdd014e
3 changed files with 254 additions and 8 deletions

View file

@ -13,6 +13,8 @@
npx ruvector
```
> **All-in-One Package**: The core `ruvector` package includes everything — vector search, graph queries, GNN layers, tensor compression, and WASM support. No additional packages needed.
## What Problem Does RuVector Solve?
Traditional vector databases just store and search. When you ask "find similar items," they return results but never get smarter.
@ -22,6 +24,8 @@ Traditional vector databases just store and search. When you ask "find similar i
1. **Store vectors** like any vector DB (embeddings from OpenAI, Cohere, etc.)
2. **Query with Cypher** like Neo4j (`MATCH (a)-[:SIMILAR]->(b) RETURN b`)
3. **The index learns** — GNN layers make search results improve over time
4. **Compress automatically** — 2-32x memory reduction with adaptive tiered compression
5. **Run anywhere** — Node.js, browser (WASM), or native Rust
Think of it as: **Pinecone + Neo4j + PyTorch** in one Rust package.
@ -55,6 +59,10 @@ const enhanced = layer.forward(query, neighbors, weights);
// Compression (2-32x memory savings)
const compressed = ruvector.compress(embedding, 0.3);
// Tiny Dancer: AI agent routing
const router = new ruvector.Router();
const decision = router.route(candidates, { optimize: 'cost' });
```
### Rust
@ -90,6 +98,7 @@ let enhanced = layer.forward(&query, &neighbors, &weights);
| **Hyperedges** | Connect 3+ nodes at once | Model complex relationships |
| **Tensor Compression** | f32→f16→PQ8→PQ4→Binary | 2-32x memory reduction |
| **Differentiable Search** | Soft attention k-NN | End-to-end trainable |
| **Tiny Dancer** | FastGRNN neural routing | Optimize LLM inference costs |
| **WASM/Browser** | Full client-side support | Run AI search offline |
## Comparison
@ -101,6 +110,7 @@ let enhanced = layer.forward(&query, &neighbors, &weights);
| **Graph Queries** | ✅ Cypher | ❌ | ❌ | ❌ | ❌ |
| **Hyperedges** | ✅ | ❌ | ❌ | ❌ | ❌ |
| **Self-Learning (GNN)** | ✅ | ❌ | ❌ | ❌ | ❌ |
| **AI Agent Routing** | ✅ Tiny Dancer | ❌ | ❌ | ❌ | ❌ |
| **Auto-Compression** | ✅ 2-32x | ❌ | ❌ | ✅ | ❌ |
| **Browser/WASM** | ✅ | ❌ | ❌ | ❌ | ❌ |
| **Differentiable** | ✅ | ❌ | ❌ | ❌ | ❌ |
@ -187,11 +197,12 @@ RETURN related
```
crates/
├── ruvector-core/ # Vector DB engine (HNSW, storage)
├── ruvector-graph/ # Graph DB + Cypher parser
├── ruvector-gnn/ # GNN layers, compression, training
├── ruvector-gnn-wasm/ # WebAssembly bindings
└── ruvector-gnn-node/ # Node.js bindings (napi-rs)
├── ruvector-core/ # Vector DB engine (HNSW, storage)
├── ruvector-graph/ # Graph DB + Cypher parser + Hyperedges
├── ruvector-gnn/ # GNN layers, compression, training
├── ruvector-tiny-dancer-core/ # AI agent routing (FastGRNN)
├── ruvector-*-wasm/ # WebAssembly bindings
└── ruvector-*-node/ # Node.js bindings (napi-rs)
```
## Contributing

View file

@ -217,11 +217,13 @@ impl VectorDB {
/// Array of vector IDs
#[wasm_bindgen(js_name = insertBatch)]
pub fn insert_batch(&self, entries: JsValue) -> Result<Vec<String>, JsValue> {
let js_entries: Vec<JsValue> = from_value(entries)
.map_err(|e| JsValue::from_str(&format!("Invalid entries array: {}", e)))?;
// Convert JsValue to Array using reflection
let entries_array: js_sys::Array = entries.dyn_into()
.map_err(|_| JsValue::from_str("entries must be an array"))?;
let mut vector_entries = Vec::new();
for js_entry in js_entries {
for i in 0..entries_array.length() {
let js_entry = entries_array.get(i);
let vector_arr: Float32Array = Reflect::get(&js_entry, &"vector".into())?.dyn_into()?;
let id: Option<String> = Reflect::get(&js_entry, &"id".into())?.as_string();
let metadata = Reflect::get(&js_entry, &"metadata".into()).ok();

View file

@ -0,0 +1,233 @@
# Cypher Query Language Reference
RuVector implements a Neo4j-compatible Cypher query language with extensions for hyperedges.
## Quick Examples
```cypher
-- Create nodes
CREATE (p:Person {name: 'Alice', age: 30})
-- Create relationships
CREATE (a:Person {name: 'Alice'})-[:KNOWS]->(b:Person {name: 'Bob'})
-- Pattern matching
MATCH (p:Person)-[:KNOWS]->(friend)
WHERE p.name = 'Alice'
RETURN friend.name
-- Hyperedges (N-ary relationships)
CREATE (a:Person)-[:ATTENDED]->(meeting:Meeting, room:Room, company:Company)
```
## Supported Clauses
### MATCH
Find patterns in the graph.
```cypher
-- Simple node
MATCH (n:Person)
RETURN n
-- With relationship
MATCH (a:Person)-[:KNOWS]->(b:Person)
RETURN a.name, b.name
-- Variable-length paths
MATCH (a)-[*1..3]->(b)
RETURN a, b
-- Optional matching
OPTIONAL MATCH (p:Person)-[:OWNS]->(c:Car)
RETURN p.name, c.model
```
### CREATE
Create new nodes and relationships.
```cypher
-- Single node
CREATE (n:Person {name: 'Alice'})
-- Multiple labels
CREATE (n:Person:Employee {name: 'Bob'})
-- With relationship
CREATE (a:Person {name: 'Alice'})-[:FRIEND]->(b:Person {name: 'Bob'})
```
### MERGE
Create if not exists, match if exists.
```cypher
MERGE (p:Person {email: 'alice@example.com'})
ON CREATE SET p.created = timestamp()
ON MATCH SET p.lastSeen = timestamp()
```
### SET
Update properties.
```cypher
MATCH (p:Person {name: 'Alice'})
SET p.age = 31, p.updated = timestamp()
```
### DELETE
Remove nodes and relationships.
```cypher
-- Delete node (must have no relationships)
MATCH (p:Person {name: 'Temp'})
DELETE p
-- Delete node and all relationships
MATCH (p:Person {name: 'Temp'})
DETACH DELETE p
```
### RETURN
Project results.
```cypher
MATCH (p:Person)
RETURN p.name AS name, p.age
ORDER BY p.age DESC
SKIP 10
LIMIT 5
```
### WITH
Intermediate projection (query chaining).
```cypher
MATCH (p:Person)
WITH p.name AS name, COUNT(*) AS count
WHERE count > 1
RETURN name, count
```
### WHERE
Filter results.
```cypher
MATCH (p:Person)
WHERE p.age > 21 AND p.city = 'NYC'
RETURN p
-- Pattern predicates
WHERE (p)-[:KNOWS]->(:Expert)
```
## Hyperedges (N-ary Relationships)
RuVector extends Cypher with hyperedge support for N-ary relationships:
```cypher
-- Create hyperedge (3+ nodes)
CREATE (author:Person)-[:WROTE]->(paper:Paper, journal:Journal, year:Year)
-- Match hyperedge
MATCH (a:Person)-[r:ATTENDED]->(meeting, room, company)
RETURN a.name, meeting.topic, room.number
```
## Expressions
### Operators
| Type | Operators |
|------|-----------|
| Arithmetic | `+`, `-`, `*`, `/`, `%`, `^` |
| Comparison | `=`, `<>`, `<`, `>`, `<=`, `>=` |
| Logical | `AND`, `OR`, `NOT`, `XOR` |
| String | `STARTS WITH`, `ENDS WITH`, `CONTAINS` |
| Null | `IS NULL`, `IS NOT NULL` |
| List | `IN`, `[]` (indexing) |
### Functions
```cypher
-- String
RETURN toUpper(name), toLower(name), trim(name), substring(name, 0, 5)
-- Numeric
RETURN abs(x), ceil(x), floor(x), round(x), sqrt(x)
-- Collections
RETURN size(list), head(list), tail(list), range(1, 10)
-- Type
RETURN type(r), labels(n), keys(n)
```
### Aggregations
```cypher
MATCH (p:Person)
RETURN
COUNT(*) AS total,
AVG(p.age) AS avgAge,
MIN(p.age) AS minAge,
MAX(p.age) AS maxAge,
SUM(p.salary) AS totalSalary,
COLLECT(p.name) AS names
```
### CASE Expressions
```cypher
MATCH (p:Person)
RETURN p.name,
CASE
WHEN p.age < 18 THEN 'minor'
WHEN p.age < 65 THEN 'adult'
ELSE 'senior'
END AS category
```
## Data Types
| Type | Example |
|------|---------|
| Integer | `42`, `-17` |
| Float | `3.14`, `-2.5e10` |
| String | `'hello'`, `"world"` |
| Boolean | `true`, `false` |
| Null | `null` |
| List | `[1, 2, 3]`, `['a', 'b']` |
| Map | `{name: 'Alice', age: 30}` |
## Path Variables
```cypher
-- Assign path to variable
MATCH p = (a:Person)-[:KNOWS*]->(b:Person)
RETURN p, length(p)
-- Path functions
RETURN nodes(p), relationships(p), length(p)
```
## Best Practices
1. **Use labels** - Always specify node labels for faster lookups
2. **Index properties** - Create indexes on frequently queried properties
3. **Limit results** - Use `LIMIT` to avoid large result sets
4. **Parameterize** - Use parameters for values to enable query caching
## See Also
- [Getting Started Guide](../guide/GETTING_STARTED.md)
- [Node.js API](./NODEJS_API.md)
- [Rust API](./RUST_API.md)
- [GNN Architecture](../gnn-layer-implementation.md)