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 0caaa2c0c0a..5dc4dbb4a04 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 @@ -70,8 +70,9 @@ public AnthropicApi anthropicApi(AnthropicConnectionProperties connectionPropert 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 7f56f2d059e..871bae627a6 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 void setBaseUrl(String baseUrl) { 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 e70cd9bacbe..79867bde59e 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 void connectionProperties() { 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 void connectionProperties() { 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 87098c6d938..b1fddb018a6 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 @@ -65,6 +65,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"; @@ -79,6 +81,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(); @@ -90,37 +94,40 @@ public class AnthropicApi { * @param anthropicApiKey Anthropic api Key. */ public AnthropicApi(String anthropicApiKey) { - this(DEFAULT_BASE_URL, anthropicApiKey); + this(DEFAULT_BASE_URL, DEFAULT_MESSAGE_COMPLETIONS_PATH, anthropicApiKey); } /** * Create a new client api. * @param baseUrl api base URL. + * @param completionsPath path to append to the base URL. * @param anthropicApiKey Anthropic api Key. */ - public AnthropicApi(String baseUrl, String anthropicApiKey) { - this(baseUrl, anthropicApiKey, DEFAULT_ANTHROPIC_VERSION, RestClient.builder(), WebClient.builder(), - RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER); + public AnthropicApi(String baseUrl, String completionsPath, String anthropicApiKey) { + this(baseUrl, completionsPath, anthropicApiKey, DEFAULT_ANTHROPIC_VERSION, RestClient.builder(), + WebClient.builder(), RetryUtils.DEFAULT_RESPONSE_ERROR_HANDLER); } /** * 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 restClientBuilder RestClient builder. * @param webClientBuilder WebClient builder. * @param responseErrorHandler Response error handler. */ - 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) { - this(baseUrl, anthropicApiKey, anthropicVersion, restClientBuilder, webClientBuilder, responseErrorHandler, - DEFAULT_ANTHROPIC_BETA_VERSION); + this(baseUrl, completionsPath, 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. @@ -128,7 +135,7 @@ public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVers * @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) { @@ -139,6 +146,8 @@ public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVers headers.setContentType(MediaType.APPLICATION_JSON); }; + this.completionsPath = completionsPath; + this.restClient = restClientBuilder.baseUrl(baseUrl) .defaultHeaders(jsonContentHeaders) .defaultStatusHandler(responseErrorHandler) @@ -178,7 +187,7 @@ public ResponseEntity chatCompletionEntity(ChatCompletio 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() @@ -214,7 +223,7 @@ public Flux chatCompletionStream(ChatCompletionRequest c 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()