From 25cdd9c3be4023d1ddf9a1222ddd4963f335f96f Mon Sep 17 00:00:00 2001 From: extio-de Date: Sun, 5 Jul 2026 14:01:54 +0200 Subject: [PATCH] refactor: update base URL handling in ChatCompletionClient and TextCompletionClient for improved flexibility --- .../oai/completion/chat/ChatCompletionClient.java | 12 ++++++++---- .../oai/completion/text/TextCompletionClient.java | 12 ++++++++---- .../de/extio/lmlib/token/LlamaServerTokenizer.java | 14 ++++++++++++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java b/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java index 19bb5b8..2372190 100755 --- a/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java +++ b/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java @@ -14,19 +14,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; -import tools.jackson.core.JacksonException; - import de.extio.lmlib.client.Chunk; import de.extio.lmlib.client.Completion; import de.extio.lmlib.client.Conversation; +import de.extio.lmlib.client.Conversation.Turn; import de.extio.lmlib.client.ToolCall; import de.extio.lmlib.client.ToolCallData; import de.extio.lmlib.client.ToolDefinition; -import de.extio.lmlib.client.Conversation.Turn; import de.extio.lmlib.client.oai.completion.AbstractCompletionClient; import de.extio.lmlib.profile.ModelCategory; import de.extio.lmlib.profile.ModelProfile; import de.extio.lmlib.profile.ModelProfile.ModelProvider; +import tools.jackson.core.JacksonException; public class ChatCompletionClient extends AbstractCompletionClient { @@ -69,9 +68,14 @@ public class ChatCompletionClient extends AbstractCompletionClient { final LocalDateTime start = LocalDateTime.now(); final var restClient = this.restClientBuilder.baseUrl(modelProfile.url()).build(); + final var path = switch (modelProfile.url()) { + case final String url when url.endsWith("v1") -> "/chat/completions"; + case final String url when url.endsWith("v1/") -> "/chat/completions"; + default -> "/v1/chat/completions"; + }; var requestSpec = restClient .method(HttpMethod.POST) - .uri("/v1/chat/completions") + .uri(path) .header("Content-Type", "application/json"); if (modelProfile.apiKey() != null && !modelProfile.apiKey().isBlank()) { requestSpec = requestSpec.header("Authorization", "Bearer " + modelProfile.apiKey()); diff --git a/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java b/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java index 538d76d..049456c 100755 --- a/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java +++ b/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java @@ -14,20 +14,19 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; -import tools.jackson.core.JacksonException; - import de.extio.lmlib.client.Chunk; import de.extio.lmlib.client.Completion; import de.extio.lmlib.client.CompletionFinishReason; import de.extio.lmlib.client.Conversation; -import de.extio.lmlib.client.ToolCallData; import de.extio.lmlib.client.Conversation.Turn; +import de.extio.lmlib.client.ToolCallData; import de.extio.lmlib.client.oai.completion.AbstractCompletionClient; import de.extio.lmlib.profile.ModelCategory; import de.extio.lmlib.profile.ModelProfile; import de.extio.lmlib.profile.ModelProfile.ModelProvider; import de.extio.lmlib.prompt.PromptStrategy; import de.extio.lmlib.prompt.PromptStrategyFactory; +import tools.jackson.core.JacksonException; public class TextCompletionClient extends AbstractCompletionClient { @@ -72,9 +71,14 @@ public class TextCompletionClient extends AbstractCompletionClient { LOGGER.debug("Requesting completion at {}", modelProfile.url()); final LocalDateTime start = LocalDateTime.now(); final var restClient = this.restClientBuilder.baseUrl(modelProfile.url()).build(); + final var path = switch (modelProfile.url()) { + case final String url when url.endsWith("v1") -> "/completions"; + case final String url when url.endsWith("v1/") -> "/completions"; + default -> "/v1/completions"; + }; var requestSpec = restClient .method(HttpMethod.POST) - .uri("/v1/completions") + .uri(path) .header("Content-Type", "application/json"); if (modelProfile.apiKey() != null && !modelProfile.apiKey().isBlank()) { requestSpec = requestSpec.header("Authorization", "Bearer " + modelProfile.apiKey()); diff --git a/src/main/java/de/extio/lmlib/token/LlamaServerTokenizer.java b/src/main/java/de/extio/lmlib/token/LlamaServerTokenizer.java index 8dbf5e8..474f85b 100755 --- a/src/main/java/de/extio/lmlib/token/LlamaServerTokenizer.java +++ b/src/main/java/de/extio/lmlib/token/LlamaServerTokenizer.java @@ -31,7 +31,12 @@ final class LlamaServerTokenizer implements Tokenizer { public List tokenize(final String txt, final ModelProfile modelProfile) { LOGGER.debug("Requesting tokenizing"); final var request = new TokenizeRequest(txt); - final var restClient = this.restClientBuilder.baseUrl(modelProfile.url()).build(); + final var baseUrl = switch (modelProfile.url()) { + case final String url when url.endsWith("/v1") -> modelProfile.url().substring(0, modelProfile.url().length() - 3); + case final String url when url.endsWith("/v1/") -> modelProfile.url().substring(0, modelProfile.url().length() - 4); + default -> modelProfile.url(); + }; + final var restClient = this.restClientBuilder.baseUrl(baseUrl).build(); final var response = restClient .method(HttpMethod.POST) .uri("/tokenize") @@ -60,7 +65,12 @@ final class LlamaServerTokenizer implements Tokenizer { public String detokenize(final List tokens, final ModelProfile modelProfile) { LOGGER.debug("Requesting detokenizing"); final var request = new DetokenizeRequest(tokens); - final var restClient = this.restClientBuilder.baseUrl(modelProfile.url()).build(); + final var baseUrl = switch (modelProfile.url()) { + case final String url when url.endsWith("/v1") -> modelProfile.url().substring(0, modelProfile.url().length() - 3); + case final String url when url.endsWith("/v1/") -> modelProfile.url().substring(0, modelProfile.url().length() - 4); + default -> modelProfile.url(); + }; + final var restClient = this.restClientBuilder.baseUrl(baseUrl).build(); final var response = restClient .method(HttpMethod.POST) .uri("/detokenize")