mccullocht commented on code in PR #16030:
URL: https://github.com/apache/lucene/pull/16030#discussion_r4049370617


##########
lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104ScalarQuantizedVectorsWriter.java:
##########
@@ -320,39 +351,167 @@ private QuantizedByteVectorValues 
mergedQuantizedVectorValues(
     return new QuantizedFloatVectorValues(vectorValues, quantizer, encoding, 
centroid);
   }
 
+  /**
+   * Returns a view that quantizes a single segment's float vectors against 
{@code centroid} using
+   * this writer's encoding, without consulting any quantized bytes the 
segment may already store.
+   */
+  private QuantizedFloatVectorValues quantizeFromFloats(
+      KnnVectorsReader reader, FieldInfo fieldInfo, float[] centroid) throws 
IOException {
+    OptimizedScalarQuantizer quantizer =
+        new OptimizedScalarQuantizer(fieldInfo.getVectorSimilarityFunction());
+    FloatVectorValues vectorValues =
+        fieldInfo.getVectorEncoding() == VectorEncoding.FLOAT16
+            ? new 
Float16AsFloatVectorValues(reader.getFloat16VectorValues(fieldInfo.name))
+            : reader.getFloatVectorValues(fieldInfo.name);
+    if (fieldInfo.getVectorSimilarityFunction() == COSINE) {
+      vectorValues = new NormalizedFloatVectorValues(vectorValues);
+    }
+    return new QuantizedFloatVectorValues(vectorValues, quantizer, encoding, 
centroid);
+  }
+
   @Override
   public void mergeOneFlatVectorField(FieldInfo fieldInfo, MergeState 
mergeState)
       throws IOException {
-    // Don't need access to the random vectors, we can just use the merged
-    rawVectorDelegate.mergeOneFlatVectorField(fieldInfo, mergeState);
     if (fieldInfo.getVectorEncoding().isFloatingPoint() == false) {
+      rawVectorDelegate.mergeOneFlatVectorField(fieldInfo, mergeState);
       return;
     }
-    final float[] centroid;
+    switch (mode) {
+      case CENTERED -> {
+        failIfFloatVectorsMissing(fieldInfo, mergeState);
+        mergeOneFlatVectorFieldCentered(fieldInfo, mergeState);
+      }
+      case DATA_BLIND_WITH_FLOATS -> {
+        // The output segment stores full-precision floats, so every 
contributing segment must
+        // provide them; the quantized merge then re-quantizes them against 
the zero centroid.
+        failIfFloatVectorsMissing(fieldInfo, mergeState);
+        rawVectorDelegate.mergeOneFlatVectorField(fieldInfo, mergeState);
+        mergeOneFlatVectorFieldDataBlind(fieldInfo, mergeState);
+      }
+      case DATA_BLIND_WITHOUT_FLOATS -> 
mergeOneFlatVectorFieldDataBlind(fieldInfo, mergeState);
+    }
+  }
+
+  /**
+   * Fails the merge when the output mode stores full-precision float vectors 
({@code mode} is
+   * {@link Mode#CENTERED} or {@link Mode#DATA_BLIND_WITH_FLOATS}) but a 
contributing segment cannot
+   * supply them, e.g. a segment written in {@link 
Mode#DATA_BLIND_WITHOUT_FLOATS}. Such segments
+   * can only offer dequantized (already-quantized) values in place of true 
full-precision vectors;
+   * this fails loudly rather than silently degrading quality.
+   */
+  private void failIfFloatVectorsMissing(FieldInfo fieldInfo, MergeState 
mergeState)
+      throws IOException {
+    for (int i = 0; i < mergeState.knnVectorsReaders.length; i++) {
+      KnnVectorsReader reader = mergeState.knnVectorsReaders[i];
+      if (reader == null || hasRawVectorValues(reader, fieldInfo)) {
+        continue;
+      }
+      // Tolerate segments that have no vectors for the field at all; they 
contribute nothing.
+      FloatVectorValues values = floatingPointVectorValues(reader, fieldInfo);
+      if (values == null || values.size() == 0) {
+        continue;
+      }
+      throw new IllegalStateException(

Review Comment:
   I'd prefer to be consistent here -- allowing "empty" segments this way might 
lead to some confusion about why it is or isn't working.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to