函数回调

FunctionCallbackinterface 提供了一种标准化的方式来实现大型语言模型 (LLM) 函数调用功能。它允许开发人员注册自定义函数,当在提示中检测到特定条件或意图时,AI 模型可以调用这些函数。spring-doc.cadn.net.cn

FunctionCallbackinterface 定义了几个关键方法:spring-doc.cadn.net.cn

Builder 模式

Spring AI 提供了一个 Fluent 构建器 API,用于创建FunctionCallback实现。 这对于定义函数回调特别有用,您可以务实地、动态地使用ChatClientChatModelmodel 调用。spring-doc.cadn.net.cn

使用FunctionCallback.builder()方法创建新的生成器实例并链接配置方法以设置函数名称、描述、输入类型和其他属性。 这FunctionCallback.Builder是具有以下结构的层次结构:spring-doc.cadn.net.cn

函数调用方法

转换任何java.util.function.Function,BiFunction,SupplierConsumer转换为FunctionCallback可以由 AI 模型调用。spring-doc.cadn.net.cn

您可以使用 lambda 表达式或方法引用来定义函数逻辑,但必须使用inputType(TYPE).

函数<I, O>

FunctionCallback callback = FunctionCallback.builder()
    .function("processOrder", (Order order) -> processOrderLogic(order))
    .description("Process a new order")
    .inputType(Order.class)
    .build();

BiFunction<I、ToolContext、O>

将 Function 与输入类型 <I> 和其他 ToolContext 参数一起使用:spring-doc.cadn.net.cn

FunctionCallback callback = FunctionCallback.builder()
    .function("processOrder", (Order order, ToolContext context) ->
        processOrderWithContext(order, context))
    .description("Process a new order with context")
    .inputType(Order.class)
    .build();

供应商<O>

java.util.Supplier<O>java.util.function.Function<Void, O>要定义不采用任何输入的函数,请执行以下作:spring-doc.cadn.net.cn

FunctionCallback.builder()
	.function("turnsLight", () -> state.put("Light", "ON"))
    .description("Turns light on in the living room")
    .inputType(Void.class)
	.build();

消费者<I>

java.util.Consumer<I>java.util.function.Function<I, Void>要定义不产生 output 的函数,请执行以下作:spring-doc.cadn.net.cn

record LightInfo(String roomName, boolean isOn) {}

FunctionCallback.builder()
	.function("turnsLight", (LightInfo lightInfo) -> {
				logger.info("Turning light to [" + lightInfo.isOn + "] in " + lightInfo.roomName());
			})
    .description("Turns light on/off in a selected room")
    .inputType(LightInfo.class)
	.build();

泛型输入类型

使用ParameterizedTypeReference要使用通用输入类型定义函数:spring-doc.cadn.net.cn

record TrainSearchRequest<T>(T data) {}

record TrainSearchSchedule(String from, String to, String date) {}

record TrainSearchScheduleResponse(String from, String to, String date, String trainNumber) {}

FunctionCallback.builder()
	.function("trainSchedule", (TrainSearchRequest<TrainSearchSchedule> request) -> {
        logger.info("Schedule: " + request.data().from() + " to " + request.data().to());
        return new TrainSearchScheduleResponse(request.data().from(), request.  data().to(), "", "123");
    })
    .description("Schedule a train reservation")
    .inputType(new ParameterizedTypeReference<TrainSearchRequest<TrainSearchSchedule>>() {})
	.build();

方法调用方法

通过反射启用方法调用,同时自动处理 JSON 架构生成和参数转换。它对于将 Java 方法作为可调用函数集成到 AI 模型交互中特别有用。spring-doc.cadn.net.cn

调用的方法实现FunctionCallback接口并提供:spring-doc.cadn.net.cn

静态方法调用

您可以通过提供方法名称、参数类型和目标类来引用类中的静态方法。spring-doc.cadn.net.cn

public class WeatherService {
    public static String getWeather(String city, TemperatureUnit unit) {
        return "Temperature in " + city + ": 20" + unit;
    }
}

FunctionCallback callback = FunctionCallback.builder()
    .method("getWeather", String.class, TemperatureUnit.class)
    .description("Get weather information for a city")
    .targetClass(WeatherService.class)
    .build();

对象实例方法调用

您可以通过提供方法名称、参数类型和目标对象实例来引用类中的实例方法。spring-doc.cadn.net.cn

public class DeviceController {
    public void setDeviceState(String deviceId, boolean state, ToolContext context) {
        Map<String, Object> contextData = context.getContext();
        // Implementation using context data
    }
}

DeviceController controller = new DeviceController();

String response = ChatClient.create(chatModel).prompt()
    .user("Turn on the living room lights")
    .functions(FunctionCallback.builder()
        .method("setDeviceState", String.class,boolean.class,ToolContext.class)
        .description("Control device state")
        .targetObject(controller)
        .build())
    .toolContext(Map.of("location", "home"))
    .call()
    .content();
(可选)使用.name(),您可以设置与方法名称不同的自定义函数名称。

常见配置

您可以使用几种常见配置来自定义函数回调。spring-doc.cadn.net.cn

架构类型

该框架支持不同的架构类型来为输入参数生成架构:spring-doc.cadn.net.cn

FunctionCallback.builder()
    .schemaType(SchemaType.OPEN_API_SCHEMA)
    // ... other configuration
    .build();

自定义响应处理

您可以提供自定义响应转换器,以便在将函数响应发送回 AI 模型之前设置函数响应的格式。 大多数 AI 模型都需要文本响应,因此您有责任将函数响应转换为文本格式。 默认情况下,响应将转换为 String。spring-doc.cadn.net.cn

许多模型可以很好地处理 JSON 响应,因此您可以返回 JSON 字符串。
FunctionCallback.builder()
    .responseConverter(response ->
        customResponseFormatter.format(response))
    // ... other configuration
    .build();

自定义对象映射

Spring AI 使用 ObjectMapper 进行 JSON 序列化和反序列化。 您可以提供自定义 ObjectMapper 来处理自定义对象映射:spring-doc.cadn.net.cn

FunctionCallback.builder()
    .objectMapper(customObjectMapper)
    // ... other configuration
    .build();

最佳实践

描述性名称和描述

输入类型和架构

  • 对于函数调用方法,显式定义输入类型并使用ParameterizedTypeReference对于泛型类型。spring-doc.cadn.net.cn

  • 当自动生成的 schema 不满足要求时,请考虑使用自定义 schema。spring-doc.cadn.net.cn

错误处理

工具上下文使用

  • 当需要 User 提供的其他状态或上下文,而不是 AI 模型生成的函数输入的一部分时,请使用 ToolContextspring-doc.cadn.net.cn

  • BiFunction<I, ToolContext, O>以在函数调用方法中访问 ToolContext,并添加ToolContextparameter 的 intent 方法。spring-doc.cadn.net.cn

Schema 生成说明

要避免的常见陷阱

缺少描述

架构不匹配