从 FunctionCallback 迁移到 ToolCallback API

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

本指南将帮助你从已弃用的 FunctionCallback API 迁移至 Spring AI 中全新的 ToolCallback API。有关新 API 的详细信息,请参阅 工具调用(Tools Calling) 文档。

变化概览

此次变更是 Spring AI 为增强工具调用功能所做整体改进的一部分。新 API 采用 "tools" 术语替代原有 "functions" 命名,以更符合行业惯例。在通过弃用方法保持向后兼容的同时,涉及多项接口变更。

关键性改变

  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 用法

之前:

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

之后:

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 中的默认函数

之前:

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 显式查找目标方法并传递给 Builder。你也可以选择使用带有 @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. Builder 模式已针对常见使用场景进行简化。

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

时间线

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