From d7eb9bb32e37d846c6c79807501caed00c781ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cclaudio-code=E2=80=9D?= Date: Thu, 24 Apr 2025 00:40:18 -0300 Subject: [PATCH] Added the possibility to configure the path together with the base-url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “claudio-code” --- .../AnthropicChatAutoConfiguration.java | 5 +-- .../AnthropicConnectionProperties.java | 13 ++++++++ .../AnthropicPropertiesTests.java | 2 ++ .../ai/anthropic/api/AnthropicApi.java | 31 ++++++++++++++----- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java index 5070bc3af..e1b475e45 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java @@ -67,8 +67,9 @@ public class AnthropicChatAutoConfiguration { ObjectProvider restClientBuilderProvider, ObjectProvider webClientBuilderProvider, ResponseErrorHandler responseErrorHandler) { - return new AnthropicApi(connectionProperties.getBaseUrl(), connectionProperties.getApiKey(), - connectionProperties.getVersion(), restClientBuilderProvider.getIfAvailable(RestClient::builder), + return new AnthropicApi(connectionProperties.getBaseUrl(), connectionProperties.getCompletionsPath(), + connectionProperties.getApiKey(), connectionProperties.getVersion(), + restClientBuilderProvider.getIfAvailable(RestClient::builder), webClientBuilderProvider.getIfAvailable(WebClient::builder), responseErrorHandler, connectionProperties.getBetaVersion()); } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicConnectionProperties.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicConnectionProperties.java index 7f56f2d05..871bae627 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicConnectionProperties.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicConnectionProperties.java @@ -40,6 +40,11 @@ public class AnthropicConnectionProperties { */ private String baseUrl = AnthropicApi.DEFAULT_BASE_URL; + /** + * Path to append to the base URL + */ + private String completionsPath = AnthropicApi.DEFAULT_MESSAGE_COMPLETIONS_PATH; + /** * Anthropic API version. */ @@ -67,6 +72,14 @@ public class AnthropicConnectionProperties { this.baseUrl = baseUrl; } + public String getCompletionsPath() { + return this.completionsPath; + } + + public void setCompletionsPath(String completionsPath) { + this.completionsPath = completionsPath; + } + public String getVersion() { return this.version; } diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java index e70cd9bac..79867bde5 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java @@ -37,6 +37,7 @@ public class AnthropicPropertiesTests { new ApplicationContextRunner().withPropertyValues( // @formatter:off "spring.ai.anthropic.base-url=TEST_BASE_URL", + "spring.ai.anthropic.completions-path=message-path", "spring.ai.anthropic.api-key=abc123", "spring.ai.anthropic.version=6666", "spring.ai.anthropic.beta-version=7777", @@ -53,6 +54,7 @@ public class AnthropicPropertiesTests { assertThat(connectionProperties.getBaseUrl()).isEqualTo("TEST_BASE_URL"); assertThat(connectionProperties.getVersion()).isEqualTo("6666"); assertThat(connectionProperties.getBetaVersion()).isEqualTo("7777"); + assertThat(connectionProperties.getCompletionsPath()).isEqualTo("message-path"); assertThat(chatProperties.getOptions().getModel()).isEqualTo("MODEL_XYZ"); assertThat(chatProperties.getOptions().getTemperature()).isEqualTo(0.55); diff --git a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java index 7f4e5706e..a4105989b 100644 --- a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java +++ b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java @@ -58,6 +58,7 @@ import org.springframework.web.reactive.function.client.WebClient; * @author Jihoon Kim * @author Alexandros Pappas * @author Jonghoon Park + * @author Claudio Silva Junior * @since 1.0.0 */ public class AnthropicApi { @@ -70,6 +71,8 @@ public class AnthropicApi { public static final String DEFAULT_BASE_URL = "https://api.anthropic.com"; + public static final String DEFAULT_MESSAGE_COMPLETIONS_PATH = "/v1/messages"; + public static final String DEFAULT_ANTHROPIC_VERSION = "2023-06-01"; public static final String DEFAULT_ANTHROPIC_BETA_VERSION = "tools-2024-04-04,pdfs-2024-09-25"; @@ -84,6 +87,8 @@ public class AnthropicApi { private static final Predicate SSE_DONE_PREDICATE = "[DONE]"::equals; + private final String completionsPath; + private final RestClient restClient; private final StreamHelper streamHelper = new StreamHelper(); @@ -122,13 +127,14 @@ public class AnthropicApi { public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVersion, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler) { - this(baseUrl, anthropicApiKey, anthropicVersion, restClientBuilder, webClientBuilder, responseErrorHandler, - DEFAULT_ANTHROPIC_BETA_VERSION); + this(baseUrl, DEFAULT_MESSAGE_COMPLETIONS_PATH, anthropicApiKey, anthropicVersion, restClientBuilder, + webClientBuilder, responseErrorHandler, DEFAULT_ANTHROPIC_BETA_VERSION); } /** * Create a new client api. * @param baseUrl api base URL. + * @param completionsPath path to append to the base URL. * @param anthropicApiKey Anthropic api Key. * @param anthropicVersion Anthropic version. * @param restClientBuilder RestClient builder. @@ -136,7 +142,7 @@ public class AnthropicApi { * @param responseErrorHandler Response error handler. * @param anthropicBetaFeatures Anthropic beta features. */ - public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVersion, + public AnthropicApi(String baseUrl, String completionsPath, String anthropicApiKey, String anthropicVersion, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler, String anthropicBetaFeatures) { @@ -147,6 +153,8 @@ public class AnthropicApi { headers.setContentType(MediaType.APPLICATION_JSON); }; + this.completionsPath = completionsPath; + this.restClient = restClientBuilder.baseUrl(baseUrl) .defaultHeaders(jsonContentHeaders) .defaultStatusHandler(responseErrorHandler) @@ -186,7 +194,7 @@ public class AnthropicApi { Assert.notNull(additionalHttpHeader, "The additional HTTP headers can not be null."); return this.restClient.post() - .uri("/v1/messages") + .uri(this.completionsPath) .headers(headers -> headers.addAll(additionalHttpHeader)) .body(chatRequest) .retrieve() @@ -222,7 +230,7 @@ public class AnthropicApi { AtomicReference chatCompletionReference = new AtomicReference<>(); return this.webClient.post() - .uri("/v1/messages") + .uri(this.completionsPath) .headers(headers -> headers.addAll(additionalHttpHeader)) .body(Mono.just(chatRequest), ChatCompletionRequest.class) .retrieve() @@ -1335,6 +1343,8 @@ public class AnthropicApi { private String baseUrl = DEFAULT_BASE_URL; + private String completionsPath = DEFAULT_MESSAGE_COMPLETIONS_PATH; + private String apiKey; private String anthropicVersion = DEFAULT_ANTHROPIC_VERSION; @@ -1353,6 +1363,12 @@ public class AnthropicApi { return this; } + public Builder completionsPath(String completionsPath) { + Assert.hasText(completionsPath, "completionsPath cannot be null or empty"); + this.completionsPath = completionsPath; + return this; + } + public Builder apiKey(String apiKey) { Assert.notNull(apiKey, "apiKey cannot be null"); this.apiKey = apiKey; @@ -1391,8 +1407,9 @@ public class AnthropicApi { public AnthropicApi build() { Assert.notNull(this.apiKey, "apiKey must be set"); - return new AnthropicApi(this.baseUrl, this.apiKey, this.anthropicVersion, this.restClientBuilder, - this.webClientBuilder, this.responseErrorHandler, this.anthropicBetaFeatures); + return new AnthropicApi(this.baseUrl, this.completionsPath, this.apiKey, this.anthropicVersion, + this.restClientBuilder, this.webClientBuilder, this.responseErrorHandler, + this.anthropicBetaFeatures); } }