AI项目博客
记录 AI 工程实践与大模型应用

Spring AI Alibaba 11|Tools 工具 · 创建工具:基础工具定义

Spring AI 提供了对从函数指定工具的内置支持,可以通过编程方式使用低级 FunctionToolCallback 实现,也可以动态地作为在运行时解析的 @Bean。

编程方式规范:FunctionToolCallback

你可以通过编程方式构建 FunctionToolCallback,将函数类型(Function、Supplier、Consumer 或 BiFunction)转换为工具。

import java.util.function.Function;

public class WeatherService implements Function<WeatherRequest, WeatherResponse> {
  public WeatherResponse apply(WeatherRequest request) {
      return new WeatherResponse(30.0, Unit.C);
  }
}

public enum Unit { C, F }
public record WeatherRequest(String location, Unit unit) {}
public record WeatherResponse(double temp, Unit unit) {}

FunctionToolCallback.Builder 允许你构建 FunctionToolCallback 实例并提供有关工具的关键信息:

  • name: 工具的名称。AI 模型使用此名称在调用时识别工具。因此,在同一上下文中不允许有两个同名的工具。对于特定的聊天请求,名称在模型可用的所有工具中必须是唯一的。必需。
  • toolFunction: 表示工具方法的函数对象(Function、Supplier、Consumer 或 BiFunction)。必需。
  • description: 工具的描述,模型可以使用它来了解何时以及如何调用工具。如果未提供,将使用方法名称作为工具描述。但是,强烈建议提供详细描述,因为这对于模型理解工具的目的和使用方式至关重要。如果未提供良好的描述,可能导致模型在应该使用工具时不使用,或者使用不正确。
  • inputType: 函数输入的类型。必需。
  • inputSchema: 工具输入参数的 JSON schema。如果未提供,将根据 inputType 自动生成 schema。你可以使用 @ToolParam 注解提供有关输入参数的附加信息,例如描述或参数是必需还是可选。默认情况下,所有输入参数都被视为必需。
  • toolMetadata: 定义附加设置的 ToolMetadata 实例,例如是否应将结果直接返回给客户端,以及要使用的结果转换器。你可以使用 ToolMetadata.Builder 类构建它。
  • toolCallResultConverter: 用于将工具调用结果转换为字符串对象以发送回 AI 模型的 ToolCallResultConverter 实例。如果未提供,将使用默认转换器(DefaultToolCallResultConverter)。
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;

ToolCallback toolCallback = FunctionToolCallback
  .builder("currentWeather", new WeatherService())
  .description("Get the weather in location")
  .inputType(WeatherRequest.class)
  .build();

函数的输入和输出可以是 Void 或 POJO。输入和输出 POJO 必须是可序列化的,因为结果将被序列化并发送回模型。函数以及输入和输出类型必须是公共的。

重要提示:某些类型不受支持。有关更多详细信息,请参阅函数工具限制。

添加工具到 ChatClient:

使用编程规范方法时,你可以将 FunctionToolCallback 实例传递给 ChatClient 的 toolCallbacks() 方法。该工具仅对添加到的特定聊天请求可用。

import org.springframework.ai.chat.client.ChatClient;

ToolCallback toolCallback = ...;

ChatClient.create(chatModel)
  .prompt("What's the weather like in Copenhagen?")
  .toolCallbacks(toolCallback)
  .call()
  .content();

添加默认工具到 ChatClient:

使用编程规范方法时,你可以通过将 FunctionToolCallback 实例传递给 defaultToolCallbacks() 方法将默认工具添加到 ChatClient.Builder。如果同时提供默认工具和运行时工具,运行时工具将完全覆盖默认工具。

ChatModel chatModel = ...;
ToolCallback toolCallback = ...;

ChatClient chatClient = ChatClient.builder(chatModel)
  .defaultToolCallbacks(toolCallback)
  .build();

