Skip to content

Commit 34fc691

Browse files
cmiles74ilayaperumalg
authored andcommitted
Add more timeout configuration options for AWS Bedrock
When submitting large requests or receiving large response, AWS Bedrock request may experience latency that exceeds our default settings. Here we add additional configuration options to allow increasing these timeout settings. Signed-off-by: Christopher Miles <[email protected]>
1 parent d619727 commit 34fc691

File tree

5 files changed

+115
-10
lines changed

5 files changed

+115
-10
lines changed

auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/main/java/org/springframework/ai/model/bedrock/autoconfigure/BedrockAwsConnectionProperties.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,30 @@ public class BedrockAwsConnectionProperties {
5353
private String sessionToken;
5454

5555
/**
56-
* Set model timeout, Defaults 5 min.
56+
* Maximum duration of the entire API call operation.
5757
*/
5858
private Duration timeout = Duration.ofMinutes(5L);
5959

60+
/**
61+
* Maximum time to wait while establishing connection with AWS service.
62+
*/
63+
private Duration connectionTimeout = Duration.ofSeconds(5L);
64+
65+
/**
66+
* Maximum duration spent reading response data.
67+
*/
68+
private Duration asyncReadTimeout = Duration.ofSeconds(30L);
69+
70+
/**
71+
* Maximum time to wait for a new connection from the pool.
72+
*/
73+
private Duration connectionAcquisitionTimeout = Duration.ofSeconds(30L);
74+
75+
/**
76+
* Maximum time to wait for response data.
77+
*/
78+
private Duration socketTimeout = Duration.ofSeconds(90L);
79+
6080
public String getRegion() {
6181
return this.region;
6282
}
@@ -89,6 +109,38 @@ public void setTimeout(Duration timeout) {
89109
this.timeout = timeout;
90110
}
91111

112+
public Duration getConnectionTimeout() {
113+
return this.connectionTimeout;
114+
}
115+
116+
public void setConnectionTimeout(Duration connectionTimeout) {
117+
this.connectionTimeout = connectionTimeout;
118+
}
119+
120+
public Duration getAsyncReadTimeout() {
121+
return this.asyncReadTimeout;
122+
}
123+
124+
public void setAsyncReadTimeout(Duration asyncReadTimeout) {
125+
this.asyncReadTimeout = asyncReadTimeout;
126+
}
127+
128+
public Duration getConnectionAcquisitionTimeout() {
129+
return this.connectionAcquisitionTimeout;
130+
}
131+
132+
public void setConnectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) {
133+
this.connectionAcquisitionTimeout = connectionAcquisitionTimeout;
134+
}
135+
136+
public Duration getSocketTimeout() {
137+
return this.socketTimeout;
138+
}
139+
140+
public void setSocketTimeout(Duration socketTimeout) {
141+
this.socketTimeout = socketTimeout;
142+
}
143+
92144
public String getSessionToken() {
93145
return this.sessionToken;
94146
}

auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/main/java/org/springframework/ai/model/bedrock/converse/autoconfigure/BedrockConverseProxyChatAutoConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ public BedrockProxyChatModel bedrockProxyChatModel(AwsCredentialsProvider creden
7575
.credentialsProvider(credentialsProvider)
7676
.region(regionProvider.getRegion())
7777
.timeout(connectionProperties.getTimeout())
78+
.connectionTimeout(connectionProperties.getConnectionTimeout())
79+
.asyncReadTimeout(connectionProperties.getAsyncReadTimeout())
80+
.connectionAcquisitionTimeout(connectionProperties.getConnectionAcquisitionTimeout())
81+
.socketTimeout(connectionProperties.getSocketTimeout())
7882
.defaultOptions(chatProperties.getOptions())
7983
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
8084
.toolCallingManager(toolCallingManager)

models/spring-ai-bedrock-converse/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@
7676
<version>${bedrockruntime.version}</version>
7777
</dependency>
7878

79+
<dependency>
80+
<groupId>software.amazon.awssdk</groupId>
81+
<artifactId>apache-client</artifactId>
82+
<version>${bedrockruntime.version}</version>
83+
</dependency>
84+
7985
<!-- test dependencies -->
8086
<dependency>
8187
<groupId>org.springframework.ai</groupId>

models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import software.amazon.awssdk.core.SdkBytes;
4141
import software.amazon.awssdk.core.document.Document;
4242
import software.amazon.awssdk.core.exception.SdkClientException;
43+
import software.amazon.awssdk.http.apache.ApacheHttpClient;
4344
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
4445
import software.amazon.awssdk.regions.Region;
4546
import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
@@ -863,7 +864,15 @@ public static final class Builder {
863864

864865
private Region region = Region.US_EAST_1;
865866

866-
private Duration timeout = Duration.ofMinutes(10);
867+
private Duration timeout = Duration.ofMinutes(5L);
868+
869+
private Duration connectionTimeout = Duration.ofSeconds(5L);
870+
871+
private Duration asyncReadTimeout = Duration.ofSeconds(30L);
872+
873+
private Duration connectionAcquisitionTimeout = Duration.ofSeconds(30L);
874+
875+
private Duration socketTimeout = Duration.ofSeconds(30L);
867876

868877
private ToolCallingManager toolCallingManager;
869878

@@ -917,6 +926,30 @@ public Builder timeout(Duration timeout) {
917926
return this;
918927
}
919928

929+
public Builder connectionTimeout(Duration connectionTimeout) {
930+
Assert.notNull(connectionTimeout, "'connectionTimeout' must not be null.");
931+
this.connectionTimeout = connectionTimeout;
932+
return this;
933+
}
934+
935+
public Builder asyncReadTimeout(Duration asyncReadTimeout) {
936+
Assert.notNull(asyncReadTimeout, "'asyncReadTimeout' must not be null.");
937+
this.asyncReadTimeout = asyncReadTimeout;
938+
return this;
939+
}
940+
941+
public Builder connectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) {
942+
Assert.notNull(connectionAcquisitionTimeout, "'connectionAcquisitionTimeout' must not be null.");
943+
this.connectionAcquisitionTimeout = connectionAcquisitionTimeout;
944+
return this;
945+
}
946+
947+
public Builder socketTimeout(Duration socketTimeout) {
948+
Assert.notNull(socketTimeout, "'socketTimeout' must not be null.");
949+
this.socketTimeout = socketTimeout;
950+
return this;
951+
}
952+
920953
public Builder defaultOptions(BedrockChatOptions defaultOptions) {
921954
Assert.notNull(defaultOptions, "'defaultOptions' must not be null.");
922955
this.defaultOptions = defaultOptions;
@@ -948,20 +981,27 @@ public Builder bedrockRuntimeAsyncClient(BedrockRuntimeAsyncClient bedrockRuntim
948981
public BedrockProxyChatModel build() {
949982

950983
if (this.bedrockRuntimeClient == null) {
984+
985+
var httpClientBuilder = ApacheHttpClient.builder()
986+
.connectionAcquisitionTimeout(this.connectionAcquisitionTimeout)
987+
.connectionTimeout(this.connectionTimeout)
988+
.socketTimeout(this.socketTimeout);
989+
951990
this.bedrockRuntimeClient = BedrockRuntimeClient.builder()
952991
.region(this.region)
953-
.httpClientBuilder(null)
992+
.httpClientBuilder(httpClientBuilder)
954993
.credentialsProvider(this.credentialsProvider)
955994
.overrideConfiguration(c -> c.apiCallTimeout(this.timeout))
956995
.build();
957996
}
958997

959998
if (this.bedrockRuntimeAsyncClient == null) {
960999

961-
// TODO: Is it ok to configure the NettyNioAsyncHttpClient explicitly???
9621000
var httpClientBuilder = NettyNioAsyncHttpClient.builder()
9631001
.tcpKeepAlive(true)
964-
.connectionAcquisitionTimeout(Duration.ofSeconds(30))
1002+
.readTimeout(this.asyncReadTimeout)
1003+
.connectionTimeout(this.connectionTimeout)
1004+
.connectionAcquisitionTimeout(this.connectionAcquisitionTimeout)
9651005
.maxConcurrency(200);
9661006

9671007
var builder = BedrockRuntimeAsyncClient.builder()

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/bedrock-converse.adoc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,14 @@ The prefix `spring.ai.bedrock.aws` is the property prefix to configure the conne
7373
|====
7474
| Property | Description | Default
7575

76-
| spring.ai.bedrock.aws.region | AWS region to use. | us-east-1
77-
| spring.ai.bedrock.aws.timeout | AWS timeout to use. | 5m
78-
| spring.ai.bedrock.aws.access-key | AWS access key. | -
79-
| spring.ai.bedrock.aws.secret-key | AWS secret key. | -
80-
| spring.ai.bedrock.aws.session-token | AWS session token for temporary credentials. | -
76+
| spring.ai.bedrock.aws.region | AWS region to use | us-east-1
77+
| spring.ai.bedrock.aws.timeout | AWS max duration for entire API call | 5m
78+
| spring.ai.bedrock.aws.connectionTimeout | Max duration to wait while establishing connection | 5s
79+
| spring.ai.bedrock.aws.connectionAcquisitionTimeout | Max duration to wait for new connection from the pool | 30s
80+
| spring.ai.bedrock.aws.asyncReadTimeout | Max duration spent reading asynchronous responses | 30s
81+
| spring.ai.bedrock.aws.access-key | AWS access key | -
82+
| spring.ai.bedrock.aws.secret-key | AWS secret key | -
83+
| spring.ai.bedrock.aws.session-token | AWS session token for temporary credentials | -
8184
|====
8285

8386
[NOTE]

0 commit comments

Comments
 (0)