Skip to content

Commit 6a195ee

Browse files
tzolovilayaperumalg
authored andcommitted
refactor(core): extract common function callback builder functionality
Extracts shared function callback builder functionality into DefaultCommonCallbackInvokingSpec base class, reducing code duplication across builder implementations. Makes FunctionInvokingSpec and MethodInvokingSpec extend CommonCallbackInvokingSpec for better code organization. Also fixes function/description builder order in Anthropic tests. - Introduced a common base class for function callback builders to centralize shared logic - Standardized the order of method chaining for function and description in multiple AI model test classes - Refactored test cases across various AI model integrations - Corrected builder method order from .description().function() to .function().description() and .description().method() to .method().description() - Updated multiple test files to consistently use .function() before .description() - Updated documentation examples to reflect new builder method order - Modified DefaultFunctionCallbackResolver to maintain new builder method order - Updated DefaultChatClient and ChatClient test classes to reflect new builder pattern - Simplified callback specification by removing parent spec reference - Removed cascading getter logic for description, schema type, and other properties - Minor adjustments to function callback builder and invoking specs
1 parent dcc8d5b commit 6a195ee

File tree

72 files changed

+403
-318
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+403
-318
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,9 @@ void functionCallTest() {
276276
var promptOptions = AnthropicChatOptions.builder()
277277
.withModel(AnthropicApi.ChatModel.CLAUDE_3_OPUS.getName())
278278
.withFunctionCallbacks(List.of(FunctionCallback.builder()
279+
.function("getCurrentWeather", new MockWeatherService())
279280
.description(
280281
"Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.")
281-
.function("getCurrentWeather", new MockWeatherService())
282282
.inputType(MockWeatherService.Request.class)
283283
.build()))
284284
.build();
@@ -304,9 +304,9 @@ void streamFunctionCallTest() {
304304
var promptOptions = AnthropicChatOptions.builder()
305305
.withModel(AnthropicApi.ChatModel.CLAUDE_3_5_SONNET.getName())
306306
.withFunctionCallbacks(List.of(FunctionCallback.builder()
307+
.function("getCurrentWeather", new MockWeatherService())
307308
.description(
308309
"Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.")
309-
.function("getCurrentWeather", new MockWeatherService())
310310
.inputType(MockWeatherService.Request.class)
311311
.build()))
312312
.build();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ void defaultFunctionCallTest() {
250250
// @formatter:off
251251
String response = ChatClient.builder(this.chatModel)
252252
.defaultFunctions(FunctionCallback.builder()
253-
.description("Get the weather in location")
254253
.function("getCurrentWeather", new MockWeatherService())
254+
.description("Get the weather in location")
255255
.inputType(MockWeatherService.Request.class)
256256
.build())
257257
.defaultUser(u -> u.text("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius."))
@@ -273,8 +273,8 @@ void streamFunctionCallTest() {
273273
Flux<String> response = ChatClient.create(this.chatModel).prompt()
274274
.user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.")
275275
.functions(FunctionCallback.builder()
276-
.description("Get the weather in location")
277276
.function("getCurrentWeather", new MockWeatherService())
277+
.description("Get the weather in location")
278278
.inputType(MockWeatherService.Request.class)
279279
.build())
280280
.stream()

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ void methodGetWeatherStatic() {
8080
String response = ChatClient.create(this.chatModel).prompt()
8181
.user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.")
8282
.functions(FunctionCallback.builder()
83-
.description("Get the weather in location")
8483
.method("getWeatherStatic", String.class, Unit.class)
84+
.description("Get the weather in location")
8585
.targetClass(TestFunctionClass.class)
8686
.build())
8787
.call()
@@ -102,8 +102,8 @@ void methodTurnLightNoResponse() {
102102
String response = ChatClient.create(this.chatModel).prompt()
103103
.user("Turn light on in the living room.")
104104
.functions(FunctionCallback.builder()
105-
.description("Turn light on in the living room.")
106105
.method("turnLight", String.class, boolean.class)
106+
.description("Turn light on in the living room.")
107107
.targetObject(targetObject)
108108
.build())
109109
.call()
@@ -125,8 +125,8 @@ void methodGetWeatherNonStatic() {
125125
String response = ChatClient.create(this.chatModel).prompt()
126126
.user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.")
127127
.functions(FunctionCallback.builder()
128-
.description("Get the weather in location")
129128
.method("getWeatherNonStatic", String.class, Unit.class)
129+
.description("Get the weather in location")
130130
.targetObject(targetObject)
131131
.build())
132132
.call()
@@ -147,8 +147,8 @@ void methodGetWeatherToolContext() {
147147
String response = ChatClient.create(this.chatModel).prompt()
148148
.user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.")
149149
.functions(FunctionCallback.builder()
150-
.description("Get the weather in location")
151150
.method("getWeatherWithContext", String.class, Unit.class, ToolContext.class)
151+
.description("Get the weather in location")
152152
.targetObject(targetObject)
153153
.build())
154154
.toolContext(Map.of("tool", "value"))
@@ -174,8 +174,8 @@ void methodGetWeatherToolContextButNonContextMethod() {
174174
assertThatThrownBy(() -> ChatClient.create(this.chatModel).prompt()
175175
.user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.")
176176
.functions(FunctionCallback.builder()
177-
.description("Get the weather in location")
178177
.method("getWeatherNonStatic", String.class, Unit.class)
178+
.description("Get the weather in location")
179179
.targetObject(targetObject)
180180
.build())
181181
.toolContext(Map.of("tool", "value"))
@@ -195,8 +195,8 @@ void methodNoParameters() {
195195
String response = ChatClient.create(this.chatModel).prompt()
196196
.user("Turn light on in the living room.")
197197
.functions(FunctionCallback.builder()
198-
.description("Can turn lights on in the Living Room")
199198
.method("turnLivingRoomLightOn")
199+
.description("Can turn lights on in the Living Room")
200200
.targetObject(targetObject)
201201
.build())
202202
.call()

models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/function/AzureOpenAiChatModelFunctionCallIT.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ void functionCallTest() {
7070
var promptOptions = AzureOpenAiChatOptions.builder()
7171
.withDeploymentName(this.selectedModel)
7272
.withFunctionCallbacks(List.of(FunctionCallback.builder()
73-
.description("Get the current weather in a given location")
7473
.function("getCurrentWeather", new MockWeatherService())
74+
.description("Get the current weather in a given location")
7575
.inputType(MockWeatherService.Request.class)
7676
.build()))
7777
.build();
@@ -94,8 +94,8 @@ void functionCallSequentialTest() {
9494
var promptOptions = AzureOpenAiChatOptions.builder()
9595
.withDeploymentName(this.selectedModel)
9696
.withFunctionCallbacks(List.of(FunctionCallback.builder()
97-
.description("Get the current weather in a given location")
9897
.function("getCurrentWeather", new MockWeatherService())
98+
.description("Get the current weather in a given location")
9999
.inputType(MockWeatherService.Request.class)
100100
.build()))
101101
.build();
@@ -116,8 +116,8 @@ void streamFunctionCallTest() {
116116
var promptOptions = AzureOpenAiChatOptions.builder()
117117
.withDeploymentName(this.selectedModel)
118118
.withFunctionCallbacks(List.of(FunctionCallback.builder()
119-
.description("Get the current weather in a given location")
120119
.function("getCurrentWeather", new MockWeatherService())
120+
.description("Get the current weather in a given location")
121121
.inputType(MockWeatherService.Request.class)
122122
.build()))
123123
.build();
@@ -153,8 +153,8 @@ void functionCallSequentialAndStreamTest() {
153153
var promptOptions = AzureOpenAiChatOptions.builder()
154154
.withDeploymentName(this.selectedModel)
155155
.withFunctionCallbacks(List.of(FunctionCallback.builder()
156-
.description("Get the current weather in a given location")
157156
.function("getCurrentWeather", new MockWeatherService())
157+
.description("Get the current weather in a given location")
158158
.inputType(MockWeatherService.Request.class)
159159
.build()))
160160
.build();

models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,10 @@ void functionCallTest() {
214214
String response = ChatClient.create(this.chatModel)
215215
.prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.")
216216
.functions(FunctionCallback.builder()
217-
.description("Get the weather in location")
218-
.function("getCurrentWeather", new MockWeatherService())
219-
.inputType(MockWeatherService.Request.class)
220-
.build())
217+
.function("getCurrentWeather", new MockWeatherService())
218+
.description("Get the weather in location")
219+
.inputType(MockWeatherService.Request.class)
220+
.build())
221221
.call()
222222
.content();
223223
// @formatter:on
@@ -234,10 +234,10 @@ void functionCallWithUsageMetadataTest() {
234234
ChatResponse response = ChatClient.create(this.chatModel)
235235
.prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.")
236236
.functions(FunctionCallback.builder()
237-
.description("Get the weather in location")
238-
.function("getCurrentWeather", new MockWeatherService())
239-
.inputType(MockWeatherService.Request.class)
240-
.build())
237+
.function("getCurrentWeather", new MockWeatherService())
238+
.description("Get the weather in location")
239+
.inputType(MockWeatherService.Request.class)
240+
.build())
241241
.call()
242242
.chatResponse();
243243
// @formatter:on
@@ -269,10 +269,10 @@ void functionCallWithAdvisorTest() {
269269
String response = ChatClient.create(this.chatModel)
270270
.prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.")
271271
.functions(FunctionCallback.builder()
272-
.description("Get the weather in location")
273-
.function("getCurrentWeather", new MockWeatherService())
274-
.inputType(MockWeatherService.Request.class)
275-
.build())
272+
.function("getCurrentWeather", new MockWeatherService())
273+
.description("Get the weather in location")
274+
.inputType(MockWeatherService.Request.class)
275+
.build())
276276
.advisors(new SimpleLoggerAdvisor())
277277
.call()
278278
.content();
@@ -289,8 +289,8 @@ void defaultFunctionCallTest() {
289289
// @formatter:off
290290
String response = ChatClient.builder(this.chatModel)
291291
.defaultFunctions(FunctionCallback.builder()
292-
.description("Get the weather in location")
293292
.function("getCurrentWeather", new MockWeatherService())
293+
.description("Get the weather in location")
294294
.inputType(MockWeatherService.Request.class)
295295
.build())
296296
.defaultUser(u -> u.text("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius."))
@@ -312,8 +312,8 @@ void streamFunctionCallTest() {
312312
Flux<ChatResponse> response = ChatClient.create(this.chatModel).prompt()
313313
.user("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.")
314314
.functions(FunctionCallback.builder()
315-
.description("Get the weather in location")
316315
.function("getCurrentWeather", new MockWeatherService())
316+
.description("Get the weather in location")
317317
.inputType(MockWeatherService.Request.class)
318318
.build())
319319
.stream()
@@ -354,8 +354,8 @@ void singularStreamFunctionCallTest() {
354354
Flux<String> response = ChatClient.create(this.chatModel).prompt()
355355
.user("What's the weather like in Paris? Return the temperature in Celsius.")
356356
.functions(FunctionCallback.builder()
357-
.description("Get the weather in location")
358357
.function("getCurrentWeather", new MockWeatherService())
358+
.description("Get the weather in location")
359359
.inputType(MockWeatherService.Request.class)
360360
.build())
361361
.stream()

models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseUsageAggregationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ public void callWithToolUse() {
139139
.willReturn(converseResponseFinal);
140140

141141
FunctionCallback functionCallback = FunctionCallback.builder()
142-
.description("Gets the weather in location")
143142
.function("getCurrentWeather", (Request request) -> "15.0°C")
143+
.description("Gets the weather in location")
144144
.inputType(Request.class)
145145
.build();
146146

models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModelIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,9 @@ void functionCallTest() {
255255

256256
var promptOptions = FunctionCallingOptions.builder()
257257
.withFunctionCallbacks(List.of(FunctionCallback.builder()
258+
.function("getCurrentWeather", new MockWeatherService())
258259
.description(
259260
"Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.")
260-
.function("getCurrentWeather", new MockWeatherService())
261261
.inputType(MockWeatherService.Request.class)
262262
.build()))
263263
.build();
@@ -283,9 +283,9 @@ void streamFunctionCallTest() {
283283
var promptOptions = FunctionCallingOptions.builder()
284284
.withModel("anthropic.claude-3-5-sonnet-20240620-v1:0")
285285
.withFunctionCallbacks(List.of(FunctionCallback.builder()
286+
.function("getCurrentWeather", new MockWeatherService())
286287
.description(
287288
"Get the weather in location. Return temperature in 36°F or 36°C format. Use multi-turn if needed.")
288-
.function("getCurrentWeather", new MockWeatherService())
289289
.inputType(MockWeatherService.Request.class)
290290
.build()))
291291
.build();

models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/experiments/BedrockConverseChatModelMain2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public static void main(String[] args) {
5353
PortableFunctionCallingOptions.builder()
5454
.withModel(modelId)
5555
.withFunctionCallbacks(List.of(FunctionCallback.builder()
56-
.description("Get the weather in location")
5756
.function("getCurrentWeather", new MockWeatherService())
57+
.description("Get the weather in location")
5858
.inputType(MockWeatherService.Request.class)
5959
.build()))
6060
.build());

models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/experiments/BedrockConverseChatModelMain3.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public static void main(String[] args) {
5151
PortableFunctionCallingOptions.builder()
5252
.withModel(modelId)
5353
.withFunctionCallbacks(List.of(FunctionCallback.builder()
54-
.description("Get the weather in location")
5554
.function("getCurrentWeather", new MockWeatherService())
55+
.description("Get the weather in location")
5656
.inputType(MockWeatherService.Request.class)
5757
.build()))
5858
.build());

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public void promptOptionsTools() {
6868
MiniMaxChatOptions.builder()
6969
.withModel("PROMPT_MODEL")
7070
.withFunctionCallbacks(List.of(FunctionCallback.builder()
71-
.description("Get the weather in location")
7271
.function(TOOL_FUNCTION_NAME, new MockWeatherService())
72+
.description("Get the weather in location")
7373
.inputType(MockWeatherService.Request.class)
7474
.build()))
7575
.build()),
@@ -95,8 +95,8 @@ public void defaultOptionsTools() {
9595
MiniMaxChatOptions.builder()
9696
.withModel("DEFAULT_MODEL")
9797
.withFunctionCallbacks(List.of(FunctionCallback.builder()
98-
.description("Get the weather in location")
9998
.function(TOOL_FUNCTION_NAME, new MockWeatherService())
99+
.description("Get the weather in location")
100100
.inputType(MockWeatherService.Request.class)
101101
.build()))
102102
.build());
@@ -127,8 +127,8 @@ public void defaultOptionsTools() {
127127
request = client.createRequest(new Prompt("Test message content",
128128
MiniMaxChatOptions.builder()
129129
.withFunctionCallbacks(List.of(FunctionCallback.builder()
130-
.description("Overridden function description")
131130
.function(TOOL_FUNCTION_NAME, new MockWeatherService())
131+
.description("Overridden function description")
132132
.inputType(MockWeatherService.Request.class)
133133
.build()))
134134
.build()),

0 commit comments

Comments
 (0)