Skip to content

Commit b7ecf25

Browse files
committed
Expose Vamana build and serialize through a public cuvs-java API
cuVS provides a GPU Vamana builder and DiskANN-compatible serialization, and the generated Panama bindings for it already exist in cuvs-java, but there is no public API, so nothing can call Vamana from Java. This adds VamanaIndex and VamanaIndexParams beside CagraIndex. Scope is build and serialize only, matching the native surface. cuVS exposes no Vamana search entry point, so neither does this. serialize takes a Path prefix rather than an OutputStream, because one native call writes two files, the graph at the prefix and the dataset at prefix + ".data". VamanaIndexParams.Builder mirrors the native RAFT_EXPECTS checks so an invalid configuration fails in Java with a readable message instead of inside a GPU kernel. The native index may retain a non-owning device view of the dataset, so the index holds a reference to keep it alive and closes it only when it created the matrix from a float[][]. newVamanaIndexBuilder is added to CuVSProvider as a default method rather than an abstract one so that providers written against an earlier version of the interface keep compiling.
1 parent 29735e8 commit b7ecf25

9 files changed

Lines changed: 1296 additions & 1 deletion

File tree

fern/pages/neighbors/vamana.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Vamana works well when you want to build large DiskANN-compatible graph indexes
1010

1111
[C API](/api-reference/c-api-neighbors-vamana) | [C++ API](/api-reference/cpp-api-neighbors-vamana) | [Python API](/api-reference/python-api-neighbors-vamana) | [Rust API](/api-reference/rust-api-cuvs-neighbors-vamana)
1212

13-
Vamana currently supports build and serialize operations in NVIDIA cuVS. Search is performed by loading the serialized index with DiskANN. Java and Go do not currently expose standalone Vamana bindings.
13+
Vamana currently supports build and serialize operations in NVIDIA cuVS. Search is performed by loading the serialized index with DiskANN. Java exposes build and serialize through `VamanaIndex`; Go does not currently expose standalone Vamana bindings.
1414

1515
### Building an index
1616

