从 FunctionCallback 迁移至 ToolCallback API
本指南将帮助您将已弃用的 FunctionCallback API 迁移到 Spring AI 中新的 ToolCallback API。有关新 API 的更多信息,请查阅 工具调用 文档。
变更概述
这些变更是 Spring AI 中一项更广泛的改进与扩展工具调用能力工作的一部分。其中,新 API 从"函数"术语转向"工具"术语,以更好地与行业惯例保持一致。这涉及多项 API 变更,同时通过已弃用的方法保持向后兼容性。
关键变化
-
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()
迁移示例
1. 基础函数回调
之前:
FunctionCallback.builder()
.function("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build()
之后:
FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build()
2. ChatClient 使用方法
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();
之后:
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. 基于方法的函数回调
之前:
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()
或者使用声明式方法:
class WeatherTools {
@Tool(description = "Get the weather in location")
public void getWeatherInLocation(String location, Unit unit) {
// ...
}
}
你可以使用相同的 ChatClient#tools() API 来注册基于方法的工具回调:
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();
或者使用声明式方法:
String response = ChatClient.create(chatModel)
.prompt()
.user("What's the weather like in San Francisco?")
.tools(new WeatherTools())
.call()
.content();
4. 选项配置
之前:
FunctionCallingOptions.builder()
.model(modelName)
.function("weatherFunction")
.build()
之后:
ToolCallingChatOptions.builder()
.model(modelName)
.toolNames("weatherFunction")
.build()
5. 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()
之后:
ChatClient.builder(chatModel)
.defaultTools(FunctionToolCallback.builder("getCurrentWeather", new MockWeatherService())
.description("Get the weather in location")
.inputType(MockWeatherService.Request.class)
.build())
.build()
6. Spring Bean 配置
之前:
@Bean
public FunctionCallback weatherFunctionInfo() {
return FunctionCallback.builder()
.function("WeatherInfo", new MockWeatherService())
.description("Get the current weather")
.inputType(MockWeatherService.Request.class)
.build();
}
之后:
@Bean
public ToolCallback weatherFunctionInfo() {
return FunctionToolCallback.builder("WeatherInfo", new MockWeatherService())
.description("Get the current weather")
.inputType(MockWeatherService.Request.class)
.build();
}
重大变更
-
函数回调中的
method()配置已被替换为使用ToolDefinition和MethodToolCallback的更明确方法工具配置。 -
当使用方法回调时,现在需要通过
ReflectionUtils显式查找方法并提供给构建器。或者,你也可以使用带有@Tool注解的声明式方法。 -
对于非静态方法,现在必须同时提供方法和目标对象:
MethodToolCallback.builder()
.toolDefinition(ToolDefinition.builder(toolMethod)
.description("Description")
.build())
.toolMethod(toolMethod)
.toolObject(targetObject)
.build()
弃用方法
以下方法已被弃用,并将在未来的版本中移除:
-
ChatClient.Builder.defaultFunctions(String…) -
ChatClient.Builder.defaultFunctions(FunctionCallback…) -
ChatClient.RequestSpec.functions()
请使用其 tools 对应的版本。
使用 @Tool 进行声明式规范
现在你可以使用方法级别的注解(@Tool)向 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();
附加说明
-
新API实现了工具定义与实现之间更好的分离。
-
工具定义可以在不同的实现中重复使用。
-
针对常见用例简化了构建器模式。
-
增强了对基于方法的工具的支持,并改进了错误处理。
时间线
已废弃的方法将在当前里程碑版本中为向后兼容性而保留,但将在下一个里程碑版本中移除。建议尽快迁移至新的API。