From 421e450a3e759f318857a00f509e92961522e2d4 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 3 Sep 2026 16:25:22 +0200 Subject: [PATCH 1/3] promote the no-rerankOn error into one of the errors.yaml --- .../jsonapi/exception/RequestException.java | 1 + .../FindAndRerankOperationBuilder.java | 2 +- src/main/resources/errors.yaml | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/RequestException.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/RequestException.java index d5b8fc9266..de7bb8a8a4 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/RequestException.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/RequestException.java @@ -55,6 +55,7 @@ public enum Code implements ErrorCode { INVALID_CREATE_COLLECTION_FIELD, INVALID_RERANK_OVERRIDE, + MISSING_RERANK_ON_TEXT, MISSING_RERANK_QUERY_TEXT, REQUEST_NOT_JSON, diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilder.java b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilder.java index 1e40365891..0ea03bc478 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilder.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilder.java @@ -451,7 +451,7 @@ private PathMatchLocator passageLocator() { // user has to provide a field to rerank on finalRerankField = rerankOn; } else { - throw new IllegalArgumentException("rerankOn() - rerankOn required and not specified"); + throw RequestException.Code.MISSING_RERANK_ON_TEXT.get(); } return PathMatchLocator.forPath(finalRerankField); diff --git a/src/main/resources/errors.yaml b/src/main/resources/errors.yaml index 38906b8fe8..a9f62a652e 100644 --- a/src/main/resources/errors.yaml +++ b/src/main/resources/errors.yaml @@ -281,6 +281,24 @@ request-errors: Resend the command with a valid reranking service override, or omit the override to use the collection's default reranking configuration. + # unscoped because this touches both the sort and the options + - scope: + code: MISSING_RERANK_ON_TEXT + title: Rerank field is missing + body: |- + The findAndRerank command is missing the field to read from each document for the reranking step. + + Reranking involves using a model to compare passages of text to a user query. + + For each document to rerank, a certain field is read to extract the associated passage. + + If using `$vectorize`, the name of the rerankOn field defaults to "$vectorize"; + otherwise, there is no default and the field name must be supplied. + + The field to read must be specified as `rerankOn` in the options clause, e.g. `{"rerankOn": "title"}`. + + Resend the command including the name of the field on which reranking should be done. + # unscoped because this touches both the sort and the options - scope: code: MISSING_RERANK_QUERY_TEXT From c83e0d7fe26594a52384b7ae971dd4000ae6dab5 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 3 Sep 2026 16:40:35 +0200 Subject: [PATCH 2/3] tests --- .../FindAndRerankOperationBuilderTest.java | 121 +++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java index 3ca81fc205..b065529d81 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java @@ -23,8 +23,16 @@ import io.stargate.sgv2.jsonapi.service.reranking.configuration.RerankingProvidersConfig; import io.stargate.sgv2.jsonapi.service.reranking.configuration.RerankingProvidersConfigImpl; import io.stargate.sgv2.jsonapi.service.reranking.operation.RerankingProvider; +import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorColumnDefinition; +import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorConfig; +import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorizeDefinition; +import io.stargate.sgv2.jsonapi.service.schema.EmbeddingSourceModel; +import io.stargate.sgv2.jsonapi.service.schema.SimilarityFunction; +import io.stargate.sgv2.jsonapi.service.schema.collections.CollectionLexicalDefSchemaFactory; import io.stargate.sgv2.jsonapi.service.schema.collections.CollectionRerankDef; +import io.stargate.sgv2.jsonapi.service.schema.collections.CollectionRerankDefSchemaFactory; import io.stargate.sgv2.jsonapi.service.schema.collections.CollectionSchemaObject; +import io.stargate.sgv2.jsonapi.service.schema.collections.IdConfig; import io.stargate.sgv2.jsonapi.testresource.NoGlobalResourcesTestProfile; import jakarta.inject.Inject; import java.util.List; @@ -242,15 +250,122 @@ void acceptsBoundaryValues() throws Exception { .build(); } + @Test + void failsWhenMissingRerankOnAndNotVectorizeSort() throws Exception { + var commandContext = commandContext(); + var command = + command( + """ + { + "findAndRerank": { + "sort": { "$hybrid": { "$vector": [0.1, 0.2, 0.3], "$lexical": "text" } }, + "options": { + "rerankQuery": "text" + } + } + } + """); + + assertMissingRerankOnText( + "error when no rerankOn and not vectorize sort", commandContext, command); + } + + @Test + void failsWhenBlankRerankOnAndNotVectorizeSort() throws Exception { + var commandContext = commandContext(); + var command = + command( + """ + { + "findAndRerank": { + "sort": { "$hybrid": { "$vector": [0.1, 0.2, 0.3], "$lexical": "text" } }, + "options": { + "rerankOn": " ", + "rerankQuery": "text" + } + } + } + """); + + assertMissingRerankOnText( + "error when blank rerankOn and not vectorize sort", commandContext, command); + } + + @Test + void failsWhenMissingRerankOnWithLexicalSortOnVectorizeCollection() throws Exception { + var commandContext = commandContextWithVectorize(); + var command = + command( + """ + { + "findAndRerank": { + "sort": { "$hybrid": { "$lexical": "text" } }, + "options": { + "rerankQuery": "text" + } + } + } + """); + + assertMissingRerankOnText( + "error when no rerankOn on vectorize collection with lexical sort", commandContext, command); + } + + private void assertMissingRerankOnText( + String context, + CommandContext commandContext, + FindAndRerankCommand command) { + var ex = + org.junit.jupiter.api.Assertions.assertThrowsExactly( + RequestException.class, + () -> + new FindAndRerankOperationBuilder(commandContext) + .withCommand(command) + .withFindCommandResolver(findCommandResolver) + .build(), + context); + + assertThat(ex.code) + .as("error code is " + RequestException.Code.MISSING_RERANK_ON_TEXT.name()) + .isEqualTo(RequestException.Code.MISSING_RERANK_ON_TEXT.name()); + } + private FindAndRerankCommand command(String json) throws Exception { return objectMapper.readValue(json, FindAndRerankCommand.class); } private CommandContext commandContext() { + return commandContext(testConstants.VECTOR_LEXICAL_RERANK_COLLECTION_SCHEMA_OBJECT); + } + + private CommandContext commandContextWithVectorize() { + var collectionSchema = + new CollectionSchemaObject( + testConstants.COLLECTION_IDENTIFIER, + IdConfig.defaultIdConfig(), + VectorConfig.fromColumnDefinitions( + List.of( + new VectorColumnDefinition( + io.stargate.sgv2.jsonapi.config.constants.DocumentConstants.Fields + .VECTOR_EMBEDDING_TEXT_FIELD, + -1, + SimilarityFunction.COSINE, + EmbeddingSourceModel.OTHER, + new VectorizeDefinition("custom", "custom", null, null)))), + null, + CollectionLexicalDefSchemaFactory.FOR_TESTING_ENABLED.currentVersion(null), + CollectionRerankDefSchemaFactory.FOR_TESTING_ENABLED.currentVersion( + new CollectionRerankDef( + true, + new CollectionRerankDef.RerankServiceDef( + "nvidia", "nvidia/llama-3.2-nv-rerankqa-1b-v2", null, null)))); + return commandContext(collectionSchema); + } + + private CommandContext commandContext( + CollectionSchemaObject schemaObject) { var commandContext = - testConstants.collectionContext( - CommandName.FIND_AND_RERANK, - testConstants.VECTOR_LEXICAL_RERANK_COLLECTION_SCHEMA_OBJECT); + testConstants.collectionContext(CommandName.FIND_AND_RERANK, schemaObject); var rerankingProvidersConfig = mock(RerankingProvidersConfig.class); var modelConfig = mock(RerankingProvidersConfig.RerankingProviderConfig.ModelConfig.class); From d22bbea7221fbcd2728e520dc671d028f43e7ba6 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 3 Sep 2026 16:56:22 +0200 Subject: [PATCH 3/3] formatting in test file --- .../resolver/FindAndRerankOperationBuilderTest.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java index b065529d81..dfcbf8581d 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/FindAndRerankOperationBuilderTest.java @@ -19,13 +19,13 @@ import io.stargate.sgv2.jsonapi.config.constants.RerankingConstants; import io.stargate.sgv2.jsonapi.exception.RequestException; import io.stargate.sgv2.jsonapi.exception.SchemaException; +import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorColumnDefinition; +import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorConfig; +import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorizeDefinition; import io.stargate.sgv2.jsonapi.service.provider.ApiModelSupport; import io.stargate.sgv2.jsonapi.service.reranking.configuration.RerankingProvidersConfig; import io.stargate.sgv2.jsonapi.service.reranking.configuration.RerankingProvidersConfigImpl; import io.stargate.sgv2.jsonapi.service.reranking.operation.RerankingProvider; -import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorColumnDefinition; -import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorConfig; -import io.stargate.sgv2.jsonapi.service.cqldriver.executor.VectorizeDefinition; import io.stargate.sgv2.jsonapi.service.schema.EmbeddingSourceModel; import io.stargate.sgv2.jsonapi.service.schema.SimilarityFunction; import io.stargate.sgv2.jsonapi.service.schema.collections.CollectionLexicalDefSchemaFactory; @@ -308,7 +308,9 @@ void failsWhenMissingRerankOnWithLexicalSortOnVectorizeCollection() throws Excep """); assertMissingRerankOnText( - "error when no rerankOn on vectorize collection with lexical sort", commandContext, command); + "error when no rerankOn on vectorize collection with lexical sort", + commandContext, + command); } private void assertMissingRerankOnText( @@ -364,8 +366,7 @@ private CommandContext commandContextWithVectorize() { private CommandContext commandContext( CollectionSchemaObject schemaObject) { - var commandContext = - testConstants.collectionContext(CommandName.FIND_AND_RERANK, schemaObject); + var commandContext = testConstants.collectionContext(CommandName.FIND_AND_RERANK, schemaObject); var rerankingProvidersConfig = mock(RerankingProvidersConfig.class); var modelConfig = mock(RerankingProvidersConfig.RerankingProviderConfig.ModelConfig.class);