@@ -82,6 +82,30 @@ index_params = vamana.IndexParams(
8282
index = vamana.build(index_params, dataset)
8383
```
8484

85+
</Tab>
86+
<Tab title="Java">
87+
88+
```java
89+
import com.nvidia.cuvs.*;
90+
91+
float[][] dataset = loadData();
92+
93+
try (CuVSResources resources = CuVSResources.create()) {
94+
VamanaIndexParams indexParams = new VamanaIndexParams.Builder()
95+
.withGraphDegree(64)
96+
.withVisitedSize(128)
97+
.withQueueSize(255)
98+
.build();
99+
100+
try (VamanaIndex index = VamanaIndex.newBuilder(resources)
101+
.withDataset(dataset)
102+
.withIndexParams(indexParams)
103+
.build()) {
104+
// ...
105+
}
106+
}
107+
```
108+
85109
</Tab>
86110
<Tab title="Rust">
87111

@@ -164,6 +188,23 @@ index = vamana.build(vamana.IndexParams(), dataset)
164188
vamana.save("/tmp/cuvs-vamana/index", index, include_dataset=True)
165189
```
166190

191+
</Tab>
192+
<Tab title="Java">
193+
194+
```java
195+
import com.nvidia.cuvs.*;
196+
import java.nio.file.Path;
197+
198+
try (CuVSResources resources = CuVSResources.create();
199+
VamanaIndex index = VamanaIndex.newBuilder(resources)
200+
.withDataset(loadData())
201+
.build()) {
202+
203+
// Writes DiskANN-compatible files using this path prefix.
204+
index.serialize(Path.of("/tmp/cuvs-vamana/index"), true);
205+
}
206+
```
207+
167208
</Tab>
168209
<Tab title="Rust">
169210

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package com.nvidia.cuvs;
6+
7+
import com.nvidia.cuvs.spi.CuVSProvider;
8+
import java.nio.file.Path;
9+
import java.util.Objects;
10+
11+
/**
12+
* {@link VamanaIndex} encapsulates a Vamana index, along with methods to build
13+
* it on the GPU and serialize it in the DiskANN file format.
14+
* <p>
15+
* Vamana is the graph construction algorithm behind DiskANN. cuVS currently
16+
* provides build and serialize only. There is no Vamana search API, so a
17+
* serialized index is searched by loading it with DiskANN.
18+
*
19+
* @since 26.10
20+
*/
21+
public interface VamanaIndex extends AutoCloseable {
22+
23+
@Override
24+
void close() throws Exception;
25+
26+
/**
27+
* Gets the dimensionality of the vectors in this index.
28+
*
29+
* @return the number of dimensions
30+
*/
31+
int getDimensions() throws Throwable;
32+
33+
/**
34+
* Serializes the index in the DiskANN file format, including the dataset.
35+
* <p>
36+
* This writes <b>two</b> files, {@code filePrefix} holding the graph and
37+
* {@code filePrefix + ".data"} holding the dataset.
38+
*
39+
* @param filePrefix the prefix that output file names are derived from
40+
*/
41+
default void serialize(Path filePrefix) throws Throwable {
42+
serialize(filePrefix, true);
43+
}
44+
45+
/**
46+
* Serializes the index in the DiskANN file format.
47+
* <p>
48+
* When {@code includeDataset} is true this writes {@code filePrefix} holding
49+
* the graph and {@code filePrefix + ".data"} holding the dataset. When it is
50+
* false only {@code filePrefix} is written.
51+
* <p>
52+
* The argument is a prefix and not a complete file name, matching the native
53+
* {@code file_prefix} parameter.
54+
*
55+
* @param filePrefix the prefix that output file names are derived from
56+
* @param includeDataset whether to write the dataset alongside the graph
57+
*/
58+
void serialize(Path filePrefix, boolean includeDataset) throws Throwable;
59+
60+
/**
61+
* Gets an instance of {@link CuVSResources}
62+
*
63+
* @return an instance of {@link CuVSResources}
64+
*/
65+
CuVSResources getCuVSResources();
66+
67+
/**
68+
* Creates a new Builder with an instance of {@link CuVSResources}.
69+
*
70+
* @param cuvsResources an instance of {@link CuVSResources}
71+
* @throws UnsupportedOperationException if the provider does not support cuvs
72+
*/
73+
static Builder newBuilder(CuVSResources cuvsResources) {
74+
Objects.requireNonNull(cuvsResources);
75+
return CuVSProvider.provider().newVamanaIndexBuilder(cuvsResources);
76+
}
77+
78+
/**
79+
* Builder helps configure and create an instance of {@link VamanaIndex}.
80+
*/
81+
interface Builder {
82+
83+
/**
84+
* Sets the dataset for building the {@link VamanaIndex}.
85+
*
86+
* @param vectors a two-dimensional float array
87+
* @return an instance of this Builder
88+
*/
89+
Builder withDataset(float[][] vectors);
90+
91+
/**
92+
* Sets the dataset for building the {@link VamanaIndex}.
93+
* <p>
94+
* The native builder accepts {@code float}, {@code half}, {@code uint8},
95+
* and {@code int8} datasets. Of those, {@link CuVSMatrix.DataType#FLOAT},
96+
* {@link CuVSMatrix.DataType#HALF}, and {@link CuVSMatrix.DataType#BYTE}
97+
* are reachable from Java today, where {@code BYTE} is unsigned.
98+
* {@code int8} has no corresponding {@code DataType}.
99+
* <p>
100+
* The native index may retain a non-owning device view of the dataset
101+
* rather than copying it, so the caller must keep this matrix open for at
102+
* least as long as the index and close it afterwards. A dataset supplied as
103+
* a {@code float[][]} is created and closed by the index instead.
104+
*
105+
* @param dataset a {@link CuVSMatrix} object containing the vectors
106+
* @return an instance of this Builder
107+
*/
108+
Builder withDataset(CuVSMatrix dataset);
109+
110+
/**
111+
* Registers an instance of configured {@link VamanaIndexParams} with this
112+
* Builder.
113+
*
114+
* @param vamanaIndexParameters An instance of VamanaIndexParams
115+
* @return An instance of this Builder
116+
*/
117+
Builder withIndexParams(VamanaIndexParams vamanaIndexParameters);
118+
119+
/**
120+
* Builds and returns an instance of {@link VamanaIndex}.
121+
*
122+
* @return an instance of {@link VamanaIndex}
123+
*/
124+
VamanaIndex build() throws Throwable;
125+
}
126+
}

0 commit comments

Comments
 (0)