Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# Upgrading from 4.0.x to 4.1.x

## On-disk format version 7
- Version 7 of the on-disk graph format adds one feature, inline int8 vectors (`FeatureId.INLINE_BYTE_VECTORS`):
each node's byte vector stored inline, one byte per dimension. Apart from that feature, a version 7 file has
the version 6 layout.
- JVector 4.0.x reads formats up to 6 and rejects version 7 files. `OnDiskGraphIndex.CURRENT_VERSION`,
the default for `OnDiskGraphIndexWriter.Builder` and for `CompressedVectors.write(out)`, is now 7.
- To keep a rollback to 4.0.x possible, pass the version explicitly until every reader runs 4.1:
`withVersion(6)` on graph writer builders and `write(out, 6)` for compressors and compressed vectors.
A version 6 writer rejects `INLINE_BYTE_VECTORS`.
- `OnDiskGraphIndexCompactor` always writes `CURRENT_VERSION`; it has no option to write an older version.

# Upgrading from 3.0.x to 4.0.x

## New features
Expand Down
3 changes: 2 additions & 1 deletion docs/release notes/4.1.0/709.feature.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ try (var builder = GraphIndexBuilder.builder(vectors, ByteVectorSimilarityFuncti
* Zero vectors are not supported with `COSINE` (the result is undefined); do not index them.
* Existing float32 callers keep working: `RandomAccessVectorValues.getVector` keeps its `VectorFloat<?>`
signature and `GraphIndexBuilder.build(RandomAccessVectorValues)` is retained as a forwarding overload.
* Int8 indexes require on-disk format version 6 or later.
* Int8 indexes require on-disk format version 7 or later. JVector 4.0.x reads formats up to 6 and rejects
version 7 files; a version 6 writer rejects `INLINE_BYTE_VECTORS`.
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ public int commonHeaderSize() {
public void writeHeaderFeatures(IndexWriter out, Map<FeatureId,? extends Feature> features) throws IOException {
// we restrict pre-version-3 writers to INLINE_VECTORS features, so we don't need additional version-handling here
for (Feature writer : features.values()) {
writer.writeHeader(out);
writer.writeHeader(out, getVersion());
}
}

Expand Down Expand Up @@ -415,7 +415,7 @@ public OnDiskGraphIndex loadOnDiskIndex(RandomAccessReader reader, Header header
*/
protected static Set<FeatureId> allFeatures() {
return EnumSet.of(FeatureId.INLINE_VECTORS, FeatureId.FUSED_PQ, FeatureId.NVQ_VECTORS,
FeatureId.SEPARATED_VECTORS, FeatureId.SEPARATED_NVQ, FeatureId.INLINE_BYTE_VECTORS);
FeatureId.SEPARATED_VECTORS, FeatureId.SEPARATED_NVQ);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public class GraphIndexFormatFactory {
3, new GraphIndexFormatV3(),
4, new GraphIndexFormatV4(),
5, new GraphIndexFormatV5(),
6, new GraphIndexFormatV6()
6, new GraphIndexFormatV6(),
7, new GraphIndexFormatV7()
);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.IntFunction;
import java.util.stream.Collectors;

Expand All @@ -44,7 +45,12 @@ class GraphIndexFormatV6 extends GraphIndexFormatV5 {

/** Creates the singleton format for version 6. */
GraphIndexFormatV6() {
super(6, allFeatures());
this(6, allFeatures());
}

/** Allows later feature extensions to reuse the V6 record and hierarchy layout. */
protected GraphIndexFormatV6(int version, Set<FeatureId> supportedFeatures) {
super(version, supportedFeatures);
}

/** Places fused features last so non-fused inline features occupy a contiguous prefix. */
Expand Down Expand Up @@ -112,7 +118,7 @@ public void writeHeaderFeatures(IndexWriter out, Map<FeatureId,? extends Feature
for (var featureId : features.keySet()) {
out.writeInt(featureId.ordinal());
Feature feature = features.get(featureId);
feature.writeHeader(out);
feature.writeHeader(out, getVersion());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright DataStax, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.github.jbellis.jvector.graph.disk;

import io.github.jbellis.jvector.graph.disk.feature.FeatureId;

import java.util.EnumSet;
import java.util.Set;

/**
* Version 7 adds inline int8 vectors while retaining the V6 graph record layout.
* Each node record carries its byte vector inline, one byte per dimension.
*/
final class GraphIndexFormatV7 extends GraphIndexFormatV6 {
GraphIndexFormatV7() {
super(7, supportedFeatures());
}

/** The extension is restricted to V7; earlier formats retain their feature sets. */
private static Set<FeatureId> supportedFeatures() {
var features = EnumSet.copyOf(allFeatures());
features.add(FeatureId.INLINE_BYTE_VECTORS);
return features;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
public class OnDiskGraphIndex implements ImmutableGraphIndex, AutoCloseable, Accountable
{
private static final Logger logger = LoggerFactory.getLogger(OnDiskGraphIndex.class);
public static final int CURRENT_VERSION = 6;
public static final int CURRENT_VERSION = 7;
static final int MAGIC = 0xFFFF0D61; // FFFF to distinguish from old graphs, which should never start with a negative size "ODGI"
static final VectorTypeSupport vectorTypeSupport = VectorizationProvider.getInstance().getVectorTypeSupport();
final ReaderSupplier readerSupplier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,27 @@ default boolean isFused() {

int featureSize();

/**
* Writes this feature's header at {@link io.github.jbellis.jvector.graph.disk.OnDiskGraphIndex#CURRENT_VERSION}.
*
* @deprecated a header embedded in a graph must be written at the graph's version; use
* {@link #writeHeader(IndexWriter, int)}
*/
@Deprecated
void writeHeader(IndexWriter out) throws IOException;

/**
* Writes this feature's header for a graph written at {@code version}. Features that serialize a
* compressor write it at this version, so a graph written at an older version is laid out as that
* version wrote it. The default ignores the version, for headers that don't depend on it.
*
* @param out the output to write to
* @param version the on-disk format version of the graph being written
*/
default void writeHeader(IndexWriter out, int version) throws IOException {
writeHeader(out);
}

default void writeInline(IndexWriter out, State state) throws IOException {
// default no-op
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,15 @@ public QuantizationCompactionStrategy createCompactionStrategy(CompactionContext
return new FusedCompactionStrategy(ctx, this, retrainer);
}

@Deprecated
@Override
public void writeHeader(IndexWriter out) throws IOException {
pq.write(out, OnDiskGraphIndex.CURRENT_VERSION);
writeHeader(out, OnDiskGraphIndex.CURRENT_VERSION);
}

@Override
public void writeHeader(IndexWriter out, int version) throws IOException {
pq.write(out, version);
}

// this is an awkward fit for the Feature.State design since we need to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.github.jbellis.jvector.disk.IndexWriter;
import io.github.jbellis.jvector.disk.RandomAccessReader;
import io.github.jbellis.jvector.graph.disk.CommonHeader;
import io.github.jbellis.jvector.graph.disk.OnDiskGraphIndex;
import io.github.jbellis.jvector.vector.VectorizationProvider;
import io.github.jbellis.jvector.vector.types.ByteSequence;
import io.github.jbellis.jvector.vector.types.VectorTypeSupport;
Expand Down Expand Up @@ -72,8 +73,14 @@ static InlineByteVectors load(CommonHeader header, RandomAccessReader reader) {
return new InlineByteVectors(header.dimension);
}

@Deprecated
@Override
public void writeHeader(IndexWriter out) {
writeHeader(out, OnDiskGraphIndex.CURRENT_VERSION);
}

@Override
public void writeHeader(IndexWriter out, int version) {
// common header carries dimension; nothing extra needed
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.github.jbellis.jvector.disk.IndexWriter;
import io.github.jbellis.jvector.disk.RandomAccessReader;
import io.github.jbellis.jvector.graph.disk.CommonHeader;
import io.github.jbellis.jvector.graph.disk.OnDiskGraphIndex;
import io.github.jbellis.jvector.vector.VectorizationProvider;
import io.github.jbellis.jvector.vector.types.VectorFloat;
import io.github.jbellis.jvector.vector.types.VectorTypeSupport;
Expand Down Expand Up @@ -58,8 +59,14 @@ static InlineVectors load(CommonHeader header, RandomAccessReader reader) {
return new InlineVectors(header.dimension);
}

@Deprecated
@Override
public void writeHeader(IndexWriter out) {
writeHeader(out, OnDiskGraphIndex.CURRENT_VERSION);
}

@Override
public void writeHeader(IndexWriter out, int version) {
// common header contains dimension, which is sufficient
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,15 @@ static NVQ load(CommonHeader header, RandomAccessReader reader) {
}
}

@Deprecated
@Override
public void writeHeader(IndexWriter out) throws IOException {
nvq.write(out, OnDiskGraphIndex.CURRENT_VERSION);
writeHeader(out, OnDiskGraphIndex.CURRENT_VERSION);
}

@Override
public void writeHeader(IndexWriter out, int version) throws IOException {
nvq.write(out, version);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ public int featureSize() {
return nvq.compressedVectorSize();
}

@Deprecated
@Override
public void writeHeader(IndexWriter out) throws IOException {
nvq.write(out, OnDiskGraphIndex.CURRENT_VERSION);
writeHeader(out, OnDiskGraphIndex.CURRENT_VERSION);
}

@Override
public void writeHeader(IndexWriter out, int version) throws IOException {
nvq.write(out, version);
out.writeLong(offset);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.github.jbellis.jvector.disk.IndexWriter;
import io.github.jbellis.jvector.disk.RandomAccessReader;
import io.github.jbellis.jvector.graph.disk.CommonHeader;
import io.github.jbellis.jvector.graph.disk.OnDiskGraphIndex;
import io.github.jbellis.jvector.vector.VectorizationProvider;
import io.github.jbellis.jvector.vector.types.VectorTypeSupport;

Expand Down Expand Up @@ -60,8 +61,14 @@ public int featureSize() {
return dimension * Float.BYTES;
}

@Deprecated
@Override
public void writeHeader(IndexWriter out) throws IOException {
writeHeader(out, OnDiskGraphIndex.CURRENT_VERSION);
}

@Override
public void writeHeader(IndexWriter out, int version) throws IOException {
out.writeLong(offset);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: cap-10M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: cap-1M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: cohere-english-v3-10M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: cohere-english-v3-1M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: colbert-1M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: default
# Prefetch bounded batches instead of preloading the entire dataset into memory.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: dpr-gemma-10M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: dpr-gemma-1M
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: glove-100-angular
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: glove-200-angular
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: glove-25-angular
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: glove-50-angular
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: lastfm-64-dot
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: nytimes-256-angular
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This is here for loader testing purposes only, use other datasets for realistic test data
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: sift-128-euclidean
useDatasetPrefetching: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
yamlSchemaVersion: 1
onDiskIndexVersion: 6
onDiskIndexVersion: 7

dataset: wiki-multilingual-v3-int8-1m

Expand Down
Loading
Loading