前言在上一章中我们通过 ChatMemory 让 AI 拥有了“记忆力”。但在真实的企业级业务中大模型存在天然的局限性它无法获取实时的业务数据、无法精确执行复杂的内部逻辑更无法直接操作你的数据库。为了让 AI 从“只能说”进化到“能做事”Spring AI 提供了强大的 Function Calling工具调用 机制。核心原理我们在本地定义好 Java 方法并将这些方法的描述Schema告诉大模型。当用户提问时大模型会根据语义判断是否需要调用工具如果需要它会返回一个“调用意图”包含函数名和参数由我们的 Spring 程序在本地执行该函数并将执行结果返回给大模型最终由大模型组织成自然语言回复给用户。本章我们以“智能订单 库存查询系统”为例完整讲清 Spring AI Tool Calling 的正确打开方式并避开 stream 模式的坑。一、环境前置说明运行前提电脑安装 Ollama客户端提前拉取开源模型文件JDK21Gradle8.8SpringBoot3.5.14SpringAI1.1.7IDEA2023 社区版本章代码是在上一篇的基础上新增/修改的二、 AI 从“会说”到“会做”1、AI只能聊天不能执行业务动作在前面的章节中我们已经让 AI 具备多轮对话记忆能力Chat Memory流式输出Stream但此时的 AI 仍然有一个核心问题它只能聊天不能执行业务动作。例如用户输入查询订单 10001AI 就无法给出相关的业务性回答。2、Function Calling 是什么Function Calling工具调用就是让 AI 在需要时自动调用你的 Java 方法。流程如下3、本章目标智能订单 库存系统我们实现两个工具查询订单查询库存三、业务层Service1. 订单服务packagecom.example.demo.service;importorg.springframework.stereotype.Service;ServicepublicclassOrderService{publicStringqueryOrder(StringorderId){return 订单号%s 状态已发货 快递顺丰速运 .formatted(orderId);}}2. 库存服务packagecom.example.demo.service;importorg.springframework.stereotype.Service;ServicepublicclassInventoryService{publicStringqueryInventory(Stringproduct){return 商品%s 库存128件 .formatted(product);}}四、Tool 层关键1. 订单 Toolpackagecom.example.demo.tools;importcom.example.demo.service.OrderService;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.stereotype.Component;importorg.springframework.stereotype.Service;ComponentpublicclassOrderTools{privatefinalOrderServiceorderService;publicOrderTools(OrderServiceorderService){this.orderServiceorderService;}Tool(namequeryOrder,description根据订单号查询订单信息)publicStringqueryOrder(StringorderId){returnorderService.queryOrder(orderId);}}2. 库存 Toolpackagecom.example.demo.tools;importcom.example.demo.service.InventoryService;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.stereotype.Component;ComponentpublicclassInventoryTools{privatefinalInventoryServiceinventoryService;publicInventoryTools(InventoryServiceinventoryService){this.inventoryServiceinventoryService;}Tool(namequeryInventory,description查询商品库存)publicStringqueryInventory(StringproductName){returninventoryService.queryInventory(productName);}}五、ChatClient 配置工具定义好后我们需要在构建 ChatClient 时将其注入。Spring AI 会在后台自动把这些方法的签名转换成 JSON Schema 传给通义千问。修改你的 ChatMemoryConfig.java将Tools 注入并绑定Bean(qwenMemoryChatClient)publicChatClientqwenMemoryChatClient(// 明确指定注入通义千问的模型 BeanQualifier(qwenChatModel)ChatModelqwenChatModel,ChatMemorychatMemory,OrderToolsorderTools,InventoryToolsinventoryTools){returnChatClient.builder(qwenChatModel)// 使用 Builder 模式挂载对话记忆 Advisor.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).defaultTools(orderTools,inventoryTools).build();}七、Controller编辑controller用于测试GetMapping(/chat/call_test)publicStringtest(RequestParam(defaultValuedefault-session)StringconversationId,RequestParamStringmsg){returnqwenMemoryChatClient.prompt().user(msg).advisors(a-a.param(ChatMemory.CONVERSATION_ID,conversationId)).call().content();}踩坑Tool Calling stream 不稳定Qwen / OpenAI兼容模型Tool Calling 必须使用 call()八、测试效果查询订单http://localhost:8080/ai/chat/call_test?msg%E6%9F%A5%E8%AF%A2%E8%AE%A2%E5%8D%9510001查询库存http://localhost:8080/ai/chat/call_test?msgiPhone16%E8%BF%98%E6%9C%89%E5%BA%93%E5%AD%98%E5%90%97结果如下九、本章总结与进阶思考通过短短几十行代码我们成功让大模型跨越了“语言世界”触碰到了真实的“业务世界”。Function Calling 在企业级开发中的核心价值在于解耦AI 只负责“意图识别”和“自然语言组织”具体的业务逻辑查库、调第三方接口依然由我们传统的 Java 代码完成。安全AI 永远无法直接执行 SQL它只能调用我们暴露的、经过严格参数校验的 Tool 方法。至此你的 AI 应用已经具备了“记忆”与“行动”两大核心能力。十、 参考文献SpringAI官方文档
第十二篇:Spring AI 实战 12|Function Calling(工具调用):让 AI 拥有“动手能力”
前言在上一章中我们通过 ChatMemory 让 AI 拥有了“记忆力”。但在真实的企业级业务中大模型存在天然的局限性它无法获取实时的业务数据、无法精确执行复杂的内部逻辑更无法直接操作你的数据库。为了让 AI 从“只能说”进化到“能做事”Spring AI 提供了强大的 Function Calling工具调用 机制。核心原理我们在本地定义好 Java 方法并将这些方法的描述Schema告诉大模型。当用户提问时大模型会根据语义判断是否需要调用工具如果需要它会返回一个“调用意图”包含函数名和参数由我们的 Spring 程序在本地执行该函数并将执行结果返回给大模型最终由大模型组织成自然语言回复给用户。本章我们以“智能订单 库存查询系统”为例完整讲清 Spring AI Tool Calling 的正确打开方式并避开 stream 模式的坑。一、环境前置说明运行前提电脑安装 Ollama客户端提前拉取开源模型文件JDK21Gradle8.8SpringBoot3.5.14SpringAI1.1.7IDEA2023 社区版本章代码是在上一篇的基础上新增/修改的二、 AI 从“会说”到“会做”1、AI只能聊天不能执行业务动作在前面的章节中我们已经让 AI 具备多轮对话记忆能力Chat Memory流式输出Stream但此时的 AI 仍然有一个核心问题它只能聊天不能执行业务动作。例如用户输入查询订单 10001AI 就无法给出相关的业务性回答。2、Function Calling 是什么Function Calling工具调用就是让 AI 在需要时自动调用你的 Java 方法。流程如下3、本章目标智能订单 库存系统我们实现两个工具查询订单查询库存三、业务层Service1. 订单服务packagecom.example.demo.service;importorg.springframework.stereotype.Service;ServicepublicclassOrderService{publicStringqueryOrder(StringorderId){return 订单号%s 状态已发货 快递顺丰速运 .formatted(orderId);}}2. 库存服务packagecom.example.demo.service;importorg.springframework.stereotype.Service;ServicepublicclassInventoryService{publicStringqueryInventory(Stringproduct){return 商品%s 库存128件 .formatted(product);}}四、Tool 层关键1. 订单 Toolpackagecom.example.demo.tools;importcom.example.demo.service.OrderService;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.stereotype.Component;importorg.springframework.stereotype.Service;ComponentpublicclassOrderTools{privatefinalOrderServiceorderService;publicOrderTools(OrderServiceorderService){this.orderServiceorderService;}Tool(namequeryOrder,description根据订单号查询订单信息)publicStringqueryOrder(StringorderId){returnorderService.queryOrder(orderId);}}2. 库存 Toolpackagecom.example.demo.tools;importcom.example.demo.service.InventoryService;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.stereotype.Component;ComponentpublicclassInventoryTools{privatefinalInventoryServiceinventoryService;publicInventoryTools(InventoryServiceinventoryService){this.inventoryServiceinventoryService;}Tool(namequeryInventory,description查询商品库存)publicStringqueryInventory(StringproductName){returninventoryService.queryInventory(productName);}}五、ChatClient 配置工具定义好后我们需要在构建 ChatClient 时将其注入。Spring AI 会在后台自动把这些方法的签名转换成 JSON Schema 传给通义千问。修改你的 ChatMemoryConfig.java将Tools 注入并绑定Bean(qwenMemoryChatClient)publicChatClientqwenMemoryChatClient(// 明确指定注入通义千问的模型 BeanQualifier(qwenChatModel)ChatModelqwenChatModel,ChatMemorychatMemory,OrderToolsorderTools,InventoryToolsinventoryTools){returnChatClient.builder(qwenChatModel)// 使用 Builder 模式挂载对话记忆 Advisor.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).defaultTools(orderTools,inventoryTools).build();}七、Controller编辑controller用于测试GetMapping(/chat/call_test)publicStringtest(RequestParam(defaultValuedefault-session)StringconversationId,RequestParamStringmsg){returnqwenMemoryChatClient.prompt().user(msg).advisors(a-a.param(ChatMemory.CONVERSATION_ID,conversationId)).call().content();}踩坑Tool Calling stream 不稳定Qwen / OpenAI兼容模型Tool Calling 必须使用 call()八、测试效果查询订单http://localhost:8080/ai/chat/call_test?msg%E6%9F%A5%E8%AF%A2%E8%AE%A2%E5%8D%9510001查询库存http://localhost:8080/ai/chat/call_test?msgiPhone16%E8%BF%98%E6%9C%89%E5%BA%93%E5%AD%98%E5%90%97结果如下九、本章总结与进阶思考通过短短几十行代码我们成功让大模型跨越了“语言世界”触碰到了真实的“业务世界”。Function Calling 在企业级开发中的核心价值在于解耦AI 只负责“意图识别”和“自然语言组织”具体的业务逻辑查库、调第三方接口依然由我们传统的 Java 代码完成。安全AI 永远无法直接执行 SQL它只能调用我们暴露的、经过严格参数校验的 Tool 方法。至此你的 AI 应用已经具备了“记忆”与“行动”两大核心能力。十、 参考文献SpringAI官方文档