cuvs-node
v0.0.1
Published
Node.js bindings for NVIDIA cuVS - GPU-accelerated vector search and clustering
Maintainers
Readme
cuvs-node
Node.js bindings for NVIDIA cuVS - GPU-accelerated vector search and clustering.
Build, search, and serialize high-performance vector indexes directly from Node.js using NVIDIA GPUs.
Getting Started
You need a Linux machine with an NVIDIA GPU (A100, H100, or similar) and CUDA 12.x drivers. Cloud GPU instances from RunPod, Lambda, or similar providers work.
Step 1: Install Node.js
ARCH=$(uname -m)
if [ "$ARCH" = "aarch64" ]; then
NODE_ARCH="arm64"
else
NODE_ARCH="x64"
fi
curl -fsSL https://nodejs.org/dist/v20.19.0/node-v20.19.0-linux-${NODE_ARCH}.tar.xz | tar -xJ -C /usr/local --strip-components=1 2>/dev/null || \
curl -fsSL https://nodejs.org/dist/v20.19.0/node-v20.19.0-linux-${NODE_ARCH}.tar.xz | sudo tar -xJ -C /usr/local --strip-components=1
npm install -g node-gyp 2>/dev/null || sudo npm install -g node-gypStep 2: Clone this repo
cd /workspace
git clone https://github.com/638Labs/cuvs-node.git
cd cuvs-nodeStep 3: Run setup
chmod +x scripts/*.sh
./scripts/setup.shThis installs conda, cuVS, builds the native addon, and runs the full test suite. Takes about 15-20 minutes on a fresh instance. On a previously configured instance, it skips what is already installed and goes straight to build and verify.
When it finishes, you should see:
=================================
Status: ALL TESTS PASSEDIf you see that, everything is working.
Step 4: Development
Setup is complete. To start working on the code, activate the environment:
source ~/miniforge3/etc/profile.d/conda.sh
conda activate cuvs-dev
export LD_LIBRARY_PATH="$CONDA_PREFIX/lib:$LD_LIBRARY_PATH"Edit code, then build and test:
npm run build
./scripts/verify.shWhen ready to commit, deactivate conda first (conda conflicts with git's SSH):
conda deactivate && conda deactivate
unset LD_LIBRARY_PATH
git add -A && git commit -m "your message" && git pushActivate the environment before running any examples (see Step 4).
Quick Example
This example builds a GPU-accelerated nearest neighbor index from 10,000 random vectors with 128 dimensions, searches it with 3 query vectors to find the 10 closest matches for each, then saves and reloads the index from disk.
See examples/basic.js for a runnable example. Run it with:
node examples/basic.jsRebuilding and Re-verifying
After making code changes:
npm run build
./scripts/verify.shAPI
Resources
Wraps GPU handles, CUDA streams, and memory pools. Create one per process, reuse across operations, dispose when done.
new Resources()- allocate cuVS resources on the default GPU.resources.dispose()- free the underlying handles. Idempotent.
CagraIndex
GPU-accelerated approximate nearest neighbor index using the CAGRA (Cuda Anns GRAph) algorithm. Graph-based; best general-purpose ANN on GPU.
CagraIndex.build(resources, dataset, { rows, cols })- build an index from aFloat32Arrayofrows * colsvalues laid out row-major. Returns aCagraIndex.index.search(resources, queries, { rows, cols, k })- search the index with aFloat32Arrayof query vectors. Returns{ indices: Uint32Array, distances: Float32Array }, each of lengthrows * k. Results are sorted ascending by distance per query.index.serialize(resources, path)- write the index to disk.CagraIndex.deserialize(resources, path)- load a previously serialized index. Returns aCagraIndex.index.toHnsw(resources)- convert this CAGRA graph to anHnswIndexfor CPU-side search. Returns anHnswIndex.
IvfFlatIndex
Inverted-file index with flat (uncompressed) lists. Fast to build, exact distances within probed lists, higher memory than IVF-PQ.
IvfFlatIndex.build(resources, dataset, { rows, cols })- build an index from aFloat32Arrayofrows * colsvalues laid out row-major. Returns anIvfFlatIndex.index.search(resources, queries, { rows, cols, k })- search the index with aFloat32Arrayof query vectors. Returns{ indices: Uint32Array, distances: Float32Array }, each of lengthrows * k. Results are sorted ascending by distance per query.index.serialize(resources, path)- write the index to disk.IvfFlatIndex.deserialize(resources, path)- load a previously serialized index. Returns anIvfFlatIndex.
IvfPqIndex
Inverted-file index with product quantization. Lower memory than IVF-Flat, approximate distances via PQ codes, good for very large datasets.
IvfPqIndex.build(resources, dataset, { rows, cols })- build an index from aFloat32Arrayofrows * colsvalues laid out row-major. Returns anIvfPqIndex.index.search(resources, queries, { rows, cols, k })- search the index with aFloat32Arrayof query vectors. Returns{ indices: Uint32Array, distances: Float32Array }, each of lengthrows * k. Results are sorted ascending by distance per query.index.serialize(resources, path)- write the index to disk.IvfPqIndex.deserialize(resources, path)- load a previously serialized index. Returns anIvfPqIndex.
BruteForceIndex
Exact nearest neighbor search via brute-force pairwise distance. Ground-truth baseline and the right choice for small datasets.
BruteForceIndex.build(resources, dataset, { rows, cols })- build an index from aFloat32Arrayofrows * colsvalues laid out row-major. Returns aBruteForceIndex.index.search(resources, queries, { rows, cols, k })- search the index with aFloat32Arrayof query vectors. Returns{ indices: Uint32Array, distances: Float32Array }, each of lengthrows * k. Results are sorted ascending by distance per query.index.serialize(resources, path)- write the index to disk.BruteForceIndex.deserialize(resources, path)- load a previously serialized index. Returns aBruteForceIndex.
HnswIndex
CPU-side HNSW graph, produced by converting a GPU-built CagraIndex. Build on GPU for speed, serve on CPU for cheap deployment.
HnswIndexinstances are created viacagraIndex.toHnsw(resources)orHnswIndex.deserialize(resources, path); there is no standalonebuildmethod.index.search(resources, queries, { rows, cols, k })- search the index with aFloat32Arrayof query vectors. Returns{ indices: Uint32Array, distances: Float32Array }, each of lengthrows * k. Results are sorted ascending by distance per query.index.serialize(resources, path)- write the index to disk.HnswIndex.deserialize(resources, path)- load a previously serialized index. Returns anHnswIndex.
Important: Git and Conda
Conda modifies library paths that can break git's SSH. Always deactivate conda before git operations:
conda deactivate && conda deactivate
unset LD_LIBRARY_PATH
git add -A && git commit -m "your message" && git pushThen reactivate when you need to build or test again:
source ~/miniforge3/etc/profile.d/conda.sh
conda activate cuvs-dev
export LD_LIBRARY_PATH="$CONDA_PREFIX/lib:$LD_LIBRARY_PATH"License
Apache-2.0
