Anthropic: make the beta features header value configurable

- add new spring.ai.anthropic.beta-version property.
  - add ITs.

  Resolves #1068
This commit is contained in:
Christian Tzolov
2024-07-18 20:53:11 +02:00
parent 50d34b8a48
commit 5dc9480eea
6 changed files with 58 additions and 4 deletions

View File

@@ -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<String> 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<HttpHeaders> 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);
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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<ChatResponse> responseFlux = chatModel.stream(new Prompt(new UserMessage("Hello")));

View File

@@ -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);