当前位置: 首页 > news >正文

AI修炼记1-Tool Calling

文章目录

  • 一. Tool Calling 的介绍
    • 1. Tool注解
    • 2. ToolParam注解
    • 3. 调用流程图与schema格式
  • 二. Tool Calling 的使用
    • 1. 公共配置
      • (1) 引入依赖
      • (2) 配置文件
    • 2. ChatClient
      • (1) 采用声明式方式, 定义运行时工具
      • (2) 采用声明式方式, 定义默认工具
      • (3) 采用编程式方式, 定义运行时工具
      • (4) 采用编程式方式, 定义默认工具
    • 3. Chat Model
      • (1) 采用声明式方式, 定义运行时工具
      • (2) 采用声明式方式, 定义默认工具
      • (3) 采用编程式方式, 定义运行时工具
      • (4) 采用编程式方式, 定义默认工具
  • 三. 工具定义时的规范
    • 1. ToolCallback
    • 2. Result Conversion
    • 3. MethodToolCallback
    • 3. ToolDefinition
    • 5. ToolContext
    • 6. Return Direct(直接返回)
    • 7. 工具执行

通过阿里云百炼API文档 对 Spring AI Alibaba API 学习和使用
通过 Spring AI 官方文档 和 Spring AI 中文翻译文档 来对Spring AI进行学习

一. Tool Calling 的介绍

1. 我们可以将AI大模型(LLM)理解成一个知识渊博的的智者, 知道人类大部分的知识, 可以说是最强大脑, 但是AI大模型这个最强大脑却有个缺点, 光想却不做
2. 当你给大模型说你帮我查询当前时, 大模型就犯难了, 因为你一个版本的训练参数就那么多, 大模型只能从自己已知的知识库中寻找, 而你当前要查询的时间肯定已经超过了模型发布后的时间, 就会出现时间查询不正确的情况。
3. 归根究底是因为大模型中没有查询当前时间的API, 只知道该怎么查, 却动不了手, 因此Tool Calling 的出现就是帮助AI大模型来动手工具。

1. Tool注解

description 最为重要, 想要它实现什么作用, 越详细越好


2. ToolParam注解

ToolParam 和 Tool 搭配使用, 因为JSON Schema的书写较繁琐, Spring AI 会根据方法的参数自动生成, ToolParam 就可以配置每个参数是否必传和额外的描述信息



3. 调用流程图与schema格式

调用工具流程

1. 在请求中进行工具的定义, 通过Spring AI, 将信息序列化成模型可以识别的格式后, 发送给AI模型
2. AI模型得到了工具的信息, 分析了请求之后决定调用工具, 于是, 将要调用工具的请求信息发送给Spring AI 应用程序, 信息中包含工具的名称和参数
3. Spring AI 通过发送过来的信息, 去调用工具, 如果有参数, 会将参数一并发送给工具
4. Tool工具处理完后, 将结果发送给Spring AI
5. Spring AI 将工具执行的结果, 以工具响应消息的形式添加到上下文, 再调用一次AI模型
6. AI模型将调用工具后的结果, 进一步优化后, 发送到Spring AI, 转化为应用层格式, 进行响应

实体类转化成 JSON 后对应的 JSON Schema

二. Tool Calling 的使用

当默认工具和运行时工具同时存在时, 运行时工具会覆盖掉默认工具

1. 公共配置

(1) 引入依赖

<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><!--响应式编程框架,异步与流式调用的依赖,使用Alibaba需要引入的依赖,不引入的调用时会报错--><dependency><groupId>org.springframework</groupId><artifactId>spring-webflux</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-bom</artifactId><version>1.0.0.2</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

(2) 配置文件

spring:ai:dashscope:api-key:${DASHSCOPE_API_KEY}logging:pattern:console:'%d{HH:mm:ss.SSS}%c%M%L[%thread]%m%n' file:'%d{HH:mm:ss.SSS}%c%M%L[%thread]%m%n' level:org.springframework.ai.retry.autoconfigure:error

