refactor: update base URL handling in ChatCompletionClient and TextCompletionClient for improved flexibility

This commit is contained in:
extio-de
2026-07-05 14:01:54 +02:00
parent e811c9b2fe
commit 25cdd9c3be
3 changed files with 28 additions and 10 deletions

View File

@@ -14,19 +14,18 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import tools.jackson.core.JacksonException;
import de.extio.lmlib.client.Chunk; import de.extio.lmlib.client.Chunk;
import de.extio.lmlib.client.Completion; import de.extio.lmlib.client.Completion;
import de.extio.lmlib.client.Conversation; import de.extio.lmlib.client.Conversation;
import de.extio.lmlib.client.Conversation.Turn;
import de.extio.lmlib.client.ToolCall; import de.extio.lmlib.client.ToolCall;
import de.extio.lmlib.client.ToolCallData; import de.extio.lmlib.client.ToolCallData;
import de.extio.lmlib.client.ToolDefinition; 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.client.oai.completion.AbstractCompletionClient;
import de.extio.lmlib.profile.ModelCategory; import de.extio.lmlib.profile.ModelCategory;
import de.extio.lmlib.profile.ModelProfile; import de.extio.lmlib.profile.ModelProfile;
import de.extio.lmlib.profile.ModelProfile.ModelProvider; import de.extio.lmlib.profile.ModelProfile.ModelProvider;
import tools.jackson.core.JacksonException;
public class ChatCompletionClient extends AbstractCompletionClient { public class ChatCompletionClient extends AbstractCompletionClient {
@@ -69,9 +68,14 @@ public class ChatCompletionClient extends AbstractCompletionClient {
final LocalDateTime start = LocalDateTime.now(); final LocalDateTime start = LocalDateTime.now();
final var restClient = this.restClientBuilder.baseUrl(modelProfile.url()).build(); 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 var requestSpec = restClient
.method(HttpMethod.POST) .method(HttpMethod.POST)
.uri("/v1/chat/completions") .uri(path)
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
if (modelProfile.apiKey() != null && !modelProfile.apiKey().isBlank()) { if (modelProfile.apiKey() != null && !modelProfile.apiKey().isBlank()) {
requestSpec = requestSpec.header("Authorization", "Bearer " + modelProfile.apiKey()); requestSpec = requestSpec.header("Authorization", "Bearer " + modelProfile.apiKey());

View File

@@ -14,20 +14,19 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import tools.jackson.core.JacksonException;
import de.extio.lmlib.client.Chunk; import de.extio.lmlib.client.Chunk;
import de.extio.lmlib.client.Completion; import de.extio.lmlib.client.Completion;
import de.extio.lmlib.client.CompletionFinishReason; import de.extio.lmlib.client.CompletionFinishReason;
import de.extio.lmlib.client.Conversation; import de.extio.lmlib.client.Conversation;
import de.extio.lmlib.client.ToolCallData;
import de.extio.lmlib.client.Conversation.Turn; 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.client.oai.completion.AbstractCompletionClient;
import de.extio.lmlib.profile.ModelCategory; import de.extio.lmlib.profile.ModelCategory;
import de.extio.lmlib.profile.ModelProfile; import de.extio.lmlib.profile.ModelProfile;
import de.extio.lmlib.profile.ModelProfile.ModelProvider; import de.extio.lmlib.profile.ModelProfile.ModelProvider;
import de.extio.lmlib.prompt.PromptStrategy; import de.extio.lmlib.prompt.PromptStrategy;
import de.extio.lmlib.prompt.PromptStrategyFactory; import de.extio.lmlib.prompt.PromptStrategyFactory;
import tools.jackson.core.JacksonException;
public class TextCompletionClient extends AbstractCompletionClient { public class TextCompletionClient extends AbstractCompletionClient {
@@ -72,9 +71,14 @@ public class TextCompletionClient extends AbstractCompletionClient {
LOGGER.debug("Requesting completion at {}", modelProfile.url()); LOGGER.debug("Requesting completion at {}", modelProfile.url());
final LocalDateTime start = LocalDateTime.now(); final LocalDateTime start = LocalDateTime.now();
final var restClient = this.restClientBuilder.baseUrl(modelProfile.url()).build(); 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 var requestSpec = restClient
.method(HttpMethod.POST) .method(HttpMethod.POST)
.uri("/v1/completions") .uri(path)
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
if (modelProfile.apiKey() != null && !modelProfile.apiKey().isBlank()) { if (modelProfile.apiKey() != null && !modelProfile.apiKey().isBlank()) {
requestSpec = requestSpec.header("Authorization", "Bearer " + modelProfile.apiKey()); requestSpec = requestSpec.header("Authorization", "Bearer " + modelProfile.apiKey());

View File

@@ -31,7 +31,12 @@ final class LlamaServerTokenizer implements Tokenizer {
public List<Long> tokenize(final String txt, final ModelProfile modelProfile) { public List<Long> tokenize(final String txt, final ModelProfile modelProfile) {
LOGGER.debug("Requesting tokenizing"); LOGGER.debug("Requesting tokenizing");
final var request = new TokenizeRequest(txt); 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 final var response = restClient
.method(HttpMethod.POST) .method(HttpMethod.POST)
.uri("/tokenize") .uri("/tokenize")
@@ -60,7 +65,12 @@ final class LlamaServerTokenizer implements Tokenizer {
public String detokenize(final List<Long> tokens, final ModelProfile modelProfile) { public String detokenize(final List<Long> tokens, final ModelProfile modelProfile) {
LOGGER.debug("Requesting detokenizing"); LOGGER.debug("Requesting detokenizing");
final var request = new DetokenizeRequest(tokens); 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 final var response = restClient
.method(HttpMethod.POST) .method(HttpMethod.POST)
.uri("/detokenize") .uri("/detokenize")