Skip to content

Commit 2b0b45b

Browse files
sdeleuzesobychacko
authored andcommitted
Remove Bedrock setters from options
- Remove `@NestedConfigurationProperty` from `BedrockConverseProxyChatProperties` - Expose options directly under the `spring.ai.bedrock.chat` prefix instead of `spring.ai.bedrock.chat.options` - Implement Spring Boot deprecation mechanism for the legacy `options` nested properties to gracefully guide users during upgrades Signed-off-by: Sébastien Deleuze <sdeleuze@users.noreply.github.com>
1 parent a4e99c5 commit 2b0b45b

9 files changed

Lines changed: 284 additions & 98 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* @author Christian Tzolov
5050
* @author Wei Jiang
5151
* @author Pawel Potaczala
52+
* @author Sébastien Deleuze
5253
*/
5354
@AutoConfiguration
5455
@EnableConfigurationProperties({ BedrockConverseProxyChatProperties.class, BedrockAwsConnectionConfiguration.class })
@@ -78,7 +79,7 @@ public BedrockProxyChatModel bedrockProxyChatModel(AwsCredentialsProvider creden
7879
.asyncReadTimeout(connectionProperties.getAsyncReadTimeout())
7980
.connectionAcquisitionTimeout(connectionProperties.getConnectionAcquisitionTimeout())
8081
.socketTimeout(connectionProperties.getSocketTimeout())
81-
.defaultOptions(chatProperties.getOptions())
82+
.defaultOptions(chatProperties.toOptions())
8283
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
8384
.toolCallingManager(toolCallingManager)
8485
.toolExecutionEligibilityPredicate(

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

Lines changed: 254 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@
1616

1717
package org.springframework.ai.model.bedrock.converse.autoconfigure;
1818

19+
import java.util.HashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
import org.jspecify.annotations.Nullable;
24+
1925
import org.springframework.ai.bedrock.converse.BedrockChatOptions;
26+
import org.springframework.ai.bedrock.converse.api.BedrockCacheOptions;
2027
import org.springframework.boot.context.properties.ConfigurationProperties;
21-
import org.springframework.boot.context.properties.NestedConfigurationProperty;
28+
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
2229

2330
/**
2431
* Configuration properties for Bedrock Converse.
2532
*
2633
* @author Christian Tzolov
2734
* @author Josh Long
35+
* @author Sébastien Deleuze
2836
* @since 1.0.0
2937
*/
3038
@ConfigurationProperties(BedrockConverseProxyChatProperties.CONFIG_PREFIX)
@@ -37,12 +45,29 @@ public class BedrockConverseProxyChatProperties {
3745
*/
3846
private boolean enabled;
3947

40-
@NestedConfigurationProperty
41-
private final BedrockChatOptions options = BedrockChatOptions.builder().temperature(0.7).maxTokens(300).build();
48+
private @Nullable String model;
4249

43-
public BedrockChatOptions getOptions() {
44-
return this.options;
45-
}
50+
private @Nullable Double frequencyPenalty;
51+
52+
private @Nullable Integer maxTokens = 300;
53+
54+
private @Nullable Double presencePenalty;
55+
56+
private Map<String, String> requestParameters = new HashMap<>();
57+
58+
private @Nullable List<String> stopSequences;
59+
60+
private @Nullable Double temperature = 0.7;
61+
62+
private @Nullable Integer topK;
63+
64+
private @Nullable Double topP;
65+
66+
private @Nullable Boolean internalToolExecutionEnabled;
67+
68+
private @Nullable BedrockCacheOptions cacheOptions;
69+
70+
private final Options options = new Options();
4671

4772
public boolean isEnabled() {
4873
return this.enabled;
@@ -52,4 +77,227 @@ public void setEnabled(boolean enabled) {
5277
this.enabled = enabled;
5378
}
5479

80+
public @Nullable String getModel() {
81+
return this.model;
82+
}
83+
84+
public void setModel(@Nullable String model) {
85+
this.model = model;
86+
}
87+
88+
public @Nullable Double getFrequencyPenalty() {
89+
return this.frequencyPenalty;
90+
}
91+
92+
public void setFrequencyPenalty(@Nullable Double frequencyPenalty) {
93+
this.frequencyPenalty = frequencyPenalty;
94+
}
95+
96+
public @Nullable Integer getMaxTokens() {
97+
return this.maxTokens;
98+
}
99+
100+
public void setMaxTokens(@Nullable Integer maxTokens) {
101+
this.maxTokens = maxTokens;
102+
}
103+
104+
public @Nullable Double getPresencePenalty() {
105+
return this.presencePenalty;
106+
}
107+
108+
public void setPresencePenalty(@Nullable Double presencePenalty) {
109+
this.presencePenalty = presencePenalty;
110+
}
111+
112+
public Map<String, String> getRequestParameters() {
113+
return this.requestParameters;
114+
}
115+
116+
public void setRequestParameters(Map<String, String> requestParameters) {
117+
this.requestParameters = requestParameters;
118+
}
119+
120+
public @Nullable List<String> getStopSequences() {
121+
return this.stopSequences;
122+
}
123+
124+
public void setStopSequences(@Nullable List<String> stopSequences) {
125+
this.stopSequences = stopSequences;
126+
}
127+
128+
public @Nullable Double getTemperature() {
129+
return this.temperature;
130+
}
131+
132+
public void setTemperature(@Nullable Double temperature) {
133+
this.temperature = temperature;
134+
}
135+
136+
public @Nullable Integer getTopK() {
137+
return this.topK;
138+
}
139+
140+
public void setTopK(@Nullable Integer topK) {
141+
this.topK = topK;
142+
}
143+
144+
public @Nullable Double getTopP() {
145+
return this.topP;
146+
}
147+
148+
public void setTopP(@Nullable Double topP) {
149+
this.topP = topP;
150+
}
151+
152+
public @Nullable Boolean getInternalToolExecutionEnabled() {
153+
return this.internalToolExecutionEnabled;
154+
}
155+
156+
public void setInternalToolExecutionEnabled(@Nullable Boolean internalToolExecutionEnabled) {
157+
this.internalToolExecutionEnabled = internalToolExecutionEnabled;
158+
}
159+
160+
public @Nullable BedrockCacheOptions getCacheOptions() {
161+
return this.cacheOptions;
162+
}
163+
164+
public void setCacheOptions(@Nullable BedrockCacheOptions cacheOptions) {
165+
this.cacheOptions = cacheOptions;
166+
}
167+
168+
public Options getOptions() {
169+
return this.options;
170+
}
171+
172+
public BedrockChatOptions toOptions() {
173+
return BedrockChatOptions.builder()
174+
.model(this.model)
175+
.frequencyPenalty(this.frequencyPenalty)
176+
.maxTokens(this.maxTokens)
177+
.presencePenalty(this.presencePenalty)
178+
.requestParameters(this.requestParameters)
179+
.stopSequences(this.stopSequences)
180+
.temperature(this.temperature)
181+
.topK(this.topK)
182+
.topP(this.topP)
183+
.internalToolExecutionEnabled(this.internalToolExecutionEnabled)
184+
.cacheOptions(this.cacheOptions)
185+
.build();
186+
}
187+
188+
public class Options {
189+
190+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.model")
191+
@Deprecated(since = "2.0.0", forRemoval = true)
192+
public @Nullable String getModel() {
193+
return BedrockConverseProxyChatProperties.this.getModel();
194+
}
195+
196+
public void setModel(@Nullable String model) {
197+
BedrockConverseProxyChatProperties.this.setModel(model);
198+
}
199+
200+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.frequency-penalty")
201+
@Deprecated(since = "2.0.0", forRemoval = true)
202+
public @Nullable Double getFrequencyPenalty() {
203+
return BedrockConverseProxyChatProperties.this.getFrequencyPenalty();
204+
}
205+
206+
public void setFrequencyPenalty(@Nullable Double frequencyPenalty) {
207+
BedrockConverseProxyChatProperties.this.setFrequencyPenalty(frequencyPenalty);
208+
}
209+
210+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.max-tokens")
211+
@Deprecated(since = "2.0.0", forRemoval = true)
212+
public @Nullable Integer getMaxTokens() {
213+
return BedrockConverseProxyChatProperties.this.getMaxTokens();
214+
}
215+
216+
public void setMaxTokens(@Nullable Integer maxTokens) {
217+
BedrockConverseProxyChatProperties.this.setMaxTokens(maxTokens);
218+
}
219+
220+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.presence-penalty")
221+
@Deprecated(since = "2.0.0", forRemoval = true)
222+
public @Nullable Double getPresencePenalty() {
223+
return BedrockConverseProxyChatProperties.this.getPresencePenalty();
224+
}
225+
226+
public void setPresencePenalty(@Nullable Double presencePenalty) {
227+
BedrockConverseProxyChatProperties.this.setPresencePenalty(presencePenalty);
228+
}
229+
230+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.request-parameters")
231+
@Deprecated(since = "2.0.0", forRemoval = true)
232+
public Map<String, String> getRequestParameters() {
233+
return BedrockConverseProxyChatProperties.this.getRequestParameters();
234+
}
235+
236+
public void setRequestParameters(Map<String, String> requestParameters) {
237+
BedrockConverseProxyChatProperties.this.setRequestParameters(requestParameters);
238+
}
239+
240+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.stop-sequences")
241+
@Deprecated(since = "2.0.0", forRemoval = true)
242+
public @Nullable List<String> getStopSequences() {
243+
return BedrockConverseProxyChatProperties.this.getStopSequences();
244+
}
245+
246+
public void setStopSequences(@Nullable List<String> stopSequences) {
247+
BedrockConverseProxyChatProperties.this.setStopSequences(stopSequences);
248+
}
249+
250+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.temperature")
251+
@Deprecated(since = "2.0.0", forRemoval = true)
252+
public @Nullable Double getTemperature() {
253+
return BedrockConverseProxyChatProperties.this.getTemperature();
254+
}
255+
256+
public void setTemperature(@Nullable Double temperature) {
257+
BedrockConverseProxyChatProperties.this.setTemperature(temperature);
258+
}
259+
260+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.top-k")
261+
@Deprecated(since = "2.0.0", forRemoval = true)
262+
public @Nullable Integer getTopK() {
263+
return BedrockConverseProxyChatProperties.this.getTopK();
264+
}
265+
266+
public void setTopK(@Nullable Integer topK) {
267+
BedrockConverseProxyChatProperties.this.setTopK(topK);
268+
}
269+
270+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.top-p")
271+
@Deprecated(since = "2.0.0", forRemoval = true)
272+
public @Nullable Double getTopP() {
273+
return BedrockConverseProxyChatProperties.this.getTopP();
274+
}
275+
276+
public void setTopP(@Nullable Double topP) {
277+
BedrockConverseProxyChatProperties.this.setTopP(topP);
278+
}
279+
280+
@DeprecatedConfigurationProperty(
281+
replacement = "spring.ai.bedrock.converse.chat.internal-tool-execution-enabled")
282+
@Deprecated(since = "2.0.0", forRemoval = true)
283+
public @Nullable Boolean getInternalToolExecutionEnabled() {
284+
return BedrockConverseProxyChatProperties.this.getInternalToolExecutionEnabled();
285+
}
286+
287+
public void setInternalToolExecutionEnabled(@Nullable Boolean internalToolExecutionEnabled) {
288+
BedrockConverseProxyChatProperties.this.setInternalToolExecutionEnabled(internalToolExecutionEnabled);
289+
}
290+
291+
@DeprecatedConfigurationProperty(replacement = "spring.ai.bedrock.converse.chat.cache-options")
292+
@Deprecated(since = "2.0.0", forRemoval = true)
293+
public @Nullable BedrockCacheOptions getCacheOptions() {
294+
return BedrockConverseProxyChatProperties.this.getCacheOptions();
295+
}
296+
297+
public void setCacheOptions(@Nullable BedrockCacheOptions cacheOptions) {
298+
BedrockConverseProxyChatProperties.this.setCacheOptions(cacheOptions);
299+
}
300+
301+
}
302+
55303
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ public class BedrockConverseProxyChatAutoConfigurationIT {
4444
private static final Log logger = LogFactory.getLog(BedrockConverseProxyChatAutoConfigurationIT.class);
4545

4646
private final ApplicationContextRunner contextRunner = BedrockTestUtils.getContextRunner()
47-
.withPropertyValues(
48-
"spring.ai.bedrock.converse.chat.options.model=" + "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
49-
"spring.ai.bedrock.converse.chat.options.temperature=0.5")
47+
.withPropertyValues("spring.ai.bedrock.converse.chat.model=" + "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
48+
"spring.ai.bedrock.converse.chat.temperature=0.5")
5049
.withConfiguration(AutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class,
5150
ToolCallingAutoConfiguration.class));
5251

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
* @author Christian Tzolov
3030
* @author Pawel Potaczala
3131
* @author Issam El-atif
32+
* @author Sebastien Deleuze
3233
*
3334
* Unit Tests for {@link BedrockConverseProxyChatProperties}.
3435
*/
@@ -39,28 +40,27 @@ public void chatOptionsTest() {
3940

4041
new ApplicationContextRunner().withPropertyValues(
4142
// @formatter:off
42-
"spring.ai.bedrock.converse.chat.options.model=MODEL_XYZ",
43+
"spring.ai.bedrock.converse.chat.model=MODEL_XYZ",
4344

44-
"spring.ai.bedrock.converse.chat.options.max-tokens=123",
45-
"spring.ai.bedrock.converse.chat.options.metadata.user-id=MyUserId",
46-
"spring.ai.bedrock.converse.chat.options.stop_sequences=boza,koza",
45+
"spring.ai.bedrock.converse.chat.max-tokens=123",
46+
"spring.ai.bedrock.converse.chat.stop-sequences=boza,koza",
4747

48-
"spring.ai.bedrock.converse.chat.options.temperature=0.55",
49-
"spring.ai.bedrock.converse.chat.options.top-p=0.56",
50-
"spring.ai.bedrock.converse.chat.options.top-k=100"
48+
"spring.ai.bedrock.converse.chat.temperature=0.55",
49+
"spring.ai.bedrock.converse.chat.top-p=0.56",
50+
"spring.ai.bedrock.converse.chat.top-k=100"
5151
)
5252
// @formatter:on
5353
.withConfiguration(AutoConfigurations.of(BedrockConverseProxyChatAutoConfiguration.class,
5454
ToolCallingAutoConfiguration.class))
5555
.run(context -> {
5656
var chatProperties = context.getBean(BedrockConverseProxyChatProperties.class);
5757

58-
assertThat(chatProperties.getOptions().getModel()).isEqualTo("MODEL_XYZ");
59-
assertThat(chatProperties.getOptions().getMaxTokens()).isEqualTo(123);
60-
assertThat(chatProperties.getOptions().getStopSequences()).contains("boza", "koza");
61-
assertThat(chatProperties.getOptions().getTemperature()).isEqualTo(0.55);
62-
assertThat(chatProperties.getOptions().getTopP()).isEqualTo(0.56);
63-
assertThat(chatProperties.getOptions().getTopK()).isEqualTo(100);
58+
assertThat(chatProperties.getModel()).isEqualTo("MODEL_XYZ");
59+
assertThat(chatProperties.getMaxTokens()).isEqualTo(123);
60+
assertThat(chatProperties.getStopSequences()).contains("boza", "koza");
61+
assertThat(chatProperties.getTemperature()).isEqualTo(0.55);
62+
assertThat(chatProperties.getTopP()).isEqualTo(0.56);
63+
assertThat(chatProperties.getTopK()).isEqualTo(100);
6464

6565
});
6666
}

auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void functionCallTest() {
5757

5858
this.contextRunner
5959
.withPropertyValues(
60-
"spring.ai.bedrock.converse.chat.options.model=" + "us.anthropic.claude-haiku-4-5-20251001-v1:0")
60+
"spring.ai.bedrock.converse.chat.model=" + "us.anthropic.claude-haiku-4-5-20251001-v1:0")
6161
.run(context -> {
6262

6363
BedrockProxyChatModel chatModel = context.getBean(BedrockProxyChatModel.class);
@@ -86,7 +86,7 @@ void functionStreamTest() {
8686

8787
this.contextRunner
8888
.withPropertyValues(
89-
"spring.ai.bedrock.converse.chat.options.model=" + "us.anthropic.claude-haiku-4-5-20251001-v1:0")
89+
"spring.ai.bedrock.converse.chat.model=" + "us.anthropic.claude-haiku-4-5-20251001-v1:0")
9090
.run(context -> {
9191

9292
BedrockProxyChatModel chatModel = context.getBean(BedrockProxyChatModel.class);

auto-configurations/models/spring-ai-autoconfigure-model-bedrock-ai/src/test/java/org/springframework/ai/model/bedrock/converse/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class FunctionCallWithPromptFunctionIT {
5050
void functionCallTest() {
5151
this.contextRunner
5252
.withPropertyValues(
53-
"spring.ai.bedrock.converse.chat.options.model=" + "us.anthropic.claude-haiku-4-5-20251001-v1:0")
53+
"spring.ai.bedrock.converse.chat.model=" + "us.anthropic.claude-haiku-4-5-20251001-v1:0")
5454
.run(context -> {
5555

5656
BedrockProxyChatModel chatModel = context.getBean(BedrockProxyChatModel.class);

0 commit comments

Comments
 (0)