Skip to content

Commit 51ffd04

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 <twitch@nervestaple.com>
1 parent a216bf1 commit 51ffd04

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(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 & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import software.amazon.awssdk.core.SdkBytes;
4747
import software.amazon.awssdk.core.document.Document;
4848
import software.amazon.awssdk.core.exception.SdkClientException;
49+
import software.amazon.awssdk.http.apache.ApacheHttpClient;
4950
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
5051
import software.amazon.awssdk.regions.Region;
5152
import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
@@ -782,7 +783,15 @@ public static final class Builder {
782783

783784
private Region region = Region.US_EAST_1;
784785

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

787796
private ToolCallingManager toolCallingManager;
788797

@@ -836,6 +845,30 @@ public Builder timeout(Duration timeout) {
836845
return this;
837846
}
838847

848+
public Builder connectionTimeout(Duration connectionTimeout) {
849+
Assert.notNull(connectionTimeout, "'connectionTimeout' must not be null.");
850+
this.connectionTimeout = connectionTimeout;
851+
return this;
852+
}
853+
854+
public Builder asyncReadTimeout(Duration asyncReadTimeout) {
855+
Assert.notNull(asyncReadTimeout, "'asyncReadTimeout' must not be null.");
856+
this.asyncReadTimeout = asyncReadTimeout;
857+
return this;
858+
}
859+
860+
public Builder connectionAcquisitionTimeout(Duration connectionAcquisitionTimeout) {
861+
Assert.notNull(connectionAcquisitionTimeout, "'connectionAcquisitionTimeout' must not be null.");
862+
this.connectionAcquisitionTimeout = connectionAcquisitionTimeout;
863+
return this;
864+
}
865+
866+
public Builder socketTimeout(Duration socketTimeout) {
867+
Assert.notNull(socketTimeout, "'socketTimeout' must not be null.");
868+
this.socketTimeout = socketTimeout;
869+
return this;
870+
}
871+
839872
public Builder defaultOptions(BedrockChatOptions defaultOptions) {
840873
Assert.notNull(defaultOptions, "'defaultOptions' must not be null.");
841874
this.defaultOptions = defaultOptions;
@@ -867,20 +900,27 @@ public Builder bedrockRuntimeAsyncClient(BedrockRuntimeAsyncClient bedrockRuntim
867900
public BedrockProxyChatModel build() {
868901

869902
if (this.bedrockRuntimeClient == null) {
903+
904+
var httpClientBuilder = ApacheHttpClient.builder()
905+
.connectionAcquisitionTimeout(connectionAcquisitionTimeout)
906+
.connectionTimeout(this.connectionTimeout)
907+
.socketTimeout(this.socketTimeout);
908+
870909
this.bedrockRuntimeClient = BedrockRuntimeClient.builder()
871910
.region(this.region)
872-
.httpClientBuilder(null)
911+
.httpClientBuilder(httpClientBuilder)
873912
.credentialsProvider(this.credentialsProvider)
874913
.overrideConfiguration(c -> c.apiCallTimeout(this.timeout))
875914
.build();
876915
}
877916

878917
if (this.bedrockRuntimeAsyncClient == null) {
879918

880-
// TODO: Is it ok to configure the NettyNioAsyncHttpClient explicitly???
881919
var httpClientBuilder = NettyNioAsyncHttpClient.builder()
882920
.tcpKeepAlive(true)
883-
.connectionAcquisitionTimeout(Duration.ofSeconds(30))
921+
.readTimeout(this.asyncReadTimeout)
922+
.connectionTimeout(this.connectionTimeout)
923+
.connectionAcquisitionTimeout(this.connectionAcquisitionTimeout)
884924
.maxConcurrency(200);
885925

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