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 8a668f465..ec4e897a7 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_ANTHROPIC_BETA_VERSION = "tools-2024-04-04"; + public static final String BETA_MAX_TOKENS = "max-tokens-3-5-sonnet-2024-07-15"; + private static final Predicate SSE_DONE_PREDICATE = "[DONE]"::equals; private final RestClient restClient; @@ -98,11 +100,26 @@ public class AnthropicApi { */ public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVersion, RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler) { + this(baseUrl, anthropicApiKey, anthropicVersion, restClientBuilder, responseErrorHandler, + DEFAULT_ANTHROPIC_BETA_VERSION); + } + + /** + * Create a new client api. + * @param baseUrl api base URL. + * @param anthropicApiKey Anthropic api Key. + * @param restClientBuilder RestClient builder. + * @param responseErrorHandler Response error handler. + * @param anthropicBetaFeatures Anthropic beta features. + */ + public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVersion, + RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler, + String anthropicBetaFeatures) { Consumer jsonContentHeaders = headers -> { headers.add(HEADER_X_API_KEY, anthropicApiKey); headers.add(HEADER_ANTHROPIC_VERSION, anthropicVersion); - headers.add(HEADER_ANTHROPIC_BETA, DEFAULT_ANTHROPIC_BETA_VERSION); + headers.add(HEADER_ANTHROPIC_BETA, anthropicBetaFeatures); headers.setContentType(MediaType.APPLICATION_JSON); }; diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc index e1984f7c8..3f3c1c361 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/anthropic-chat.adoc @@ -84,6 +84,8 @@ The prefix `spring.ai.anthropic` is used as the property prefix that lets you co | spring.ai.anthropic.base-url | The URL to connect to | https://api.anthropic.com | spring.ai.anthropic.version | Anthropic API version | 2023-06-01 | spring.ai.anthropic.api-key | The API Key | - +| spring.ai.anthropic.beta-version | Enables new/experimental features. If set to `max-tokens-3-5-sonnet-2024-07-15` +the output tokens limit is increased from `4096` to `8192` tokens (for claude-3-5-sonnet only). | `tools-2024-04-04` |==== ==== Configuration Properties diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java index 1df8e716d..0d84ba76f 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java @@ -56,7 +56,8 @@ public class AnthropicAutoConfiguration { RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler) { return new AnthropicApi(connectionProperties.getBaseUrl(), connectionProperties.getApiKey(), - connectionProperties.getVersion(), restClientBuilder, responseErrorHandler); + connectionProperties.getVersion(), restClientBuilder, responseErrorHandler, + connectionProperties.getBetaVersion()); } @Bean diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicConnectionProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicConnectionProperties.java index 9577b8771..3ad6e4ed9 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicConnectionProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicConnectionProperties.java @@ -44,6 +44,12 @@ public class AnthropicConnectionProperties { */ private String version = AnthropicApi.DEFAULT_ANTHROPIC_VERSION; + /** + * Beta features version. Such as tools-2024-04-04 or + * max-tokens-3-5-sonnet-2024-07-15. + */ + private String betaVersion = AnthropicApi.DEFAULT_ANTHROPIC_BETA_VERSION; + public String getApiKey() { return this.apiKey; } @@ -68,4 +74,12 @@ public class AnthropicConnectionProperties { this.version = version; } + public String getBetaVersion() { + return this.betaVersion; + } + + public void setBetaVersion(String betaVersion) { + this.betaVersion = betaVersion; + } + } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java index f51680928..f35b324c9 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfigurationIT.java @@ -25,6 +25,8 @@ import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.anthropic.AnthropicChatModel; +import org.springframework.ai.anthropic.AnthropicChatOptions; +import org.springframework.ai.anthropic.api.AnthropicApi; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; @@ -45,7 +47,7 @@ public class AnthropicAutoConfigurationIT { .withConfiguration(AutoConfigurations.of(AnthropicAutoConfiguration.class)); @Test - void generate() { + void call() { contextRunner.run(context -> { AnthropicChatModel chatModel = context.getBean(AnthropicChatModel.class); String response = chatModel.call("Hello"); @@ -55,7 +57,21 @@ public class AnthropicAutoConfigurationIT { } @Test - void generateStreaming() { + void callWith8KResponseContext() { + contextRunner + .withPropertyValues("spring.ai.anthropic.beta-version=" + AnthropicApi.BETA_MAX_TOKENS, + "spring.ai.anthropic.chat.options.model=" + AnthropicApi.ChatModel.CLAUDE_3_5_SONNET.getValue()) + .run(context -> { + AnthropicChatModel chatModel = context.getBean(AnthropicChatModel.class); + var optoins = AnthropicChatOptions.builder().withMaxTokens(8192).build(); + var response = chatModel.call(new Prompt("Tell me a joke", optoins)); + assertThat(response.getResult().getOutput().getContent()).isNotEmpty(); + logger.info("Response: " + response); + }); + } + + @Test + void stream() { contextRunner.run(context -> { AnthropicChatModel chatModel = context.getBean(AnthropicChatModel.class); Flux responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello"))); diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java index 086e7e5b5..0cee943b0 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/anthropic/AnthropicPropertiesTests.java @@ -37,6 +37,8 @@ public class AnthropicPropertiesTests { // @formatter:off "spring.ai.anthropic.base-url=TEST_BASE_URL", "spring.ai.anthropic.api-key=abc123", + "spring.ai.anthropic.version=6666", + "spring.ai.anthropic.beta-version=7777", "spring.ai.anthropic.chat.options.model=MODEL_XYZ", "spring.ai.anthropic.chat.options.temperature=0.55") // @formatter:on @@ -48,6 +50,8 @@ public class AnthropicPropertiesTests { assertThat(connectionProperties.getApiKey()).isEqualTo("abc123"); assertThat(connectionProperties.getBaseUrl()).isEqualTo("TEST_BASE_URL"); + assertThat(connectionProperties.getVersion()).isEqualTo("6666"); + assertThat(connectionProperties.getBetaVersion()).isEqualTo("7777"); assertThat(chatProperties.getOptions().getModel()).isEqualTo("MODEL_XYZ"); assertThat(chatProperties.getOptions().getTemperature()).isEqualTo(0.55f);