@wiscale/velesdb-sdk 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +480 -185
- package/dist/index.d.mts +367 -40
- package/dist/index.d.ts +367 -40
- package/dist/index.js +1283 -456
- package/dist/index.mjs +1281 -456
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
# @wiscale/velesdb-sdk
|
|
2
2
|
|
|
3
|
-
Official TypeScript SDK for VelesDB -
|
|
3
|
+
Official TypeScript SDK for [VelesDB](https://github.com/cyberlife-coder/VelesDB) -- the local-first vector database for AI and RAG. Sub-millisecond semantic search in Browser and Node.js.
|
|
4
|
+
|
|
5
|
+
**v1.6.0** | Node.js >= 18 | Browser (WASM) | MIT License
|
|
6
|
+
|
|
7
|
+
## What's New in v1.6.0
|
|
8
|
+
|
|
9
|
+
- **Agent Memory API** -- semantic, episodic, and procedural memory for AI agents (REST only)
|
|
10
|
+
- **Graph collections** -- dedicated `createGraphCollection()` for knowledge graphs (REST only)
|
|
11
|
+
- **Metadata-only collections** -- reference tables with no vectors, joinable via VelesQL
|
|
12
|
+
- **Sparse vector support** -- hybrid sparse+dense search on insert and query (REST + WASM)
|
|
13
|
+
- **Stream insert with backpressure** -- `streamInsert()` for high-throughput ingestion (REST only)
|
|
14
|
+
- **Product Quantization training** -- `trainPq()` for further memory compression (REST only)
|
|
15
|
+
- **Collection analytics** -- `analyzeCollection()`, `getCollectionStats()`, `getCollectionConfig()` (REST only)
|
|
16
|
+
- **Property indexes** -- `createIndex()` / `listIndexes()` / `dropIndex()` for O(1) lookups (REST only)
|
|
17
|
+
- **Query introspection** -- `queryExplain()` and `collectionSanity()` diagnostics (REST only)
|
|
18
|
+
- **Batch search** -- `searchBatch()` for parallel multi-query execution
|
|
19
|
+
- **Lightweight search** -- `searchIds()` returns only IDs and scores (REST only)
|
|
4
20
|
|
|
5
21
|
## Installation
|
|
6
22
|
|
|
@@ -10,65 +26,73 @@ npm install @wiscale/velesdb-sdk
|
|
|
10
26
|
|
|
11
27
|
## Quick Start
|
|
12
28
|
|
|
13
|
-
### WASM Backend (Browser/Node.js)
|
|
29
|
+
### WASM Backend (Browser / Node.js)
|
|
30
|
+
|
|
31
|
+
The WASM backend runs entirely in-process -- no server required. Ideal for browser apps, prototyping, and edge deployments.
|
|
14
32
|
|
|
15
33
|
```typescript
|
|
16
34
|
import { VelesDB } from '@wiscale/velesdb-sdk';
|
|
17
35
|
|
|
18
|
-
//
|
|
36
|
+
// 1. Create a client with WASM backend
|
|
19
37
|
const db = new VelesDB({ backend: 'wasm' });
|
|
20
38
|
await db.init();
|
|
21
39
|
|
|
22
|
-
// Create a collection
|
|
40
|
+
// 2. Create a collection (768 dimensions for BERT, 1536 for OpenAI, etc.)
|
|
23
41
|
await db.createCollection('documents', {
|
|
24
|
-
dimension: 768,
|
|
42
|
+
dimension: 768,
|
|
25
43
|
metric: 'cosine'
|
|
26
44
|
});
|
|
27
45
|
|
|
28
|
-
// Insert vectors
|
|
46
|
+
// 3. Insert vectors with metadata
|
|
29
47
|
await db.insert('documents', {
|
|
30
48
|
id: 'doc-1',
|
|
31
49
|
vector: new Float32Array(768).fill(0.1),
|
|
32
50
|
payload: { title: 'Hello World', category: 'greeting' }
|
|
33
51
|
});
|
|
34
52
|
|
|
35
|
-
// Batch insert
|
|
53
|
+
// 4. Batch insert for better throughput
|
|
36
54
|
await db.insertBatch('documents', [
|
|
37
|
-
{ id: 'doc-2', vector:
|
|
38
|
-
{ id: 'doc-3', vector:
|
|
55
|
+
{ id: 'doc-2', vector: new Float32Array(768).fill(0.2), payload: { title: 'Second doc' } },
|
|
56
|
+
{ id: 'doc-3', vector: new Float32Array(768).fill(0.3), payload: { title: 'Third doc' } },
|
|
39
57
|
]);
|
|
40
58
|
|
|
41
|
-
// Search
|
|
59
|
+
// 5. Search for similar vectors
|
|
42
60
|
const results = await db.search('documents', queryVector, { k: 5 });
|
|
43
61
|
console.log(results);
|
|
44
|
-
// [{ id: 'doc-1', score: 0.95, payload: { title: '
|
|
62
|
+
// [{ id: 'doc-1', score: 0.95, payload: { title: 'Hello World', ... } }, ...]
|
|
45
63
|
|
|
46
|
-
// Cleanup
|
|
64
|
+
// 6. Cleanup
|
|
47
65
|
await db.close();
|
|
48
66
|
```
|
|
49
67
|
|
|
50
68
|
### REST Backend (Server)
|
|
51
69
|
|
|
70
|
+
The REST backend connects to a running VelesDB server. Use this for production deployments, multi-client access, and persistent storage.
|
|
71
|
+
|
|
52
72
|
```typescript
|
|
53
73
|
import { VelesDB } from '@wiscale/velesdb-sdk';
|
|
54
74
|
|
|
55
75
|
const db = new VelesDB({
|
|
56
76
|
backend: 'rest',
|
|
57
77
|
url: 'http://localhost:8080',
|
|
58
|
-
apiKey: 'your-api-key'
|
|
78
|
+
apiKey: 'your-api-key' // optional
|
|
59
79
|
});
|
|
60
80
|
|
|
61
81
|
await db.init();
|
|
62
82
|
|
|
63
83
|
// Same API as WASM backend
|
|
64
84
|
await db.createCollection('products', { dimension: 1536 });
|
|
65
|
-
await db.insert('products', { id:
|
|
66
|
-
const results = await db.search('products',
|
|
85
|
+
await db.insert('products', { id: 1, vector: embedding });
|
|
86
|
+
const results = await db.search('products', queryVector, { k: 10 });
|
|
67
87
|
```
|
|
68
88
|
|
|
89
|
+
> **REST backend note:** Document IDs must be numeric integers in the range `0..Number.MAX_SAFE_INTEGER`. String IDs are only supported with the WASM backend.
|
|
90
|
+
|
|
69
91
|
## API Reference
|
|
70
92
|
|
|
71
|
-
###
|
|
93
|
+
### Client
|
|
94
|
+
|
|
95
|
+
#### `new VelesDB(config)`
|
|
72
96
|
|
|
73
97
|
Create a new VelesDB client.
|
|
74
98
|
|
|
@@ -77,346 +101,617 @@ Create a new VelesDB client.
|
|
|
77
101
|
| `backend` | `'wasm' \| 'rest'` | Yes | Backend type |
|
|
78
102
|
| `url` | `string` | REST only | Server URL |
|
|
79
103
|
| `apiKey` | `string` | No | API key for authentication |
|
|
80
|
-
| `timeout` | `number` | No | Request timeout
|
|
104
|
+
| `timeout` | `number` | No | Request timeout in ms (default: 30000) |
|
|
105
|
+
|
|
106
|
+
#### `db.init()`
|
|
107
|
+
|
|
108
|
+
Initialize the client. **Must be called before any operations.** For the REST backend, this verifies connectivity to the server.
|
|
109
|
+
|
|
110
|
+
#### `db.close()`
|
|
111
|
+
|
|
112
|
+
Close the client and release resources.
|
|
81
113
|
|
|
82
|
-
|
|
114
|
+
---
|
|
83
115
|
|
|
84
|
-
|
|
116
|
+
### Collection Management
|
|
85
117
|
|
|
86
|
-
|
|
118
|
+
#### `db.createCollection(name, config)`
|
|
87
119
|
|
|
88
|
-
Create a
|
|
120
|
+
Create a vector collection.
|
|
89
121
|
|
|
90
122
|
| Option | Type | Default | Description |
|
|
91
123
|
|--------|------|---------|-------------|
|
|
92
124
|
| `dimension` | `number` | Required | Vector dimension |
|
|
93
125
|
| `metric` | `'cosine' \| 'euclidean' \| 'dot' \| 'hamming' \| 'jaccard'` | `'cosine'` | Distance metric |
|
|
94
|
-
| `storageMode` | `'full' \| 'sq8' \| 'binary'` | `'full'` |
|
|
126
|
+
| `storageMode` | `'full' \| 'sq8' \| 'binary'` | `'full'` | Quantization mode |
|
|
127
|
+
| `hnsw` | `{ m?: number, efConstruction?: number }` | - | HNSW index tuning |
|
|
128
|
+
| `description` | `string` | - | Optional description |
|
|
95
129
|
|
|
96
|
-
|
|
130
|
+
##### Storage Modes
|
|
97
131
|
|
|
98
132
|
| Mode | Memory (768D) | Compression | Use Case |
|
|
99
133
|
|------|---------------|-------------|----------|
|
|
100
134
|
| `full` | 3 KB/vector | 1x | Default, max precision |
|
|
101
|
-
| `sq8` | 776 B/vector | **4x** |
|
|
102
|
-
| `binary` | 96 B/vector | **32x** | Edge, IoT |
|
|
135
|
+
| `sq8` | 776 B/vector | **4x** | Production scale, RAM-constrained |
|
|
136
|
+
| `binary` | 96 B/vector | **32x** | Edge devices, IoT |
|
|
103
137
|
|
|
104
138
|
```typescript
|
|
105
|
-
// Memory-optimized collection
|
|
106
139
|
await db.createCollection('embeddings', {
|
|
107
140
|
dimension: 768,
|
|
108
141
|
metric: 'cosine',
|
|
109
|
-
storageMode: 'sq8'
|
|
142
|
+
storageMode: 'sq8',
|
|
143
|
+
hnsw: { m: 16, efConstruction: 200 }
|
|
110
144
|
});
|
|
111
145
|
```
|
|
112
146
|
|
|
113
|
-
|
|
147
|
+
#### `db.createGraphCollection(name, config?)`
|
|
148
|
+
|
|
149
|
+
Create a dedicated graph collection for knowledge graph workloads.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
await db.createGraphCollection('social', {
|
|
153
|
+
dimension: 384, // optional: embed nodes for vector+graph queries
|
|
154
|
+
metric: 'cosine',
|
|
155
|
+
schemaMode: 'schemaless' // or 'strict'
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `db.createMetadataCollection(name)`
|
|
160
|
+
|
|
161
|
+
Create a metadata-only collection (no vectors). Useful for reference tables that can be JOINed with vector collections via VelesQL.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
await db.createMetadataCollection('products');
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### `db.deleteCollection(name)`
|
|
114
168
|
|
|
115
|
-
|
|
169
|
+
Delete a collection and all its data.
|
|
170
|
+
|
|
171
|
+
#### `db.getCollection(name)`
|
|
172
|
+
|
|
173
|
+
Get collection info. Returns `null` if not found.
|
|
174
|
+
|
|
175
|
+
#### `db.listCollections()`
|
|
176
|
+
|
|
177
|
+
List all collections. Returns an array of `Collection` objects.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### Insert and Retrieve
|
|
182
|
+
|
|
183
|
+
#### `db.insert(collection, document)`
|
|
184
|
+
|
|
185
|
+
Insert a single vector document.
|
|
116
186
|
|
|
117
187
|
```typescript
|
|
118
188
|
await db.insert('docs', {
|
|
119
189
|
id: 'unique-id',
|
|
120
|
-
vector: [0.1, 0.2,
|
|
121
|
-
payload: { key: 'value' }
|
|
190
|
+
vector: [0.1, 0.2, 0.3], // number[] or Float32Array
|
|
191
|
+
payload: { key: 'value' }, // optional metadata
|
|
192
|
+
sparseVector: { 42: 0.8, 99: 0.3 } // optional sparse vector for hybrid search
|
|
122
193
|
});
|
|
123
194
|
```
|
|
124
195
|
|
|
125
|
-
|
|
196
|
+
#### `db.insertBatch(collection, documents)`
|
|
197
|
+
|
|
198
|
+
Insert multiple vectors in a single call. More efficient than repeated `insert()`.
|
|
126
199
|
|
|
127
|
-
|
|
200
|
+
```typescript
|
|
201
|
+
await db.insertBatch('docs', [
|
|
202
|
+
{ id: 'a', vector: vecA, payload: { title: 'First' } },
|
|
203
|
+
{ id: 'b', vector: vecB, payload: { title: 'Second' } },
|
|
204
|
+
]);
|
|
205
|
+
```
|
|
128
206
|
|
|
129
|
-
|
|
207
|
+
#### `db.streamInsert(collection, documents)`
|
|
130
208
|
|
|
131
|
-
|
|
209
|
+
Insert documents with server backpressure support. Sends documents sequentially, respecting 429 rate limits. Throws `BackpressureError` if the server pushes back.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
await db.streamInsert('docs', largeDocumentArray);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### `db.get(collection, id)`
|
|
216
|
+
|
|
217
|
+
Get a document by ID. Returns `null` if not found.
|
|
218
|
+
|
|
219
|
+
#### `db.delete(collection, id)`
|
|
220
|
+
|
|
221
|
+
Delete a document by ID. Returns `true` if deleted, `false` if not found.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Search
|
|
226
|
+
|
|
227
|
+
#### `db.search(collection, query, options?)`
|
|
228
|
+
|
|
229
|
+
Vector similarity search.
|
|
132
230
|
|
|
133
231
|
| Option | Type | Default | Description |
|
|
134
232
|
|--------|------|---------|-------------|
|
|
135
233
|
| `k` | `number` | `10` | Number of results |
|
|
136
|
-
| `filter` | `object` | - |
|
|
234
|
+
| `filter` | `object` | - | Payload filter expression |
|
|
137
235
|
| `includeVectors` | `boolean` | `false` | Include vectors in results |
|
|
236
|
+
| `sparseVector` | `Record<number, number>` | - | Sparse vector for hybrid sparse+dense search |
|
|
138
237
|
|
|
139
|
-
|
|
238
|
+
```typescript
|
|
239
|
+
const results = await db.search('docs', queryVector, {
|
|
240
|
+
k: 10,
|
|
241
|
+
filter: { category: 'tech' },
|
|
242
|
+
includeVectors: true
|
|
243
|
+
});
|
|
244
|
+
// Returns: SearchResult[] = [{ id, score, payload?, vector? }, ...]
|
|
245
|
+
```
|
|
140
246
|
|
|
141
|
-
|
|
247
|
+
#### `db.searchBatch(collection, searches)`
|
|
142
248
|
|
|
143
|
-
|
|
249
|
+
Execute multiple search queries in parallel.
|
|
144
250
|
|
|
145
|
-
|
|
251
|
+
```typescript
|
|
252
|
+
const batchResults = await db.searchBatch('docs', [
|
|
253
|
+
{ vector: queryA, k: 5 },
|
|
254
|
+
{ vector: queryB, k: 10, filter: { type: 'article' } },
|
|
255
|
+
]);
|
|
256
|
+
// Returns: SearchResult[][] (one result array per query)
|
|
257
|
+
```
|
|
146
258
|
|
|
147
|
-
|
|
259
|
+
#### `db.searchIds(collection, query, options?)`
|
|
148
260
|
|
|
149
|
-
|
|
261
|
+
Lightweight search returning only IDs and scores (no payloads).
|
|
150
262
|
|
|
151
263
|
```typescript
|
|
152
|
-
const
|
|
264
|
+
const hits = await db.searchIds('docs', queryVector, { k: 100 });
|
|
265
|
+
// Returns: Array<{ id: number, score: number }>
|
|
153
266
|
```
|
|
154
267
|
|
|
155
|
-
|
|
268
|
+
#### `db.textSearch(collection, query, options?)`
|
|
156
269
|
|
|
157
|
-
|
|
270
|
+
Full-text search using BM25 scoring.
|
|
158
271
|
|
|
159
272
|
```typescript
|
|
160
|
-
const results = await db.
|
|
161
|
-
'docs',
|
|
162
|
-
queryVector,
|
|
163
|
-
'machine learning',
|
|
164
|
-
{ k: 10, vectorWeight: 0.7 } // 0.7 = 70% vector, 30% text
|
|
165
|
-
);
|
|
273
|
+
const results = await db.textSearch('docs', 'machine learning', { k: 10 });
|
|
166
274
|
```
|
|
167
275
|
|
|
168
|
-
|
|
276
|
+
#### `db.hybridSearch(collection, vector, textQuery, options?)`
|
|
169
277
|
|
|
170
|
-
|
|
278
|
+
Combined vector similarity + BM25 text search with RRF fusion.
|
|
171
279
|
|
|
172
280
|
```typescript
|
|
173
|
-
|
|
174
|
-
const results = await db.query(
|
|
175
|
-
'documents',
|
|
176
|
-
"SELECT * FROM documents WHERE category = 'tech' LIMIT 10"
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
// With vector parameter
|
|
180
|
-
const results = await db.query(
|
|
181
|
-
'documents',
|
|
182
|
-
"SELECT * FROM documents WHERE VECTOR NEAR $query LIMIT 5",
|
|
183
|
-
{ query: [0.1, 0.2, ...] }
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
// Hybrid query
|
|
187
|
-
const results = await db.query(
|
|
281
|
+
const results = await db.hybridSearch(
|
|
188
282
|
'docs',
|
|
189
|
-
|
|
190
|
-
|
|
283
|
+
queryVector,
|
|
284
|
+
'machine learning',
|
|
285
|
+
{ k: 10, vectorWeight: 0.7 } // 70% vector, 30% text
|
|
191
286
|
);
|
|
192
287
|
```
|
|
193
288
|
|
|
194
|
-
|
|
289
|
+
#### `db.multiQuerySearch(collection, vectors, options?)`
|
|
195
290
|
|
|
196
|
-
Multi-query fusion search for RAG pipelines using Multiple Query Generation (MQG).
|
|
291
|
+
Multi-query fusion search for RAG pipelines using Multiple Query Generation (MQG). Combines results from several query vectors into a single ranked list.
|
|
197
292
|
|
|
198
293
|
| Option | Type | Default | Description |
|
|
199
294
|
|--------|------|---------|-------------|
|
|
200
295
|
| `k` | `number` | `10` | Number of results |
|
|
201
296
|
| `fusion` | `'rrf' \| 'average' \| 'maximum' \| 'weighted'` | `'rrf'` | Fusion strategy |
|
|
202
297
|
| `fusionParams` | `object` | `{ k: 60 }` | Strategy-specific parameters |
|
|
203
|
-
| `filter` | `object` | - |
|
|
298
|
+
| `filter` | `object` | - | Payload filter expression |
|
|
204
299
|
|
|
205
300
|
```typescript
|
|
206
|
-
// RRF fusion (default)
|
|
301
|
+
// RRF fusion (default) -- best for most RAG use cases
|
|
207
302
|
const results = await db.multiQuerySearch('docs', [emb1, emb2, emb3], {
|
|
208
303
|
k: 10,
|
|
209
304
|
fusion: 'rrf',
|
|
210
305
|
fusionParams: { k: 60 }
|
|
211
306
|
});
|
|
212
307
|
|
|
213
|
-
// Weighted fusion
|
|
308
|
+
// Weighted fusion
|
|
214
309
|
const results = await db.multiQuerySearch('docs', [emb1, emb2], {
|
|
215
310
|
k: 10,
|
|
216
311
|
fusion: 'weighted',
|
|
217
312
|
fusionParams: { avgWeight: 0.6, maxWeight: 0.3, hitWeight: 0.1 }
|
|
218
313
|
});
|
|
314
|
+
```
|
|
219
315
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
316
|
+
> **Note:** WASM supports `rrf`, `average`, `maximum`. The `weighted` strategy is REST-only.
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
### Collection Utilities
|
|
321
|
+
|
|
322
|
+
#### `db.isEmpty(collection)`
|
|
323
|
+
|
|
324
|
+
Returns `true` if the collection contains no vectors.
|
|
325
|
+
|
|
326
|
+
#### `db.flush(collection)`
|
|
327
|
+
|
|
328
|
+
Flush pending changes to disk. **REST backend only** -- the WASM backend runs in-memory and this is a no-op.
|
|
329
|
+
|
|
330
|
+
#### `db.analyzeCollection(collection)`
|
|
331
|
+
|
|
332
|
+
Compute and return collection statistics.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
const stats = await db.analyzeCollection('docs');
|
|
336
|
+
console.log(stats.totalPoints, stats.totalSizeBytes);
|
|
225
337
|
```
|
|
226
338
|
|
|
227
|
-
|
|
339
|
+
#### `db.getCollectionStats(collection)`
|
|
340
|
+
|
|
341
|
+
Get previously computed statistics. Returns `null` if the collection has not been analyzed yet.
|
|
228
342
|
|
|
229
|
-
|
|
343
|
+
#### `db.getCollectionConfig(collection)`
|
|
230
344
|
|
|
231
|
-
|
|
345
|
+
Get detailed collection configuration (dimension, metric, storage mode, point count, schema).
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
### VelesQL Queries
|
|
350
|
+
|
|
351
|
+
#### `db.query(collection, queryString, params?, options?)`
|
|
352
|
+
|
|
353
|
+
Execute a VelesQL query. Supports SELECT, WHERE, vector NEAR, GROUP BY, HAVING, ORDER BY, JOIN, UNION/INTERSECT/EXCEPT, and USING FUSION.
|
|
232
354
|
|
|
233
355
|
```typescript
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
356
|
+
// Vector similarity search
|
|
357
|
+
const result = await db.query(
|
|
358
|
+
'documents',
|
|
359
|
+
'SELECT * FROM documents WHERE VECTOR NEAR $query LIMIT 5',
|
|
360
|
+
{ query: [0.1, 0.2, 0.3] }
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
// Aggregation
|
|
364
|
+
const agg = await db.query(
|
|
365
|
+
'products',
|
|
366
|
+
`SELECT category, COUNT(*), AVG(price)
|
|
367
|
+
FROM products
|
|
368
|
+
GROUP BY category
|
|
369
|
+
HAVING COUNT(*) > 5`
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// Hybrid vector + text
|
|
373
|
+
const hybrid = await db.query(
|
|
374
|
+
'docs',
|
|
375
|
+
"SELECT * FROM docs WHERE VECTOR NEAR $v AND content MATCH 'rust' LIMIT 10",
|
|
376
|
+
{ v: queryVector }
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
// Cross-collection JOIN
|
|
380
|
+
const joined = await db.query(
|
|
381
|
+
'orders',
|
|
382
|
+
`SELECT * FROM orders
|
|
383
|
+
JOIN customers AS c ON orders.customer_id = c.id
|
|
384
|
+
WHERE status = $status`,
|
|
385
|
+
{ status: 'active' }
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
// Set operations
|
|
389
|
+
const combined = await db.query('users',
|
|
390
|
+
'SELECT * FROM active_users UNION SELECT * FROM archived_users'
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// Fusion strategy
|
|
394
|
+
const fused = await db.query('docs',
|
|
395
|
+
"SELECT * FROM docs USING FUSION(strategy = 'rrf', k = 60) LIMIT 20"
|
|
396
|
+
);
|
|
238
397
|
```
|
|
239
398
|
|
|
240
|
-
|
|
399
|
+
Query options:
|
|
400
|
+
|
|
401
|
+
| Option | Type | Default | Description |
|
|
402
|
+
|--------|------|---------|-------------|
|
|
403
|
+
| `timeoutMs` | `number` | `30000` | Query timeout in milliseconds |
|
|
404
|
+
| `stream` | `boolean` | `false` | Enable streaming response |
|
|
405
|
+
|
|
406
|
+
#### `db.queryExplain(queryString, params?)`
|
|
241
407
|
|
|
242
|
-
|
|
408
|
+
Get the execution plan for a VelesQL query without running it. Returns plan steps, estimated cost, index usage, and detected features.
|
|
243
409
|
|
|
244
410
|
```typescript
|
|
245
|
-
await db.
|
|
411
|
+
const plan = await db.queryExplain(
|
|
412
|
+
'SELECT * FROM docs WHERE VECTOR NEAR $v LIMIT 10',
|
|
413
|
+
{ v: queryVector }
|
|
414
|
+
);
|
|
415
|
+
console.log(plan.plan); // step-by-step execution plan
|
|
416
|
+
console.log(plan.estimatedCost); // { usesIndex, selectivity, complexity }
|
|
417
|
+
console.log(plan.features); // { hasVectorSearch, hasFilter, hasJoin, ... }
|
|
246
418
|
```
|
|
247
419
|
|
|
248
|
-
|
|
420
|
+
#### `db.collectionSanity(collection)`
|
|
249
421
|
|
|
250
|
-
|
|
422
|
+
Run diagnostic checks on a collection (dimensions, search readiness, error counts, hints).
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
const report = await db.collectionSanity('docs');
|
|
426
|
+
console.log(report.checks); // { hasVectors, searchReady, dimensionConfigured }
|
|
427
|
+
console.log(report.diagnostics); // { searchRequestsTotal, dimensionMismatchTotal, ... }
|
|
428
|
+
console.log(report.hints); // actionable suggestions
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
### VelesQL Query Builder
|
|
434
|
+
|
|
435
|
+
Build type-safe VelesQL queries with a fluent API instead of raw strings.
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
import { velesql } from '@wiscale/velesdb-sdk';
|
|
439
|
+
|
|
440
|
+
// Vector similarity with filters
|
|
441
|
+
const builder = velesql()
|
|
442
|
+
.match('d', 'Document')
|
|
443
|
+
.nearVector('$queryVector', queryVector)
|
|
444
|
+
.andWhere('d.category = $cat', { cat: 'tech' })
|
|
445
|
+
.orderBy('similarity()', 'DESC')
|
|
446
|
+
.limit(10);
|
|
251
447
|
|
|
252
|
-
|
|
448
|
+
const queryString = builder.toVelesQL();
|
|
449
|
+
const params = builder.getParams();
|
|
450
|
+
const results = await db.query('documents', queryString, params);
|
|
253
451
|
|
|
254
|
-
|
|
452
|
+
// Graph traversal with relationships
|
|
453
|
+
const graphQuery = velesql()
|
|
454
|
+
.match('p', 'Person')
|
|
455
|
+
.rel('KNOWS')
|
|
456
|
+
.to('f', 'Person')
|
|
457
|
+
.where('p.age > 25')
|
|
458
|
+
.return(['p.name', 'f.name'])
|
|
459
|
+
.toVelesQL();
|
|
460
|
+
// => "MATCH (p:Person)-[:KNOWS]->(f:Person) WHERE p.age > 25 RETURN p.name, f.name"
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Builder methods: `match()`, `rel()`, `to()`, `where()`, `andWhere()`, `orWhere()`, `nearVector()`, `limit()`, `offset()`, `orderBy()`, `return()`, `returnAll()`, `fusion()`.
|
|
464
|
+
|
|
465
|
+
---
|
|
255
466
|
|
|
256
|
-
###
|
|
467
|
+
### Knowledge Graph API
|
|
468
|
+
|
|
469
|
+
#### `db.addEdge(collection, edge)`
|
|
470
|
+
|
|
471
|
+
Add a directed edge between two nodes.
|
|
257
472
|
|
|
258
473
|
```typescript
|
|
259
474
|
await db.addEdge('social', {
|
|
260
|
-
id: 1,
|
|
475
|
+
id: 1,
|
|
476
|
+
source: 100,
|
|
477
|
+
target: 200,
|
|
261
478
|
label: 'FOLLOWS',
|
|
262
479
|
properties: { since: '2024-01-01' }
|
|
263
480
|
});
|
|
264
481
|
```
|
|
265
482
|
|
|
266
|
-
|
|
483
|
+
#### `db.getEdges(collection, options?)`
|
|
484
|
+
|
|
485
|
+
Query edges, optionally filtered by label.
|
|
267
486
|
|
|
268
487
|
```typescript
|
|
269
488
|
const edges = await db.getEdges('social', { label: 'FOLLOWS' });
|
|
270
489
|
```
|
|
271
490
|
|
|
272
|
-
|
|
491
|
+
#### `db.traverseGraph(collection, request)`
|
|
492
|
+
|
|
493
|
+
Traverse the graph using BFS or DFS from a source node.
|
|
273
494
|
|
|
274
495
|
```typescript
|
|
275
496
|
const result = await db.traverseGraph('social', {
|
|
276
|
-
source: 100,
|
|
497
|
+
source: 100,
|
|
498
|
+
strategy: 'bfs',
|
|
499
|
+
maxDepth: 3,
|
|
500
|
+
limit: 100,
|
|
501
|
+
relTypes: ['FOLLOWS', 'KNOWS']
|
|
277
502
|
});
|
|
503
|
+
|
|
504
|
+
for (const node of result.results) {
|
|
505
|
+
console.log(`Node ${node.targetId} at depth ${node.depth}`);
|
|
506
|
+
}
|
|
278
507
|
```
|
|
279
508
|
|
|
280
|
-
|
|
509
|
+
#### `db.getNodeDegree(collection, nodeId)`
|
|
510
|
+
|
|
511
|
+
Get the in-degree and out-degree of a node.
|
|
281
512
|
|
|
282
513
|
```typescript
|
|
283
514
|
const degree = await db.getNodeDegree('social', 100);
|
|
515
|
+
console.log(`In: ${degree.inDegree}, Out: ${degree.outDegree}`);
|
|
284
516
|
```
|
|
285
517
|
|
|
286
|
-
|
|
518
|
+
---
|
|
287
519
|
|
|
288
|
-
|
|
520
|
+
### Property Indexes
|
|
289
521
|
|
|
290
|
-
|
|
522
|
+
Create secondary indexes for fast lookups on payload fields.
|
|
291
523
|
|
|
292
|
-
|
|
293
|
-
// Group by with aggregates
|
|
294
|
-
const result = await db.query('products', `
|
|
295
|
-
SELECT category, COUNT(*), AVG(price)
|
|
296
|
-
FROM products
|
|
297
|
-
GROUP BY category
|
|
298
|
-
HAVING COUNT(*) > 5 AND AVG(price) > 50
|
|
299
|
-
`);
|
|
524
|
+
#### `db.createIndex(collection, options)`
|
|
300
525
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
526
|
+
```typescript
|
|
527
|
+
// Hash index for O(1) equality lookups
|
|
528
|
+
await db.createIndex('users', { label: 'Person', property: 'email' });
|
|
529
|
+
|
|
530
|
+
// Range index for O(log n) range queries
|
|
531
|
+
await db.createIndex('events', {
|
|
532
|
+
label: 'Event',
|
|
533
|
+
property: 'timestamp',
|
|
534
|
+
indexType: 'range'
|
|
535
|
+
});
|
|
305
536
|
```
|
|
306
537
|
|
|
307
|
-
|
|
538
|
+
#### `db.listIndexes(collection)`
|
|
308
539
|
|
|
309
540
|
```typescript
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
SELECT * FROM docs
|
|
313
|
-
ORDER BY similarity(vector, $v) DESC
|
|
314
|
-
LIMIT 10
|
|
315
|
-
`, { v: queryVector });
|
|
541
|
+
const indexes = await db.listIndexes('users');
|
|
542
|
+
// [{ label, property, indexType, cardinality, memoryBytes }, ...]
|
|
316
543
|
```
|
|
317
544
|
|
|
318
|
-
|
|
545
|
+
#### `db.hasIndex(collection, label, property)`
|
|
546
|
+
|
|
547
|
+
Returns `true` if the specified index exists.
|
|
548
|
+
|
|
549
|
+
#### `db.dropIndex(collection, label, property)`
|
|
550
|
+
|
|
551
|
+
Drop an index. Returns `true` if the index existed and was removed.
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
555
|
+
### Product Quantization
|
|
556
|
+
|
|
557
|
+
#### `db.trainPq(collection, options?)`
|
|
558
|
+
|
|
559
|
+
Train Product Quantization on a collection for further memory compression beyond SQ8. **REST backend only** -- delegates to velesdb-server; not available in the WASM backend.
|
|
319
560
|
|
|
320
561
|
```typescript
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
`, { status: 'active' });
|
|
562
|
+
const result = await db.trainPq('embeddings', {
|
|
563
|
+
m: 8, // number of subquantizers
|
|
564
|
+
k: 256, // centroids per subquantizer
|
|
565
|
+
opq: true // enable Optimized PQ
|
|
566
|
+
});
|
|
327
567
|
```
|
|
328
568
|
|
|
329
|
-
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
### Agent Memory API
|
|
572
|
+
|
|
573
|
+
The Agent Memory API provides three memory types for AI agents, built on top of VelesDB's vector and graph storage.
|
|
330
574
|
|
|
331
575
|
```typescript
|
|
332
|
-
|
|
333
|
-
const result = await db.query('users', `
|
|
334
|
-
SELECT * FROM active_users
|
|
335
|
-
UNION
|
|
336
|
-
SELECT * FROM archived_users
|
|
337
|
-
`);
|
|
576
|
+
import { VelesDB } from '@wiscale/velesdb-sdk';
|
|
338
577
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
SELECT id FROM active_users
|
|
344
|
-
`);
|
|
578
|
+
const db = new VelesDB({ backend: 'rest', url: 'http://localhost:8080' });
|
|
579
|
+
await db.init();
|
|
580
|
+
|
|
581
|
+
const memory = db.agentMemory({ dimension: 384 });
|
|
345
582
|
```
|
|
346
583
|
|
|
347
|
-
|
|
584
|
+
#### Semantic Memory (facts and knowledge)
|
|
348
585
|
|
|
349
586
|
```typescript
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
587
|
+
// Store a fact
|
|
588
|
+
await memory.storeFact('knowledge', {
|
|
589
|
+
id: 1,
|
|
590
|
+
text: 'VelesDB uses HNSW for vector indexing',
|
|
591
|
+
embedding: factEmbedding,
|
|
592
|
+
metadata: { source: 'docs', confidence: 0.95 }
|
|
593
|
+
});
|
|
356
594
|
|
|
357
|
-
//
|
|
358
|
-
const
|
|
359
|
-
SELECT * FROM docs
|
|
360
|
-
USING FUSION(strategy = 'weighted', vector_weight = 0.7, graph_weight = 0.3)
|
|
361
|
-
LIMIT 20
|
|
362
|
-
`);
|
|
595
|
+
// Recall similar facts
|
|
596
|
+
const facts = await memory.searchFacts('knowledge', queryEmbedding, 5);
|
|
363
597
|
```
|
|
364
598
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
Build type-safe VelesQL queries with the fluent builder API.
|
|
599
|
+
#### Episodic Memory (events and experiences)
|
|
368
600
|
|
|
369
601
|
```typescript
|
|
370
|
-
|
|
602
|
+
// Record an event
|
|
603
|
+
await memory.recordEvent('events', {
|
|
604
|
+
eventType: 'user_query',
|
|
605
|
+
data: { query: 'How does HNSW work?', response: '...' },
|
|
606
|
+
embedding: eventEmbedding,
|
|
607
|
+
metadata: { timestamp: Date.now() }
|
|
608
|
+
});
|
|
371
609
|
|
|
372
|
-
//
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
.nearVector('$queryVector', queryVector)
|
|
376
|
-
.andWhere('d.category = $cat', { cat: 'tech' })
|
|
377
|
-
.limit(10);
|
|
610
|
+
// Recall similar events
|
|
611
|
+
const events = await memory.recallEvents('events', queryEmbedding, 5);
|
|
612
|
+
```
|
|
378
613
|
|
|
379
|
-
|
|
380
|
-
const params = builder.getParams();
|
|
381
|
-
const results = await db.query('documents', queryString, params);
|
|
614
|
+
#### Procedural Memory (learned patterns)
|
|
382
615
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
.
|
|
389
|
-
|
|
390
|
-
|
|
616
|
+
```typescript
|
|
617
|
+
// Store a procedure
|
|
618
|
+
await memory.learnProcedure('procedures', {
|
|
619
|
+
name: 'deploy-to-prod',
|
|
620
|
+
steps: ['Run tests', 'Build artifacts', 'Push to registry', 'Deploy'],
|
|
621
|
+
metadata: { lastUsed: Date.now() }
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
// Find matching procedures
|
|
625
|
+
const procs = await memory.recallProcedures('procedures', queryEmbedding, 3);
|
|
391
626
|
```
|
|
392
627
|
|
|
628
|
+
---
|
|
629
|
+
|
|
393
630
|
## Error Handling
|
|
394
631
|
|
|
632
|
+
All error classes extend `VelesDBError` and include a `code` property for programmatic handling.
|
|
633
|
+
|
|
395
634
|
```typescript
|
|
396
|
-
import {
|
|
635
|
+
import {
|
|
636
|
+
VelesDBError,
|
|
637
|
+
ValidationError,
|
|
638
|
+
ConnectionError,
|
|
639
|
+
NotFoundError,
|
|
640
|
+
BackpressureError
|
|
641
|
+
} from '@wiscale/velesdb-sdk';
|
|
397
642
|
|
|
398
643
|
try {
|
|
399
|
-
await db.search('nonexistent',
|
|
644
|
+
await db.search('nonexistent', queryVector);
|
|
400
645
|
} catch (error) {
|
|
401
646
|
if (error instanceof NotFoundError) {
|
|
402
647
|
console.log('Collection not found');
|
|
403
648
|
} else if (error instanceof ValidationError) {
|
|
404
649
|
console.log('Invalid input:', error.message);
|
|
405
650
|
} else if (error instanceof ConnectionError) {
|
|
406
|
-
console.log('
|
|
651
|
+
console.log('Server unreachable:', error.message);
|
|
652
|
+
} else if (error instanceof BackpressureError) {
|
|
653
|
+
console.log('Server overloaded, retry later');
|
|
407
654
|
}
|
|
408
655
|
}
|
|
409
656
|
```
|
|
410
657
|
|
|
658
|
+
## Exports
|
|
659
|
+
|
|
660
|
+
Everything is importable from the package root:
|
|
661
|
+
|
|
662
|
+
```typescript
|
|
663
|
+
import {
|
|
664
|
+
// Client
|
|
665
|
+
VelesDB,
|
|
666
|
+
AgentMemoryClient,
|
|
667
|
+
|
|
668
|
+
// Backends (advanced: use VelesDB client instead)
|
|
669
|
+
WasmBackend,
|
|
670
|
+
RestBackend,
|
|
671
|
+
|
|
672
|
+
// Query builder
|
|
673
|
+
VelesQLBuilder,
|
|
674
|
+
velesql,
|
|
675
|
+
|
|
676
|
+
// Error classes
|
|
677
|
+
VelesDBError,
|
|
678
|
+
ValidationError,
|
|
679
|
+
ConnectionError,
|
|
680
|
+
NotFoundError,
|
|
681
|
+
BackpressureError,
|
|
682
|
+
|
|
683
|
+
// Types (selected)
|
|
684
|
+
type VelesDBConfig,
|
|
685
|
+
type CollectionConfig,
|
|
686
|
+
type VectorDocument,
|
|
687
|
+
type SearchOptions,
|
|
688
|
+
type SearchResult,
|
|
689
|
+
type SparseVector,
|
|
690
|
+
type MultiQuerySearchOptions,
|
|
691
|
+
type GraphEdge,
|
|
692
|
+
type AddEdgeRequest,
|
|
693
|
+
type TraverseRequest,
|
|
694
|
+
type TraverseResponse,
|
|
695
|
+
type QueryApiResponse,
|
|
696
|
+
type AgentMemoryConfig,
|
|
697
|
+
type SemanticEntry,
|
|
698
|
+
type EpisodicEvent,
|
|
699
|
+
type ProceduralPattern,
|
|
700
|
+
} from '@wiscale/velesdb-sdk';
|
|
701
|
+
```
|
|
702
|
+
|
|
411
703
|
## Performance Tips
|
|
412
704
|
|
|
413
|
-
1. **Use
|
|
414
|
-
2. **Reuse Float32Array
|
|
415
|
-
3. **Use WASM backend** for browser apps (
|
|
416
|
-
4. **
|
|
705
|
+
1. **Use `insertBatch()`** instead of repeated `insert()` calls
|
|
706
|
+
2. **Reuse `Float32Array`** buffers for query vectors when possible
|
|
707
|
+
3. **Use WASM backend** for browser apps (zero network latency)
|
|
708
|
+
4. **Use `searchIds()`** when you only need IDs and scores (skips payload transfer)
|
|
709
|
+
5. **Use `streamInsert()`** for high-throughput ingestion with backpressure handling
|
|
710
|
+
6. **Pre-initialize** the client at app startup (`await db.init()`)
|
|
711
|
+
7. **Tune HNSW** with `hnsw: { m: 16, efConstruction: 200 }` for higher recall
|
|
417
712
|
|
|
418
713
|
## License
|
|
419
714
|
|
|
420
|
-
MIT License
|
|
715
|
+
MIT License -- See [LICENSE](./LICENSE) for details.
|
|
421
716
|
|
|
422
|
-
VelesDB Core
|
|
717
|
+
VelesDB Core and Server are licensed under VelesDB Core License 1.0 (source-available).
|