From d27da63d73bcc013cacd2a14dfc1b04d4f3f1d26 Mon Sep 17 00:00:00 2001 From: Mark Wolters Date: Wed, 11 Mar 2026 17:18:58 -0400 Subject: [PATCH 1/2] fix for bug causing tests to use FP vectors in search --- .../java/io/github/jbellis/jvector/example/Grid.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java b/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java index 89fd7da83..93b6335cc 100644 --- a/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java +++ b/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java @@ -830,8 +830,16 @@ public static List runAllAndCollectResults( var compressor = getCompressor(buildCompressor, ds); var searchCompressorObj = getCompressor(searchCompressor, ds); - CompressedVectors cvArg = (searchCompressorObj instanceof CompressedVectors) ? (CompressedVectors) searchCompressorObj : null; - + // Encode vectors for reranking if a compressor is provided + CompressedVectors cvArg; + if (searchCompressorObj == null) { + cvArg = null; + } else { + cvArg = searchCompressorObj.encodeAll(ds.getBaseRavv()); + System.out.format("%s: %s encoded %d vectors [%.2f MB] for search%n", + ds.getName(), searchCompressorObj, ds.getBaseVectors().size(), + (cvArg.ramBytesUsed() / 1024f / 1024f)); + } // If cache is disabled, we use the (tmp) testDirectory as the output Path outputDir = cache.isEnabled() ? cache.cacheDir().toAbsolutePath() : testDirectory; From 591c5072b39e2ea7dc85fd70621bacd28f8d522e Mon Sep 17 00:00:00 2001 From: Mark Wolters Date: Fri, 13 Mar 2026 11:02:17 -0400 Subject: [PATCH 2/2] adding safeguards and logging --- .../github/jbellis/jvector/example/Grid.java | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java b/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java index 93b6335cc..a5989011f 100644 --- a/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java +++ b/jvector-examples/src/main/java/io/github/jbellis/jvector/example/Grid.java @@ -303,6 +303,7 @@ static void runOneGraph(OnDiskGraphIndexCache cache, CompressedVectors cv; if (featureSetForIndex.contains(FeatureId.FUSED_PQ)) { cv = null; + System.out.format("%s: configured to use FUSED PQ, skipping vector compression%n", ds.getName()); } else { constructionMetrics.resetSearch(); // per (index, cpSupplier) config @@ -312,11 +313,17 @@ static void runOneGraph(OnDiskGraphIndexCache cache, if (compressor == null) { cv = null; + System.out.format("%s: No search compressor configured, FULL PRECISION vectors will be used for search%n", ds.getName()); } else { long start = System.nanoTime(); cv = constructionMetrics.search(searchQuantType) .timeEncode(() -> compressor.encodeAll(ds.getBaseRavv())); double encodingTimeS = (System.nanoTime() - start) / 1_000_000_000.0; + if (cv == null) { + throw new IllegalStateException(String.format( + "Compressor '%s' was provided but failed to encode vectors for dataset '%s'. " + + "Aborting to prevent false recall results.", compressor, ds.getName())); + } System.out.format("%s: %s encoded %d vectors [%.2f MB] in %.2fs%n", ds.getName(), compressor, ds.getBaseVectors().size(), (cv.ramBytesUsed() / 1024f / 1024f), encodingTimeS); } } @@ -832,13 +839,26 @@ public static List runAllAndCollectResults( var searchCompressorObj = getCompressor(searchCompressor, ds); // Encode vectors for reranking if a compressor is provided CompressedVectors cvArg; - if (searchCompressorObj == null) { + if (features.contains(FeatureId.FUSED_PQ)) { cvArg = null; + System.out.format("%s: configured to use FUSED PQ, skipping vector compression%n", ds.getName()); } else { - cvArg = searchCompressorObj.encodeAll(ds.getBaseRavv()); - System.out.format("%s: %s encoded %d vectors [%.2f MB] for search%n", - ds.getName(), searchCompressorObj, ds.getBaseVectors().size(), - (cvArg.ramBytesUsed() / 1024f / 1024f)); + if (searchCompressorObj == null) { + cvArg = null; + System.out.format("%s: No search compressor configured, " + + "FULL PRECISION vectors will be used for search%n", ds.getName()); + } else { + cvArg = searchCompressorObj.encodeAll(ds.getBaseRavv()); + if (cvArg == null) { + throw new IllegalStateException(String.format( + "Compressor '%s' was provided but failed to encode vectors for dataset '%s'. " + + "Aborting to prevent false recall results.", + searchCompressorObj, ds.getName())); + } + System.out.format("%s: %s encoded %d vectors [%.2f MB] for search%n", + ds.getName(), searchCompressorObj, ds.getBaseVectors().size(), + (cvArg.ramBytesUsed() / 1024f / 1024f)); + } } // If cache is disabled, we use the (tmp) testDirectory as the output Path outputDir = cache.isEnabled() ? cache.cacheDir().toAbsolutePath() : testDirectory;