Skip to content

Commit cfec303

Browse files
committed
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 965b1d2 commit cfec303

File tree

5 files changed

+115
-11
lines changed

5 files changed

+115
-11
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(480L);
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 connectionTimeout;
114+
}
115+
116+
public void setConnectionTimeout(Duration connectionTimeout) {
117+
this.connectionTimeout = connectionTimeout;
118+
}
119+
120+
public Duration getAsyncReadTimeout() {
121+
return asyncReadTimeout;
122+
}
123+
124+
public void setAsyncReadTimeout(Duration asyncReadTimeout) {
125+
this.asyncReadTimeout = asyncReadTimeout;
126+
}
127+
128+
public Duration getConnectionAcquisitionTimeout() {
129+
return connectionAcquisitionTimeout;
130+
}
131+
132+
public void setConnectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) {
133+
this.connectionAcquisitionTimeout = connectionAcquisitionTimeout;
134+
}
135+
136+
public Duration getSocketTimeout() {
137+
return 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
@@ -76,6 +76,10 @@ public BedrockProxyChatModel bedrockProxyChatModel(AwsCredentialsProvider creden
7676
.credentialsProvider(credentialsProvider)
7777
.region(regionProvider.getRegion())
7878
.timeout(connectionProperties.getTimeout())
79+
.connectionTimeout(connectionProperties.getConnectionTimeout())
80+
.asyncReadTimeout(connectionProperties.getAsyncReadTimeout())
81+
.connectionAcquisitionTimeout(connectionProperties.getConnectionAcquisitionTimeout())
82+
.socketTimeout(connectionProperties.getSocketTimeout())
7983
.defaultOptions(chatProperties.getOptions())
8084
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
8185
.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 & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import software.amazon.awssdk.core.SdkBytes;
4242
import software.amazon.awssdk.core.document.Document;
4343
import software.amazon.awssdk.core.exception.SdkClientException;
44+
import software.amazon.awssdk.http.apache.ApacheHttpClient;
4445
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
4546
import software.amazon.awssdk.regions.Region;
4647
import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
@@ -781,7 +782,15 @@ public static final class Builder {
781782

782783
private Region region = Region.US_EAST_1;
783784

784-
private Duration timeout = Duration.ofMinutes(10);
785+
private Duration timeout = Duration.ofMinutes(5L);
786+
787+
private Duration connectionTimeout = Duration.ofSeconds(5L);
788+
789+
private Duration asyncReadTimeout = Duration.ofSeconds(30L);
790+
791+
private Duration connectionAcquisitionTimeout = Duration.ofSeconds(30L);
792+
793+
private Duration socketTimeout = Duration.ofSeconds(30L);
785794

786795
private ToolCallingManager toolCallingManager;
787796

@@ -835,6 +844,30 @@ public Builder timeout(Duration timeout) {
835844
return this;
836845
}
837846

847+
public Builder connectionTimeout(Duration connectionTimeout) {
848+
Assert.notNull(connectionTimeout, "'connectionTimeout' must not be null.");
849+
this.connectionTimeout = connectionTimeout;
850+
return this;
851+
}
852+
853+
public Builder asyncReadTimeout(Duration asyncReadTimeout) {
854+
Assert.notNull(asyncReadTimeout, "'asyncReadTimeout' must not be null.");
855+
this.asyncReadTimeout = asyncReadTimeout;
856+
return this;
857+
}
858+
859+
public Builder connectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) {
860+
Assert.notNull(connectionAcquisitionTimeout, "'connectionAcquisitionTimeout' must not be null.");
861+
this.connectionAcquisitionTimeout = connectionAcquisitionTimeout;
862+
return this;
863+
}
864+
865+
public Builder socketTimeout(Duration socketTimeout) {
866+
Assert.notNull(socketTimeout, "'socketTimeout' must not be null.");
867+
this.socketTimeout = socketTimeout;
868+
return this;
869+
}
870+
838871
public Builder defaultOptions(ToolCallingChatOptions defaultOptions) {
839872
Assert.notNull(defaultOptions, "'defaultOptions' must not be null.");
840873
this.defaultOptions = defaultOptions;
@@ -864,22 +897,28 @@ public Builder bedrockRuntimeAsyncClient(BedrockRuntimeAsyncClient bedrockRuntim
864897
}
865898

866899
public BedrockProxyChatModel build() {
867-
868900
if (this.bedrockRuntimeClient == null) {
901+
902+
var httpClientBuilder = ApacheHttpClient.builder()
903+
.connectionAcquisitionTimeout(connectionAcquisitionTimeout)
904+
.connectionTimeout(this.connectionTimeout)
905+
.socketTimeout(this.socketTimeout);
906+
869907
this.bedrockRuntimeClient = BedrockRuntimeClient.builder()
870908
.region(this.region)
871-
.httpClientBuilder(null)
909+
.httpClientBuilder(httpClientBuilder)
872910
.credentialsProvider(this.credentialsProvider)
873911
.overrideConfiguration(c -> c.apiCallTimeout(this.timeout))
874912
.build();
875913
}
876914

877915
if (this.bedrockRuntimeAsyncClient == null) {
878916

879-
// TODO: Is it ok to configure the NettyNioAsyncHttpClient explicitly???
880917
var httpClientBuilder = NettyNioAsyncHttpClient.builder()
881918
.tcpKeepAlive(true)
882-
.connectionAcquisitionTimeout(Duration.ofSeconds(30))
919+
.readTimeout(this.asyncReadTimeout)
920+
.connectionTimeout(this.connectionTimeout)
921+
.connectionAcquisitionTimeout(this.connectionAcquisitionTimeout)
883922
.maxConcurrency(200);
884923

885924
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)