Spring AI(第五章)Tools自定义工具调用
Spring AI第五章Tools自定义工具调用文章目录Spring AI第五章Tools自定义工具调用一、章节目的二、工具调用三、如何自定义工具3.1 定义工具类3.2 注册工具类3.3 引用工具类3.4 实际工作流程四、示例代码4.1 自定义网络检索工具(searchApi)4.2 注册自定义工具4.3 构造AI大模型对象五、测试代码一、章节目的了解工具调用的场景如何自定义工具类通过AI大模型自动调用自定义工具实现网络检索功能二、工具调用工具调用Tool Calling是指大模型在生成回答的过程中根据上下文需求自动调用外部工具或API来获取额外信息、执行操作或返回结构化结果。为什么需要工具调用1.大模型本身不具备行业特定功能。目前大厂提供的通用 AI 大模型如 OpenAI、通义千问、Claude 等主要擅长自然语言理解与生成但不具备企业内部业务逻辑或垂直领域知识。例如查询公司数据库、调用企业内部 API、控制物联网设备、执行自动化任务等这些都超出了模型原生能力范围。2.实现模型与业务系统的深度集成。通过工具调用Tool Calling开发者可以将模型与实际业务逻辑绑定让 AI 不仅“会说话”还能“做事”。模型可根据语义自动选择并调用预定义的函数或接口从而实现如“查库存”“搜索报告”“分析日志”等智能化场景。3.增强模型的实时性与准确性。大模型的知识往往停留在训练数据的时间点而现实世界不断变化。通过调用实时工具如搜索引擎、数据库接口等模型能够动态获取最新数据生成更符合当下语境和事实的回答。4.提升企业应用的可控性与安全性。工具调用让开发者可以明确规定模型的“可执行范围”例如只允许调用公司内部定义的安全工具方法从而防止模型随意访问外部资源或生成不受控的操作。5.支持模块化扩展与功能复用。每个工具类都是一个独立、可复用的业务模块开发者可以持续新增工具而无需修改模型本身极大提高系统的可维护性与扩展性。小结大厂提供的AI大模型不具备行业垂直领域的特定功能、所以需要开发者根据公司业务自定义工具方法三、如何自定义工具工具调用的核心在于“定义 → 注册 → 引用”。通过这三个步骤可以让 AI 模型自动识别并调用你实现的业务逻辑。3.1 定义工具类不支持的参数或返回值类型、以下类型 Spring AI 无法正确序列化因此不支持Optional异步类型如 CompletableFuture、Future响应式类型如 Flow、Mono、Flux函数式类型如 Function、Supplier、Consumer推荐使用的参数或返回值类型基础类型String、int、long、double 等POJO普通 Java 对象recordJava 16 的轻量级数据结构集合类型List、Map 等Spring AI 会扫描所有 Tool 方法并将方法签名和参数转为 JSON Schema。大模型根据这些描述调用方法因此参数和返回值必须可序列化否则调用会失败。importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.ai.tool.annotation.ToolParam;importorg.springframework.stereotype.Service;/** * 示例工具类退票工具 * 作用当用户提出“退票”请求时大模型会自动调用该方法执行退票操作。 */publicclassRefundTool{/** * 定义一个供 AI 调用的退票方法 * * Tool 说明这是一个可被大模型自动调用的工具方法 * Tool description 描述这个方式是干什么用的、AI大模型会根据上下文结合方法描述决定是否调用 * ToolParam 用来告诉模型参数的含义方便自动生成 JSON Schema * ToolParam description 描述调用这个方法需要传入什么参数 */Tool(description退票操作根据用户的姓名和预订号执行退票)publicStringrefundTicket(ToolParam(description预订号必须传入用户的预订号)StringticketNumber,ToolParam(description姓名必须传入用户的姓名)Stringname){// 实际业务逻辑此处仅为示例// 例如调用内部服务 ticketService.refund(ticketNumber, name);System.out.println(正在为用户 name 处理退票订单号ticketNumber);return退票成功订单号ticketNumber;}}3.2 注册工具类ToolCallback 是 Spring AI 框架中的核心接口用于定义工具调用的回调机制定义工具的统一调用接口提供工具元数据名称、描述处理工具调用参数和返回值ToolCallbacks.from() 就是工具对象 → AI 可调用工具的转换器importorg.springframework.ai.tool.ToolCallback;importorg.springframework.ai.tool.ToolCallbacks;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;ConfigurationpublicclassToolConfig{BeanpublicToolCallback[]registerTools(){RefundToolrefundToolnewRefundTool();// 创建工具实例returnToolCallbacks.from(refundTool);// 转换为 AI 可调用工具}}3.3 引用工具类注入工具对象、大模型对话时配置即可importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.ai.chat.ChatClient;importorg.springframework.ai.chat.ChatResponse;importorg.springframework.ai.chat.ChatModel;importorg.springframework.ai.tool.ToolCallback;importorg.springframework.stereotype.Service;importjakarta.annotation.Resource;ServicepublicclassChatService{ResourceprivateToolCallback[]allTools;// 注入自定义工具AutowiredprivateChatModeldashscopeChatModel;// 注入 Spring AI 提供的 ChatModel用于与大模型进行对话和消息处理publicStringdoChat(Stringmessage){ChatClientchatClientChatClient.builder(dashscopeChatModel).build();ChatResponsechatResponsechatClient.prompt().user(message)// 用户消息.tools(allTools)// 自定义工具.call()// 阻塞调用.chatResponse();// 返回 ChatResponse 对象returnchatResponse.getResult().getOutput().getText();}}3.4 实际工作流程1. 定义阶段Spring AI 会扫描所有带 Tool 的方法并将它们转换为 JSON Schema 格式的函数定义。2. 调用阶段当大模型识别到用户想“退票”时它会自动触发 refundTicket() 方法并传入提取到的参数如姓名、预订号。3. 响应阶段方法执行后返回结果如 “退票成功”模型会将结果整合到自然语言回答中返回给用户。四、示例代码4.1 自定义网络检索工具(searchApi)关于自定义工具开发者可以自行实现各种工具方法、比如系统某个业务的增删改查通用的网络数据采集、网络文件下载、文件读取、终端命令执行等等searchApi获取API Keyhttps://serpapi.com/配置文件application-local.yml# searchApisearch-api:api-key:searchApi官网获取的Api Keypom依赖!-- HuTool 小工具 --dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.8.37/version/dependency!-- 支持大模型机构化输出 --dependencygroupIdcom.github.victools/groupIdartifactIdjsonschema-generator/artifactIdversion4.38.0/version/dependencyimportcn.hutool.http.HttpUtil;importcn.hutool.json.JSONArray;importcn.hutool.json.JSONObject;importcn.hutool.json.JSONUtil;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.ai.tool.annotation.ToolParam;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.stream.Collectors;/** * 通过Search API 实现联网查询功能 */publicclassWebSearchTool{// SearchAPI 的搜索接口地址privatestaticfinalStringSEARCH_API_URLhttps://www.searchapi.io/api/v1/search;privatefinalStringapiKey;publicWebSearchTool(StringapiKey){this.apiKeyapiKey;}/** * Tool description 描述这个方式是干什么用的、AI大模型会根据上下文结合方法描述决定是否调用 * ToolParam description 描述调用这个方法需要传入什么参数 * * param query * return */Tool(description从百度搜索引擎中检索信息)publicStringsearchWeb(ToolParam(description需要搜索查询的关键词)Stringquery){MapString,ObjectparamMapnewHashMap();paramMap.put(q,query);paramMap.put(api_key,apiKey);paramMap.put(engine,baidu);try{StringresponseHttpUtil.get(SEARCH_API_URL,paramMap);// 取出返回结果的前 5 条JSONObjectjsonObjectJSONUtil.parseObj(response);// 提取 organic_results 部分JSONArrayorganicResultsjsonObject.getJSONArray(organic_results);ListObjectobjectsorganicResults.subList(0,5);// 拼接搜索结果为字符串Stringresultobjects.stream().map(obj-{JSONObjecttmpJSONObject(JSONObject)obj;returntmpJSONObject.toString();}).collect(Collectors.joining(,));returnresult;}catch(Exceptione){return搜索百度时出错 e.getMessage();}}}4.2 注册自定义工具importorg.springframework.ai.tool.ToolCallback;importorg.springframework.ai.tool.ToolCallbacks;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;/** * 工具注册配置类 * 注册所有可用的工具类供 Spring AI 使用 */ConfigurationpublicclassToolRegistration{Value(${search-api.api-key})privateStringsearchApiKey;/** * 所有工具类都由 Spring 容器统一管理、支持依赖注入、生命周期管理、AOP 等 * * ToolCallback 是 Spring AI 框架中的核心接口用于定义工具调用的回调机制 * 定义工具的统一调用接口 * 提供工具元数据名称、描述 * 处理工具调用参数和返回值 * * return */BeanpublicToolCallback[]allTools(){// 网络搜索工具基于API Key进行网络搜索获取实时信息WebSearchToolwebSearchToolnewWebSearchTool(searchApiKey);// ToolCallbacks.from() 就是工具对象 → AI 可调用工具的转换器returnToolCallbacks.from(webSearchTool);}}4.3 构造AI大模型对象importlombok.extern.slf4j.Slf4j;importorg.exi.exiaiagent.advisor.MyLoggerAdvisor;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;importorg.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;importorg.springframework.ai.chat.memory.ChatMemory;importorg.springframework.ai.chat.memory.InMemoryChatMemory;importorg.springframework.ai.chat.model.ChatModel;importorg.springframework.ai.chat.model.ChatResponse;importorg.springframework.ai.tool.ToolCallback;importorg.springframework.ai.vectorstore.VectorStore;importorg.springframework.core.io.ClassPathResource;importorg.springframework.core.io.Resource;importorg.springframework.stereotype.Component;importstaticorg.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;importstaticorg.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;/** * 构建可以调用自定义函数工具的AI大模型对象 */ComponentSlf4jpublicclassChatToolApp{privatefinalChatClientchatClient;// 注入自定义的内存向量数据库 Bean对象jakarta.annotation.ResourceprivateVectorStorememoryVectorStore;// 注入 自定义的工具类对象jakarta.annotation.ResourceprivateToolCallback[]allTools;publicChatToolApp(ChatModeldashscopeChatModel){// 加载自定义 提示词文件ResourcepromptResourcenewClassPathResource(static/prompt/test_prompt.st);// 创建内存存储对象ChatMemorychatMemoryUseMemoryChatMemory();chatClientChatClient.builder(dashscopeChatModel).defaultSystem(promptResource)// 配置自定义提示词.defaultAdvisors(newMessageChatMemoryAdvisor(chatMemory),// 配置上下文记忆存储对象newMyLoggerAdvisor()// 配置自定义的日志拦截器).build();}/** * 基于计算机内存存储、实现读取、写入聊天上下文 * return */publicChatMemoryUseMemoryChatMemory(){/** * 默认使用MessageWindowChatMemory * 存储位置: JVM 内存 (InMemoryChatMemoryRepository) * 数据持久化: 不持久化应用重启后丢失 * 消息窗口: maxMessages 20默认可配置 */InMemoryChatMemorychatMemorynewInMemoryChatMemory();returnchatMemory;}publicStringdoChat(Stringmessage,StringchatId){ChatResponsechatResponsechatClient.prompt().user(message).advisors(advisorSpec-advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY,chatId)// 指定聊天记忆存储ID.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY,10)// 获取最近10条聊天记忆)// 通过QuestionAnswerAdvisor拦截器实现检索增强、并指定自定义的内存向量数据库.advisors(newQuestionAnswerAdvisor(memoryVectorStore)).tools(allTools)// 配置注册好的自定义工具.call()// 阻塞式响应.chatResponse();// 返回ChatResponse对象StringcontentchatResponse.getResult().getOutput().getText();// 获取chatResponse的结果数据log.info(content: {},content);returncontent;}}五、测试代码importjakarta.annotation.Resource;importorg.junit.jupiter.api.Assertions;importorg.junit.jupiter.api.Test;importorg.springframework.boot.test.context.SpringBootTest;importstaticorg.junit.jupiter.api.Assertions.*;SpringBootTestclassChatToolAppTest{/** * Resource 注解的作用是先根据字段名后根据类型 来自动匹配注入对应的 Bean */ResourceprivateChatToolAppchatToolApp;TestvoiddoChat(){StringchatIda5daa1bb-e5e2-427e-9a74-68650459511f;Stringmessage帮我查一下2025王者荣耀年度总决赛成都AG大战重庆狼队哪只队伍赢了、比分是多少;StringanswerchatToolApp.doChat(message,chatId);Assertions.assertNotNull(answer);}}测试结果

相关新闻

18万帧压成41张图:视频语义压缩管线实战

18万帧压成41张图:视频语义压缩管线实战

1. 从 18 万帧到 41 张图,这个压缩比到底怎么来的第一次看到“18 万帧压成 41 张图”这个数字,我下意识觉得是标题党。18 万帧,按 30fps 算就是 100 分钟的视频,压成 41 张图,等于平均每 2.4 分钟才留一张画面。这要是…

2026/9/19 3:17:25 阅读更多 →
YOLO桌面版工具:开箱即用的目标检测应用

YOLO桌面版工具:开箱即用的目标检测应用

1. 这不是又一个“跑通YOLO”的Demo,而是一个真正能塞进设计师、质检员、巡检员电脑里的工具你有没有遇到过这样的场景:工厂产线主管想用AI查漏补缺,但让他装Python环境、配CUDA、改config文件?他第一反应是关掉网页。学校老师想带…

2026/9/19 3:16:25 阅读更多 →
四台Ryzen AI Max+ 395搭建本地大模型推理集群实战

四台Ryzen AI Max+ 395搭建本地大模型推理集群实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 3:16:25 阅读更多 →

最新新闻

Cherry Studio 知识库后端实现解析:分层架构、JobManager 调度与增删改查链路

Cherry Studio 知识库后端实现解析:分层架构、JobManager 调度与增删改查链路

Cherry Studio 知识库后端实现解析:分层架构、JobManager 调度与增删改查链路 【免费下载链接】cherry-studio 🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端 项目地址: https://gitcode.com/CherryHQ/cherry-studio 导读 本文基于 C…

2026/9/19 3:58:44 阅读更多 →
gbrain Doctor 前端元数据扫描增量化的架构设计:从有界磁盘遍历到 DB-backed 增量状态(Phase 2)

gbrain Doctor 前端元数据扫描增量化的架构设计:从有界磁盘遍历到 DB-backed 增量状态(Phase 2)

gbrain Doctor 前端元数据扫描增量化的架构设计:从有界磁盘遍历到 DB-backed 增量状态(Phase 2) 【免费下载链接】gbrain Garrys Opinionated OpenClaw/Hermes Agent Brain 项目地址: https://gitcode.com/gh_mirrors/gb/gbrain 本篇技…

2026/9/19 3:58:44 阅读更多 →
YuE2 官方可运行示例实战:从 City Lights 歌词到可编辑 ABC 谱的生成、和声改编与符号校验

YuE2 官方可运行示例实战:从 City Lights 歌词到可编辑 ABC 谱的生成、和声改编与符号校验

YuE2 官方可运行示例实战:从 City Lights 歌词到可编辑 ABC 谱的生成、和声改编与符号校验 【免费下载链接】YuE YuE2: frontier music generation with symbolic planning, zero-shot covers, and agentic music editing. 项目地址: https://gitcode.com/GitHub_…

2026/9/19 3:58:44 阅读更多 →
RoCEv2网络拥塞排查:AllReduce训练锯齿曲线30分钟定位指南

RoCEv2网络拥塞排查:AllReduce训练锯齿曲线30分钟定位指南

1. 锯齿不是玄学:AllReduce 训练曲线背后发生了什么先说你最痛的那个画面:跑千卡/百卡规模的分布式训练,打开看板,AllReduce 阶段的吞吐曲线像心电图一样,每隔几十秒到几分钟就往下掉一截,然后又拉上来。Lo…

2026/9/19 3:58:44 阅读更多 →
StarRocks 数学函数 SIN 详解:语法、返回值与向量化实现原理

StarRocks 数学函数 SIN 详解:语法、返回值与向量化实现原理

StarRocks 数学函数 SIN 详解:语法、返回值与向量化实现原理 【免费下载链接】starrocks The worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks p…

2026/9/19 3:58:44 阅读更多 →
免费开源 Mac 菜单栏管理工具 Ice:10 分钟搞定图标收纳与刘海屏遮挡

免费开源 Mac 菜单栏管理工具 Ice:10 分钟搞定图标收纳与刘海屏遮挡

免费开源 Mac 菜单栏管理工具 Ice:10 分钟搞定图标收纳与刘海屏遮挡 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 每多开一个后台应用,屏幕顶部就多冒出一个图标&#xff0…

2026/9/19 3:57:44 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介:面向机器学习、深度学习与数据建模学习者的一份完整研究文献,聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本,系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程,展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型,在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志,发现loss从凌晨两点就开始往上爬,一路从0.8涨到1.35,整整六个小时没人发现。那六个小时的训练不仅白跑,还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud 🌤️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/19 3:59:36 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/19 3:53:08 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/17 10:19:14 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/15 21:39:18 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →