Bedrock client autoconfiguration support external AwsCredentialsProvider and AwsRegionProvider

This commit is contained in:
wmz7year
2024-04-16 14:29:58 +08:00
parent 65e6880fa0
commit 563f9b48af
20 changed files with 404 additions and 24 deletions

View File

@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Flux;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi.AnthropicChatRequest;
import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi.AnthropicChatResponse;
@@ -32,6 +33,7 @@ import org.springframework.util.Assert;
/**
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
// @formatter:off
@@ -92,6 +94,20 @@ public class AnthropicChatBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new AnthropicChatBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use. See the {@link AnthropicChatModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public AnthropicChatBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
// https://github.com/build-on-aws/amazon-bedrock-java-examples/blob/main/example_code/bedrock-runtime/src/main/java/aws/community/examples/InvokeBedrockStreamingAsync.java
// https://docs.anthropic.com/claude/reference/complete_post

View File

@@ -26,6 +26,7 @@ import org.springframework.ai.bedrock.api.AbstractBedrockApi;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import java.time.Duration;
import java.util.List;
@@ -39,6 +40,7 @@ import java.util.List;
*
* @author Ben Middleton
* @author Christian Tzolov
* @author Wei Jiang
* @since 1.0.0
*/
// @formatter:off
@@ -96,6 +98,20 @@ public class Anthropic3ChatBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new AnthropicChatBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use. See the {@link AnthropicChatModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public Anthropic3ChatBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
// https://github.com/build-on-aws/amazon-bedrock-java-examples/blob/main/example_code/bedrock-runtime/src/main/java/aws/community/examples/InvokeBedrockStreamingAsync.java
// https://docs.anthropic.com/claude/reference/complete_post

View File

@@ -61,6 +61,7 @@ import org.springframework.util.Assert;
* @see <a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html">Model Parameters</a>
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
public abstract class AbstractBedrockApi<I, O, SO> {
@@ -69,7 +70,7 @@ public abstract class AbstractBedrockApi<I, O, SO> {
private final String modelId;
private final ObjectMapper objectMapper;
private final String region;
private final Region region;
private final BedrockRuntimeClient client;
private final BedrockRuntimeAsyncClient clientStreaming;
@@ -93,7 +94,7 @@ public abstract class AbstractBedrockApi<I, O, SO> {
this(modelId, ProfileCredentialsProvider.builder().build(), region, ModelOptionsUtils.OBJECT_MAPPER, timeout);
}
/**
/**
* Create a new AbstractBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use.
@@ -105,6 +106,7 @@ public abstract class AbstractBedrockApi<I, O, SO> {
ObjectMapper objectMapper) {
this(modelId, credentialsProvider, region, objectMapper, Duration.ofMinutes(5));
}
/**
* Create a new AbstractBedrockApi instance using the provided credentials provider, region and object mapper.
*
@@ -118,10 +120,26 @@ public abstract class AbstractBedrockApi<I, O, SO> {
*/
public AbstractBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, String region,
ObjectMapper objectMapper, Duration timeout) {
this(modelId, credentialsProvider, Region.of(region), objectMapper, timeout);
}
/**
* Create a new AbstractBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout Configure the amount of time to allow the client to complete the execution of an API call.
* This timeout covers the entire client execution except for marshalling. This includes request handler execution,
* all HTTP requests including retries, unmarshalling, etc. This value should always be positive, if present.
*/
public AbstractBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
Assert.hasText(modelId, "Model id must not be empty");
Assert.notNull(credentialsProvider, "Credentials provider must not be null");
Assert.hasText(region, "Region must not be empty");
Assert.notNull(region, "Region must not be empty");
Assert.notNull(objectMapper, "Object mapper must not be null");
Assert.notNull(timeout, "Timeout must not be null");
@@ -131,13 +149,13 @@ public abstract class AbstractBedrockApi<I, O, SO> {
this.client = BedrockRuntimeClient.builder()
.region(Region.of(this.region))
.region(this.region)
.credentialsProvider(credentialsProvider)
.overrideConfiguration(c -> c.apiCallTimeout(timeout))
.build();
this.clientStreaming = BedrockRuntimeAsyncClient.builder()
.region(Region.of(this.region))
.region(this.region)
.credentialsProvider(credentialsProvider)
.overrideConfiguration(c -> c.apiCallTimeout(timeout))
.build();
@@ -153,7 +171,7 @@ public abstract class AbstractBedrockApi<I, O, SO> {
/**
* @return The AWS region.
*/
public String getRegion() {
public Region getRegion() {
return this.region;
}

View File

@@ -25,6 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Flux;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import org.springframework.ai.bedrock.api.AbstractBedrockApi;
import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi.CohereChatRequest;
@@ -36,6 +37,7 @@ import org.springframework.util.Assert;
* https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-cohere.html
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
public class CohereChatBedrockApi extends
@@ -91,6 +93,20 @@ public class CohereChatBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new CohereChatBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use. See the {@link CohereChatModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public CohereChatBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* CohereChatRequest encapsulates the request parameters for the Cohere command model.
*

View File

@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import org.springframework.ai.bedrock.api.AbstractBedrockApi;
import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi.CohereEmbeddingRequest;
@@ -34,6 +35,7 @@ import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi.Coher
* https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-cohere.html#model-parameters-embed
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
public class CohereEmbeddingBedrockApi extends
@@ -91,6 +93,21 @@ public class CohereEmbeddingBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new CohereEmbeddingBedrockApi instance using the provided credentials provider, region and object
* mapper.
*
* @param modelId The model id to use. See the {@link CohereEmbeddingModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public CohereEmbeddingBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* The Cohere Embed model request.
*

View File

@@ -29,12 +29,14 @@ import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi.
import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi.Ai21Jurassic2ChatResponse;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
/**
* Java client for the Bedrock Jurassic2 chat model.
* https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-jurassic2.html
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
public class Ai21Jurassic2ChatBedrockApi extends
@@ -92,6 +94,20 @@ public class Ai21Jurassic2ChatBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new Ai21Jurassic2ChatBedrockApi instance.
*
* @param modelId The model id to use. See the {@link Ai21Jurassic2ChatBedrockApi.Ai21Jurassic2ChatModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public Ai21Jurassic2ChatBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* AI21 Jurassic2 chat request parameters.
*

View File

@@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Flux;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import org.springframework.ai.bedrock.api.AbstractBedrockApi;
import org.springframework.ai.bedrock.llama2.api.Llama2ChatBedrockApi.Llama2ChatRequest;
@@ -34,6 +35,7 @@ import java.time.Duration;
* https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-meta.html
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
public class Llama2ChatBedrockApi extends
@@ -89,6 +91,20 @@ public class Llama2ChatBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new Llama2ChatBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use. See the {@link Llama2ChatModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public Llama2ChatBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Llama2ChatRequest encapsulates the request parameters for the Meta Llama2 chat model.
*

View File

@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.publisher.Flux;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import org.springframework.ai.bedrock.api.AbstractBedrockApi;
import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi.TitanChatRequest;
@@ -38,6 +39,7 @@ import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi.TitanChatRes
* https://docs.aws.amazon.com/bedrock/latest/userguide/titan-text-models.html
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
// @formatter:off
@@ -92,6 +94,20 @@ public class TitanChatBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new TitanChatBedrockApi instance using the provided credentials provider, region and object mapper.
*
* @param modelId The model id to use. See the {@link TitanChatModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public TitanChatBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* TitanChatRequest encapsulates the request parameters for the Titan chat model.
*

View File

@@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import org.springframework.ai.bedrock.api.AbstractBedrockApi;
import org.springframework.ai.bedrock.titan.api.TitanEmbeddingBedrockApi.TitanEmbeddingRequest;
@@ -34,6 +35,7 @@ import org.springframework.util.Assert;
* https://docs.aws.amazon.com/bedrock/latest/userguide/titan-multiemb-models.html
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
// @formatter:off
@@ -65,6 +67,20 @@ public class TitanEmbeddingBedrockApi extends
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Create a new TitanEmbeddingBedrockApi instance.
*
* @param modelId The model id to use. See the {@link TitanEmbeddingModel} for the supported models.
* @param credentialsProvider The credentials provider to connect to AWS.
* @param region The AWS region to use.
* @param objectMapper The object mapper to use for JSON serialization and deserialization.
* @param timeout The timeout to use.
*/
public TitanEmbeddingBedrockApi(String modelId, AwsCredentialsProvider credentialsProvider, Region region,
ObjectMapper objectMapper, Duration timeout) {
super(modelId, credentialsProvider, region, objectMapper, timeout);
}
/**
* Titan Embedding request parameters.
*

View File

@@ -63,6 +63,18 @@ AWS credentials are resolved in the following order:
6. Credentials delivered through the Amazon EC2 container service if the `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` environment variable is set and the security manager has permission to access the variable.
7. Instance profile credentials delivered through the Amazon EC2 metadata service or set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
AWS region is resolved in the following order:
1. Spring-AI Bedrock `spring.ai.bedrock.aws.region` property.
2. Java System Properties - `aws.region`.
3. Environment Variables - `AWS_REGION`.
4. Credential profiles file at the default location (`~/.aws/credentials`) shared by all AWS SDKs and the AWS CLI.
5. Instance profile region delivered through the Amazon EC2 metadata service.
In addition to the standard Spring-AI Bedrock credentials and region properties configuration, Spring-AI provides support for custom `AwsCredentialsProvider` and `AwsRegionProvider` beans.
NOTE: For example, using Spring-AI and https://spring.io/projects/spring-cloud-aws[Spring Cloud for Amazon Web Services] at the same time. Spring-AI is compatible with Spring Cloud for Amazon Web Services credential configuration.
=== Enable selected Bedrock model
NOTE: By default, all models are disabled. You have to enable the chosen Bedrock models explicitly using the `spring.ai.bedrock.<model>.<chat|embedding>.enabled=true` property.

View File

@@ -19,6 +19,9 @@ import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -28,6 +31,7 @@ import org.springframework.util.StringUtils;
/**
* @author Christian Tzolov
* @author Wei Jiang
*/
@Configuration
@EnableConfigurationProperties({ BedrockAwsConnectionProperties.class })
@@ -45,4 +49,38 @@ public class BedrockAwsConnectionConfiguration {
return DefaultCredentialsProvider.create();
}
@Bean
@ConditionalOnMissingBean
public AwsRegionProvider regionProvider(BedrockAwsConnectionProperties properties) {
if (StringUtils.hasText(properties.getRegion())) {
return new StaticRegionProvider(properties.getRegion());
}
return DefaultAwsRegionProviderChain.builder().build();
}
/**
* @author Wei Jiang
*/
static class StaticRegionProvider implements AwsRegionProvider {
private final Region region;
public StaticRegionProvider(String region) {
try {
this.region = Region.of(region);
}
catch (IllegalArgumentException e) {
throw new IllegalArgumentException("The region '" + region + "' is not a valid region!", e);
}
}
@Override
public Region getRegion() {
return this.region;
}
}
}

View File

@@ -21,6 +21,7 @@ import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperti
import org.springframework.ai.bedrock.anthropic.BedrockAnthropicChatClient;
import org.springframework.ai.bedrock.anthropic.api.AnthropicChatBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -28,6 +29,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
/**
* {@link AutoConfiguration Auto-configuration} for Bedrock Anthropic Chat Client.
@@ -35,6 +37,7 @@ import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
* Leverages the Spring Cloud AWS to resolve the {@link AwsCredentialsProvider}.
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
@AutoConfiguration
@@ -46,16 +49,18 @@ public class BedrockAnthropicChatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public AnthropicChatBedrockApi anthropicApi(AwsCredentialsProvider credentialsProvider,
BedrockAnthropicChatProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new AnthropicChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockAnthropicChatProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new AnthropicChatBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnBean(AnthropicChatBedrockApi.class)
public BedrockAnthropicChatClient anthropicChatClient(AnthropicChatBedrockApi anthropicApi,
BedrockAnthropicChatProperties properties) {
return new BedrockAnthropicChatClient(anthropicApi, properties.getOptions());
}

View File

@@ -21,6 +21,7 @@ import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperti
import org.springframework.ai.bedrock.anthropic3.BedrockAnthropic3ChatClient;
import org.springframework.ai.bedrock.anthropic3.api.Anthropic3ChatBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -28,6 +29,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
/**
* {@link AutoConfiguration Auto-configuration} for Bedrock Anthropic Chat Client.
@@ -47,13 +49,16 @@ public class BedrockAnthropic3ChatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public Anthropic3ChatBedrockApi anthropic3Api(AwsCredentialsProvider credentialsProvider,
BedrockAnthropic3ChatProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new Anthropic3ChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockAnthropic3ChatProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new Anthropic3ChatBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnBean(Anthropic3ChatBedrockApi.class)
public BedrockAnthropic3ChatClient anthropic3ChatClient(Anthropic3ChatBedrockApi anthropicApi,
BedrockAnthropic3ChatProperties properties) {
return new BedrockAnthropic3ChatClient(anthropicApi, properties.getOptions());

View File

@@ -21,6 +21,7 @@ import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperti
import org.springframework.ai.bedrock.cohere.BedrockCohereChatClient;
import org.springframework.ai.bedrock.cohere.api.CohereChatBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -28,11 +29,13 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
/**
* {@link AutoConfiguration Auto-configuration} for Bedrock Cohere Chat Client.
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
@AutoConfiguration
@@ -44,13 +47,16 @@ public class BedrockCohereChatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public CohereChatBedrockApi cohereChatApi(AwsCredentialsProvider credentialsProvider,
BedrockCohereChatProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new CohereChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockCohereChatProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new CohereChatBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnBean(CohereChatBedrockApi.class)
public BedrockCohereChatClient cohereChatClient(CohereChatBedrockApi cohereChatApi,
BedrockCohereChatProperties properties) {

View File

@@ -17,12 +17,14 @@ package org.springframework.ai.autoconfigure.bedrock.cohere;
import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration;
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties;
import org.springframework.ai.bedrock.cohere.BedrockCohereEmbeddingClient;
import org.springframework.ai.bedrock.cohere.api.CohereEmbeddingBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -34,6 +36,7 @@ import org.springframework.context.annotation.Import;
* {@link AutoConfiguration Auto-configuration} for Bedrock Cohere Embedding Client.
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
@AutoConfiguration
@@ -45,14 +48,17 @@ public class BedrockCohereEmbeddingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public CohereEmbeddingBedrockApi cohereEmbeddingApi(AwsCredentialsProvider credentialsProvider,
BedrockCohereEmbeddingProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new CohereEmbeddingBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockCohereEmbeddingProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new CohereEmbeddingBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(CohereEmbeddingBedrockApi.class)
public BedrockCohereEmbeddingClient cohereEmbeddingClient(CohereEmbeddingBedrockApi cohereEmbeddingApi,
BedrockCohereEmbeddingProperties properties) {

View File

@@ -22,6 +22,7 @@ import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperti
import org.springframework.ai.bedrock.jurassic2.BedrockAi21Jurassic2ChatClient;
import org.springframework.ai.bedrock.jurassic2.api.Ai21Jurassic2ChatBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -29,11 +30,13 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
/**
* {@link AutoConfiguration Auto-configuration} for Bedrock Jurassic2 Chat Client.
*
* @author Ahmed Yousri
* @author Wei Jiang
* @since 1.0.0
*/
@AutoConfiguration
@@ -46,13 +49,16 @@ public class BedrockAi21Jurassic2ChatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public Ai21Jurassic2ChatBedrockApi ai21Jurassic2ChatBedrockApi(AwsCredentialsProvider credentialsProvider,
BedrockAi21Jurassic2ChatProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new Ai21Jurassic2ChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockAi21Jurassic2ChatProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new Ai21Jurassic2ChatBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnBean(Ai21Jurassic2ChatBedrockApi.class)
public BedrockAi21Jurassic2ChatClient jurassic2ChatClient(Ai21Jurassic2ChatBedrockApi ai21Jurassic2ChatBedrockApi,
BedrockAi21Jurassic2ChatProperties properties) {

View File

@@ -17,12 +17,14 @@ package org.springframework.ai.autoconfigure.bedrock.llama2;
import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration;
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties;
import org.springframework.ai.bedrock.llama2.BedrockLlama2ChatClient;
import org.springframework.ai.bedrock.llama2.api.Llama2ChatBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -36,6 +38,7 @@ import org.springframework.context.annotation.Import;
* Leverages the Spring Cloud AWS to resolve the {@link AwsCredentialsProvider}.
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
@AutoConfiguration
@@ -47,13 +50,15 @@ public class BedrockLlama2ChatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Llama2ChatBedrockApi llama2Api(AwsCredentialsProvider credentialsProvider,
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public Llama2ChatBedrockApi llama2Api(AwsCredentialsProvider credentialsProvider, AwsRegionProvider regionProvider,
BedrockLlama2ChatProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new Llama2ChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
return new Llama2ChatBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnBean(Llama2ChatBedrockApi.class)
public BedrockLlama2ChatClient llama2ChatClient(Llama2ChatBedrockApi llama2Api,
BedrockLlama2ChatProperties properties) {

View File

@@ -21,6 +21,7 @@ import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperti
import org.springframework.ai.bedrock.titan.BedrockTitanChatClient;
import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -28,11 +29,13 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
/**
* {@link AutoConfiguration Auto-configuration} for Bedrock Titan Chat Client.
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
@AutoConfiguration
@@ -44,14 +47,16 @@ public class BedrockTitanChatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public TitanChatBedrockApi titanChatBedrockApi(AwsCredentialsProvider credentialsProvider,
BedrockTitanChatProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new TitanChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockTitanChatProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new TitanChatBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnBean(TitanChatBedrockApi.class)
public BedrockTitanChatClient titanChatClient(TitanChatBedrockApi titanChatApi,
BedrockTitanChatProperties properties) {

View File

@@ -17,12 +17,14 @@ package org.springframework.ai.autoconfigure.bedrock.titan;
import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionConfiguration;
import org.springframework.ai.autoconfigure.bedrock.BedrockAwsConnectionProperties;
import org.springframework.ai.bedrock.titan.BedrockTitanEmbeddingClient;
import org.springframework.ai.bedrock.titan.api.TitanEmbeddingBedrockApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -34,6 +36,7 @@ import org.springframework.context.annotation.Import;
* {@link AutoConfiguration Auto-configuration} for Bedrock Titan Embedding Client.
*
* @author Christian Tzolov
* @author Wei Jiang
* @since 0.8.0
*/
@AutoConfiguration
@@ -45,14 +48,17 @@ public class BedrockTitanEmbeddingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean({ AwsCredentialsProvider.class, AwsRegionProvider.class })
public TitanEmbeddingBedrockApi titanEmbeddingBedrockApi(AwsCredentialsProvider credentialsProvider,
BedrockTitanEmbeddingProperties properties, BedrockAwsConnectionProperties awsProperties) {
return new TitanEmbeddingBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(),
AwsRegionProvider regionProvider, BedrockTitanEmbeddingProperties properties,
BedrockAwsConnectionProperties awsProperties) {
return new TitanEmbeddingBedrockApi(properties.getModel(), credentialsProvider, regionProvider.getRegion(),
new ObjectMapper(), awsProperties.getTimeout());
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(TitanEmbeddingBedrockApi.class)
public BedrockTitanEmbeddingClient titanEmbeddingClient(TitanEmbeddingBedrockApi titanEmbeddingApi,
BedrockTitanEmbeddingProperties properties) {

View File

@@ -0,0 +1,139 @@
/*
* Copyright 2023 - 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ai.autoconfigure.bedrock;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.providers.AwsRegionProvider;
/**
* @author Wei Jiang
* @since 0.8.1
*/
@EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".*")
@EnabledIfEnvironmentVariable(named = "AWS_SECRET_ACCESS_KEY", matches = ".*")
public class BedrockAwsConnectionConfigurationIT {
@Test
public void autoConfigureAWSCredentialAndRegionProvider() {
new ApplicationContextRunner()
.withPropertyValues("spring.ai.bedrock.aws.access-key=" + System.getenv("AWS_ACCESS_KEY_ID"),
"spring.ai.bedrock.aws.secret-key=" + System.getenv("AWS_SECRET_ACCESS_KEY"),
"spring.ai.bedrock.aws.region=" + Region.US_EAST_1.id())
.withConfiguration(AutoConfigurations.of(TestAutoConfiguration.class))
.run((context) -> {
var awsCredentialsProvider = context.getBean(AwsCredentialsProvider.class);
var awsRegionProvider = context.getBean(AwsRegionProvider.class);
assertThat(awsCredentialsProvider).isNotNull();
assertThat(awsRegionProvider).isNotNull();
var credentials = awsCredentialsProvider.resolveCredentials();
assertThat(credentials).isNotNull();
assertThat(credentials.accessKeyId()).isEqualTo(System.getenv("AWS_ACCESS_KEY_ID"));
assertThat(credentials.secretAccessKey()).isEqualTo(System.getenv("AWS_SECRET_ACCESS_KEY"));
assertThat(awsRegionProvider.getRegion()).isEqualTo(Region.US_EAST_1);
});
}
@Test
public void autoConfigureWithCustomAWSCredentialAndRegionProvider() {
new ApplicationContextRunner()
.withPropertyValues("spring.ai.bedrock.aws.access-key=" + System.getenv("AWS_ACCESS_KEY_ID"),
"spring.ai.bedrock.aws.secret-key=" + System.getenv("AWS_SECRET_ACCESS_KEY"),
"spring.ai.bedrock.aws.region=" + Region.US_EAST_1.id())
.withConfiguration(AutoConfigurations.of(TestAutoConfiguration.class,
CustomAwsCredentialsProviderAndAwsRegionProviderAutoConfiguration.class))
.run((context) -> {
var awsCredentialsProvider = context.getBean(AwsCredentialsProvider.class);
var awsRegionProvider = context.getBean(AwsRegionProvider.class);
assertThat(awsCredentialsProvider).isNotNull();
assertThat(awsRegionProvider).isNotNull();
var credentials = awsCredentialsProvider.resolveCredentials();
assertThat(credentials).isNotNull();
assertThat(credentials.accessKeyId()).isEqualTo("CUSTOM_ACCESS_KEY");
assertThat(credentials.secretAccessKey()).isEqualTo("CUSTOM_SECRET_ACCESS_KEY");
assertThat(awsRegionProvider.getRegion()).isEqualTo(Region.AWS_GLOBAL);
});
}
@EnableConfigurationProperties({ BedrockAwsConnectionProperties.class })
@Import(BedrockAwsConnectionConfiguration.class)
static class TestAutoConfiguration {
}
@AutoConfiguration
static class CustomAwsCredentialsProviderAndAwsRegionProviderAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public AwsCredentialsProvider credentialsProvider() {
return new AwsCredentialsProvider() {
@Override
public AwsCredentials resolveCredentials() {
return new AwsCredentials() {
@Override
public String accessKeyId() {
return "CUSTOM_ACCESS_KEY";
}
@Override
public String secretAccessKey() {
return "CUSTOM_SECRET_ACCESS_KEY";
}
};
}
};
}
@Bean
@ConditionalOnMissingBean
public AwsRegionProvider regionProvider() {
return new AwsRegionProvider() {
@Override
public Region getRegion() {
return Region.AWS_GLOBAL;
}
};
}
}
}