方法工具顾名思义就是将类的方法作为 AI 大模型可以调用的工具(此调用并非真实的调用,而是 AI 可以知道你提供了哪些工具,可以根据需要选择合适的工具,并且提供参数,由 Spring AI 根据 AI 响应的内容去调用)。但是 AI 大模型怎么知道那些方法是工具呢?为此,Spring AI 为方法转工具(即 ToolCallback)提供两种内置方式:
声明式:通过 @Tool 注解实现。
编程式:通过底层的 MethodToolCallback 实现。
声明式方式非常简单,你只需为方法添加 @Tool 注解,即可将其转换为工具。例如:
public class DateTimeTools { @Tool(description = "获取用户所在时区的当前日期和时间") public String getCurrentDateTime() { return LocalDateTime.now().atZone( LocaleContextHolder.getTimeZone().toZoneId()).toString(); } }
上述示例将 getCurrentDateTime() 转换成了一个工具,该工具用来获取用户所在时区的当前日期和时间,其中 description 属性用来描述工具的作用。注意,描述一定要准确清晰,AI 大模型才能更精确的识别出要调用的工具。
@Tool 注解用于将普通方法标记为 Spring AI 可调用的工具。定义如下:
package org.springframework.ai.tool.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.ai.tool.execution.DefaultToolCallResultConverter; import org.springframework.ai.tool.execution.ToolCallResultConverter; @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Tool { /** * 工具的名称,用于在AI模型中标识该工具 * 默认为空字符串,此时通常会使用方法名作为工具名称 * * @return 工具名称 */ String name() default ""; /** * 工具的描述信息,用于向AI模型说明该工具的功能和用途 * 帮助AI模型判断何时需要调用该工具,以及如何正确使用 * * @return 工具描述 */ String description() default ""; /** * 指定工具调用结果是否直接返回给用户,而不经过AI模型二次处理 * 默认为false,表示结果需要返回给AI模型,由模型生成最终响应 * 如果设为true,则工具执行结果将直接作为对用户的回应 * * @return 是否直接返回结果 */ boolean returnDirect() default false; /** * 工具调用结果的转换器类型,用于将方法返回值转换为AI模型可处理的格式 * 默认为 DefaultToolCallResultConverter,提供基础的结果转换功能 * 可自定义实现 ToolCallResultConverter 接口以处理特殊格式转换需求 * * @return 结果转换器类 */ Class<? extends ToolCallResultConverter> resultConverter() default DefaultToolCallResultConverter.class; }
基于上述定义,@Tool 注解允许你配置以下关键工具信息:
name:工具名称。如果不指定,默认使用方法名称。AI 模型通过此名称识别并调用工具,因此不允许在同一类中存在同名工具,及不要进行方法重载。注意,模型处理单个聊天请求时,所有可用工具的名称必须保持全局唯一。
description:工具描述,用于指导模型判断何时及如何调用该工具。如果未指定,默认使用方法名称作为工具描述。强烈建议提供详细描述信息,因为这对模型理解工具的用途和使用方式非常重要。如果描述不充分,可能导致模型本应该调用工具时而未调用,或错误调用工具。
returnDirect:控制工具结果直接返回客户端(true)还是传回模型(false)。
resultConverter:用于将工具调用结果转换为字符串对象的 ToolCallResultConverter 实现,该字符串将返回至 AI 模型。
📢注意,被 @Tool 注解修饰的方法既可以是静态方法也可以是实例方法,并且可具有任意可见性(public、protected、package-private 或 private)。包含该方法的类既可以是顶级类也可以是嵌套类,同样支持任意可见性(只要在计划实例化的位置可访问即可)。
Spring AI 为使用 @Tool 注解的方法提供内置的 AOT(提前编译)支持,前提是包含这些方法的类必须是 Spring Bean(例如使用 @Component 注解)。否则,你需要为 GraalVM 编译器提供必要的配置,例如通过使用 @RegisterReflection(memberCategories = MemberCategory.INVOKE_DECLARED_METHODS) 注解标记该类。
你还可以为方法(即工具)定义任意数量的参数(包括无参数),支持大多数类型(基本类型、POJO、枚举、List、数组、Map 等)。同样,方法可以返回大多数类型,包括 void。若方法有返回值,则返回类型必须是可序列化类型,因为结果将被序列化并发送回模型。
Spring AI 将自动为 @Tool 注解方法的输入参数生成 JSON Schema。该 Schema 供模型理解如何调用工具及准备工具请求。你可使用 @ToolParam 注解为输入参数提供额外信息(如描述、是否必需等),默认情况下所有输入参数均为必填参数。例如:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; public class DateTimeTools { @Tool(description = "为给定时间设置用户闹钟") public void setAlarm(@ToolParam(description = "ISO-8601格式的时间") String time) { LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME); System.out.println("闹钟设置为 " + alarmTime); } }
@ToolParam 注解允许你配置工具参数的关键信息,描述工具方法参数元信息。配合 @Tool 注解使用,为 AI 模型提供工具参数的约束和说明,帮助模型正确传递参数。
@ToolParam 注解定义如下:
package org.springframework.ai.tool.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ToolParam { /** * 指定该参数是否为必填项 * 默认为true,表示参数必须提供,否则工具调用可能失败 * 若设为false,AI模型可根据实际情况选择是否传递该参数 * * @return 参数是否必填 */ boolean required() default true; /** * 参数的描述信息,用于向AI模型说明该参数的含义、取值范围或格式要求 * 帮助AI模型理解如何正确填充参数值,提高工具调用的准确性 * * @return 参数描述文本 */ String description() default ""; }
注意,如果参数标注了 @Nullable 注解,则该参数将被视为可选参数,除非通过 @ToolParam 显式标记为必填参数。除 @ToolParam 注解外,你还可使用 Swagger 的 @Schema 或 Jackson 的 @JsonProperty 注解。
当使用声明式配置方案时,你可以在调用 ChatClient 时通过 tools() 方法传入工具类实例。此类工具仅在添加它们的特定聊天请求中可用。例如:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { return ChatClient.create(chatModel) .prompt("明天是星期几?") // 设置可用的工具给大模型,让大模型知道有哪些工具可以使用 .tools(new DateTimeTools()) .call().content(); } }
在底层实现中,ChatClient 将根据工具类实例中每个被 @Tool 注解修饰的方法来生成对应的 ToolCallback,并将其传递给模型。如下图:
若你希望自己生成 ToolCallback,可使用 ToolCallbacks 工具类。如下:
ToolCallback[] dateTimeTools = ToolCallbacks.from(new DateTimeTools());
当使用声明式配置方案时,你可以通过向 ChatClient.Builder 的 defaultTools() 方法传入工具类实例来添加默认工具。若同时提供默认工具和运行时工具(通过 tools() 方法传入的工具 ),运行时工具将完全覆盖默认工具。
注意:默认工具在所有基于同一 ChatClient.Builder 构建的 ChatClient 实例执行的聊天请求间共享。此类工具适用于跨聊天请求的通用功能,但若使用不当可能存在风险 —— 导致工具在不该出现的场景中可用。
简单示例:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { ChatClient chatClient = ChatClient.builder(chatModel) .defaultTools(new DateTimeTools()) .build(); return chatClient.prompt("明天是星期几?") .call().content(); } }
当使用声明式配置方案时,你可以通过调用 ChatModel 时使用的 ToolCallingChatOptions 中的 toolCallbacks() 方法传入工具类实例。此类工具仅在添加它们的特定聊天请求中可用。例如:
class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // 使用 ToolCallbacks 工具类将对象中使用 @Tool 的方法转换为 TooCallback ToolCallback[] dateTimeTools = ToolCallbacks.from(new DateTimeTools()); ChatOptions chatOptions = ToolCallingChatOptions.builder() .toolCallbacks(dateTimeTools) .build(); Prompt prompt = new Prompt("明天是星期几?", chatOptions); return chatModel.call(prompt).getResult().getOutput().getText(); } }
当使用声明式配置方案时,你可以在构建 ChatModel 时通过 ToolCallingChatOptions 实例的 toolCallbacks() 方法传入工具类实例来添加默认工具。若同时提供默认工具和运行时工具,运行时工具将完全覆盖默认工具。
注意:默认工具在该 ChatModel 实例执行的所有聊天请求间共享。此类工具适用于跨请求的通用功能,但需谨慎使用 — 否则可能导致工具在不该被调用的场景下可用。
@RestController class MyController { @Value("${spring.ai.openai.base-url}") private String baseUrl; @Value("${spring.ai.openai.api-key}") private String apiKey; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // 使用 ToolCallbacks 工具类将对象中使用 @Tool 的方法转换为 TooCallback ToolCallback[] dateTimeTools = ToolCallbacks.from(new DateTimeTools()); ChatModel chatModel = OpenAiChatModel.builder() .openAiApi(OpenAiApi.builder().baseUrl(baseUrl).apiKey(apiKey).build()) // 看这里,使用 OpenAiChatOptions 的 toolCallbacks() 方法去设置默认的 ToolCallback .defaultOptions(OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_4_TURBO) // 模型名 .toolCallbacks(dateTimeTools) .build() ) .build(); return chatModel.call("明天是星期几?"); } }
除了上述的 @Tool 注解外,你还可以通过编程的方式去构建 MethodToolCallback,将方法转换为工具。下面是一个普通的类:
public class DateTimeTools { public String getCurrentDateTime() { return LocalDateTime.now().atZone( LocaleContextHolder.getTimeZone().toZoneId()).toString(); } }
要手动构建 MethodToolCallback,需要用到如下 Builder:
MethodToolCallback.Builder 是用于构建 MethodToolCallback 实例的建造类。MethodToolCallback 用于定义当 AI 模型需要调用特定方法工具时的回调逻辑,包括方法执行、结果处理等,而 Builder 则通过链式 API 简化了这一对象的创建过程。
MethodToolCallback.Builder 定义如下:
字段说明:
toolDefinition:定义工具名称、描述及输入模式的 ToolDefinition 实例(必需项),可通过 ToolDefinition.Builder 类构建。
toolMetadata:定义额外设置的 ToolMetadata 实例(如是否将结果直接返回客户端、使用的结果转换器等),可通过 ToolMetadata.Builder 类构建。
toolMethod:表示工具方法的 Method 实例(必需项)。
toolObject:包含工具方法的对象实例(若方法为静态方法则可省略此参数)。
toolCallResultConverter:用于将工具调用结果转换为 String 对象并返回 AI 模型的 ToolCallResultConverter 实例(未配置时默认使用 DefaultToolCallResultConverter)。
简单实例:
Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); MethodToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder().build()) // 工具元信息 .toolMetadata(ToolMetadata.from(method)) // 工具方法的 Method 实例 .toolMethod(method) // 包含工具的对象 .toolObject(new DateTimeTools()) // 工具调用结果转换器 .toolCallResultConverter(new DefaultToolCallResultConverter()) .build();
ToolDefinition.Builder 是构建 ToolDefinition 实例的核心建造类,用于定义 AI 模型可调用的工具元数据(Metadata)。ToolDefinition 是工具调用(Tool Calling)机制的基础,它向 AI 模型描述工具的功能、参数格式、调用方式等信息,而 Builder 则通过链式 API 简化了这一对象的创建过程,让开发者能更灵活地配置工具属性。
ToolDefinition.Builder 的定义如下:
字段说明:
name:工具名称。如果未指定,默认使用方法名称。AI 模型通过此名称识别调用工具,因此不允许在同一类中存在同名工具。模型处理单个聊天请求时,所有可用工具的名称必须保持全局唯一。
description:工具描述,用于帮助模型理解何时及如何调用该工具。如果未提供,将使用方法名称作为工具描述。但强烈建议提供详细描述,因为这对模型理解工具的用途及使用方法至关重要。如果描述不充分,可能导致模型在该调用工具时未调用,或错误调用工具。
inputSchema:工具输入参数的 JSON Schema(一种用于描述和验证 JSON 数据结构的规范。它定义了 JSON 数据应遵循的格式、类型、约束等规则,相当于 JSON 数据的 "蓝图" 或 "契约",能够确保不同系统之间交换的 JSON 数据符合预期结构)。如果未提供,将根据方法参数自动生成。你可使用 @ToolParam 注解提供输入参数的额外信息(如描述、是否必需等),默认情况下所有输入参数均为必需参数。
简单示例:
Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); String jsonSchema = JsonSchemaGenerator.generateForMethodInput(method); MethodToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name("getCurrentDateTime") .description("获取用户所在时区的当前日期和时间") .inputSchema(""" { "$schema" : "https://json-schema.org/draft/2020-12/schema", "type" : "object", "properties" : { }, "required" : [ ], "additionalProperties" : false } """) .build()) // 工具元信息 .toolMetadata(ToolMetadata.from(method)) // 工具方法的 Method 实例 .toolMethod(method) // 包含工具的对象 .toolObject(new DateTimeTools()) // 工具调用结果转换器 .toolCallResultConverter(new DefaultToolCallResultConverter()) .build();
注意,如果你不想自己手动编写 inputSchema,可以通过 JsonSchemaGenerator 帮你自动生成,如下:
Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); String inputSchema = JsonSchemaGenerator.generateForMethodInput(method); //....
ToolMetadata.Builder 是用于构建 ToolMetadata 实例的建造者类,主要用于定义工具的元数据信息。ToolMetadata 包含了工具的核心描述信息,帮助 AI 模型理解工具的用途、参数要求和调用方式,是工具调用(Tool Calling)机制中连接 AI 模型与实际工具逻辑的重要桥梁。
ToolMetadata.Builder 定义如下:
字段说明:
returnDirect:控制是否将工具结果直接返回客户端(true)还是传回模型(false)。
下面是一个通过编程方式定义 MethodToolCallback 的完整例子:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // ReflectionUtils 是 Spring 提供的工具方法,获取指定类中某个方法的 Method 实例 Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); // 手动定义 ToolCallback ToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name(method.getName()) .description("获取用户所在时区的当前日期和时间") .inputSchema(JsonSchemaGenerator.generateForMethodInput(method)) .build()) // 工具对应的方法实例 .toolMethod(method) // 工具所属对象 .toolObject(new DateTimeTools()) .build(); Prompt prompt = new Prompt("明天是星期几?", ToolCallingChatOptions.builder() .toolCallbacks(toolCallback) .build()); return chatModel.call(prompt).getResult().getOutput().getText(); } }
注意,工具方法既可以是静态方法也可以是实例方法,并且可具有任意可见性(public、protected、package-private 或 private)。包含该方法的类既可以是顶级类也可以是嵌套类,同样支持任意可见性(只要在计划实例化的位置可访问即可)。
Spring AI 为工具方法提供内置的 AOT(提前编译)支持,前提是包含这些方法的类必须是 Spring Bean(例如使用 @Component 注解)。否则,你需要为 GraalVM 编译器提供必要的配置,例如通过使用 @RegisterReflection(memberCategories = MemberCategory.INVOKE_DECLARED_METHODS) 注解标记该类。
你还可以为工具方法定义任意数量的参数(包括无参数),支持大多数类型(基本类型、POJO、枚举、List、数组、Map 等)。同样,方法可以返回大多数类型,包括 void。若方法有返回值,则返回类型必须是可序列化类型,因为结果将被序列化并发送回模型。
如果方法为静态方法,则可省略 toolObject() 方法,例如:
public class DateTimeTools { // 静态方法 public static String getCurrentDateTime() { return LocalDateTime.now().atZone( LocaleContextHolder.getTimeZone().toZoneId()).toString(); } }
使用 MethodToolCallback 手动转换工具方法:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // ReflectionUtils 是 Spring 提供的工具方法,获取指定类中某个方法的 Method 实例 Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); // 手动定义 ToolCallback ToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name(method.getName()) .description("获取用户所在时区的当前日期和时间") .inputSchema(JsonSchemaGenerator.generateForMethodInput(method)) .build()) // 工具对应的方法实例 .toolMethod(method) // .toolObject(new DateTimeTools()) // 不需要了 .build(); Prompt prompt = new Prompt("明天是星期几?", ToolCallingChatOptions.builder() .toolCallbacks(toolCallback) .build()); return chatModel.call(prompt).getResult().getOutput().getText(); } }
注意,记得使用 JsonSchemaGenerator.generateForMethodInput(method) 生成方法参数的 JSON Schema,并通过 inputSchema() 设置,否则将抛出如下错误信息:
java.lang.IllegalArgumentException: inputSchema cannot be null or empty at org.springframework.util.Assert.hasText(Assert.java:253) ~[spring-core-6.2.7.jar:6.2.7] at org.springframework.ai.tool.definition.DefaultToolDefinition.<init>(DefaultToolDefinition.java:34) ~[spring-ai-model-1.0.0.jar:1.0.0] at org.springframework.ai.tool.definition.DefaultToolDefinition$Builder.build(DefaultToolDefinition.java:72) ~[spring-ai-model-1.0.0.jar:1.0.0]
你可使用 @ToolParam 注解为输入参数提供额外信息(如描述、是否必需等),默认情况下所有输入参数均为必需参数。例如:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import org.springframework.ai.tool.annotation.ToolParam; class DateTimeTools { void setAlarm(@ToolParam(description = "ISO-8601格式的时间") String time) { LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME); System.out.println("闹钟设置为 " + alarmTime); } }
@ToolParam 注解允许你配置工具参数的以下关键信息:
description:参数描述,用于帮助模型更准确地理解如何使用该参数。例如:参数格式要求、允许取值范围等。
required:指定参数是否为必需项(默认值:true,即所有参数默认必需)。
如果参数标注了 @Nullable 注解,则该参数将被视为可选参数,除非通过 @ToolParam 显式标记为必需参数。除 @ToolParam 注解外,你还可使用 Swagger 的 @Schema 或 Jackson 的 @JsonProperty 注解。
当使用编程式配置方案时,你可以通过 ChatClient 的 tools() 方法传入 MethodToolCallback 实例。该工具仅在添加它的特定聊天请求中可用。例如:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // ReflectionUtils 是 Spring 提供的工具方法,获取指定类中某个方法的 Method 实例 Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); // 手动定义 ToolCallback ToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name(method.getName()) .description("获取用户所在时区的当前日期和时间") .inputSchema(JsonSchemaGenerator.generateForMethodInput(method)) .build()) // 工具对应的方法实例 .toolMethod(method) // 工具所属对象 .toolObject(new DateTimeTools()) .build(); return ChatClient.create(chatModel) .prompt("明天是星期几?") .toolCallbacks(toolCallback) // 将 ToolCallback 设置给 ChatClient .call() .content(); } }
当使用编程式配置方案时,你可以通过向 ChatClient.Builder 的 defaultTools() 方法传入 MethodToolCallback 实例来添加默认工具。若同时提供默认工具和运行时工具,运行时工具将完全覆盖默认工具。
默认工具在所有基于同一 ChatClient.Builder 构建的 ChatClient 实例执行的聊天请求间共享。此类工具适用于跨聊天请求的通用功能,但若使用不当可能存在风险 — 导致工具在不该出现的场景中可用。
例如:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // ReflectionUtils 是 Spring 提供的工具方法,获取指定类中某个方法的 Method 实例 Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); // 手动定义 ToolCallback ToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name(method.getName()) .description("获取用户所在时区的当前日期和时间") .inputSchema(JsonSchemaGenerator.generateForMethodInput(method)) .build()) // 工具对应的方法实例 .toolMethod(method) // 工具所属对象 .toolObject(new DateTimeTools()) .build(); ChatClient chatClient = ChatClient.builder(chatModel) .defaultToolCallbacks(toolCallback) .build(); return chatClient.prompt("明天是星期几?").call().content(); } }
当使用编程式配置方案时,你可以通过调用 ChatModel 时使用的 ToolCallingChatOptions 中的 toolCallbacks() 方法传入 MethodToolCallback 实例。该工具仅在添加它的特定聊天请求中可用。
例如:
@RestController class MyController { @Autowired private ChatModel chatModel; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // ReflectionUtils 是 Spring 提供的工具方法,获取指定类中某个方法的 Method 实例 Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); // 手动定义 ToolCallback ToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name(method.getName()) .description("获取用户所在时区的当前日期和时间") .inputSchema(JsonSchemaGenerator.generateForMethodInput(method)) .build()) // 工具对应的方法实例 .toolMethod(method) // 工具所属对象 .toolObject(new DateTimeTools()) .build(); ChatOptions chatOptions = ToolCallingChatOptions.builder() .toolCallbacks(toolCallback) .build(); Prompt prompt = new Prompt("明天是星期几?", chatOptions); return chatModel.call(prompt).getResult().getOutput().getText(); } }
使用编程式配置方案时,你可以在构建 ChatModel 时,通过用于创建 ChatModel 的 ToolCallingChatOptions 实例的 toolCallbacks() 方法传入 MethodToolCallback 实例来添加默认工具。若同时提供默认工具和运行时工具,运行时工具将完全覆盖默认工具。
默认工具在该 ChatModel 实例处理的所有聊天请求间共享。此类工具适用于跨聊天请求的通用功能,但若使用不当,可能导致工具在不该出现的场景中被调用。
例如:
@RestController class MyController { @Value("${spring.ai.openai.base-url}") private String baseUrl; @Value("${spring.ai.openai.api-key}") private String apiKey; // 模型使用 gpt-4-turbo // GPT-4 全面支持工具调用功能,且在处理复杂度、准确性和灵活性上显著优于 GPT-3.5-turbo // http://localhost:8080/ai @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8") public String ai() { // ReflectionUtils 是 Spring 提供的工具方法,获取指定类中某个方法的 Method 实例 Method method = ReflectionUtils.findMethod(DateTimeTools.class, "getCurrentDateTime"); // 手动定义 ToolCallback ToolCallback toolCallback = MethodToolCallback.builder() // 工具定义 .toolDefinition(ToolDefinition.builder() .name(method.getName()) .description("获取用户所在时区的当前日期和时间") .inputSchema(JsonSchemaGenerator.generateForMethodInput(method)) .build()) // 工具对应的方法实例 .toolMethod(method) // 工具所属对象 .toolObject(new DateTimeTools()) .build(); ChatModel chatModel = OpenAiChatModel.builder() .openAiApi(OpenAiApi.builder().baseUrl(baseUrl).apiKey(apiKey).build()) // 看这里,使用 OpenAiChatOptions 的 toolCallbacks() 方法去设置默认的 ToolCallback .defaultOptions(OpenAiChatOptions.builder() .model(OpenAiApi.ChatModel.GPT_4_TURBO) // 模型名 .toolCallbacks(toolCallback) .build() ) .build(); return chatModel.call("明天是星期几?"); } }
以下类型目前不支持作为工具方法的参数或返回类型:
Optional
异步类型(如 CompletableFuture、Future)
响应式类型 (如 Flow、Mono、Flux)
函数式类型(如 Function、Supplier、Consumer)
注意,函数式类型在基于函数的工具规范方法中受支持。