注意:默认工具在从同一 ChatClient.Builder 构建的所有 ChatClient 实例执行的所有聊天请求中共享。它们对于跨不同聊天请求常用的工具很有用,但如果不小心使用也可能很危险,可能在不应该使用时使它们可用。

添加工具到 ChatModel:

使用编程规范方法时,你可以将 FunctionToolCallback 实例传递给 ToolCallingChatOptions 的 toolCallbacks() 方法。该工具仅对添加到的特定聊天请求可用。

import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.ToolCallingChatOptions;

ChatModel chatModel = ...;
ToolCallback toolCallback = ...;

ChatOptions chatOptions = ToolCallingChatOptions.builder()
  .toolCallbacks(toolCallback)
  .build();

Prompt prompt = new Prompt("What's the weather like in Copenhagen?", chatOptions);
chatModel.call(prompt);

动态规范:@Bean

你可以将工具定义为 Spring beans,让 Spring AI 使用 ToolCallbackResolver 接口(通过 SpringBeanToolCallbackResolver 实现)在运行时动态解析它们,而不是以编程方式指定工具。此选项使你可以将任何 Function、Supplier、Consumer 或 BiFunction bean 用作工具。bean 名称将用作工具名称,Spring Framework 的 @Description 注解可用于为工具提供描述,供模型用来了解何时以及如何调用工具。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import java.util.function.Function;

@Configuration(proxyBeanMethods = false)
class WeatherTools {

  WeatherService weatherService = new WeatherService();

  @Bean
  @Description("Get the weather in location")
  Function<WeatherRequest, WeatherResponse> currentWeather() {
      return weatherService;
  }
}

重要提示:某些类型不受支持。有关更多详细信息,请参阅函数工具限制。

工具输入参数的 JSON schema 将自动生成。你可以使用 @ToolParam 注解提供有关输入参数的附加信息,例如描述或参数是必需还是可选。默认情况下,所有输入参数都被视为必需。

import org.springframework.ai.tool.annotation.ToolParam;

record WeatherRequest(
  @ToolParam(description = "The name of a city or a country") String location,
  Unit unit
) {}

此工具规范方法的缺点是不保证类型安全,因为工具解析是在运行时完成的。为了缓解这一问题,你可以使用 @Bean 注解显式指定工具名称并将值存储在常量中,以便你可以在聊天请求中使用它而不是硬编码工具名称。

@Configuration(proxyBeanMethods = false)
class WeatherTools {

  public static final String CURRENT_WEATHER_TOOL = "currentWeather";

  @Bean(CURRENT_WEATHER_TOOL)
  @Description("Get the weather in location")
  Function<WeatherRequest, WeatherResponse> currentWeather() {
      // ...
  }
}

添加工具到 ChatClient(使用动态规范):

ChatClient.create(chatModel)
  .prompt("What's the weather like in Copenhagen?")
  .toolNames("currentWeather")
  .call()
  .content();

添加默认工具到 ChatClient(使用动态规范):

ChatModel chatModel = ...;

ChatClient chatClient = ChatClient.builder(chatModel)
  .defaultToolNames("currentWeather")
  .build();

函数工具限制

以下类型目前不支持作为用作工具的函数的输入或输出类型:

  • 原始类型
  • Optional
  • 集合类型(例如 List、Map、Array、Set)
  • 异步类型(例如 CompletableFuture、Future)
  • 响应式类型(例如 Flow、Mono、Flux)

使用基于方法的工具规范方法支持原始类型和集合。

本文整理自 Spring AI Alibaba 官方文档《Tools 工具》:https://java2ai.com/docs/frameworks/agent-framework/tutorials/tools

赞(0)
未经允许不得转载:AI项目博客 » Spring AI Alibaba 11|Tools 工具 · 创建工具:基础工具定义

评论 抢沙发

AI项目博客

专注 AI 工程化落地 —— 覆盖智能体、大模型、Java AI 与 Python 的学习笔记,以及 AI 平台的项目实战记录。

关于本站文章归档

登录

找回密码

注册