孝感市网站建设_网站建设公司_前后端分离_seo优化
2025/12/19 13:55:16 网站建设 项目流程

官网地址:https://docs.spring.io/spring-ai/reference/api/tools.html

1、描述

工具调用功能可以让LLM与API或者工具交互,增强其能力,SpringAI提供便捷的API来定义工具、解析模型的工具调用请求并执行工具调用。
工具主要用于:

  • 信息检索。这种类别的工具可用于从外部(数据库、Web服务、文件系统或者Web搜索引擎等)检索信息,目的是增强模型的知识,可以获得最新的知识或者查询数据库特定的数据。
  • 执行操作。这种类别的工具可用于在软件系统中执行操作,例如发送邮件、在数据库中创建新纪录、提交表单或者触发工作流,目的是可以自动化需要人工干预或者显示编程的任务,比如查询订单状态信息、填写表单或者在代码生成场景中生成模板代码等。

注意(安全考虑):

LLM定位是一个纯粹的“决策和规划的大脑”,所有涉及与外部交互都由我们自己控制,比如网络请求、数据库查询或者文件操作等,LLM 和工具执行环境隔离,可以从根本上解决 LLM 的行为失控,从而构建安全可靠的 AI 应用。

例如:我们提供一个工具,用来获取城市的天气情况,当我们提供了@Tool 的注解的方法,LLM 只能发现方法getWeather,以及参数 city,以及返回参数,它无法直接创建 HTTP 请求直接调用weatherApiClient。代码如下:

 @Tool(description = "根据城市名称获取天气")public String getWeather(String city) {// 模型只能“请求”调用 getWeather("上海")// 实际的 HTTP 调用发生在这里,完全由你的代码控制return weatherApiClient.fetchFromSomeAPI(city);}

SpringAI 支持工具调用的组件与流程
image

2、声明式:@Tool

通过注解@Tool 将方法转换为工具,例如:

   @Tool(description = "获取当前时间")String getCurrentTime() {return DateTime.now().toMsStr();}

@Tool 关键信息:

  • name:工具的名称。如果没有设置,则使用方法名称,LLM 使用此名称在调用工具时识别它,在同一类中不允许有两个同名的工具,名称在特定聊天可用的所有工具中必须是唯一的,建议设置为全局唯一。
  • description:工具的描述。LLM 使用描述来理解何时及如何调用工具,如果没有设置,方法名称将作为工具描述,但是强烈建议设置工具描述,这个对LLM 理解工具的作用和如何使用很重要,如果工具描述不准确,会导致 LLM 使用不到该工具或者使用使用不正确。
  • returnDirect:工具结果是直接返回给客户端还是传回模型,默认 false,默认传递回模型
  • resultConverter:用于将工具调用结果转换为 String 对象以发送会 AI 模型的ToolCallResultConverter实现。

@ ToolParam关键信息

  • description:参数的描述,模型可以使用它更好地理解如何使用它。例如,参数应该采用什么格式,允许什么值等等。
  • required:参数是必需还是可选。默认情况下,所有参数都被认为是必需的。

3、将工具添加到ChatClient

3.1、添加工具:

ChatClient.create(chatModel).prompt("What day is tomorrow?").tools(new DateTimeTools()).call().content();

3.2、添加默认工具:

    @Beanpublic ChatClient chatClient(OllamaChatModel ollamaChatModel) {return ChatClient.builder(ollamaChatModel).defaultTools(new DateTimeTools()).build();}

在底层,ChatClient 将从工具类实例中的每个 @Tool 注解方法生成一个 ToolCallback 并将其传递给模型。如果您希望自己生成 ToolCallback,可以使用 ToolCallbacks 实用程序类。
如果同时设置了运行行工具和默认工具,默认工具会被覆盖。

3.3、方法工具限制

目前不支持以下类型作为用作工具的方法的参数或返回类型:

  • Optional
  • 异步类型(例如 CompletableFuture、Future)
  • 响应式类型(例如 Flow、Mono、Flux)
  • 函数式类型(例如 Function、Supplier、Consumer)。
    函数式类型通过基于函数的工具规范方法受支持

4、函数作为工具

Spring AI 提供内置支持,用于从函数指定工具,无论是使用低级 FunctionToolCallback 实现以编程方式实现,还是作为在运行时解析的 @Bean 动态实现。

4.1、FunctionToolCallback

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

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) {}@Beanpublic ChatClient chatClient(OllamaChatModel ollamaChatModel) {FunctionToolCallback<WeatherRequest, WeathResponse> functionToolCallback = FunctionToolCallback.builder("当前天气", new WeatherService()).description("获取当前地区的天气").inputType(WeatherRequest.class).build();return ChatClient.builder(ollamaChatModel).defaultToolCallbacks(functionToolCallback).build();}

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

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

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

5、ToolContext

Spring AI 支持通过 ToolContext API 将额外的上下文信息传递给工具。此功能允许您提供额外的、用户提供的数据,这些数据可以在工具执行期间与 AI 模型传递的工具参数一起使用。

@Component
public class DateTimeTools {@Tool(description = "获取当前时间")String getCurrentTime(ToolContext toolContext) {String conversationId = toolContext.getContext().get(ChatMemory.CONVERSATION_ID).toString();System.out.println("调用该工具的对话 ID 为:" + conversationId);return DateTime.now().toMsStr();}
}@PostMapping("chat")public Flux<String> chat(@RequestBody ChatReq chatReq) {return chatClient.prompt(chatReq.getMessage()).advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatReq.getMemoryId())).toolContext(Map.of(ChatMemory.CONVERSATION_ID, chatReq.getMemoryId())).stream().content();}

结果输出:image

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询