I define a tool as a function (FaT) as described in the documentation and pass it to the chat model as described in the documentation. However, I then receive the following error message.
Caused by: java.lang.IllegalStateException: No @Tool annotated methods found in get_ProductDetailsByCustomer.Did you mean to pass a ToolCallback or ToolCallbackProvider? If so, you have to use .toolCallbacks() instead of .tool()
When I debug it in Spring AI, it quickly becomes clear why. It always goes to the following method and doesn't distinguish between a MaT and a FaT. It always looks for the @Tool annotation.
public final class ToolCallbacks {
private ToolCallbacks() {
}
public static ToolCallback[] from(Object... sources) {
return MethodToolCallbackProvider.builder().toolObjects(sources).build().getToolCallbacks();
}
}
I'm using Java 21, Spring Boot 3.5, and Spring AI 1.0.0.
Here's the code again:
Tool as Function
@Configuration
public class InsuranceProductDetailsByCustomerFunctionConfiguration {
@Bean("get_ProductDetailsByCustomer")
@Description("Stellt eine Anfrage an den Versicherungsservice, um Produktdaten zu erhalten.")
public Function<String,Product> createProductDetailsByCustomerFunction(InsuranceProductService insuranceProductService) {
return customer -> insuranceProductService.getProductDetailsByCustomer(customer);
}
}
Passing the tool as a function to the chat client
var chatClient = builder.defaultAdvisors( MessageChatMemoryAdvisor.builder(chatMemory).build())
.defaultSystem(prompt.getContents())
.defaultTools(insuranceCustomerDetailsTool)
.defaultTools("get_ProductDetailsByCustomer")
.build();
Thank you for your support!!
Comment From: sunyuhan1998
Currently, Spring AI does not support tools with a return type of Function
. You can refer to the documentation at https://docs.spring.io/spring-ai/reference/1.1-SNAPSHOT/api/tools.html#_method_tool_limitations
Comment From: Thinkenterprise
The documentation references the limitation of MaT. I was talking about Function as Tool. The documentation for Function as Tool shows the following example under the Dynamic Specification section.
@Configuration(proxyBeanMethods = false)
class WeatherTools {
public static final String CURRENT_WEATHER_TOOL = "currentWeather";
@Bean(CURRENT_WEATHER_TOOL)
@Description("Get the weather in location")
Function<WeatherRequest, WeatherResponse> currentWeather() {
...
}
}
The limitations of Function as Toll are described below. Here is the excerpt:
Function Tool Limitations
The following types are not currently supported as input or output types for functions used as tools:
Primitive types
Optional
Collection types (e.g. List, Map, Array, Set)
Asynchronous types (e.g. CompletableFuture, Future)
Reactive types (e.g. Flow, Mono, Flux).
It doesn't say that the Function Interfaces aren't supported.
In my opinion, the error lies in the implementation of the Spring AI framework of ChatClient
. There, there's no distinction between MaT and FaT when adding the tool via the ChatClient
.
But that's just a guess; I'm not that familiar with the framework.
Comment From: sunyuhan1998
@Thinkenterprise Sorry, this was my oversight. I hadn't noticed that your current scenario is FaT
.
I believe the cause of the issue you're currently encountering is that you're using the wrong method to pass tools to the ChatClient
. In a FaT
scenario, you should use defaultToolNames
instead of defaultTools
. Like this:
.defaultToolNames("get_ProductDetailsByCustomer")
This is also described in the documentation: Adding Tools to ChatClient
Additionally, I noticed that your Function
parameter type is String
, which I think is inappropriate because this would cause the model to be unclear about the meaning of the parameters. I recommend encapsulating it into a class and using @ToolParam
to explain the meaning of each property in the class.
Can this resolve your issue?
Comment From: Thinkenterprise
After the changes, it worked. The documentation misled me in the following places.
First:
ChatClient.create(chatModel)
.prompt("What's the weather like in Copenhagen?")
.tools("currentWeather")
.call()
.content();
Second:
ChatModel chatModel = ...
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultTools("currentWeather")
.build();
I think that should be corrected. Thank you for the quick help!!
Comment From: ilayaperumalg
@sunyuhan1998 Thanks for the inputs. @Thinkenterprise Thanks for reporting and the feedback. Please feel free to submit a PR with the documentation changes.
Comment From: sunyuhan1998
After the changes, it worked. The documentation misled me in the following places.
First:
ChatClient.create(chatModel) .prompt("What's the weather like in Copenhagen?") .tools("currentWeather") .call() .content(); Second:
ChatModel chatModel = ... ChatClient chatClient = ChatClient.builder(chatModel) .defaultTools("currentWeather") .build(); I think that should be corrected. Thank you for the quick help!!
I guess the document you are currently viewing is the 1.0.0 version. I noticed that this part of the content has already been corrected in the 1.1.0 version of the documentation. You can refer to https://docs.spring.io/spring-ai/reference/1.1-SNAPSHOT/api/tools.html. Hope this helps!