Spring AI 进阶实战:手把手教大模型学会“用工具”
如果 AI 只能动嘴不能动手,那它顶多是个“嘴强王者”。今天我们让它学会“调用工具”,从此能查天气、设闹钟、写代码、订机票!
在前两篇文章中,我们已经让 AI 具备了 短期记忆(Chat Memory) 和 永久历史(Chat History)。但现在的 AI 还有一个致命缺陷:它只会说,不会做。
你问它“现在几点?”,它只能尴尬地告诉你“我无法获取实时时间”; 你让它“10 分钟后提醒我开会”,它更是爱莫能助。
这是因为大语言模型本身 没有手脚,无法与外部世界交互。而 Tool Calling(工具调用 / 函数调用) 就是给 AI 装上“手脚”的关键技术。
今天这篇文章,我们就用最通俗的代码,带你打通 AI 与现实世界的最后一道墙。
一、什么是 Tool Calling?为什么需要它?
在 AI 原生应用中,Tool Calling 是一种标准模式:让大模型能够识别用户意图,并主动调用你预先定义好的“外部工具”来完成任务。
这些工具主要干两类事:
1. 信息检索 —— 让 AI “有问必答”
模型的知识有截止日期,它不知道今天的天气、不知道最新的股价、也不知道你数据库里的订单状态。
工具的作用:帮它去外部查。
查数据库 调天气 API 读本地文件
2. 执行操作 —— 让 AI “有事真上”
模型能生成“旅行计划”,但它不能真的帮你订机票;它能写邮件草稿,但不能真帮你发出去。
工具的作用:替它去执行。
发邮件 设闹钟 操作 IoT 设备
二、代码实操:给 AI 配个“手表”和“闹钟”
我们需要知道,AI是基于数据训练的,那么现在的时间等这些信息他是无法知道的

不过,我们现在可以通过工具来解决这些问题。我们以两个最直观的工具为例:获取当前时间 和 设置闹钟。
1. 定义工具类:DateTimeTools
在 Spring AI 中,把一个普通方法变成 AI 可调用的工具,只需要加一个 @Tool 注解。
import org.springframework.ai.tool.annotation.Tool;import org.springframework.context.i18n.LocaleContextHolder;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;publicclassDateTimeTools{/** * 工具1:获取当前日期时间 * @return 当前时间的字符串 */@Tool(name = "getCurrentDateTime", description = "获取当前准确的日期和时间")private String getCurrentDateTime(){return LocalDateTime.now() .atZone(LocaleContextHolder.getTimeZone().toZoneId()) .toString(); }/** * 工具2:设置闹钟 * @param time ISO-8601 格式的时间字符串 */@Tool(description = "设置一个闹钟,参数 time 必须是 ISO-8601 格式的字符串")publicvoidsetAlarm(String time){ LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME); System.out.println("Alarm set for" + alarmTime); }}💡 注解详解:
name:工具的名字,模型靠这个名字来决定调用谁(不写默认用方法名)。description:至关重要! 模型全靠这段描述来理解“什么时候该用这个工具”。描述越清晰,AI 越聪明。
2. 把工具交给 AI:注入 ChatClient
定义好了工具,接下来就是告诉 Spring AI 有这么一个“工具箱”可以用。
@GetMapping("/chat")public String chat(@RequestParam(defaultValue = "你是谁?") String prompt) { String content = chatClient .prompt() .user(prompt) .tools(new DateTimeTools()) // 👈 关键:把工具箱递给 AI .call() .content();return content;}3. 效果实测
场景一:信息检索
用户问:“现在是什么时间?”

场景二:执行操作
用户问:“帮我设一个 3分钟后的闹钟。”
AI 会先调用 getCurrentDateTime 算出当前时间,计算出 10 分钟后的 ISO-8601 时间串,然后调用 setAlarm 方法。

三、幕后机制:AI 和工具到底是怎么“勾搭”上的?
整个过程比你想象的要精密。Spring AI 遵循了一套标准的 Tool Calling 交互流程:

定义与携带:你在后端写好的 @Tool方法,会在发起请求时,连同用户的问题一起,被 Spring AI 打包成 JSON Schema 发给大模型。模型决策:模型看了你的问题,发现必须知道“实时时间”才能回答。于是它暂停输出,回复一句指令:“我要调用 getCurrentDateTime,参数为空。”本地执行:注意,这一步发生在你的服务器上! Spring AI 框架收到模型想调工具的指令,立刻在本地执行你写好的 getCurrentDateTime()Java 方法。结果加工:方法执行完返回了一个 LocalDateTime对象。应用程序有权在这一步对结果进行处理(比如转换成更友好的“北京时间下午 2 点 30 分”字符串)。这一步是你版本里的亮点,不能省略。二次投喂:Spring AI 把加工好的结果(比如“当前时间是 14:30:00”)塞回给大模型,相当于悄悄给它递了一张小纸条。 最终回答:模型低头看了小纸条,然后抬起头对你笑着说:“现在是下午两点半。”
⚠️ 重要提示:工具是在 你的后端服务器 执行的,不是在 AI 厂商的云端执行的。你的数据库密码等 都是安全的。
四、工具箱的四种挂载姿势
Spring AI 提供了非常灵活的配置方式,适应不同的开发习惯:
1. 添加Tool添加到 ChatClient
ChatClient.create(chatModel) .prompt() .tools(new DateTimeTools()) .call() .content();2. 添加Default Tools添加到 ChatClient
ChatClient chatClient = ChatClient.builder(chatModel) .defaultTools(new DateTimeTools()) .build();3. 添加Tool到ChatModel
ToolCallback[] dateTimeTools = ToolCallbacks.from(new DateTimeTools());ChatOptions chatOptions = ToolCallingChatOptions.builder() .toolCallbacks(dateTimeTools) .build();Prompt prompt = new Prompt("明天是几月几号?", chatOptions);chatModel.call(prompt);4. 添加Default Tools添加到 ChatModel
ToolCallback[] dateTimeTools = ToolCallbacks.from(new DateTimeTools());ChatModel chatModel = OllamaChatModel.builder() .ollamaApi(OllamaApi.builder().build()) .defaultOptions(ToolCallingChatOptions.builder() .toolCallbacks(dateTimeTools) .build()) .build();五、总结
通过今天的文章,我们成功让大模型从 “只会动嘴” 进化到了 “能动手办事”。
核心注解: @Tool是连接 AI 意图与 Java 代码的桥梁。关键配置: description写得越好,AI 调用得越准。安全边界:代码跑在你服务器上,安全可控。
学会了 Tool Calling,你的 Spring AI 应用才算真正具备了 生产力。接下来,无论是对接企业内部系统、操作数据库,还是控制智能家居,思路都是一通百通。
如果觉得文章对你有帮助,欢迎 点赞、在看、分享 三连支持!有任何疑问,欢迎在评论区留言交流~
夜雨聆风