2. ChatClient

声明式, 用的是 DateTimeTools 查询时间的工具
编程式, 用的是 WeatherTools 查询天气工具

(1) 采用声明式方式, 定义运行时工具

1. 定义查询时间工具👇

publicclassDateTimeTools{// Get the current date and time in the user's timezone@Tool(description="获取当前区域的时间")StringgetCurrentDateTime(){returnLocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();}}

2. 查询api👇

@RestController@RequestMapping("/chat")publicclassChatController{privateChatClientclient;publicChatController(DashScopeChatModelchatModel){client=ChatClient.builder(chatModel).build();// chat客户端使用的是阿里的聊天模型}@RequestMapping("/call")publicStringcall(Stringmsg){returnclient.prompt("你叫景画").user(msg).tools(newDateTimeTools()).call().content();}}

3. 结果对比👇
没加 Tool Calling 工具方法之前


加了工具之后

(2) 采用声明式方式, 定义默认工具

在构造方法中创建ChatClient实例时, 使用defaultTools方法

publicChatClientController(DashScopeChatModelchatModel){// chat客户端使用的是阿里的聊天模型client=ChatClient.builder(chatModel).defaultTools(newDateTimeTools()).build();}

2. 使用client客户端时, 就可以除掉tools方法了

@RequestMapping("/call")publicStringcall(Stringmsg){returnclient.prompt().user(msg).call().content();}

(3) 采用编程式方式, 定义运行时工具

1. 创建工具要使用的方法

publicclassWeatherTools{publicStringgetCurrentWeatherByCityName(StringcityName){switch(cityName){case"北京":return"北京今天天⽓: 晴空万⾥";case"上海":return"上海今天天⽓: 电闪雷鸣";case"⼴州":return"⼴州今天天⽓: 细⾬蒙蒙";default:return"没有该城市的天⽓信息";}}}

2. 将要使用的方法变为 MethodToolCallback 工具实例, 我们为了方便, 采用Bean注解交给Spring管理

@ConfigurationpublicclassToolConfig{@Bean("weatherTool")publicToolCallbackweatherTool(){// 通过反射获取方法Methodmethod=ReflectionUtils.findMethod(WeatherTools.class,"getCurrentWeatherByCityName",String.class);ToolCallbacktoolCallback=MethodToolCallback.builder().toolDefinition(ToolDefinitions.builder(method).description("根据城市名称, 获取天气").build()).toolMethod(method)// 必填项.toolObject(newWeatherTools())// 必填项, 从哪个类中获取的方法.build();returntoolCallback;}}

3. 引入到 ChatClient 中

@Resource(name="weatherTool")privateToolCallbackweatherTool;// 编程式@RequestMapping("/call2")publicStringcall2(Stringmsg){returnclient.prompt().user(msg).toolCallbacks(weatherTool).call().content();}

运行图


(4) 采用编程式方式, 定义默认工具

通过构造方法的方式, 将 ToolCallback 作为参数从Spring容器中获取

publicChatClientController(DashScopeChatModelchatModel,ToolCallbackweatherTool){// chat客户端使用的是阿里的聊天模型client=ChatClient.builder(chatModel).defaultToolCallbacks(weatherTool).build();}

3. Chat Model

(1) 采用声明式方式, 定义运行时工具

定义查询时间的工具

@ComponentpublicclassDateTimeTools{// Get the current date and time in the user's timezone@Tool(description="获取当前区域的时间")StringgetCurrentDateTime(){returnLocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();}@Tool(description="Set a user alarm for the given time")voidsetAlarm(@ToolParam(description="Time in ISO-8601 format")Stringtime){LocalDateTimealarmTime=LocalDateTime.parse(time,DateTimeFormatter.ISO_DATE_TIME);System.out.println("Alarm set for "+alarmTime);}}

在查询方法中获取ToolCallback实例, 然后放入选项中

@RequestMapping("/call")publicStringcall(Stringmsg){// 获取 ToolCallback实例, 然后加入到model的toolCallbacks中来调用ToolCallback[]dateTimeTools=ToolCallbacks.from(newDateTimeTools());ChatOptionschatOptions=ToolCallingChatOptions.builder().toolCallbacks(dateTimeTools).build();Promptprompt=newPrompt(msg,chatOptions);returnchatModel.call(prompt).getResult().getOutput().getText();}

使用普通的构造方式即可, 只需要将DashScopeChatModel 注入

@AutowiredpublicChatModelController(DashScopeChatModelchatModel){this.chatModel=chatModel;}

(2) 采用声明式方式, 定义默认工具

publicChatModelController(DashScopeChatModelchatModel,DateTimeToolsdateTimeTools){// 构建默认工具列表(dateTimeTools 生成的 ToolCallback)ToolCallback[]dateTimeToolCallbacks=ToolCallbacks.from(dateTimeTools);// 创建合并后的工具列表List<ToolCallback>allToolCallbacks=newArrayList<>();if(dateTimeToolCallbacks!=null){allToolCallbacks.addAll(Arrays.asList(dateTimeToolCallbacks));}chatModel.setDashScopeChatOptions(DashScopeChatOptions.builder().withModel("qwen-turbo").withToolCallbacks(allToolCallbacks).build());this.chatModel=chatModel;}

(3) 采用编程式方式, 定义运行时工具

因为我们已经将查询天气的工具 WeatherTool 通过bean注解交给了Spring容器管理, 这里不再重复过程, 直接使用
注入 weatherTool 实例

@Resource(name="weatherTool")privateToolCallbackweatherTool;@RequestMapping("/call3")publicStringcall3(Stringmsg){ChatOptionschatOptions=ToolCallingChatOptions.builder().toolCallbacks(weatherTool).build();Promptprompt=newPrompt(msg,chatOptions);returnchatModel.call(prompt).getResult().getOutput().getText();}

(4) 采用编程式方式, 定义默认工具

通过构造方法的方式, 将 ToolCallback 作为参数从Spring容器中获取

publicChatModelController(DashScopeChatModelchatModel,ToolCallbackweatherTool){ArrayList<ToolCallback>toolCallbacks=newArrayList<>();toolCallbacks.add(weatherTool);chatModel.setDashScopeChatOptions(DashScopeChatOptions.builder().withModel("qwen-turbo").withToolCallbacks(toolCallbacks).build());this.chatModel=chatModel;}

三. 工具定义时的规范

借鉴于 Spring AI 中文文档, 这里是简单了解

1. ToolCallback

ToolCallback 是与AI模型交互的接口


2. Result Conversion

工具调用结果通过 ToolCallResultConverter 序列化后返回 AI 模型。该接口提供将工具调用结果转换为 String 对象的能力

3. MethodToolCallback

MethodToolCallback 实现了ToolCallback接口, 是Spring AI 框架实现Tool Calling 的核心机制之一, 主要作用是将普通方法封装为AI模型可调用的工具

3. ToolDefinition

MethodToolCallback 类的属性之一, 该接口提供AI模型识别工具可用性所需的信息

5. ToolContext

Spring AI 支持通过 ToolContext API 向工具传递额外的上下文信息。此功能允许你提供用户自定义的额外数据,这些数据可与 AI 模型传递的工具参数一起在工具执行过程中使用
实现流程: 👇

1. 通过发送请求将上下文信息发送给Spring AI应用程序, Spring AI 经过分析后, 将其发送给工具Tool
2. ToolContext 的任何数据都不会发送给AI模型


定义工具, 通过ToolContext 参数来获取从请求中传来的上下文信息👇

publicclassContextIdTools{@Tool(description="获取工具上下文信息")publicvoidgetId(ToolContexttoolContext){System.out.println("获取到的id: "+toolContext.getContext().get("id"));}}

在请求中定义工具上下文信息👇

@RequestMapping("/call3")publicStringcall3(Stringmsg){returnclient.prompt().user(msg).tools(newContextIdTools()).toolContext(Map.of("id","111222")).call().content();}

6. Return Direct(直接返回)

1. 某些场景下,你可能希望将结果直接返回调用方而非传回模型。例如:当构建依赖 RAG 工具的代理时,你可能希望直接将检索结果返回调用方,而非传回模型进行不必要的后处理;又或者某些工具应当终止代理的推理循环
2. 每个 ToolCallback 实现均可定义工具调用结果应直接返回调用方还是传回模型。默认结果为传回模型,但你可按工具单独修改此行为

7. 工具执行

http://www.jsqmd.com/news/691546/

相关文章:

  • RePKG终极教程:5分钟学会Wallpaper Engine资源提取与转换
  • 2026年合肥最好吃火锅电话查询推荐:联系方式与特色汇总 - 品牌推荐
  • 猫抓浏览器扩展:现代网页媒体资源嗅探与管理解决方案
  • 个人电子合同自动签署程序,实现基于哈希的简易签约,记录签约时间,双方标识,生成不可篡改凭证,适用于私人借款,合租协议。防止事后抵赖。
  • 如何5秒内智能获取百度网盘提取码:免费开源工具的完整教程
  • AzurLaneAutoScript终极指南:24小时智能挂机解放双手
  • Qwen3-ForcedAligner-0.6B新手入门:纯本地运行,无需代码经验
  • Phi-3-mini-4k-instruct-gguf镜像升级路径:从GGUF-v2到v3格式迁移与兼容性处理
  • B站会员购抢票终极指南:新手也能轻松掌握的免费自动化工具
  • 2026年口碑好的城市更新品牌公司推荐,专业服务全解析 - 工业推荐榜
  • PyTorch 2.8镜像完整指南:RTX 4090D深度优化环境下的大模型训练避坑手册
  • 用1个CMakeLists.txt补丁+3行编译标志,让旧项目自动满足2026内存安全等级L2(附实测ARM64/RISC-V对比报告)
  • 嵌入式软件开发系列文章——1 ARM架构下Cortex-M 内核单片机开发环境搭建—1-3 STM32CubeMX
  • 2026年考研复试机构怎么选,实力强的和有面试指导的大型企业有哪些 - 工业品网
  • Albumentations高级用法:针对金属反光表面的CLAHE与RandomGamma增强(工业质检实战)
  • 如何快速上手BepInEx:游戏插件框架的完整安装与配置指南
  • 合约编译失败却找不到原因?C++26合约诊断工具链首曝:`contract-linter` + `clang-contract-trace` 双引擎精准定位隐式合约传播瓶颈
  • 2026 论文双检突围:9 款查重 + 降 AIGC 率工具实测
  • Red Panda Dev-C++:Windows平台上最友好的C++轻量级开发环境终极指南
  • 家庭收支链上记账小程序,每笔收支写入链式结构,不可删除,支持家庭成员共同查看,解决账目争议,隐瞒消费问题。
  • 【数据处理与统计分析】2.Numpy库介绍以及使用
  • 2026拉勾网JA4+指纹反爬机制突破:10万条岗位数据分析实战
  • 2026年合肥最好吃火锅电话查询推荐:精选推荐与使用指南 - 品牌推荐
  • RISC-V微架构侧信道攻击检测技术解析
  • nli-MiniLM2-L6-H768真实案例:跨境电商产品描述多国语言主题归类
  • C语言实现消消乐游戏(8)
  • 告别命令行!在VSCode里一键调试你的Vue3 + Element Plus项目(附完整launch.json配置)
  • 【C++26合约编程成本控制白皮书】:20年架构师亲授——规避隐性开销的7大编译期拦截策略
  • 终极指南:3步掌握哔哩下载姬,轻松获取8K超清B站视频
  • 解决方案:构建基于电话号码的地理位置定位系统