diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java index a66b94b3e..dcd03c0c4 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java @@ -60,7 +60,7 @@ public class FunctionCallbackInPrompt2IT { String content = ChatClient.builder(chatModel).build().prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris?") - .tools(FunctionToolCallback + .toolCallbacks(FunctionToolCallback .builder("CurrentWeatherService", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) @@ -88,7 +88,7 @@ public class FunctionCallbackInPrompt2IT { // @formatter:off String content = ChatClient.builder(chatModel).build().prompt() .user("Turn the light on in the kitchen and in the living room!") - .tools(FunctionToolCallback + .toolCallbacks(FunctionToolCallback .builder("turnLight", (LightInfo lightInfo) -> { logger.info("Turning light to [" + lightInfo.isOn + "] in " + lightInfo.roomName()); state.put(lightInfo.roomName(), lightInfo.isOn()); @@ -114,7 +114,7 @@ public class FunctionCallbackInPrompt2IT { // @formatter:off String content = ChatClient.builder(chatModel).build().prompt() .user("What's the weather like in Amsterdam?") - .tools(FunctionToolCallback + .toolCallbacks(FunctionToolCallback .builder("CurrentWeatherService", input -> "18 degrees Celsius") .description("Get the weather in location") .inputType(MockWeatherService.Request.class) @@ -138,7 +138,7 @@ public class FunctionCallbackInPrompt2IT { // @formatter:off String content = ChatClient.builder(chatModel).build().prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris?") - .tools(FunctionToolCallback + .toolCallbacks(FunctionToolCallback .builder("CurrentWeatherService", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java index a8f511d40..6418246e5 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java @@ -174,7 +174,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { ChatClient chatClient = ChatClient.builder(chatModel).build(); String content = chatClient.prompt("What's the weather like in San Francisco, Tokyo, and Paris?") - .tools("weatherFunctionWithContext") + .toolNames("weatherFunctionWithContext") .toolContext(Map.of("sessionId", "123")) .call() .content(); @@ -206,7 +206,7 @@ class FunctionCallbackWithPlainFunctionBeanIT { ChatClient chatClient = ChatClient.builder(chatModel).build(); String content = chatClient.prompt("What's the weather like in San Francisco, Tokyo, and Paris?") - .tools("weatherFunctionWithClassBiFunction") + .toolNames("weatherFunctionWithClassBiFunction") .toolContext(Map.of("sessionId", "123")) .call() .content(); diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java index 0b71c6f61..c211879ba 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java @@ -55,7 +55,7 @@ public class OpenAiFunctionCallback2IT { // @formatter:off ChatClient chatClient = ChatClient.builder(chatModel) - .defaultTools("WeatherInfo") + .defaultToolNames("WeatherInfo") .defaultUser(u -> u.text("What's the weather like in {cities}?")) .build(); @@ -78,7 +78,7 @@ public class OpenAiFunctionCallback2IT { // @formatter:off String content = ChatClient.builder(chatModel).build().prompt() - .tools("WeatherInfo") + .toolNames("WeatherInfo") .user("What's the weather like in San Francisco, Tokyo, and Paris?") .stream().content() .collectList().block().stream().collect(Collectors.joining()); diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientIT.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientIT.java index 5353d48c4..5bd91be7e 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientIT.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientIT.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; @@ -213,7 +212,7 @@ class AnthropicChatClientIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .inputType(MockWeatherService.Request.class) .build()) .call() @@ -231,7 +230,7 @@ class AnthropicChatClientIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeatherInLocation", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeatherInLocation", new MockWeatherService()) .inputType(MockWeatherService.Request.class) .build()) .call() @@ -248,7 +247,7 @@ class AnthropicChatClientIT { // @formatter:off String response = ChatClient.builder(this.chatModel) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -270,7 +269,7 @@ class AnthropicChatClientIT { // @formatter:off Flux response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientMethodInvokingFunctionCallbackIT.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientMethodInvokingFunctionCallbackIT.java index 97331aa93..cb3f4fdb6 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientMethodInvokingFunctionCallbackIT.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientMethodInvokingFunctionCallbackIT.java @@ -67,7 +67,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod).build()) .toolMethod(toolMethod) .build()) @@ -89,7 +89,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -116,7 +116,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { String response = ChatClient.create(this.chatModel).prompt() .user("Turn light on in the living room.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(turnLightMethod) .description("Turn light on in the living room.") .build()) @@ -144,7 +144,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -171,7 +171,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -202,7 +202,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { assertThatThrownBy(() -> ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -227,7 +227,7 @@ class AnthropicChatClientMethodInvokingFunctionCallbackIT { String response = ChatClient.create(this.chatModel).prompt() .user("Turn light on in the living room.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolMethod(toolMethod) .toolDefinition(ToolDefinition.builder(toolMethod) .description("Can turn lights on in the Living Room") diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java index 999cb475a..d735dc40a 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/BedrockConverseChatClientIT.java @@ -212,7 +212,7 @@ class BedrockConverseChatClientIT { // @formatter:off String response = ChatClient.create(this.chatModel) .prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -231,7 +231,7 @@ class BedrockConverseChatClientIT { // @formatter:off ChatResponse response = ChatClient.create(this.chatModel) .prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -265,7 +265,7 @@ class BedrockConverseChatClientIT { // @formatter:off String response = ChatClient.create(this.chatModel) .prompt("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -284,7 +284,7 @@ class BedrockConverseChatClientIT { // @formatter:off String response = ChatClient.builder(this.chatModel) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -306,7 +306,7 @@ class BedrockConverseChatClientIT { // @formatter:off Flux response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Return the temperature in Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -347,7 +347,7 @@ class BedrockConverseChatClientIT { // @formatter:off Flux response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in Paris? Return the temperature in Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) diff --git a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/client/BedrockNovaChatClientIT.java b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/client/BedrockNovaChatClientIT.java index 9efd3c2e8..4e6ade3c4 100644 --- a/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/client/BedrockNovaChatClientIT.java +++ b/models/spring-ai-bedrock-converse/src/test/java/org/springframework/ai/bedrock/converse/client/BedrockNovaChatClientIT.java @@ -141,7 +141,7 @@ public class BedrockNovaChatClientIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", (WeatherRequest request) -> { + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", (WeatherRequest request) -> { if (request.location().contains("Paris")) { return new WeatherResponse(15, request.unit()); } diff --git a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java index bd9b23312..47971707e 100644 --- a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java +++ b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java @@ -228,7 +228,7 @@ class MistralAiChatClientIT { String response = ChatClient.create(this.chatModel).prompt() .options(MistralAiChatOptions.builder().model(MistralAiApi.ChatModel.SMALL).toolChoice(ToolChoice.AUTO).build()) .user(u -> u.text("What's the weather like in San Francisco, Tokyo, and Paris? Use parallel function calling if required. Response should be in Celsius.")) - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -249,7 +249,7 @@ class MistralAiChatClientIT { // @formatter:off String response = ChatClient.builder(this.chatModel) .defaultOptions(MistralAiChatOptions.builder().model(MistralAiApi.ChatModel.SMALL).build()) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -272,7 +272,7 @@ class MistralAiChatClientIT { Flux response = ChatClient.create(this.chatModel).prompt() .options(MistralAiChatOptions.builder().model(MistralAiApi.ChatModel.SMALL).build()) .user("What's the weather like in San Francisco, Tokyo, and Paris? Use parallel function calling if required. Response should be in Celsius.") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelFunctionCallingIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelFunctionCallingIT.java index 2bcbb7f38..81213f288 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelFunctionCallingIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelFunctionCallingIT.java @@ -69,7 +69,7 @@ class OpenAiChatModelFunctionCallingIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("Turn the light on in the living room") - .tools(FunctionToolCallback.builder("turnsLightOnInTheLivingRoom", () -> state.put("Light", "ON")) + .toolCallbacks(FunctionToolCallback.builder("turnsLightOnInTheLivingRoom", () -> state.put("Light", "ON")) .build()) .call() .content(); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiPaymentTransactionIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiPaymentTransactionIT.java index 91331799f..b80f5186d 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiPaymentTransactionIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiPaymentTransactionIT.java @@ -82,7 +82,7 @@ public class OpenAiPaymentTransactionIT { public void transactionPaymentStatuses(String functionName) { List content = this.chatClient.prompt() .advisors(new LoggingAdvisor()) - .tools(functionName) + .toolNames(functionName) .user(""" What is the status of my payment transactions 001, 002 and 003? """) @@ -113,7 +113,7 @@ public class OpenAiPaymentTransactionIT { Flux flux = this.chatClient.prompt() .advisors(new LoggingAdvisor()) - .tools(functionName) + .toolNames(functionName) .user(u -> u.text(""" What is the status of my payment transactions 001, 002 and 003? diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java index 46599801f..66d6011e2 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java @@ -251,7 +251,7 @@ class OpenAiChatClientIT extends AbstractIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user(u -> u.text("What's the weather like in San Francisco, Tokyo, and Paris?")) - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -269,7 +269,7 @@ class OpenAiChatClientIT extends AbstractIT { // @formatter:off String response = ChatClient.builder(this.chatModel) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -289,7 +289,7 @@ class OpenAiChatClientIT extends AbstractIT { // @formatter:off Flux response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris?") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMethodInvokingFunctionCallbackIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMethodInvokingFunctionCallbackIT.java index df93556fe..5c5eec2f7 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMethodInvokingFunctionCallbackIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMethodInvokingFunctionCallbackIT.java @@ -66,7 +66,7 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -91,7 +91,7 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("Turn light on in the living room.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Can turn lights on or off by room name") .build()) @@ -119,7 +119,7 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -146,7 +146,7 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -175,7 +175,7 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT { // @formatter:off assertThatThrownBy(() -> ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris? Use Celsius.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Get the weather in location") .build()) @@ -199,7 +199,7 @@ class OpenAiChatClientMethodInvokingFunctionCallbackIT { // @formatter:off String response = ChatClient.create(this.chatModel).prompt() .user("Turn light on in the living room.") - .tools(MethodToolCallback.builder() + .toolCallbacks(MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Can turn lights on in the Living Room") .build()) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMultipleFunctionCallsIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMultipleFunctionCallsIT.java index f318caf53..6626417a1 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMultipleFunctionCallsIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientMultipleFunctionCallsIT.java @@ -84,7 +84,7 @@ class OpenAiChatClientMultipleFunctionCallsIT extends AbstractIT { // @formatter:off response = chatClientBuilder.build().prompt() .user(u -> u.text("What's the weather like in San Francisco, Tokyo, and Paris?")) - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -114,7 +114,7 @@ class OpenAiChatClientMultipleFunctionCallsIT extends AbstractIT { // @formatter:off String response = ChatClient.builder(this.chatModel) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -156,7 +156,7 @@ class OpenAiChatClientMultipleFunctionCallsIT extends AbstractIT { // @formatter:off String response = ChatClient.builder(this.chatModel) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", biFunction) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", biFunction) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -199,7 +199,7 @@ class OpenAiChatClientMultipleFunctionCallsIT extends AbstractIT { // @formatter:off String response = ChatClient.builder(this.chatModel) - .defaultTools(FunctionToolCallback.builder("getCurrentWeather", biFunction) + .defaultToolCallbacks(FunctionToolCallback.builder("getCurrentWeather", biFunction) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -221,7 +221,7 @@ class OpenAiChatClientMultipleFunctionCallsIT extends AbstractIT { // @formatter:off Flux response = ChatClient.create(this.chatModel).prompt() .user("What's the weather like in San Francisco, Tokyo, and Paris?") - .tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) + .toolCallbacks(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService()) .description("Get the weather in location") .inputType(MockWeatherService.Request.class) .build()) @@ -250,7 +250,7 @@ class OpenAiChatClientMultipleFunctionCallsIT extends AbstractIT { String content = chatClient.prompt() .user("What's the weather like in Shanghai?") - .tools(FunctionToolCallback.builder("currentTemp", function) + .toolCallbacks(FunctionToolCallback.builder("currentTemp", function) .description("get current temp") .inputType(MyFunction.Req.class) .build()) diff --git a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionIT.java b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionIT.java index 9ef439a84..9ac5776bc 100644 --- a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionIT.java +++ b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionIT.java @@ -76,7 +76,7 @@ public class VertexAiGeminiPaymentTransactionIT { // @formatter:off String content = this.chatClient.prompt() .advisors(new LoggingAdvisor()) - .tools("paymentStatus") + .toolNames("paymentStatus") .user(""" What is the status of my payment transactions 001, 002 and 003? If requred invoke the function per transaction. @@ -93,7 +93,7 @@ public class VertexAiGeminiPaymentTransactionIT { Flux streamContent = this.chatClient.prompt() .advisors(new LoggingAdvisor()) - .tools("paymentStatus") + .toolNames("paymentStatus") .user(""" What is the status of my payment transactions 001, 002 and 003? If requred invoke the function per transaction. diff --git a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionMethodIT.java b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionMethodIT.java index cc12dfe8b..b5c3d2e07 100644 --- a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionMethodIT.java +++ b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/tool/VertexAiGeminiPaymentTransactionMethodIT.java @@ -76,7 +76,7 @@ public class VertexAiGeminiPaymentTransactionMethodIT { @Test public void paymentStatuses() { - String content = this.chatClient.prompt().advisors(new LoggingAdvisor()).tools("paymentStatus").user(""" + String content = this.chatClient.prompt().advisors(new LoggingAdvisor()).toolNames("paymentStatus").user(""" What is the status of my payment transactions 001, 002 and 003? If requred invoke the function per transaction. """).call().content(); @@ -91,7 +91,7 @@ public class VertexAiGeminiPaymentTransactionMethodIT { Flux streamContent = this.chatClient.prompt() .advisors(new LoggingAdvisor()) - .tools("paymentStatus") + .toolNames("paymentStatus") .user(""" What is the status of my payment transactions 001, 002 and 003? If requred invoke the function per transaction. diff --git a/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/ChatClient.java b/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/ChatClient.java index a2270c445..d6fe27574 100644 --- a/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/ChatClient.java +++ b/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/ChatClient.java @@ -220,15 +220,15 @@ public interface ChatClient { ChatClientRequestSpec options(T options); - ChatClientRequestSpec tools(String... toolNames); - - ChatClientRequestSpec tools(ToolCallback... toolCallbacks); - - ChatClientRequestSpec tools(List toolCallbacks); + ChatClientRequestSpec toolNames(String... toolNames); ChatClientRequestSpec tools(Object... toolObjects); - ChatClientRequestSpec tools(ToolCallbackProvider... toolCallbackProviders); + ChatClientRequestSpec toolCallbacks(ToolCallback... toolCallbacks); + + ChatClientRequestSpec toolCallbacks(List toolCallbacks); + + ChatClientRequestSpec toolCallbacks(ToolCallbackProvider... toolCallbackProviders); ChatClientRequestSpec toolContext(Map toolContext); @@ -287,15 +287,15 @@ public interface ChatClient { Builder defaultTemplateRenderer(TemplateRenderer templateRenderer); - Builder defaultTools(String... toolNames); - - Builder defaultTools(ToolCallback... toolCallbacks); - - Builder defaultTools(List toolCallbacks); + Builder defaultToolNames(String... toolNames); Builder defaultTools(Object... toolObjects); - Builder defaultTools(ToolCallbackProvider... toolCallbackProviders); + Builder defaultToolCallbacks(ToolCallback... toolCallbacks); + + Builder defaultToolCallbacks(List toolCallbacks); + + Builder defaultToolCallbacks(ToolCallbackProvider... toolCallbackProviders); Builder defaultToolContext(Map toolContext); diff --git a/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClient.java b/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClient.java index 590f5d017..b680a99c4 100644 --- a/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClient.java +++ b/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClient.java @@ -768,7 +768,7 @@ public class DefaultChatClient implements ChatClient { public Builder mutate() { DefaultChatClientBuilder builder = (DefaultChatClientBuilder) ChatClient .builder(this.chatModel, this.observationRegistry, this.observationConvention) - .defaultTools(StringUtils.toStringArray(this.toolNames)); + .defaultToolNames(StringUtils.toStringArray(this.toolNames)); if (StringUtils.hasText(this.userText)) { builder.defaultUser( @@ -834,7 +834,7 @@ public class DefaultChatClient implements ChatClient { } @Override - public ChatClientRequestSpec tools(String... toolNames) { + public ChatClientRequestSpec toolNames(String... toolNames) { Assert.notNull(toolNames, "toolNames cannot be null"); Assert.noNullElements(toolNames, "toolNames cannot contain null elements"); this.toolNames.addAll(List.of(toolNames)); @@ -842,7 +842,7 @@ public class DefaultChatClient implements ChatClient { } @Override - public ChatClientRequestSpec tools(ToolCallback... toolCallbacks) { + public ChatClientRequestSpec toolCallbacks(ToolCallback... toolCallbacks) { Assert.notNull(toolCallbacks, "toolCallbacks cannot be null"); Assert.noNullElements(toolCallbacks, "toolCallbacks cannot contain null elements"); this.toolCallbacks.addAll(List.of(toolCallbacks)); @@ -850,7 +850,7 @@ public class DefaultChatClient implements ChatClient { } @Override - public ChatClientRequestSpec tools(List toolCallbacks) { + public ChatClientRequestSpec toolCallbacks(List toolCallbacks) { Assert.notNull(toolCallbacks, "toolCallbacks cannot be null"); Assert.noNullElements(toolCallbacks, "toolCallbacks cannot contain null elements"); this.toolCallbacks.addAll(toolCallbacks); @@ -866,7 +866,7 @@ public class DefaultChatClient implements ChatClient { } @Override - public ChatClientRequestSpec tools(ToolCallbackProvider... toolCallbackProviders) { + public ChatClientRequestSpec toolCallbacks(ToolCallbackProvider... toolCallbackProviders) { Assert.notNull(toolCallbackProviders, "toolCallbackProviders cannot be null"); Assert.noNullElements(toolCallbackProviders, "toolCallbackProviders cannot contain null elements"); for (ToolCallbackProvider toolCallbackProvider : toolCallbackProviders) { diff --git a/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClientBuilder.java b/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClientBuilder.java index 2c35049b3..35e011af4 100644 --- a/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClientBuilder.java +++ b/spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClientBuilder.java @@ -151,20 +151,20 @@ public class DefaultChatClientBuilder implements Builder { } @Override - public Builder defaultTools(String... toolNames) { - this.defaultRequest.tools(toolNames); + public Builder defaultToolNames(String... toolNames) { + this.defaultRequest.toolNames(toolNames); return this; } @Override - public Builder defaultTools(ToolCallback... toolCallbacks) { - this.defaultRequest.tools(toolCallbacks); + public Builder defaultToolCallbacks(ToolCallback... toolCallbacks) { + this.defaultRequest.toolCallbacks(toolCallbacks); return this; } @Override - public Builder defaultTools(List toolCallbacks) { - this.defaultRequest.tools(toolCallbacks); + public Builder defaultToolCallbacks(List toolCallbacks) { + this.defaultRequest.toolCallbacks(toolCallbacks); return this; } @@ -175,14 +175,15 @@ public class DefaultChatClientBuilder implements Builder { } @Override - public Builder defaultTools(ToolCallbackProvider... toolCallbackProviders) { - this.defaultRequest.tools(toolCallbackProviders); + public Builder defaultToolCallbacks(ToolCallbackProvider... toolCallbackProviders) { + this.defaultRequest.toolCallbacks(toolCallbackProviders); return this; } @Deprecated // Use defaultTools() public Builder defaultFunction(String name, String description, java.util.function.Function function) { - this.defaultRequest.tools(FunctionToolCallback.builder(name, function).description(description).build()); + this.defaultRequest + .toolCallbacks(FunctionToolCallback.builder(name, function).description(description).build()); return this; } @@ -203,7 +204,7 @@ public class DefaultChatClientBuilder implements Builder { void addToolCallbacks(List toolCallbacks) { Assert.notNull(toolCallbacks, "toolCallbacks cannot be null"); - this.defaultRequest.tools(toolCallbacks.toArray(ToolCallback[]::new)); + this.defaultRequest.toolCallbacks(toolCallbacks.toArray(ToolCallback[]::new)); } void addToolContext(Map toolContext) { diff --git a/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/ChatClientTest.java b/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/ChatClientTest.java index a572fc20c..b8d4b1c00 100644 --- a/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/ChatClientTest.java +++ b/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/ChatClientTest.java @@ -216,8 +216,8 @@ public class ChatClientTest { .defaultSystem(s -> s.text("Default system text {param1}, {param2}") .param("param1", "value1") .param("param2", "value2")) - .defaultTools("fun1", "fun2") - .defaultTools(FunctionToolCallback.builder("fun3", mockFunction) + .defaultToolNames("fun1", "fun2") + .defaultToolCallbacks(FunctionToolCallback.builder("fun3", mockFunction) .description("fun3description") .inputType(String.class) .build()) @@ -276,7 +276,7 @@ public class ChatClientTest { // @formatter:off chatClient = chatClient.mutate() .defaultSystem("Mutated default system text {param1}, {param2}") - .defaultTools("fun4") + .defaultToolNames("fun4") .defaultUser("Mutated default user text {uparam1}, {uparam2}") .build(); // @formatter:on @@ -346,8 +346,8 @@ public class ChatClientTest { .defaultSystem(s -> s.text("Default system text {param1}, {param2}") .param("param1", "value1") .param("param2", "value2")) - .defaultTools("fun1", "fun2") - .defaultTools(FunctionToolCallback.builder("fun3", mockFunction) + .defaultToolNames("fun1", "fun2") + .defaultToolCallbacks(FunctionToolCallback.builder("fun3", mockFunction) .description("fun3description") .inputType(String.class) .build()) @@ -363,7 +363,7 @@ public class ChatClientTest { .system("New default system text {param1}, {param2}") .user(u -> u.param("uparam1", "userValue1") .param("uparam2", "userValue2")) - .tools("fun5") + .toolNames("fun5") .mutate().build() // mutate and build new prompt .prompt().call().content(); // @formatter:on @@ -394,7 +394,7 @@ public class ChatClientTest { .system("New default system text {param1}, {param2}") .user(u -> u.param("uparam1", "userValue1") .param("uparam2", "userValue2")) - .tools("fun5") + .toolNames("fun5") .mutate().build() // mutate and build new prompt .prompt().stream().content()); // @formatter:on @@ -523,7 +523,7 @@ public class ChatClientTest { // @formatter:off ChatClient client = ChatClient.builder(this.chatModel) .defaultSystem("System text") - .defaultTools("function1") + .defaultToolNames("function1") .build(); String response = client.prompt() diff --git a/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/DefaultChatClientTests.java b/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/DefaultChatClientTests.java index 1ecf46c78..30b0199e2 100644 --- a/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/DefaultChatClientTests.java +++ b/spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/DefaultChatClientTests.java @@ -1457,7 +1457,7 @@ class DefaultChatClientTests { void whenToolNamesElementIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools("myTool", null)).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> spec.toolNames("myTool", null)).isInstanceOf(IllegalArgumentException.class) .hasMessage("toolNames cannot contain null elements"); } @@ -1466,7 +1466,7 @@ class DefaultChatClientTests { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); String toolName = "myTool"; - spec = spec.tools(toolName); + spec = spec.toolNames(toolName); DefaultChatClient.DefaultChatClientRequestSpec defaultSpec = (DefaultChatClient.DefaultChatClientRequestSpec) spec; assertThat(defaultSpec.getToolNames()).contains(toolName); } @@ -1475,7 +1475,7 @@ class DefaultChatClientTests { void whenToolCallbacksElementIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools(mock(ToolCallback.class), null)) + assertThatThrownBy(() -> spec.toolCallbacks(mock(ToolCallback.class), null)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("toolCallbacks cannot contain null elements"); } @@ -1485,7 +1485,7 @@ class DefaultChatClientTests { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); ToolCallback toolCallback = mock(ToolCallback.class); - spec = spec.tools(toolCallback); + spec = spec.toolCallbacks(toolCallback); DefaultChatClient.DefaultChatClientRequestSpec defaultSpec = (DefaultChatClient.DefaultChatClientRequestSpec) spec; assertThat(defaultSpec.getToolCallbacks()).contains(toolCallback); } @@ -1494,7 +1494,7 @@ class DefaultChatClientTests { void whenFunctionNameIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools(FunctionToolCallback.builder(null, input -> "hello") + assertThatThrownBy(() -> spec.toolCallbacks(FunctionToolCallback.builder(null, input -> "hello") .description("description") .inputType(String.class) .build())).isInstanceOf(IllegalArgumentException.class).hasMessage("name cannot be null or empty"); @@ -1504,7 +1504,7 @@ class DefaultChatClientTests { void whenFunctionNameIsEmptyThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools(FunctionToolCallback.builder("", input -> "hello") + assertThatThrownBy(() -> spec.toolCallbacks(FunctionToolCallback.builder("", input -> "hello") .description("description") .inputType(String.class) .build())).isInstanceOf(IllegalArgumentException.class).hasMessage("name cannot be null or empty"); @@ -1515,7 +1515,7 @@ class DefaultChatClientTests { void whenFunctionDescriptionIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools(FunctionToolCallback.builder("name", input -> "hello") + assertThatThrownBy(() -> spec.toolCallbacks(FunctionToolCallback.builder("name", input -> "hello") .description(null) .inputType(String.class) .build())).isInstanceOf(IllegalArgumentException.class).hasMessage("Description must not be empty"); @@ -1526,7 +1526,7 @@ class DefaultChatClientTests { void whenFunctionDescriptionIsEmptyThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools( + assertThatThrownBy(() -> spec.toolCallbacks( FunctionToolCallback.builder("name", input -> "hello").description("").inputType(String.class).build())) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Description must not be empty"); @@ -1536,7 +1536,7 @@ class DefaultChatClientTests { void whenFunctionThenReturn() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - spec = spec.tools(FunctionToolCallback.builder("name", input -> "hello") + spec = spec.toolCallbacks(FunctionToolCallback.builder("name", input -> "hello") .inputType(String.class) .description("description") .build()); @@ -1549,7 +1549,7 @@ class DefaultChatClientTests { void whenFunctionAndInputTypeThenReturn() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - spec = spec.tools(FunctionToolCallback.builder("name", input -> "hello") + spec = spec.toolCallbacks(FunctionToolCallback.builder("name", input -> "hello") .inputType(String.class) .description("description") .build()); @@ -1562,8 +1562,8 @@ class DefaultChatClientTests { void whenBiFunctionNameIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec - .tools(FunctionToolCallback.builder(null, (input, ctx) -> "hello").description("description").build())) + assertThatThrownBy(() -> spec.toolCallbacks( + FunctionToolCallback.builder(null, (input, ctx) -> "hello").description("description").build())) .isInstanceOf(IllegalArgumentException.class) .hasMessage("name cannot be null or empty"); } @@ -1572,8 +1572,8 @@ class DefaultChatClientTests { void whenBiFunctionNameIsEmptyThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec - .tools(FunctionToolCallback.builder("", (input, ctx) -> "hello").description("description").build())) + assertThatThrownBy(() -> spec.toolCallbacks( + FunctionToolCallback.builder("", (input, ctx) -> "hello").description("description").build())) .isInstanceOf(IllegalArgumentException.class) .hasMessage("name cannot be null or empty"); } @@ -1583,7 +1583,7 @@ class DefaultChatClientTests { void whenBiFunctionDescriptionIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools(FunctionToolCallback.builder("name", (input, ctx) -> "hello") + assertThatThrownBy(() -> spec.toolCallbacks(FunctionToolCallback.builder("name", (input, ctx) -> "hello") .inputType(String.class) .description(null) .build())).isInstanceOf(IllegalArgumentException.class).hasMessage("Description must not be empty"); @@ -1594,8 +1594,8 @@ class DefaultChatClientTests { void whenBiFunctionDescriptionIsEmptyThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy( - () -> spec.tools(FunctionToolCallback.builder("name", (input, ctx) -> "hello").description("").build())) + assertThatThrownBy(() -> spec + .toolCallbacks(FunctionToolCallback.builder("name", (input, ctx) -> "hello").description("").build())) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Description must not be empty"); } @@ -1604,7 +1604,7 @@ class DefaultChatClientTests { void whenBiFunctionThenReturn() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - spec = spec.tools(FunctionToolCallback.builder("name", (input, ctx) -> "hello") + spec = spec.toolCallbacks(FunctionToolCallback.builder("name", (input, ctx) -> "hello") .description("description") .inputType(String.class) .build()); @@ -1617,7 +1617,7 @@ class DefaultChatClientTests { void whenFunctionBeanNamesElementIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools("myFunction", null)).isInstanceOf(IllegalArgumentException.class) + assertThatThrownBy(() -> spec.toolNames("myFunction", null)).isInstanceOf(IllegalArgumentException.class) .hasMessage("toolNames cannot contain null elements"); } @@ -1626,7 +1626,7 @@ class DefaultChatClientTests { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); String functionBeanName = "myFunction"; - spec = spec.tools(functionBeanName); + spec = spec.toolNames(functionBeanName); DefaultChatClient.DefaultChatClientRequestSpec defaultSpec = (DefaultChatClient.DefaultChatClientRequestSpec) spec; assertThat(defaultSpec.getToolNames()).contains(functionBeanName); } @@ -1635,7 +1635,7 @@ class DefaultChatClientTests { void whenFunctionToolCallbacksElementIsNullThenThrow() { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); - assertThatThrownBy(() -> spec.tools(mock(FunctionToolCallback.class), null)) + assertThatThrownBy(() -> spec.toolCallbacks(mock(FunctionToolCallback.class), null)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("toolCallbacks cannot contain null elements"); } @@ -1645,7 +1645,7 @@ class DefaultChatClientTests { ChatClient chatClient = new DefaultChatClientBuilder(mock(ChatModel.class)).build(); ChatClient.ChatClientRequestSpec spec = chatClient.prompt(); FunctionToolCallback functionToolCallback = mock(FunctionToolCallback.class); - spec = spec.tools(functionToolCallback); + spec = spec.toolCallbacks(functionToolCallback); DefaultChatClient.DefaultChatClientRequestSpec defaultSpec = (DefaultChatClient.DefaultChatClientRequestSpec) spec; assertThat(defaultSpec.getToolCallbacks()).contains(functionToolCallback); } diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc index e250a32c8..cf40ce4b9 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc @@ -124,6 +124,13 @@ Prompt augmentedPrompt = originalPrompt.augmentUserMessage(userMessage -> This approach offers more control when you need to conditionally change parts of the `UserMessage` or work with its media and metadata, rather than just replacing the text content. +* The overloaded `tools` methods in the `ChatClient` prompt builder API have been renamed for clarity and to avoid ambiguity in method dispatching based on argument types. + +* `ChatClient.PromptRequestSpec#tools(String... toolNames)` has been renamed to `ChatClient.PromptRequestSpec#toolNames(String... toolNames)`. Use this method to specify the names of tool functions (registered elsewhere, e.g., via `@Bean` definitions with `@Description`) that the model is allowed to call. +* `ChatClient.PromptRequestSpec#tools(ToolCallback... toolCallbacks)` has been renamed to `ChatClient.PromptRequestSpec#toolCallbacks(ToolCallback... toolCallbacks)`. Use this method to provide inline `ToolCallback` instances, which include the function implementation, name, description, and input type definition. + +This change addresses potential confusion where the Java compiler might not select the intended overload based on the provided arguments. + === Prompt Templating and Advisors Several classes and methods related to prompt creation and advisor customization have been deprecated in favor of more flexible approaches using the builder pattern and the `TemplateRenderer` interface. diff --git a/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/FunctionToolCallbackTests.java b/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/FunctionToolCallbackTests.java index 927fc5095..866f3b916 100644 --- a/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/FunctionToolCallbackTests.java +++ b/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/FunctionToolCallbackTests.java @@ -66,7 +66,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("Welcome the users to the library") - .tools(Tools.WELCOME) + .toolNames(Tools.WELCOME) .call() .content(); assertThat(content).isNotEmpty(); @@ -78,7 +78,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("Welcome the users to the library") - .tools(FunctionToolCallback.builder("sayWelcome", + .toolCallbacks(FunctionToolCallback.builder("sayWelcome", (Consumer) input -> logger.info("CALLBACK - Welcoming users to the library")) .description("Welcome users to the library") .inputType(Void.class) @@ -94,7 +94,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("Welcome %s to the library".formatted("James Bond")) - .tools(Tools.WELCOME_USER) + .toolNames(Tools.WELCOME_USER) .call() .content(); assertThat(content).isNotEmpty(); @@ -106,7 +106,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("Welcome %s to the library".formatted("James Bond")) - .tools(FunctionToolCallback.builder("welcomeUser", + .toolCallbacks(FunctionToolCallback.builder("welcomeUser", (Consumer) user -> logger.info("CALLBACK - Welcoming {} to the library", ((User) user).name())) .description("Welcome a specific user to the library") .inputType(User.class) @@ -122,7 +122,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("What books written by %s are available in the library?".formatted("J.R.R. Tolkien")) - .tools(Tools.BOOKS_BY_AUTHOR) + .toolNames(Tools.BOOKS_BY_AUTHOR) .call() .content(); assertThat(content).isNotEmpty() @@ -141,7 +141,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("What books written by %s are available in the library?".formatted("J.R.R. Tolkien")) - .tools(FunctionToolCallback.builder("availableBooksByAuthor", function) + .toolCallbacks(FunctionToolCallback.builder("availableBooksByAuthor", function) .description("Get the list of books written by the given author available in the library") .inputType(Author.class) .build()) @@ -159,7 +159,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("What authors wrote the books %s and %s available in the library?".formatted("The Hobbit", "The Lion, the Witch and the Wardrobe")) - .tools(Tools.AUTHORS_BY_BOOKS) + .toolNames(Tools.AUTHORS_BY_BOOKS) .call() .content(); assertThat(content).isNotEmpty().contains("J.R.R. Tolkien").contains("C.S. Lewis"); @@ -175,7 +175,7 @@ public class FunctionToolCallbackTests { .build() .prompt() .user("What authors wrote the books %s and %s available in the library?".formatted("The Hobbit", "The Lion, the Witch and the Wardrobe")) - .tools(FunctionToolCallback.builder("authorsByAvailableBooks", function) + .toolCallbacks(FunctionToolCallback.builder("authorsByAvailableBooks", function) .description("Get the list of authors who wrote the given books available in the library") .inputType(Books.class) .build()) diff --git a/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/MethodToolCallbackTests.java b/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/MethodToolCallbackTests.java index cda509210..7b01f13f4 100644 --- a/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/MethodToolCallbackTests.java +++ b/spring-ai-integration-tests/src/test/java/org/springframework/ai/integration/tests/tool/MethodToolCallbackTests.java @@ -112,7 +112,7 @@ public class MethodToolCallbackTests { .prompt() .user("What authors wrote the books %s and %s available in the library?".formatted("The Hobbit", "The Lion, the Witch and the Wardrobe")) - .tools(ToolCallbacks.from(this.tools)) + .toolCallbacks(ToolCallbacks.from(this.tools)) .call() .content(); assertThat(content).isNotEmpty().contains("J.R.R. Tolkien").contains("C.S. Lewis");