Skip to content

Commit ae8d1ab

Browse files
committed
any UT for internalTooolExecutionMaxAttempts
Signed-off-by: lambochen <[email protected]>
1 parent fcf1a76 commit ae8d1ab

File tree

13 files changed

+126
-8
lines changed

13 files changed

+126
-8
lines changed

models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatOptions.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ public static AnthropicChatOptions fromOptions(AnthropicChatOptions fromOptions)
113113
fromOptions.getToolCallbacks() != null ? new ArrayList<>(fromOptions.getToolCallbacks()) : null)
114114
.toolNames(fromOptions.getToolNames() != null ? new HashSet<>(fromOptions.getToolNames()) : null)
115115
.internalToolExecutionEnabled(fromOptions.getInternalToolExecutionEnabled())
116+
.internalToolExecutionMaxAttempts(fromOptions.getInternalToolExecutionMaxAttempts())
116117
.toolContext(fromOptions.getToolContext() != null ? new HashMap<>(fromOptions.getToolContext()) : null)
117118
.httpHeaders(fromOptions.getHttpHeaders() != null ? new HashMap<>(fromOptions.getHttpHeaders()) : null)
118119
.build();
@@ -236,7 +237,7 @@ public Integer getInternalToolExecutionMaxAttempts() {
236237
}
237238

