diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaReranker.java b/src/main/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaReranker.java index 3ed849745..ebeb3c3de 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaReranker.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaReranker.java @@ -9,7 +9,14 @@ public record NvidiaReranker( @SerializedName("model") String model, - @SerializedName("baseUrl") String baseUrl) implements Reranker { + /** + * The module reads this as {@code baseURL}: {@code reranker-nvidia} looks the + * key up verbatim, so a {@code baseUrl} spelling is stored in the schema and + * then ignored, and reranking silently goes to the default endpoint. The + * {@code alternate} keeps configs written by older versions of this client + * readable; Gson only ever writes {@code value}. + */ + @SerializedName(value = "baseURL", alternate = { "baseUrl" }) String baseUrl) implements Reranker { @Override public Kind _kind() { diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaRerankerTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaRerankerTest.java new file mode 100644 index 000000000..bcf0598d2 --- /dev/null +++ b/src/test/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaRerankerTest.java @@ -0,0 +1,37 @@ +package io.weaviate.client6.v1.api.collections.rerankers; + +import org.assertj.core.api.Assertions; +import org.junit.Test; + +import io.weaviate.client6.v1.api.collections.Reranker; +import io.weaviate.client6.v1.internal.json.JSON; + +public class NvidiaRerankerTest { + + /** + * Collections created by earlier versions of this client have the base URL + * stored under the "baseUrl" key the module never read. Those configs still + * have to deserialize, otherwise upgrading turns a wrong value into a missing + * one. + */ + @Test + public void test_readsLegacyBaseUrlKey() { + var legacy = """ + {"reranker-nvidia": {"baseUrl": "https://legacy.example.com"}} + """; + + var reranker = JSON.deserialize(legacy, Reranker.class); + + Assertions.assertThat(reranker) + .asInstanceOf(org.assertj.core.api.InstanceOfAssertFactories.type(NvidiaReranker.class)) + .returns("https://legacy.example.com", NvidiaReranker::baseUrl); + } + + /** ...but writing always uses the key the module actually reads. */ + @Test + public void test_writesCanonicalBaseUrlKey() { + var json = JSON.serialize(Reranker.nvidia(r -> r.baseUrl("https://example.com"))); + + Assertions.assertThat(json).contains("\"baseURL\"").doesNotContain("\"baseUrl\""); + } +} diff --git a/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java b/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java index e7c0d6203..a616d92bc 100644 --- a/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java +++ b/src/test/java/io/weaviate/client6/v1/internal/json/JSONTest.java @@ -1476,6 +1476,23 @@ public static Object[][] testCases() { } """, }, + // reranker-nvidia reads "baseURL" like every other module. It had no test + // row, which is how it kept sending "baseUrl" -- stored in the schema and + // then ignored, so reranking silently used the default endpoint. + { + Reranker.class, + Reranker.nvidia(rerank -> rerank + .baseUrl("example.com") + .model("nvidia/rerank-qa-mistral-4b")), + """ + { + "reranker-nvidia": { + "baseURL": "example.com", + "model": "nvidia/rerank-qa-mistral-4b" + } + } + """, + }, // BatchReference.CustomTypeAdapterFactory {