ruvector 0.2.25 → 0.2.27
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/bin/cli.js +121 -16
- package/bin/mcp-server.js +94 -22
- package/dist/core/adaptive-embedder.d.ts +9 -0
- package/dist/core/adaptive-embedder.d.ts.map +1 -1
- package/dist/core/adaptive-embedder.js +11 -0
- package/dist/core/intelligence-engine.d.ts +1 -1
- package/dist/core/intelligence-engine.d.ts.map +1 -1
- package/dist/core/intelligence-engine.js +10 -14
- package/dist/core/learning-engine.d.ts +2 -0
- package/dist/core/learning-engine.d.ts.map +1 -1
- package/dist/core/learning-engine.js +23 -3
- package/dist/core/onnx/bundled-parallel.mjs +164 -0
- package/dist/core/onnx/embed-worker.mjs +67 -0
- package/dist/core/onnx/loader.js +434 -0
- package/dist/core/onnx/package.json +3 -0
- package/dist/core/onnx/pkg/LICENSE +21 -0
- package/dist/core/onnx/pkg/loader.js +348 -0
- package/dist/core/onnx/pkg/ruvector.db +0 -0
- package/dist/core/onnx/pkg/ruvector_onnx_embeddings_wasm.d.ts +112 -0
- package/dist/core/onnx/pkg/ruvector_onnx_embeddings_wasm.js +5 -0
- package/dist/core/onnx/pkg/ruvector_onnx_embeddings_wasm_bg.js +638 -0
- package/dist/core/onnx/pkg/ruvector_onnx_embeddings_wasm_bg.wasm +0 -0
- package/dist/core/onnx/pkg/ruvector_onnx_embeddings_wasm_bg.wasm.d.ts +29 -0
- package/dist/core/onnx-embedder.d.ts +39 -2
- package/dist/core/onnx-embedder.d.ts.map +1 -1
- package/dist/core/onnx-embedder.js +139 -20
- package/dist/core/onnx-optimized.d.ts.map +1 -1
- package/dist/core/onnx-optimized.js +6 -24
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -1
- package/package.json +4 -3
|
@@ -43,7 +43,13 @@ export interface SimilarityResult {
|
|
|
43
43
|
timeMs: number;
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
46
|
-
* Check if ONNX embedder is available
|
|
46
|
+
* Check if the ONNX embedder is *available* — i.e. the bundled WASM files are
|
|
47
|
+
* present and the embedder can be initialized.
|
|
48
|
+
*
|
|
49
|
+
* NOTE: This is a capability check, NOT a readiness check. It returns `true`
|
|
50
|
+
* before `initOnnxEmbedder()` has run (so callers can decide whether to init).
|
|
51
|
+
* To check whether the model has actually been loaded, use `isOnnxInitialized()`
|
|
52
|
+
* or `isReady()`. See https://github.com/ruvnet/RuVector/issues/523.
|
|
47
53
|
*/
|
|
48
54
|
export declare function isOnnxAvailable(): boolean;
|
|
49
55
|
/**
|
|
@@ -72,9 +78,22 @@ export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
|
72
78
|
*/
|
|
73
79
|
export declare function getDimension(): number;
|
|
74
80
|
/**
|
|
75
|
-
* Check if embedder is ready
|
|
81
|
+
* Check if the embedder has been initialized (model loaded) and is ready to
|
|
82
|
+
* embed. Returns `false` until `initOnnxEmbedder()` (or the first `embed()`,
|
|
83
|
+
* which auto-initializes) has completed successfully.
|
|
76
84
|
*/
|
|
77
85
|
export declare function isReady(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Whether the ONNX embedder has been initialized (model loaded).
|
|
88
|
+
*
|
|
89
|
+
* Post-init counterpart to `isOnnxAvailable()` (which only checks that the
|
|
90
|
+
* bundled files exist). Named distinctly from the WASM-core `isInitialized()`
|
|
91
|
+
* export to avoid a barrel name collision. Equivalent to `isReady()`; provided
|
|
92
|
+
* as a self-documenting gate so callers can distinguish "bundled" (available)
|
|
93
|
+
* from "loaded" (initialized). See
|
|
94
|
+
* https://github.com/ruvnet/RuVector/issues/523.
|
|
95
|
+
*/
|
|
96
|
+
export declare function isOnnxInitialized(): boolean;
|
|
78
97
|
/**
|
|
79
98
|
* Get embedder stats including SIMD and parallel capabilities
|
|
80
99
|
*/
|
|
@@ -91,6 +110,24 @@ export declare function getStats(): {
|
|
|
91
110
|
* Shutdown parallel workers (call on exit)
|
|
92
111
|
*/
|
|
93
112
|
export declare function shutdown(): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Initialize the bundled-WASM worker pool for high-throughput batch embedding
|
|
115
|
+
* (issue #523 SOTA). Self-contained — uses Node worker_threads + the bundled
|
|
116
|
+
* WASM over SharedArrayBuffer model bytes, no external dependency. Vectors are
|
|
117
|
+
* identical to the single-thread path (cosine-equivalent).
|
|
118
|
+
*
|
|
119
|
+
* @param numWorkers number of worker threads (default: min(cpus-2, 16))
|
|
120
|
+
*/
|
|
121
|
+
export declare function initParallelEmbedder(numWorkers?: number): Promise<boolean>;
|
|
122
|
+
/**
|
|
123
|
+
* Batch-embed via the bundled worker pool, sharded across CPU cores. Lazily
|
|
124
|
+
* starts the pool on first use. Returns embeddings in input order.
|
|
125
|
+
*/
|
|
126
|
+
export declare function embedBatchParallel(texts: string[]): Promise<number[][]>;
|
|
127
|
+
/** Number of active pool workers (0 if the pool isn't started). */
|
|
128
|
+
export declare function getParallelWorkerCount(): number;
|
|
129
|
+
/** Shut down the bundled worker pool and release its threads. */
|
|
130
|
+
export declare function shutdownParallelEmbedder(): Promise<void>;
|
|
94
131
|
export declare class OnnxEmbedder {
|
|
95
132
|
private config;
|
|
96
133
|
constructor(config?: OnnxEmbedderConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onnx-embedder.d.ts","sourceRoot":"","sources":["../../src/core/onnx-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,kBAAkB,EAAE,WAAW,GAAG,SAAS,CAAC;CACjD;AAuBD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAClC,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"onnx-embedder.d.ts","sourceRoot":"","sources":["../../src/core/onnx-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,kBAAkB,EAAE,WAAW,GAAG,SAAS,CAAC;CACjD;AAuBD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAClC,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AA0FD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,kBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuGxF;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAiBlE;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAwC5E;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAaxF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAiBjE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAUA;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAO9C;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBhF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAG7E;AAED,mEAAmE;AACnE,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,iEAAiE;AACjE,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK9D;AAGD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,GAAE,kBAAuB;IAIrC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAIxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAKhD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/D,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;CACF;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -57,8 +57,13 @@ exports.similarity = similarity;
|
|
|
57
57
|
exports.cosineSimilarity = cosineSimilarity;
|
|
58
58
|
exports.getDimension = getDimension;
|
|
59
59
|
exports.isReady = isReady;
|
|
60
|
+
exports.isOnnxInitialized = isOnnxInitialized;
|
|
60
61
|
exports.getStats = getStats;
|
|
61
62
|
exports.shutdown = shutdown;
|
|
63
|
+
exports.initParallelEmbedder = initParallelEmbedder;
|
|
64
|
+
exports.embedBatchParallel = embedBatchParallel;
|
|
65
|
+
exports.getParallelWorkerCount = getParallelWorkerCount;
|
|
66
|
+
exports.shutdownParallelEmbedder = shutdownParallelEmbedder;
|
|
62
67
|
const path = __importStar(require("path"));
|
|
63
68
|
const fs = __importStar(require("fs"));
|
|
64
69
|
const url_1 = require("url");
|
|
@@ -95,10 +100,22 @@ let loadPromise = null;
|
|
|
95
100
|
let isInitialized = false;
|
|
96
101
|
let parallelEnabled = false;
|
|
97
102
|
let parallelThreshold = 4;
|
|
103
|
+
// Captured at init so the bundled worker pool can reuse the loaded model bytes
|
|
104
|
+
// (shared to workers via SharedArrayBuffer) instead of re-downloading per worker.
|
|
105
|
+
let loadedModelBytes = null;
|
|
106
|
+
let loadedTokenizerJson = null;
|
|
107
|
+
let loadedMaxLength = 256;
|
|
108
|
+
let bundledPool = null;
|
|
98
109
|
// Default model
|
|
99
110
|
const DEFAULT_MODEL = 'all-MiniLM-L6-v2';
|
|
100
111
|
/**
|
|
101
|
-
* Check if ONNX embedder is available
|
|
112
|
+
* Check if the ONNX embedder is *available* — i.e. the bundled WASM files are
|
|
113
|
+
* present and the embedder can be initialized.
|
|
114
|
+
*
|
|
115
|
+
* NOTE: This is a capability check, NOT a readiness check. It returns `true`
|
|
116
|
+
* before `initOnnxEmbedder()` has run (so callers can decide whether to init).
|
|
117
|
+
* To check whether the model has actually been loaded, use `isOnnxInitialized()`
|
|
118
|
+
* or `isReady()`. See https://github.com/ruvnet/RuVector/issues/523.
|
|
102
119
|
*/
|
|
103
120
|
function isOnnxAvailable() {
|
|
104
121
|
try {
|
|
@@ -143,7 +160,7 @@ async function tryInitParallel(config) {
|
|
|
143
160
|
// Skip if explicitly disabled
|
|
144
161
|
if (config.enableParallel === false)
|
|
145
162
|
return false;
|
|
146
|
-
//
|
|
163
|
+
// 1) Optional external package (back-compat). Absent by default.
|
|
147
164
|
try {
|
|
148
165
|
const parallelModule = await dynamicImport('ruvector-onnx-embeddings-wasm/parallel');
|
|
149
166
|
const { ParallelEmbedder } = parallelModule;
|
|
@@ -154,15 +171,44 @@ async function tryInitParallel(config) {
|
|
|
154
171
|
parallelThreshold = config.parallelThreshold || 4;
|
|
155
172
|
parallelEnabled = true;
|
|
156
173
|
parallelAvailable = true;
|
|
157
|
-
console.error(`Parallel embedder ready: ${parallelEmbedder.numWorkers} workers, SIMD: ${simdAvailable}`);
|
|
174
|
+
console.error(`Parallel embedder ready (external): ${parallelEmbedder.numWorkers} workers, SIMD: ${simdAvailable}`);
|
|
158
175
|
return true;
|
|
159
176
|
}
|
|
160
|
-
catch
|
|
177
|
+
catch {
|
|
178
|
+
// External package not installed — fall through to the bundled pool.
|
|
179
|
+
}
|
|
180
|
+
// 2) Bundled, zero-dependency worker pool over the already-loaded model bytes.
|
|
181
|
+
// Opt-in only (enableParallel === true) so the default/'auto' path does not
|
|
182
|
+
// silently spawn worker threads for existing callers. Vectors are identical
|
|
183
|
+
// to the single-thread path (issue #523).
|
|
184
|
+
if (config.enableParallel !== true) {
|
|
161
185
|
parallelAvailable = false;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
if (!loadedModelBytes || !loadedTokenizerJson) {
|
|
190
|
+
throw new Error('model bytes unavailable for bundled pool');
|
|
165
191
|
}
|
|
192
|
+
const poolUrl = (0, url_1.pathToFileURL)(path.join(__dirname, 'onnx', 'bundled-parallel.mjs')).href;
|
|
193
|
+
const { ParallelEmbedder } = await dynamicImport(poolUrl);
|
|
194
|
+
const pool = new ParallelEmbedder({
|
|
195
|
+
modelBytes: loadedModelBytes,
|
|
196
|
+
tokenizerJson: loadedTokenizerJson,
|
|
197
|
+
maxLength: loadedMaxLength,
|
|
198
|
+
dimension: embedder ? embedder.dimension() : 384,
|
|
199
|
+
numWorkers: config.numWorkers,
|
|
200
|
+
});
|
|
201
|
+
await pool.init();
|
|
202
|
+
parallelEmbedder = pool;
|
|
203
|
+
parallelThreshold = config.parallelThreshold || 4;
|
|
204
|
+
parallelEnabled = true;
|
|
205
|
+
parallelAvailable = true;
|
|
206
|
+
console.error(`Parallel embedder ready (bundled): ${pool.numWorkers} workers, SIMD: ${simdAvailable}`);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
parallelAvailable = false;
|
|
211
|
+
console.error(`Parallel embedder not available: ${e.message}`);
|
|
166
212
|
return false;
|
|
167
213
|
}
|
|
168
214
|
}
|
|
@@ -181,22 +227,26 @@ async function initOnnxEmbedder(config = {}) {
|
|
|
181
227
|
loadPromise = (async () => {
|
|
182
228
|
try {
|
|
183
229
|
// Paths to bundled ONNX files
|
|
184
|
-
const
|
|
230
|
+
const bgJsPath = path.join(__dirname, 'onnx', 'pkg', 'ruvector_onnx_embeddings_wasm_bg.js');
|
|
231
|
+
const wasmPath = path.join(__dirname, 'onnx', 'pkg', 'ruvector_onnx_embeddings_wasm_bg.wasm');
|
|
185
232
|
const loaderPath = path.join(__dirname, 'onnx', 'loader.js');
|
|
186
|
-
if (!fs.existsSync(
|
|
233
|
+
if (!fs.existsSync(bgJsPath) || !fs.existsSync(wasmPath)) {
|
|
187
234
|
throw new Error('ONNX WASM files not bundled. The onnx/ directory is missing.');
|
|
188
235
|
}
|
|
189
|
-
//
|
|
190
|
-
|
|
236
|
+
// Load the bg.js module directly (avoids the ESM `import * as wasm from "*.wasm"`
|
|
237
|
+
// in the main .js shim which requires --experimental-wasm-modules on Node 18-24).
|
|
238
|
+
const bgUrl = (0, url_1.pathToFileURL)(bgJsPath).href;
|
|
191
239
|
const loaderUrl = (0, url_1.pathToFileURL)(loaderPath).href;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
240
|
+
wasmModule = await dynamicImport(bgUrl);
|
|
241
|
+
// Instantiate the .wasm bytes via WebAssembly API (no --experimental-wasm-modules needed).
|
|
242
|
+
const wasmBytes = fs.readFileSync(wasmPath);
|
|
243
|
+
const wasmResult = await WebAssembly.instantiate(wasmBytes, { './ruvector_onnx_embeddings_wasm_bg.js': wasmModule });
|
|
244
|
+
const wasmExports = wasmResult.instance.exports;
|
|
245
|
+
if (typeof wasmModule.__wbg_set_wasm === 'function') {
|
|
246
|
+
wasmModule.__wbg_set_wasm(wasmExports);
|
|
247
|
+
}
|
|
248
|
+
if (typeof wasmExports.__wbindgen_start === 'function') {
|
|
249
|
+
wasmExports.__wbindgen_start();
|
|
200
250
|
}
|
|
201
251
|
const loaderModule = await dynamicImport(loaderUrl);
|
|
202
252
|
const { ModelLoader } = loaderModule;
|
|
@@ -209,6 +259,10 @@ async function initOnnxEmbedder(config = {}) {
|
|
|
209
259
|
const modelId = config.modelId || DEFAULT_MODEL;
|
|
210
260
|
console.error(`Loading ONNX model: ${modelId}...`);
|
|
211
261
|
const { modelBytes, tokenizerJson, config: modelConfig } = await modelLoader.loadModel(modelId);
|
|
262
|
+
// Retain for the bundled parallel worker pool (see initParallelEmbedder).
|
|
263
|
+
loadedModelBytes = modelBytes;
|
|
264
|
+
loadedTokenizerJson = tokenizerJson;
|
|
265
|
+
loadedMaxLength = config.maxLength || modelConfig.maxLength || 256;
|
|
212
266
|
// Create embedder with config
|
|
213
267
|
const embedderConfig = new wasmModule.WasmEmbedderConfig()
|
|
214
268
|
.setMaxLength(config.maxLength || modelConfig.maxLength || 256)
|
|
@@ -350,11 +404,26 @@ function getDimension() {
|
|
|
350
404
|
return embedder ? embedder.dimension() : 384;
|
|
351
405
|
}
|
|
352
406
|
/**
|
|
353
|
-
* Check if embedder is ready
|
|
407
|
+
* Check if the embedder has been initialized (model loaded) and is ready to
|
|
408
|
+
* embed. Returns `false` until `initOnnxEmbedder()` (or the first `embed()`,
|
|
409
|
+
* which auto-initializes) has completed successfully.
|
|
354
410
|
*/
|
|
355
411
|
function isReady() {
|
|
356
412
|
return isInitialized;
|
|
357
413
|
}
|
|
414
|
+
/**
|
|
415
|
+
* Whether the ONNX embedder has been initialized (model loaded).
|
|
416
|
+
*
|
|
417
|
+
* Post-init counterpart to `isOnnxAvailable()` (which only checks that the
|
|
418
|
+
* bundled files exist). Named distinctly from the WASM-core `isInitialized()`
|
|
419
|
+
* export to avoid a barrel name collision. Equivalent to `isReady()`; provided
|
|
420
|
+
* as a self-documenting gate so callers can distinguish "bundled" (available)
|
|
421
|
+
* from "loaded" (initialized). See
|
|
422
|
+
* https://github.com/ruvnet/RuVector/issues/523.
|
|
423
|
+
*/
|
|
424
|
+
function isOnnxInitialized() {
|
|
425
|
+
return isInitialized;
|
|
426
|
+
}
|
|
358
427
|
/**
|
|
359
428
|
* Get embedder stats including SIMD and parallel capabilities
|
|
360
429
|
*/
|
|
@@ -378,6 +447,56 @@ async function shutdown() {
|
|
|
378
447
|
parallelEmbedder = null;
|
|
379
448
|
parallelEnabled = false;
|
|
380
449
|
}
|
|
450
|
+
await shutdownParallelEmbedder();
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Initialize the bundled-WASM worker pool for high-throughput batch embedding
|
|
454
|
+
* (issue #523 SOTA). Self-contained — uses Node worker_threads + the bundled
|
|
455
|
+
* WASM over SharedArrayBuffer model bytes, no external dependency. Vectors are
|
|
456
|
+
* identical to the single-thread path (cosine-equivalent).
|
|
457
|
+
*
|
|
458
|
+
* @param numWorkers number of worker threads (default: min(cpus-2, 16))
|
|
459
|
+
*/
|
|
460
|
+
async function initParallelEmbedder(numWorkers) {
|
|
461
|
+
if (bundledPool)
|
|
462
|
+
return true;
|
|
463
|
+
if (!isInitialized)
|
|
464
|
+
await initOnnxEmbedder();
|
|
465
|
+
if (!loadedModelBytes || !loadedTokenizerJson) {
|
|
466
|
+
throw new Error('Model bytes unavailable; cannot start parallel embedder.');
|
|
467
|
+
}
|
|
468
|
+
const poolUrl = (0, url_1.pathToFileURL)(path.join(__dirname, 'onnx', 'bundled-parallel.mjs')).href;
|
|
469
|
+
const { ParallelEmbedder } = await dynamicImport(poolUrl);
|
|
470
|
+
const pool = new ParallelEmbedder({
|
|
471
|
+
modelBytes: loadedModelBytes,
|
|
472
|
+
tokenizerJson: loadedTokenizerJson,
|
|
473
|
+
maxLength: loadedMaxLength,
|
|
474
|
+
dimension: getDimension(),
|
|
475
|
+
numWorkers,
|
|
476
|
+
});
|
|
477
|
+
await pool.init();
|
|
478
|
+
bundledPool = pool;
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Batch-embed via the bundled worker pool, sharded across CPU cores. Lazily
|
|
483
|
+
* starts the pool on first use. Returns embeddings in input order.
|
|
484
|
+
*/
|
|
485
|
+
async function embedBatchParallel(texts) {
|
|
486
|
+
if (!bundledPool)
|
|
487
|
+
await initParallelEmbedder();
|
|
488
|
+
return bundledPool.embedBatch(texts);
|
|
489
|
+
}
|
|
490
|
+
/** Number of active pool workers (0 if the pool isn't started). */
|
|
491
|
+
function getParallelWorkerCount() {
|
|
492
|
+
return bundledPool ? bundledPool.numWorkers : 0;
|
|
493
|
+
}
|
|
494
|
+
/** Shut down the bundled worker pool and release its threads. */
|
|
495
|
+
async function shutdownParallelEmbedder() {
|
|
496
|
+
if (bundledPool) {
|
|
497
|
+
await bundledPool.shutdown();
|
|
498
|
+
bundledPool = null;
|
|
499
|
+
}
|
|
381
500
|
}
|
|
382
501
|
// Export class wrapper for compatibility
|
|
383
502
|
class OnnxEmbedder {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onnx-optimized.d.ts","sourceRoot":"","sources":["../../src/core/onnx-optimized.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACpD,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA0HD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAA8B;IAGjD,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,cAAc,CAAwB;IAG9C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,SAAS,CAAO;gBAEZ,MAAM,GAAE,mBAAwB;IAiB5C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAWb,MAAM;
|
|
1
|
+
{"version":3,"file":"onnx-optimized.d.ts","sourceRoot":"","sources":["../../src/core/onnx-optimized.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACpD,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA0HD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAA8B;IAGjD,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,cAAc,CAAwB;IAG9C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,SAAS,CAAO;gBAEZ,MAAM,GAAE,mBAAwB;IAiB5C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAWb,MAAM;IA+DpB;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAiChD;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAmD1D;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/D;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM;IAmB1D;;OAEG;IACH,aAAa,IAAI;QACf,SAAS,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3E,SAAS,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3E,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;KACrB;IASD;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,mBAAmB,CAAC;CAG3C;AAQD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,qBAAqB,CAK5F;AAED,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAIpG;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -213,34 +213,16 @@ class OptimizedOnnxEmbedder {
|
|
|
213
213
|
}
|
|
214
214
|
const loaderModule = await dynamicImport(loaderUrl);
|
|
215
215
|
const { ModelLoader } = loaderModule;
|
|
216
|
-
//
|
|
216
|
+
// NOTE (issue #523): ModelLoader.loadModel() resolves the model by modelId
|
|
217
|
+
// from its own registry (currently FP32 all-MiniLM-L6-v2). The per-variant
|
|
218
|
+
// URLs in QUANTIZED_MODELS are not wired into the loader yet, so we must not
|
|
219
|
+
// log a quantization (FP16/INT8) that is not actually applied. When the
|
|
220
|
+
// loader gains variant support, thread the selected variant through to
|
|
221
|
+
// loadModel() here instead of computing an unused URL.
|
|
217
222
|
const modelInfo = QUANTIZED_MODELS[this.config.modelId];
|
|
218
|
-
let modelUrl;
|
|
219
223
|
if (modelInfo) {
|
|
220
|
-
if (this.config.useQuantized && this.config.quantization !== 'none') {
|
|
221
|
-
// Try quantized version first
|
|
222
|
-
if (this.config.quantization === 'int8' && modelInfo.int8) {
|
|
223
|
-
modelUrl = modelInfo.int8;
|
|
224
|
-
console.error(`Using INT8 quantized model: ${this.config.modelId}`);
|
|
225
|
-
}
|
|
226
|
-
else if (modelInfo.fp16) {
|
|
227
|
-
modelUrl = modelInfo.fp16;
|
|
228
|
-
console.error(`Using FP16 quantized model: ${this.config.modelId}`);
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
modelUrl = modelInfo.onnx;
|
|
232
|
-
console.error(`Using FP32 model (no quantized version): ${this.config.modelId}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
modelUrl = modelInfo.onnx;
|
|
237
|
-
}
|
|
238
224
|
this.dimension = modelInfo.dimension;
|
|
239
225
|
}
|
|
240
|
-
else {
|
|
241
|
-
// Fallback to default loader
|
|
242
|
-
modelUrl = '';
|
|
243
|
-
}
|
|
244
226
|
const modelLoader = new ModelLoader({
|
|
245
227
|
cache: true,
|
|
246
228
|
cacheDir: path.join(process.env.HOME || '/tmp', '.ruvector', 'models'),
|
package/dist/index.d.ts
CHANGED
|
@@ -102,5 +102,59 @@ declare class VectorDBWrapper {
|
|
|
102
102
|
export declare const VectorDb: typeof VectorDBWrapper;
|
|
103
103
|
export declare const VectorDB: typeof VectorDBWrapper;
|
|
104
104
|
export declare const NativeVectorDb: any;
|
|
105
|
+
/** High-level index class compatible with the test-suite API. */
|
|
106
|
+
export declare class VectorIndex {
|
|
107
|
+
private db;
|
|
108
|
+
private _dimension;
|
|
109
|
+
private _storagePath;
|
|
110
|
+
constructor(opts: {
|
|
111
|
+
dimension: number;
|
|
112
|
+
metric?: string;
|
|
113
|
+
indexType?: string;
|
|
114
|
+
});
|
|
115
|
+
insert(entry: {
|
|
116
|
+
id?: string;
|
|
117
|
+
values: number[];
|
|
118
|
+
}): Promise<string>;
|
|
119
|
+
insertBatch(entries: Array<{
|
|
120
|
+
id?: string;
|
|
121
|
+
values: number[];
|
|
122
|
+
}>, _opts?: {
|
|
123
|
+
batchSize?: number;
|
|
124
|
+
progressCallback?: (p: number) => void;
|
|
125
|
+
}): Promise<string[]>;
|
|
126
|
+
search(query: number[], opts: {
|
|
127
|
+
k: number;
|
|
128
|
+
}): Promise<Array<{
|
|
129
|
+
id: string;
|
|
130
|
+
score: number;
|
|
131
|
+
}>>;
|
|
132
|
+
get(id: string): Promise<{
|
|
133
|
+
id: string;
|
|
134
|
+
values: number[];
|
|
135
|
+
} | null>;
|
|
136
|
+
delete(id: string): Promise<boolean>;
|
|
137
|
+
stats(): Promise<{
|
|
138
|
+
vectorCount: number;
|
|
139
|
+
dimension: number;
|
|
140
|
+
}>;
|
|
141
|
+
clear(): Promise<void>;
|
|
142
|
+
optimize(): Promise<void>;
|
|
143
|
+
}
|
|
144
|
+
/** Get backend info (compat with old getBackendInfo() call). */
|
|
145
|
+
export declare function getBackendInfo(): {
|
|
146
|
+
type: 'native' | 'wasm';
|
|
147
|
+
version: string;
|
|
148
|
+
features: string[];
|
|
149
|
+
};
|
|
150
|
+
/** Check native availability (compat alias for isNative()). */
|
|
151
|
+
export declare function isNativeAvailable(): boolean;
|
|
152
|
+
/** Vector utility functions used by tests and downstream packages. */
|
|
153
|
+
export declare const Utils: {
|
|
154
|
+
cosineSimilarity(a: number[], b: number[]): number;
|
|
155
|
+
euclideanDistance(a: number[], b: number[]): number;
|
|
156
|
+
normalize(v: number[]): number[];
|
|
157
|
+
randomVector(dimension: number): number[];
|
|
158
|
+
};
|
|
105
159
|
export default implementation;
|
|
106
160
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,cAAc,SAAS,CAAC;AAGxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAE3B,QAAA,IAAI,cAAc,EAAE,GAAG,CAAC;AA4DxB;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,QAAQ,GAAG,KAAK,GAAG,MAAM,CAEjE;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,OAAO,CAE/B;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAMxE;AA4BD;;GAEG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,EAAE,CAAM;gBAEJ,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,GAAG,CAAA;KAAE;IAe7H;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IActH;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAUtI;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,YAAY,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,CAAC,CAAC;IAuB1N;;OAEG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IAW5G;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1C;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;IAI5B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;CAGlC;AAGD,eAAO,MAAM,QAAQ,wBAAkB,CAAC;AACxC,eAAO,MAAM,QAAQ,wBAAkB,CAAC;AAGxC,eAAO,MAAM,cAAc,KAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -25,12 +25,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
25
25
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
26
26
|
};
|
|
27
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
-
exports.NativeVectorDb = exports.VectorDB = exports.VectorDb = void 0;
|
|
28
|
+
exports.Utils = exports.VectorIndex = exports.NativeVectorDb = exports.VectorDB = exports.VectorDb = void 0;
|
|
29
29
|
exports.getImplementationType = getImplementationType;
|
|
30
30
|
exports.isNative = isNative;
|
|
31
31
|
exports.isRvf = isRvf;
|
|
32
32
|
exports.isWasm = isWasm;
|
|
33
33
|
exports.getVersion = getVersion;
|
|
34
|
+
exports.getBackendInfo = getBackendInfo;
|
|
35
|
+
exports.isNativeAvailable = isNativeAvailable;
|
|
34
36
|
__exportStar(require("./types"), exports);
|
|
35
37
|
// Export core wrappers (safe interfaces with automatic type conversion)
|
|
36
38
|
__exportStar(require("./core"), exports);
|
|
@@ -254,5 +256,104 @@ exports.VectorDb = VectorDBWrapper;
|
|
|
254
256
|
exports.VectorDB = VectorDBWrapper;
|
|
255
257
|
// Also export the raw native implementation for advanced users
|
|
256
258
|
exports.NativeVectorDb = implementation.VectorDb;
|
|
259
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
260
|
+
// Backwards-compat surface used by tests and older integrations
|
|
261
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
262
|
+
/** High-level index class compatible with the test-suite API. */
|
|
263
|
+
class VectorIndex {
|
|
264
|
+
constructor(opts) {
|
|
265
|
+
if (opts.dimension <= 0) {
|
|
266
|
+
throw new Error(`Invalid dimensions: must be positive, got ${opts.dimension}`);
|
|
267
|
+
}
|
|
268
|
+
this._dimension = opts.dimension;
|
|
269
|
+
// Use a unique temp path per instance to avoid cross-instance dimension conflicts
|
|
270
|
+
this._storagePath = require('os').tmpdir() + `/ruvector-idx-${Date.now()}-${Math.random().toString(36).slice(2)}.db`;
|
|
271
|
+
this.db = new VectorDBWrapper({ dimensions: opts.dimension, distanceMetric: opts.metric, storagePath: this._storagePath });
|
|
272
|
+
}
|
|
273
|
+
async insert(entry) {
|
|
274
|
+
return this.db.insert({ id: entry.id, vector: new Float32Array(entry.values) });
|
|
275
|
+
}
|
|
276
|
+
async insertBatch(entries, _opts) {
|
|
277
|
+
const ids = [];
|
|
278
|
+
const batchSize = _opts?.batchSize ?? entries.length;
|
|
279
|
+
for (let i = 0; i < entries.length; i += batchSize) {
|
|
280
|
+
const slice = entries.slice(i, i + batchSize);
|
|
281
|
+
const batch = slice.map(e => ({ id: e.id, vector: new Float32Array(e.values) }));
|
|
282
|
+
const batchIds = await this.db.insertBatch(batch);
|
|
283
|
+
ids.push(...batchIds);
|
|
284
|
+
_opts?.progressCallback?.(Math.min((i + batchSize) / entries.length, 1));
|
|
285
|
+
}
|
|
286
|
+
return ids;
|
|
287
|
+
}
|
|
288
|
+
async search(query, opts) {
|
|
289
|
+
return this.db.search({ vector: new Float32Array(query), k: opts.k });
|
|
290
|
+
}
|
|
291
|
+
async get(id) {
|
|
292
|
+
const r = await this.db.get(id);
|
|
293
|
+
if (!r)
|
|
294
|
+
return null;
|
|
295
|
+
return { id: r.id ?? id, values: Array.from(r.vector) };
|
|
296
|
+
}
|
|
297
|
+
async delete(id) {
|
|
298
|
+
return this.db.delete(id);
|
|
299
|
+
}
|
|
300
|
+
async stats() {
|
|
301
|
+
const count = await this.db.len();
|
|
302
|
+
return { vectorCount: count, dimension: this._dimension };
|
|
303
|
+
}
|
|
304
|
+
async clear() {
|
|
305
|
+
// Create a fresh db at a new temp path to reset state
|
|
306
|
+
const newPath = require('os').tmpdir() + `/ruvector-idx-${Date.now()}-${Math.random().toString(36).slice(2)}.db`;
|
|
307
|
+
this._storagePath = newPath;
|
|
308
|
+
this.db = new VectorDBWrapper({ dimensions: this._dimension, storagePath: newPath });
|
|
309
|
+
}
|
|
310
|
+
async optimize() {
|
|
311
|
+
// No-op: native HNSW self-optimises on insert
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
exports.VectorIndex = VectorIndex;
|
|
315
|
+
/** Get backend info (compat with old getBackendInfo() call). */
|
|
316
|
+
function getBackendInfo() {
|
|
317
|
+
const type = implementationType === 'native' ? 'native' : 'wasm';
|
|
318
|
+
const { version } = getVersion();
|
|
319
|
+
const features = type === 'native'
|
|
320
|
+
? ['SIMD', 'Multi-threading', 'Rust-native']
|
|
321
|
+
: ['Browser-compatible', 'Cross-platform'];
|
|
322
|
+
return { type, version, features };
|
|
323
|
+
}
|
|
324
|
+
/** Check native availability (compat alias for isNative()). */
|
|
325
|
+
function isNativeAvailable() {
|
|
326
|
+
return implementationType === 'native';
|
|
327
|
+
}
|
|
328
|
+
/** Vector utility functions used by tests and downstream packages. */
|
|
329
|
+
exports.Utils = {
|
|
330
|
+
cosineSimilarity(a, b) {
|
|
331
|
+
if (a.length !== b.length)
|
|
332
|
+
throw new Error('Vectors must have same dimension');
|
|
333
|
+
let dot = 0, na = 0, nb = 0;
|
|
334
|
+
for (let i = 0; i < a.length; i++) {
|
|
335
|
+
dot += a[i] * b[i];
|
|
336
|
+
na += a[i] ** 2;
|
|
337
|
+
nb += b[i] ** 2;
|
|
338
|
+
}
|
|
339
|
+
const denom = Math.sqrt(na) * Math.sqrt(nb);
|
|
340
|
+
return denom === 0 ? 0 : dot / denom;
|
|
341
|
+
},
|
|
342
|
+
euclideanDistance(a, b) {
|
|
343
|
+
if (a.length !== b.length)
|
|
344
|
+
throw new Error('Vectors must have same dimension');
|
|
345
|
+
return Math.sqrt(a.reduce((sum, v, i) => sum + (v - b[i]) ** 2, 0));
|
|
346
|
+
},
|
|
347
|
+
normalize(v) {
|
|
348
|
+
const mag = Math.sqrt(v.reduce((s, x) => s + x * x, 0));
|
|
349
|
+
if (mag === 0)
|
|
350
|
+
return v.slice();
|
|
351
|
+
return v.map(x => x / mag);
|
|
352
|
+
},
|
|
353
|
+
randomVector(dimension) {
|
|
354
|
+
const v = Array.from({ length: dimension }, () => Math.random() * 2 - 1);
|
|
355
|
+
return exports.Utils.normalize(v);
|
|
356
|
+
},
|
|
357
|
+
};
|
|
257
358
|
// Export everything from the implementation
|
|
258
359
|
exports.default = implementation;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ruvector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.27",
|
|
4
4
|
"description": "Self-learning vector database for Node.js — hybrid search, Graph RAG, FlashAttention-3, HNSW, 50+ attention mechanisms",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
"ruvector": "./bin/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsc && cp src/core/onnx
|
|
11
|
+
"build": "tsc && mkdir -p dist/core/onnx && cp -r src/core/onnx/. dist/core/onnx/",
|
|
12
12
|
"verify-dist": "node scripts/verify-dist.js",
|
|
13
|
+
"prepack": "npm run build && npm run verify-dist",
|
|
13
14
|
"prepublishOnly": "npm run build && npm run verify-dist",
|
|
14
|
-
"test": "node test/integration.js && node test/cli-commands.js"
|
|
15
|
+
"test": "node test/integration.js && node test/cli-commands.js && node test/sigterm-cleanup.js"
|
|
15
16
|
},
|
|
16
17
|
"keywords": [
|
|
17
18
|
"vector",
|