238239
@Override
239-
public void setInternalToolExecutionMaxAttempts(Integer internalToolExecutionMaxAttempts) {
240+
public void setInternalToolExecutionMaxAttempts(@Nullable Integer internalToolExecutionMaxAttempts) {
240241
this.internalToolExecutionMaxAttempts = internalToolExecutionMaxAttempts;
241242
}
242243

@@ -295,14 +296,16 @@ public boolean equals(Object o) {
295296
&& Objects.equals(this.toolCallbacks, that.toolCallbacks)
296297
&& Objects.equals(this.toolNames, that.toolNames)
297298
&& Objects.equals(this.internalToolExecutionEnabled, that.internalToolExecutionEnabled)
299+
&& Objects.equals(this.internalToolExecutionMaxAttempts, that.internalToolExecutionMaxAttempts)
298300
&& Objects.equals(this.toolContext, that.toolContext)
299301
&& Objects.equals(this.httpHeaders, that.httpHeaders);
300302
}
301303

302304
@Override
303305
public int hashCode() {
304306
return Objects.hash(this.model, this.maxTokens, this.metadata, this.stopSequences, this.temperature, this.topP,
305-
this.topK, this.thinking, this.toolCallbacks, this.toolNames, this.internalToolExecutionEnabled,
307+
this.topK, this.thinking, this.toolCallbacks, this.toolNames,
308+
this.internalToolExecutionEnabled, this.internalToolExecutionMaxAttempts,
306309
this.toolContext, this.httpHeaders);
307310
}
308311

@@ -388,6 +391,11 @@ public Builder internalToolExecutionEnabled(@Nullable Boolean internalToolExecut
388391
return this;
389392
}
390393

394+
public Builder internalToolExecutionMaxAttempts(@Nullable Integer internalToolExecutionMaxAttempts) {
395+
this.options.setInternalToolExecutionMaxAttempts(internalToolExecutionMaxAttempts);
396+
return this;
397+
}
398+
391399
public Builder toolContext(Map<String, Object> toolContext) {
392400
if (this.options.toolContext == null) {
393401
this.options.toolContext = toolContext;

models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatOptionsTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
import org.junit.jupiter.api.Test;
2323

2424
import org.springframework.ai.anthropic.api.AnthropicApi.ChatCompletionRequest.Metadata;
25+
import org.springframework.ai.model.tool.ToolCallingChatOptions;
2526

2627
import static org.assertj.core.api.Assertions.assertThat;
2728

2829
/**
2930
* Tests for {@link AnthropicChatOptions}.
3031
*
3132
* @author Alexandros Pappas
33+
* @author lambochen
3234
*/
3335
class AnthropicChatOptionsTests {
3436

@@ -59,6 +61,7 @@ void testCopy() {
5961
.topK(50)
6062
.metadata(new Metadata("userId_123"))
6163
.toolContext(Map.of("key1", "value1"))
64+
.internalToolExecutionMaxAttempts(3)
6265
.build();
6366

6467
AnthropicChatOptions copied = original.copy();
@@ -67,6 +70,8 @@ void testCopy() {
6770
// Ensure deep copy
6871
assertThat(copied.getStopSequences()).isNotSameAs(original.getStopSequences());
6972
assertThat(copied.getToolContext()).isNotSameAs(original.getToolContext());
73+
74+
assertThat(copied.getInternalToolExecutionMaxAttempts()).isEqualTo(3);
7075
}
7176

7277
@Test
@@ -99,6 +104,7 @@ void testDefaultValues() {
99104
assertThat(options.getTopP()).isNull();
100105
assertThat(options.getStopSequences()).isNull();
101106
assertThat(options.getMetadata()).isNull();
107+
assertThat(options.getInternalToolExecutionMaxAttempts()).isEqualTo(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS);
102108
}
103109

104110
}

models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatOptions.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ public static AzureOpenAiChatOptions fromOptions(AzureOpenAiChatOptions fromOpti
298298
.enhancements(fromOptions.getEnhancements())
299299
.toolContext(fromOptions.getToolContext() != null ? new HashMap<>(fromOptions.getToolContext()) : null)
300300
.internalToolExecutionEnabled(fromOptions.getInternalToolExecutionEnabled())
301+
.internalToolExecutionMaxAttempts(fromOptions.getInternalToolExecutionMaxAttempts())
301302
.streamOptions(fromOptions.getStreamOptions())
302303
.toolCallbacks(
303304
fromOptions.getToolCallbacks() != null ? new ArrayList<>(fromOptions.getToolCallbacks()) : null)
@@ -679,8 +680,8 @@ public Builder internalToolExecutionEnabled(@Nullable Boolean internalToolExecut
679680
return this;
680681
}
681682

682-
public Builder internalToolExecutionMaxIterations(@Nullable Integer internalToolExecutionMaxIterations) {
683-
this.options.setInternalToolExecutionMaxAttempts(internalToolExecutionMaxIterations);
683+
public Builder internalToolExecutionMaxAttempts(@Nullable Integer internalToolExecutionMaxAttempts) {
684+
this.options.setInternalToolExecutionMaxAttempts(internalToolExecutionMaxAttempts);
684685
return this;
685686
}
686687

models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatCompletionRequestTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
* @author Ricken Bazolo
3636
* @author Alexandros Pappas
3737
* @author Thomas Vitale
38+
* @author lambochen
3839
* @since 0.8.1
3940
*/
4041
@SpringBootTest(classes = MistralAiTestConfiguration.class)
@@ -73,6 +74,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
7374
MistralAiChatOptions defaultOptions = MistralAiChatOptions.builder()
7475
.model("DEFAULT_MODEL")
7576
.internalToolExecutionEnabled(true)
77+
.internalToolExecutionMaxAttempts(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS)
7678
.toolCallbacks(new TestToolCallback("tool1"), new TestToolCallback("tool2"))
7779
.toolNames("tool1", "tool2")
7880
.toolContext(Map.of("key1", "value1", "key2", "valueA"))
@@ -85,6 +87,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
8587

8688
MistralAiChatOptions runtimeOptions = MistralAiChatOptions.builder()
8789
.internalToolExecutionEnabled(false)
90+
.internalToolExecutionMaxAttempts(3)
8891
.toolCallbacks(new TestToolCallback("tool3"), new TestToolCallback("tool4"))
8992
.toolNames("tool3")
9093
.toolContext(Map.of("key2", "valueB"))
@@ -93,6 +96,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
9396

9497
assertThat(((ToolCallingChatOptions) prompt.getOptions())).isNotNull();
9598
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getInternalToolExecutionEnabled()).isFalse();
99+
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getInternalToolExecutionMaxAttempts()).isEqualTo(3);
96100
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getToolCallbacks()).hasSize(2);
97101
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getToolCallbacks()
98102
.stream()

models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatRequestTests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
4747
OllamaOptions defaultOptions = OllamaOptions.builder()
4848
.model("MODEL_NAME")
4949
.internalToolExecutionEnabled(true)
50+
.internalToolExecutionMaxAttempts(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS)
5051
.toolCallbacks(new TestToolCallback("tool1"), new TestToolCallback("tool2"))
5152
.toolNames("tool1", "tool2")
5253
.toolContext(Map.of("key1", "value1", "key2", "valueA"))
@@ -58,6 +59,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
5859

5960
OllamaOptions runtimeOptions = OllamaOptions.builder()
6061
.internalToolExecutionEnabled(false)
62+
.internalToolExecutionMaxAttempts(3)
6163
.toolCallbacks(new TestToolCallback("tool3"), new TestToolCallback("tool4"))
6264
.toolNames("tool3")
6365
.toolContext(Map.of("key2", "valueB"))
@@ -66,6 +68,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
6668

6769
assertThat(((ToolCallingChatOptions) prompt.getOptions())).isNotNull();
6870
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getInternalToolExecutionEnabled()).isFalse();
71+
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getInternalToolExecutionMaxAttempts()).isEqualTo(3);
6972
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getToolCallbacks()).hasSize(2);
7073
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getToolCallbacks()
7174
.stream()

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
/**
3737
* @author Christian Tzolov
3838
* @author Thomas Vitale
39+
* @author lambochen
3940
*/
4041
class ChatCompletionRequestTests {
4142

@@ -44,6 +45,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
4445
OpenAiChatOptions defaultOptions = OpenAiChatOptions.builder()
4546
.model("DEFAULT_MODEL")
4647
.internalToolExecutionEnabled(true)
48+
.internalToolExecutionMaxAttempts(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS)
4749
.toolCallbacks(new TestToolCallback("tool1"), new TestToolCallback("tool2"))
4850
.toolNames("tool1", "tool2")
4951
.toolContext(Map.of("key1", "value1", "key2", "valueA"))
@@ -56,6 +58,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
5658

5759
OpenAiChatOptions runtimeOptions = OpenAiChatOptions.builder()
5860
.internalToolExecutionEnabled(false)
61+
.internalToolExecutionMaxAttempts(10)
5962
.toolCallbacks(new TestToolCallback("tool3"), new TestToolCallback("tool4"))
6063
.toolNames("tool3")
6164
.toolContext(Map.of("key2", "valueB"))
@@ -64,6 +67,7 @@ void whenToolRuntimeOptionsThenMergeWithDefaults() {
6467

6568
assertThat(((ToolCallingChatOptions) prompt.getOptions())).isNotNull();
6669
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getInternalToolExecutionEnabled()).isFalse();
70+
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getInternalToolExecutionMaxAttempts()).isEqualTo(10);
6771
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getToolCallbacks()).hasSize(2);
6872
assertThat(((ToolCallingChatOptions) prompt.getOptions()).getToolCallbacks()
6973
.stream()

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/OpenAiChatOptionsTests.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.junit.jupiter.api.Test;
2525

26+
import org.springframework.ai.model.tool.ToolCallingChatOptions;
2627
import org.springframework.ai.openai.api.OpenAiApi;
2728
import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.AudioParameters;
2829
import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.StreamOptions;
@@ -80,6 +81,7 @@ void testBuilderWithAllFields() {
8081
.metadata(metadata)
8182
.reasoningEffort("medium")
8283
.internalToolExecutionEnabled(false)
84+
.internalToolExecutionMaxAttempts(10)
8385
.httpHeaders(Map.of("header1", "value1"))
8486
.toolContext(toolContext)
8587
.build();
@@ -88,11 +90,12 @@ void testBuilderWithAllFields() {
8890
.extracting("model", "frequencyPenalty", "logitBias", "logprobs", "topLogprobs", "maxTokens",
8991
"maxCompletionTokens", "n", "outputModalities", "outputAudio", "presencePenalty", "responseFormat",
9092
"streamOptions", "seed", "stop", "temperature", "topP", "tools", "toolChoice", "user",
91-
"parallelToolCalls", "store", "metadata", "reasoningEffort", "internalToolExecutionEnabled",
93+
"parallelToolCalls", "store", "metadata", "reasoningEffort",
94+
"internalToolExecutionEnabled", "internalToolExecutionMaxAttempts",
9295
"httpHeaders", "toolContext")
9396
.containsExactly("test-model", 0.5, logitBias, true, 5, 100, 50, 2, outputModalities, outputAudio, 0.8,
9497
responseFormat, streamOptions, 12345, stopSequences, 0.7, 0.9, tools, toolChoice, "test-user", true,
95-
false, metadata, "medium", false, Map.of("header1", "value1"), toolContext);
98+
false, metadata, "medium", false, 10, Map.of("header1", "value1"), toolContext);
9699

97100
assertThat(options.getStreamUsage()).isTrue();
98101
assertThat(options.getStreamOptions()).isEqualTo(StreamOptions.INCLUDE_USAGE);
@@ -139,6 +142,7 @@ void testCopy() {
139142
.metadata(metadata)
140143
.reasoningEffort("low")
141144
.internalToolExecutionEnabled(true)
145+
.internalToolExecutionMaxAttempts(3)
142146
.httpHeaders(Map.of("header1", "value1"))
143147
.build();
144148

@@ -187,6 +191,7 @@ void testSetters() {
187191
options.setMetadata(metadata);
188192
options.setReasoningEffort("high");
189193
options.setInternalToolExecutionEnabled(false);
194+
options.setInternalToolExecutionMaxAttempts(3);
190195
options.setHttpHeaders(Map.of("header2", "value2"));
191196

192197
assertThat(options.getModel()).isEqualTo("test-model");
@@ -214,6 +219,7 @@ void testSetters() {
214219
assertThat(options.getMetadata()).isEqualTo(metadata);
215220
assertThat(options.getReasoningEffort()).isEqualTo("high");
216221
assertThat(options.getInternalToolExecutionEnabled()).isFalse();
222+
assertThat(options.getInternalToolExecutionMaxAttempts()).isEqualTo(3);
217223
assertThat(options.getHttpHeaders()).isEqualTo(Map.of("header2", "value2"));
218224
assertThat(options.getStreamUsage()).isTrue();
219225
options.setStreamUsage(false);
@@ -253,6 +259,7 @@ void testDefaultValues() {
253259
assertThat(options.getReasoningEffort()).isNull();
254260
assertThat(options.getToolCallbacks()).isNotNull().isEmpty();
255261
assertThat(options.getInternalToolExecutionEnabled()).isNull();
262+
assertThat(options.getInternalToolExecutionMaxAttempts()).isEqualTo(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS);
256263
assertThat(options.getHttpHeaders()).isNotNull().isEmpty();
257264
assertThat(options.getToolContext()).isEqualTo(new HashMap<>());
258265
assertThat(options.getStreamUsage()).isFalse();

models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ public static VertexAiGeminiChatOptions fromOptions(VertexAiGeminiChatOptions fr
165165
options.setGoogleSearchRetrieval(fromOptions.getGoogleSearchRetrieval());
166166
options.setSafetySettings(fromOptions.getSafetySettings());
167167
options.setInternalToolExecutionEnabled(fromOptions.getInternalToolExecutionEnabled());
168+
options.setInternalToolExecutionMaxAttempts(fromOptions.getInternalToolExecutionMaxAttempts());
168169
options.setToolContext(fromOptions.getToolContext());
169170
return options;
170171
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.springframework.ai.vertexai.gemini;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.springframework.ai.model.tool.ToolCallingChatOptions;
5+
6+
import static org.junit.jupiter.api.Assertions.*;
7+
8+
class VertexAiGeminiChatOptionsTest {
9+
10+
@Test
11+
void optionsDefault() {
12+
var options = new VertexAiGeminiChatOptions();
13+
14+
assertEquals(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS, options.getInternalToolExecutionMaxAttempts());
15+
}
16+
17+
@Test
18+
void builderDefault() {
19+
var options = VertexAiGeminiChatOptions.builder().build();
20+
21+
assertEquals(ToolCallingChatOptions.DEFAULT_TOOL_EXECUTION_MAX_ATTEMPTS, options.getInternalToolExecutionMaxAttempts());
22+
}
23+
24+
@Test
25+
void testBuilder() {
26+
var options = VertexAiGeminiChatOptions.builder()
27+
.internalToolExecutionMaxAttempts(3)
28+
.build();
29+
30+
assertEquals(3, options.getInternalToolExecutionMaxAttempts());
31+
}
32+
33+
@Test
34+
void fromOptions() {
35+
var original = new VertexAiGeminiChatOptions();
36+
original.setInternalToolExecutionMaxAttempts(3);
37+
38+
var copied = VertexAiGeminiChatOptions.fromOptions(original);
39+
40+
assertEquals(original.getInternalToolExecutionMaxAttempts(), copied.getInternalToolExecutionMaxAttempts());
41+
}
42+
}

spring-ai-model/src/main/java/org/springframework/ai/model/tool/DefaultToolCallingChatOptions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public Integer getInternalToolExecutionMaxAttempts() {
128128
}
129129

130130
@Override
131-
public void setInternalToolExecutionMaxAttempts(Integer internalToolExecutionMaxAttempts) {
131+
public void setInternalToolExecutionMaxAttempts(@Nullable Integer internalToolExecutionMaxAttempts) {
132132
this.internalToolExecutionMaxAttempts = internalToolExecutionMaxAttempts;
133133
}
134134

@@ -294,7 +294,7 @@ public ToolCallingChatOptions.Builder internalToolExecutionEnabled(
294294

295295
@Override
296296
public ToolCallingChatOptions.Builder internalToolExecutionMaxAttempts(
297-
Integer internalToolExecutionMaxAttempts) {
297+
@Nullable Integer internalToolExecutionMaxAttempts) {
298298
this.options.setInternalToolExecutionMaxAttempts(internalToolExecutionMaxAttempts);
299299
return this;
300300
}

0 commit comments

Comments
 (0)