Spring AI - Tool Calling(工具调用)
一、Tool Calling
1.1、为什么要学Tool Calling
在传统的 Java 开发中,我们擅长处理确定性的逻辑(如数据库 CRUD、事务控制、微服务调用)。但在 AI 时代,大模型(LLM)虽然聪明,却有两个致命弱点:它不知道实时数据(如今天的股价、你的订单状态),也无法直接执行操作(如发邮件、改数据库)。
Spring AI 的“工具调用”(Function Calling(函数调用) / Tool Calling)正是为了解决这个问题而存在的。
1.2、Tool Calling能做什么
赋予 AI “手脚”,从“聊天机器人”升级为“智能代理”
没有函数调用,AI 只是一个会说话的百科全书,面对“帮我查一下成都现在实时天气”或“取消我的订单”这类请求,它只能回答“我无法访问实时数据”。
通过 Spring AI 的函数调用,你可以将 Java 方法注册为“工具”。当用户提问时,AI 会自动判断:“这个问题我需要调用 createOrder(自定义) 方法”,然后 Spring AI 帮你执行这个 Java 方法,拿到结果后再让 AI 组织语言回答用户。
价值点:你不需要写复杂的正则表达式或意图识别代码来解析用户指令,AI 自己会决定何时调用你的代码。
1.3、Tool Calling定义
让 大语言模型(LLM)在对话中,主动决定调用你提前注册的 Java 方法 / 外部 API接口,拿到结果后再整理成自然语言回答Spring 框架。
- LLM 不直接执行代码,只输出 “调用哪个工具、传什么参数” 的 JSON 意图Spring 框架。
- Spring AI负责解析意图、执行 Java 函数、返回结果给 LLM,完成闭环。
- 核心价值:把 LLM 从 “只会聊天” 升级为 “能办事、能查数据、能控系统”。
工作流程(5 步闭环)

用户提问 → 2. LLM 判断需调用工具 → 3. Spring AI 执行 Java 函数 → 4. 结果回传给 LLM → 5. LLM 生成最终回答。
二、Spring AI 函数调用几种方式
三种方式:
@Tool 注解式(最简单)、Function 函数式(轻量)、MethodToolCallback 编程式(灵活)。
2.1、前置环境搭建
2.1.1、技术栈介绍
JDK17+、SpringBoot.3.3.10、智谱AI GLM系列模型(glm-4、glm-4-flash)
2.1.2、创建SpringBoot项目,导入如下依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wn</groupId>
<artifactId>boot-ai-zhipu</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>boot-ai-zhipu</name>
<description>boot-ai-zhipu</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2.1.3、配置应用环境
需通过环境变量读取,禁止在代码、配置文件中明文硬编码,防止密钥泄露。

