From 6b77e71b10a6841f3dae7f2221d4fd10cf724073 Mon Sep 17 00:00:00 2001 From: Duda Nogueira Date: Tue, 25 Aug 2026 15:56:16 -0300 Subject: [PATCH] fix(rerankers): send the Nvidia reranker base URL as "baseURL" reranker-nvidia looks the key up verbatim, so the "baseUrl" spelling was stored in the schema and then ignored: reranking silently went to the default NVIDIA endpoint instead of the configured one. Verified against Weaviate 1.39.0 with a stub reranker endpoint. Two collections identical but for the key spelling: baseURL -> the stub is called, the query returns the stub's scores baseUrl -> no call to the stub, "connection to NVIDIA API failed with status: 401" from the real endpoint Every other module config in this client already uses "baseURL", which matches the server: each module reads it through a case-sensitive map lookup, and text2vec-weaviate goes as far as declaring the migration {Name: "baseUrl", NewName: "baseURL"}. The alternate keeps configs written by older versions of this client readable, so upgrading turns a wrong value into a working one rather than a missing one. Closes #607 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01WmY5dAGWCccWDoqkKNC2JU --- .../collections/rerankers/NvidiaReranker.java | 9 ++++- .../rerankers/NvidiaRerankerTest.java | 37 +++++++++++++++++++ .../client6/v1/internal/json/JSONTest.java | 17 +++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/test/java/io/weaviate/client6/v1/api/collections/rerankers/NvidiaRerankerTest.java 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 {