跳到主要内容

从 FunctionCallback 迁移至 ToolCallback API

Deepseek 3.2 中英对照 Migrating FunctionCallback to ToolCallback API Migrating from FunctionCallback to ToolCallback API

本指南将帮助您将已弃用的 FunctionCallback API 迁移到 Spring AI 中新的 ToolCallback API。有关新 API 的更多信息,请查阅 工具调用 文档。

变更概述

这些变更是 Spring AI 中一项更广泛的改进与扩展工具调用能力工作的一部分。其中,新 API 从"函数"术语转向"工具"术语,以更好地与行业惯例保持一致。这涉及多项 API 变更,同时通过已弃用的方法保持向后兼容性。

关键变化

  1. FunctionCallbackToolCallback

  2. FunctionCallback.builder().function()FunctionToolCallback.builder()

  3. FunctionCallback.builder().method()MethodToolCallback.builder()

  4. FunctionCallingOptionsToolCallingChatOptions

  5. ChatClient.builder().defaultFunctions()ChatClient.builder().defaultTools()

  6. ChatClient.functions()ChatClient.tools()

  7. FunctionCallingOptions.builder().functions()ToolCallingChatOptions.builder().toolNames()

  8. 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();
}

重大变更

  1. 函数回调中的 method() 配置已被替换为使用 ToolDefinitionMethodToolCallback 的更明确方法工具配置。

  2. 当使用方法回调时,现在需要通过 ReflectionUtils 显式查找方法并提供给构建器。或者,你也可以使用带有 @Tool 注解的声明式方法。

  3. 对于非静态方法,现在必须同时提供方法和目标对象:

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();

附加说明

  1. 新API实现了工具定义与实现之间更好的分离。

  2. 工具定义可以在不同的实现中重复使用。

  3. 针对常见用例简化了构建器模式。

  4. 增强了对基于方法的工具的支持,并改进了错误处理。

时间线

已废弃的方法将在当前里程碑版本中为向后兼容性而保留,但将在下一个里程碑版本中移除。建议尽快迁移至新的API。