2.1.4、application.yml
spring:
ai:
zhipuai:
# 智谱AI的API密钥,通过系统环境变量ZHIPUAI_API_KEY动态注入,避免硬编码泄露密钥
api-key: ${ZHIPU_API_KEY}
# 智谱AI聊天服务的配置选项
chat:
options:
model: glm-4 # 指定调用的智谱大模型版本,此处为glm-4,可根据需求更换为glm-3等其他支持的模型
2.1.5、新建聊天控制器
/**
* 聊天控制器
* 负责处理前端发起的聊天请求,集成 Spring AI 与智谱大模型
*/
@RestController
@RequestMapping("/chat")
public class ChatController {
// 声明 ChatClient 实例,用于构建提示词并与大模型交互
private ChatClient chatClient;
/**
* 构造函数注入
* Spring 容器会自动注入 ChatModel Bean
* 在此处通过 Builder 模式创建 ChatClient 实例
* @param chatModel 由 Spring AI 自动配置的底层聊天模型实现
*/
public ChatController(ChatModel chatModel) {
// 使用 ChatModel 构建 ChatClient
// 注意:原代码中 builder(chatModel).build() 没有赋值给成员变量,此处已修正为赋值操作
this.chatClient = ChatClient.builder(chatModel).build();
}
/**
* 同步聊天接口
* 接收用户消息,调用大模型生成回复,并返回完整结果
*
* @param message 用户输入的文本消息,默认值为“你好!请介绍一下自己”
* @return 大模型生成的完整文本回复
*/
@GetMapping("sync")
public String syncChat(@RequestParam(value = "message", defaultValue = "你好!请介绍一下自己") String message) {
// 1. prompt(): 创建一个新的提示词构建器
// 2. user(message): 设置用户角色的消息内容
// 3. call(): 执行同步阻塞调用,等待模型返回完整结果
// 4. content(): 从响应结果中提取纯文本内容
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
2.2、注解式(@Tool)—— 最简单、企业最常用
2.2.1、新建天气查询工具类
直接在 Spring Bean 的普通方法上加 **@Tool** 注解,Spring AI 自动生成工具定义与 JSON Schema。
/**
* 天气查询工具类
* 该类被注册为 Spring Bean,并暴露给 AI 模型作为可调用的工具(Function Calling)。
* AI 可以根据用户意图自动调用此方法来获取实时天气信息。
*/
@Component
public class WeatherTools {
/**
* 根据城市名称查询实时天气
* @param city 城市名称,例如:成都、杭州、北京等
* @return 包含温度、天气状况和湿度的格式化字符串
*/
@Tool(description = "根据城市名查询实时天气,返回温度、湿度、天气状况")
public String getWeather(
// @ToolParam 用于向 AI 描述参数的具体含义和格式要求,提高参数提取的准确率
@ToolParam(description = "城市名称,如:成都、杭州") String city) {
// TODO: 在实际生产中,此处应注入 WeatherService 并调用第三方天气 API
// 示例逻辑:模拟返回指定城市的天气数据
return "成都:28℃,晴,湿度40%";
}
}
2.2.2、修改聊天控制器
/**
* 聊天控制器
* 负责处理前端发起的聊天请求,集成 Spring AI 与智谱大模型
*/
@RestController
@RequestMapping("/chat")
public class ChatController {
// 声明 ChatClient 实例,用于构建提示词并与大模型交互
private ChatClient chatClient;
// 注入天气工具类,使其能够被大模型在需要时调用
@Autowired
private WeatherTools weatherTools;
/**
* 构造函数注入
* Spring 容器会自动注入 ChatModel Bean
* 在此处通过 Builder 模式创建 ChatClient 实例
* @param chatModel 由 Spring AI 自动配置的底层聊天模型实现
*/
public ChatController(ChatModel chatModel) {
// 使用 ChatModel 构建 ChatClient
// 注意:原代码中 builder(chatModel).build() 没有赋值给成员变量,此处已修正为赋值操作
this.chatClient = ChatClient.builder(chatModel).build();
}
/**
* 同步聊天接口
* 接收用户消息,调用大模型生成回复,并返回完整结果
*
* @param message 用户输入的文本消息,默认值为“你好!请介绍一下自己”
* @return 大模型生成的完整文本回复
*/
@GetMapping("sync")
public String syncChat(@RequestParam(value = "message", defaultValue = "你好!请介绍一下自己") String message) {
// 1. prompt(): 创建一个新的提示词构建器
// 2. tools(weatherTools): 注册可用工具,允许大模型在必要时调用 WeatherTools 获取实时数据
// 3. user(message): 设置用户角色的消息内容
// 4. call(): 执行同步阻塞调用,等待模型返回完整结果
// 5. content(): 从响应结果中提取纯文本内容
return chatClient.prompt()
.tools(weatherTools)
.user(message)
.call()
.content();
}
}
2.3、函数式(Function/ BiFunction)
注:官方推荐、轻量
2.3.1、创建函数
/**
* 汽车信息查询函数实现类
* 实现了 Java 标准的 Function 接口,用于将 AI 模型的请求转换为具体的业务查询结果。
* 该类的实例通常会被 Spring AI 包装为 ToolCallback,供大语言模型调用。
*/
public class CarFunction implements Function<CarFunction.CarRequest, String> {
/**
* 核心业务逻辑方法
* 接收包含汽车ID的请求对象,执行查询逻辑并返回结果字符串。
*
* @param request 包含查询参数(如汽车ID)的请求对象
* @return 查询结果的 JSON 格式字符串
*/
@Override
public String apply(CarRequest request) {
// 1. 参数校验(建议在实际生产环境中添加)
if (request == null || request.getCarId() == null) {
return "{\"error\": \"Invalid request: carId is missing\"}";
}
// 2. 根据查询调用第三方API获取汽车信息
// 此处省略一万字....
// 实际开发中,这里通常会注入 RestTemplate 或 WebClient 来调用外部微服务或数据库
// 3. 构建并返回结果
// 注意:手动拼接 JSON 字符串容易出错且不安全,生产环境建议使用 Jackson 或 Gson 库进行序列化
return "{'carid':" + request.getCarId() + ",'type':'SUV','color':'白色'}";
}
/**
* 内部静态类:定义工具调用的输入参数结构
* Spring AI 会利用反射分析此类,自动生成 JSON Schema,从而告诉大模型需要传入什么参数。
*/
public static class CarRequest {
/**
表示汽车编号
* 大模型在调用此工具时,会将提取到的 carId 值映射到此字段
*/
private Integer carId;
/**
* 获取汽车编号
* @return 汽车ID
*/
public Integer getCarId() {
return carId;
}
/**
* 设置汽车编号
* @param carId 汽车ID
*/
public void setCarId(Integer carId) {
this.carId = carId;
}
}
}
2.3.2、创建FunctionConfig配置类
/**
* Spring AI 工具函数配置类
* 用于将自定义的业务逻辑注册为 AI 模型可调用的工具(Tool/Function)
*/
@Configuration
public class FunctionConfig {
/**
* 注册汽车信息查询工具
*
* @return 实现了 Function 接口的 CarFunction 实例
*
* 注意:
* 1. @Description 注解用于向大语言模型描述该工具的功能,
* 模型会根据此描述判断何时调用该工具。
* 2. 返回类型 Function<CarRequest, String> 定义了工具的输入参数结构
* 和输出结果格式(通常为 JSON 字符串)。
* 3. 在较新版本的 Spring AI 中,推荐使用 ToolCallback 或 @Tool 注解,
* 但此写法在兼容旧版 API 时依然有效。
*/
@Bean
@Description("查询指定车辆(汽车)的信息,需提供汽车ID")
public Function<CarFunction.CarRequest, String> carFunction() {
// 实例化并返回具体的函数实现类
return new CarFunction();
}
}
2.3.3、ChatController使用函数调用
/**
* 同步聊天接口:处理用户消息并返回 AI 回复
* 支持工具调用(Function Calling),模型可根据语境自动选择调用天气或汽车查询工具
*
* @param message 用户输入的聊天消息,默认为“你好!请介绍一下自己”
* @return AI 生成的最终回复文本
*/
@GetMapping("sync")
public String syncChat(@RequestParam(value = "message", defaultValue = "你好!请介绍一下自己") String message) {
// 构建并执行聊天请求链式调用
return chatClient.prompt()
// 1. 注册汽车信息查询工具
// 通过 Bean 名称 "carFunction" 引用之前配置的工具,使模型具备查询车辆信息的能力
.tools("carFunction")
// 2. 设置用户消息内容
// 将前端传入的 message 作为用户角色的输入发送给大模型
.user(message)
// 3. 执行同步阻塞调用
// 发送请求至大模型,并等待模型完成推理及可能的工具调用流程,返回完整响应对象
.call()
// 4. 提取响应内容
// 从模型返回的结果对象中解析出最终的纯文本回复内容
.content();
}
2.4、MethodToolCallback 编程式(灵活)
略....
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)