Migrating from FunctionCallback to ToolCallback API
本指南帮助您将 Spring AI 中已弃用的 FunctionCallback
API 迁移到新的 ToolCallback
API。有关新 API 的更多信息,请查看 Tools Calling 文档。
This guide helps you migrate from the deprecated FunctionCallback
API to the new ToolCallback
API in Spring AI. For more information about the new APIs, check out the Tools Calling documentation.
Overview of Changes
这些更改是更广泛的努力的一部分,旨在改进和扩展 Spring AI 中的工具调用功能。除此之外,新的 API 将“functions”术语更改为“tools”,以更好地与行业惯例保持一致。这涉及多项 API 更改,同时通过已弃用的方法保持向后兼容性。
These changes are part of a broader effort to improve and extend the tool calling capabilities in Spring AI. Among the other things, the new API moves from "functions" to "tools" terminology to better align with industry conventions. This involves several API changes while maintaining backward compatibility through deprecated methods.
Key Changes
-
FunctionCallback
→ToolCallback
-
FunctionCallback.builder().function()
→FunctionToolCallback.builder()
-
FunctionCallback.builder().method()
→MethodToolCallback.builder()
-
FunctionCallingOptions
→ToolCallingChatOptions
-
ChatClient.builder().defaultFunctions()
→ChatClient.builder().defaultTools()
-
ChatClient.functions()
→ChatClient.tools()
-
FunctionCallingOptions.builder().functions()
→ToolCallingChatOptions.builder().toolNames()
-
FunctionCallingOptions.builder().functionCallbacks()
→ToolCallingChatOptions.builder().toolCallbacks()
Migration Examples
1. Basic Function Callback
之前:
Before:
FunctionCallback.builder()
.function("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build()
之后:
After:
FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build()
2. ChatClient Usage
之前:
Before:
String response = ChatClient.create(chatModel)
.prompt()
.user("What's the weather like in San Francisco?")
.functions(FunctionCallback.builder()
.function("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build())
.call()
.content();
之后:
After:
String response = ChatClient.create(chatModel)
.prompt()
.user("What's the weather like in San Francisco?")
.tools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build())
.call()
.content();
3. Method-Based Function Callbacks
之前:
Before:
FunctionCallback.builder()
.method("getWeatherInLocation", String.class, Unit.class)
.description("Get the weather in location")
.targetClass(TestFunctionClass.class)
.build()
之后:
After:
var toolMethod = ReflectionUtils.findMethod(TestFunctionClass.class, "getWeatherInLocation");
MethodToolCallback.builder()
.toolDefinition(ToolDefinition.builder(toolMethod)
.description("Get the weather in location")
.build())
.toolMethod(toolMethod)
.build()
或者使用声明式方法:
Or with the declarative approach:
class WeatherTools {
@Tool(description = "Get the weather in location")
public void getWeatherInLocation(String location, Unit unit) {
// ...
}
}
您可以使用相同的 ChatClient#tools()
API 注册基于方法的工具回调:
And you can use the same ChatClient#tools()
API to register method-based tool callbackes:
String response = ChatClient.create(chatModel)
.prompt()
.user("What's the weather like in San Francisco?")
.tools(MethodToolCallback.builder()
.toolDefinition(ToolDefinition.builder(toolMethod)
.description("Get the weather in location")
.build())
.toolMethod(toolMethod)
.build())
.call()
.content();
或者使用声明式方法:
Or with the declarative approach:
String response = ChatClient.create(chatModel)
.prompt()
.user("What's the weather like in San Francisco?")
.tools(new WeatherTools())
.call()
.content();
4. Options Configuration
之前:
Before:
FunctionCallingOptions.builder()
.model(modelName)
.function("weatherFunction")
.build()
之后:
After:
ToolCallingChatOptions.builder()
.model(modelName)
.toolNames("weatherFunction")
.build()
5. Default Functions in ChatClient Builder
之前:
Before:
ChatClient.builder(chatModel)
.defaultFunctions(FunctionCallback.builder()
.function("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build())
.build()
之后:
After:
ChatClient.builder(chatModel)
.defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build())
.build()
6. Spring Bean Configuration
之前:
Before:
@Bean
public FunctionCallback weatherFunctionInfo() {
return FunctionCallback.builder()
.function("WeatherInfo", new MockWeatherService())
.description("Get the current weather")
.inputType(MockWeatherService.Request.class)
.build();
}
之后:
After:
@Bean
public ToolCallback weatherFunctionInfo() {
return FunctionToolCallback.builder("WeatherInfo", new MockWeatherService())
.description("Get the current weather")
.inputType(MockWeatherService.Request.class)
.build();
}
Breaking Changes
-
函数回调中的
method()
配置已替换为使用ToolDefinition
和MethodToolCallback
的更显式的方法工具配置。 -
The
method()
configuration in function callbacks has been replaced with a more explicit method tool configuration usingToolDefinition
andMethodToolCallback
. -
使用基于方法的回调时,您现在需要使用
ReflectionUtils
显式查找方法并将其提供给构建器。或者,您可以使用@Tool
注解的声明性方法。 -
When using method-based callbacks, you now need to explicitly find the method using
ReflectionUtils
and provide it to the builder. Alternatively, you can use the declarative approach with the@Tool
annotation. -
对于非静态方法,您现在必须同时提供方法和目标对象:
-
For non-static methods, you must now provide both the method and the target object:
MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(toolMethod) .description("Description") .build()) .toolMethod(toolMethod) .toolObject(targetObject) .build()
Deprecated Methods
以下方法已弃用,并将在未来版本中移除:
The following methods are deprecated and will be removed in a future release:
-
ChatClient.Builder.defaultFunctions(String…)
-
ChatClient.Builder.defaultFunctions(FunctionCallback…)
-
ChatClient.RequestSpec.functions()
请改用它们的 tools
对应项。
Use their tools
counterparts instead.
Declarative Specification with @Tool
现在您可以使用方法级注解 ( @Tool
) 在 Spring AI 中注册工具:
Now you can use the method-level annotation (@Tool
) to register tools with Spring AI:
class Home {
@Tool(description = "Turn light On or Off in a room.")
void turnLight(String roomName, boolean on) {
// ...
logger.info("Turn light in room: {} to: {}", roomName, on);
}
}
String response = ChatClient.create(this.chatModel).prompt()
.user("Turn the light in the living room On.")
.tools(new Home())
.call()
.content();
Additional Notes
-
新 API 在工具定义和实现之间提供了更好的分离。
-
The new API provides better separation between tool definition and implementation.
-
工具定义可以在不同的实现之间重用。
-
Tool definitions can be reused across different implementations.
-
构建器模式已针对常见用例进行了简化。
-
The builder pattern has been simplified for common use cases.
-
更好地支持基于方法的工具,并改进了错误处理。
-
Better support for method-based tools with improved error handling.