8. Spring AI tools/function-call - 教程

news/2025/10/2 18:18:08/文章来源:https://www.cnblogs.com/ljbguanli/p/19123848

8. Spring AI tools/function-call - 教程

8. Spring AI tools/function-call

链接多个模型协调工作实战 - 初代tools:

背景:

大模型如果它无法和企业API互联那将毫无意义! 比如我们开发一个智能票务助手, 当用户需要退票, 基础大模型它肯定做不到, 因为票务信息都存在了我们系统中, 必须通过我们系统的业务方法才能进行退票。 那怎么能让大模型“调用”我们自己系统的业务方法呢? 今天叫大家通过结构化输入连接多个模型一起协同完成这个任务:

票务助手

效果

输入姓名和预定号:

普通对话:

代码:
public class AiJob {
record Job(JobType jobType, Map<String,String> keyInfos) {}public enum JobType{CANCEL,QUERY,OTHER,}}
/**
*
*/
@Configuration
public class AiConfig {
@Bean
public ChatClient planningChatClient(DashScopeChatModel chatModel,
DashScopeChatProperties options,
ChatMemory chatMemory) {
DashScopeChatOptions dashScopeChatOptions = DashScopeChatOptions.fromOptions(options.getOptions());
dashScopeChatOptions.setTemperature(0.7);
return  ChatClient.builder(chatModel)
.defaultSystem("""
# 票务助手任务拆分规则
## 1.要求
### 1.1 根据用户内容识别任务
## 2. 任务
### 2.1 JobType:退票(CANCEL) 要求用户提供姓名和预定号, 或者从对话中提取;
### 2.2 JobType:查票(QUERY) 要求用户提供预定号, 或者从对话中提取;
### 2.3 JobType:其他(OTHER)
""")
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build()
)
.defaultOptions(dashScopeChatOptions)
.build();
}
@Bean
public ChatClient botChatClient(DashScopeChatModel chatModel,
DashScopeChatProperties options,
ChatMemory chatMemory) {
DashScopeChatOptions dashScopeChatOptions = DashScopeChatOptions.fromOptions(options.getOptions());
dashScopeChatOptions.setTemperature(1.2);
return  ChatClient.builder(chatModel)
.defaultSystem("""
你是XS航空智能客服代理, 请以友好的语气服务用户。
""")
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build()
)
.defaultOptions(dashScopeChatOptions)
.build();
}
}
@RestController
public class MultiModelsController {
@Autowired
ChatClient planningChatClient;
@Autowired
ChatClient botChatClient;
@GetMapping(value = "/stream", produces = "text/stream;charset=UTF8")
Flux<String> stream(@RequestParam String message) {// 创建一个用于接收多条消息的 SinkSinks.Many<String> sink = Sinks.many().unicast().onBackpressureBuffer();// 推送消息sink.tryEmitNext("正在计划任务...<br/>");new Thread(() -> {AiJob.Job job = planningChatClient.prompt().user(message).call().entity(AiJob.Job.class);switch (job.jobType()){case CANCEL ->{System.out.println(job);// todo.. 执行业务if(job.keyInfos().size()==0){sink.tryEmitNext("请输入姓名和订单号.");}else {sink.tryEmitNext("退票成功!");}}case QUERY -> {System.out.println(job);// todo.. 执行业务sink.tryEmitNext("查询预定信息:xxxx");}case OTHER -> {Flux<String> content = botChatClient.prompt().user(message).stream().content();content.doOnNext(sink::tryEmitNext) // 推送每条AI流内容.doOnComplete(() -> sink.tryEmitComplete()).subscribe();}default -> {System.out.println(job);sink.tryEmitNext("解析失败");}}}).start();return sink.asFlux();}}

tools/function-call

想做企业级智能应用开发, 你肯定会有需求要让大模型和你的企业 API 能够互连,

因为对于基础大模型来说, 他只具备通用信息,他的参数都是拿公网进行训练,并且有一定的时间延迟, 无法得知一些具体业务数据和实时数据, 这些数据往往被各软件系统存储在自己数据库中:

比如我问大模型:“中国有多少个叫徐庶的” 他肯定不知道, 我们就需要去调用政务系统的接口。

比如我现在开发一个智能票务助手, 我现在跟AI说需要退票, AI怎么做到呢? 就需要让AI调用我们自己系统的退票业务方法,进行操作数据库。

在之前我们可以通过链接多个模型的方式达到, 但是很麻烦, 那用tools, 可以轻松完成。

tool calling也可以直接叫tool(也称为function-call), 主要用于提供大模型不具备的信息和能力:

  1. 信息检索:可用于从外部源(如数据库、Web 服务、文件系统或 Web 搜索引擎)检索信息。目标是增强模型的知识,使其能够回答无法回答的问题。例如,工具可用于检索给定位置的当前天气、检索最新的新闻文章或查询数据库以获取特定记录。 这也是一种检索增强方式。
  2. 采取行动:例如发送电子邮件、在数据库中创建新记录、提交表单或触发工作流。目标是自动执行原本需要人工干预或显式编程的任务。例如,可以使用工具为与聊天机器人交互的客户预订航班,在网页上填写表单等。

需要使用tools必须要先保证大模型支持。 比如ollama列出了支持tool的模型

使用

  1. 声明 tools (大模型调用的方法工具)的类:
@Service  // 注意要注入到 IOC容器当中
class NameCountsTools {
// @Tool 注解表示,告诉大模型提供的方法类,可以被你大模型调用使用,标识是可以被大模型调用的方法工具
@Tool(description = "长沙有多少名字的数量")
String LocationNameCounts(
// @ToolParam()使用该上述 @Tool标识的方法,要那些参数才可以调用,大模型会自动从用户的历史对话当中提取
// 出需要的“名字”信息,然后作为参数,去调用该 @Tool()标识的方法工具,如果用户对话当中没有提供
// 大模型就会告知用户需要提供“名字”
@ToolParam(description = "名字,可以是英文名") // description = "名字,可以是英文名" 这个是用于让大模型识别,
// 从而正确的从用户的历史对话当中提取的,赋值上去。
String name) {
return "10个";
}
}
  1. 将Tool类配置为bean(非必须)

  2. @Tool 用户告诉大模型提供了什么工具

  3. @ToolParam 用于告诉大模型你要用这个工具需要什么参数(非必须)

  4. 将上面声明的 Tools 类 绑定到 ChatClient(对应的大模型当中去)

@SpringBootTest
public class ToolTest {
ChatClient chatClient;
@BeforeEach
public  void init(@Autowired
DashScopeChatModel chatModel,
@Autowired  // 因为 NameCountsTools Tools 工具类,已经被我们加入到了IOC容器了
NameCountsTools nameCountsTools) {
chatClient = ChatClient.builder(chatModel)
.defaultTools(nameCountsTools) // 给大模型附加上我们的 Tools 工具类
.build();
}
@Test
public void testChatOptions() {
String content = chatClient.prompt()
.user("长沙有多少个叫徐庶的/no_think")
// .tools() 也可以单独绑定当前对话,绑定上 Tools 工具类
.call()
.content();
System.out.println(content);
}
}

原理

  1. 当我们设置了defaultTools 相当于就告诉了大模型我提供了什么工具, 你需要用我的工具必须给我什么参数, 底层实际就是将这些信息封装了json提供给大模型
  2. 当大模型识别到我们的对话需要用到工具, 就会响应需要调用tool

源码

tools注意事项:

  1. 参数或者返回值不支持:

推荐: pojo record java基础类型 list map

  1. Tools参数无法自动推算问题

问题:大模型无法将我们历史对话当中的信息,赋值转换到我们对应的 name 属性值当中。

  • 温度(即模型随机性)太低,AI可能缺失自由度变得比较拘谨(从一定程度可以解决, 但是不推荐)
  • 也可以通过描述 @ToolParam(description = “经度”) 和@Tool(description) 的 description 的值 更加明确
@Tool(description = "获取指定位置天气,根据位置自动推算经纬度")
public String getAirQuality(@ToolParam(description = "纬度") double latitude,
@ToolParam(description = "经度") double longitude) {
return "天晴";
}
  1. 大模型“强行适配”Tool参数的幻觉问题

问题:就是比如大模型将我们 的 “男,女”识别成了我们的姓名 name 赋值上了。

  • 加严参数描述与校验
@Parameter(description = "真实人名(必填,必须为人的真实姓名,严禁用其他信息代替;如缺失请传null)")
String name
  • 后端代码加强校验和兜底保护,比较稳,靠谱的方案。
  • 系统 Prompt 设定限制
“严禁随意补全或猜测工具调用参数。
参数如缺失或语义不准,请不要补充或随意传递,请直接放弃本次工具调用。”
  • 特别:高风险接口(如资金、风控等)tools方法加强人工确认,多走一步校验。
  1. 工具暴露的接口名、方法名、参数名要可读、业务化
  • AI是“看”你的签名和注释来决定用不用工具的;
  • 尽量避免乱码、缩写等。
  1. 方法参数数量不宜过多
  • 建议每个工具方法尽量少于5个参数,否则AI提示会变复杂、出错率高。

工具方法不适合做超耗时操作, 更长的耗时意味着用户延迟响应时间变长,

性能优化 能异步处理就异步处理、 查询数据 redis

6. 关于Tools的权限控制
可以利用SpringSecurity限制

@Tool(description = "退票")
@PreAuthorize("hasRole('ADMIN')")
public String cancel(
// @ToolParam告诉大模型参数的描述
@ToolParam(description = "预定号,可以是纯数字") String ticketNumber,
@ToolParam(description = "真实人名(必填,必须为人的真实姓名,严禁用其他信息代替;如缺失请传null)") String name
) {
// 当前登录用户名
String username = SecurityContextHolder.getContext().getAuthentication().getName();
// 先查询 --->先校验
ticketService.cancel(ticketNumber, name);
return username+"退票成功!";
}

将tools和权限资源一起存储, 然后动态设置tools

.defaultToolCallbacks(toolService.getToolCallList(toolService))

根据当前用户读取当前用户所属角色的所有tools

public List<ToolCallback> getToolCallList(ToolService toolService) {// 1 获取 Tools 处理的方法Method method = ReflectionUtils.findMethod(ToolService.class, "cancel",String.class,String.class);// 构建 Tool 定义信息 动态配置的方式 @Tool @ToolParam 都无效ToolDefinition toolDefinition = ToolDefinition.builder().name("cancel").description("退票")  // 对应@Tool注解当中的 description// 对应@ToolParam() 注解.inputSchema("""{"type": "object","properties": {"ticketNumber": {"type": "string","description": "预定号,可以是纯数字"},"name": {"type": "string","description": "真实人名"}},"required": ["ticketNumber", "name"]}""").build();// 一个 ToolCallback 对应一个 toolToolCallback toolCallback = MethodToolCallback.builder().toolDefinition(toolDefinition) // 将对应的 toolDefinition = @ToolParam 传入.toolMethod(method)  // method = @Tools 配置.toolObject(toolService) // 不能自己 new ,自己 new 的无法解析依赖注入.build();return List.of(toolCallback);}
  1. tools过多导致AI出现选择困难证

问题:
a. token上限
b. 选择困难证
tools的描述作用 保存 向量数据库。
实现方式:

  1. 把所有的tools描述信息存入到向量数据库,做相似性检索。
  2. 每次对话的时候根据当前对话信息检索到相似的tools(RAG)
  3. 然后动态设置tools

最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/925176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业网站优化方案范本收费网站必须备案吗

RHEL6的网络管理与RHEL5的有比较大的改变。虽然在RHEL5、6中均安装有NetworkManager&#xff0c;在RHEL5中2、3、4、5级别中默认是不启用的。但在RHEL6中&#xff0c;默认是启用的&#xff0c;NetworkManager会一直监控网卡状态&#xff0c;修改网卡参数立即生效不用重启服务。…

门户网站开发技术 知乎下载ppt模板免费

def shape_print(n): #实心等腰三角形 for y in range(n): for x in range(n-y-1):#先循环打印空格 形成一个倒直角三角形 range()中的值是形成的规律 print( ,end) for z in range(y*21):#再循环打印X 形成一个等腰三角形 range()中的值是形成的规律 print(X,end) print() pri…

electron 安装失败

清理缓存重装# 删除依赖和锁文件 rm -rf node_modules pnpm-lock.yaml# 清理pnpm缓存 pnpm store prune# 重新安装 pnpm install#一行命令rm -rf node_modules pnpm-lock.yaml && npm cache clean --force 使用…

LeetCode刷题记录----62.不同路径(Medium) - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

python基础——正则表达式 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

机器学习15:自监督式学习(Self-Supervised Learning)① - 实践

机器学习15:自监督式学习(Self-Supervised Learning)① - 实践2025-10-02 18:11 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impo…

长沙旅游网站开发旅游网站的建设背景

ChatGPT4和Gemini Ultra被Claude 3 AI模型超越了&#xff1f; 3月4日周一&#xff0c;人工智能公司Anthropic推出了Claude 3系列AI模型和新型聊天机器人&#xff0c;其中包括Opus、Sonnet和Haiku三种模型&#xff0c;该公司声称&#xff0c;这是迄今为止它们开发的最快速、最强…

2025担保合同律师事务所推荐,专业团队高效解决法律难题!

2025担保合同律师事务所推荐,专业团队高效解决法律难题!在当今复杂的经济环境中,担保合同作为金融交易和商业合作中的重要法律工具,其纠纷和风险也日益增多。根据行业数据显示,近年来担保合同相关案件的年增长率保…

「补充篇」在Cloudflare上设置并更新SRV记录

「补充篇」在Cloudflare上设置并更新SRV记录索引 │ ├─关于本教程 ├─创建SRV记录 ├─获取DNS更新令牌 ├─获取区域ID ├─获取DNS记录ID ├─更新SRV记录 └─结尾关于本教程 在之前的教程中我们已经介绍了使用…

10.1 CSP模拟26 改题记录

HZOJ 写在前面 hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh T1几分钟出思路然后在写假的道路上越改越远,T2来不及了乱写,T3猜不到结论,只有T4是合理得分、、、 A. median 题意是给定5个长为…

Spring 核心 - AOP 面向切面编程入门, 通俗易懂

Spring 核心 - AOP 面向切面编程入门, 通俗易懂撰写本文目的只有一个,让你畅快阅读 AOP 知识,并搞定以下几个问题。 AOP 面向切面编程到底是什撰写本文目的只有一个,让你畅快阅读 AOP 知识,并搞定以下几个问题。AO…

2025年筒袋磁力泵实力厂家推荐榜:高效耐用与创新技术深度解

2025年筒袋磁力泵实力厂家推荐榜:高效耐用与创新技术深度解在化工、制药、石油等工业领域,筒袋磁力泵作为一种高效、无泄漏的流体输送设备,正日益成为关键工艺环节的核心装备。其采用磁力耦合驱动技术,彻底解决了传…

2025电源适配器权威推荐榜:高效稳定、安全耐用的优质品牌之

2025电源适配器权威推荐榜:高效稳定、安全耐用的优质品牌之选在当今数字化的时代,各种电子设备充斥着我们的生活和工作,从智能手机、平板电脑到笔记本电脑、智能穿戴设备等,这些设备都离不开电源适配器来提供稳定的…

「LUCKY STUN穿透」IPv4和IPv6分离重定向

「LUCKY STUN穿透」IPv4和IPv6分离重定向关于本教程 在之前的教程中我们已经实现了通过cloudflare的页面规则 以及重定向规则实现实现stun穿透端口的“固定” 使用页面规则:「LUCKY STUN穿透」使用Cloudflare的页面规…

2025航空插头权威推荐榜:M8/m12/公母对接/5芯/五芯/三芯/4芯/3芯/12芯航空插头优质性能与可靠品质的源头厂家之选

行业背景航空插头,作为电子设备中电流、信号连接的关键部件,广泛应用于航空航天、国防、工业自动化、交通运输等众多领域。随着科技的飞速发展,各行业对电子设备的性能和可靠性要求越来越高,这也对航空插头的质量、…

2025经侦律师优质品牌推荐:上海浦信律所专业护航!

2025经侦律师优质品牌推荐:上海浦信律所专业护航!在当今复杂多变的商业环境中,经济犯罪的形式日益多样化和隐蔽化,经侦律师的重要性愈发凸显。他们不仅要具备扎实的法律知识,还要应对各种技术挑战,为客户提供专业…

建筑人才网官方网站评职称wordpress目录结构

php的错误处理是比较复杂的, 本文讲解php中所有错误相关的重要知识点做一次梳理, 便于理解php的错误机制. 基础知识 在此之前, 先熟悉一下php error的基础知识 预定义常量运行时配置异常错误处理函数预定义常量 定义了所有php的错误类型常量, 每一个常量都是一个整型数值, 它的…

制作营销网站公司竞价推广培训

在英语学习中&#xff0c;我们经常遇到一些句子包含两个成分&#xff0c;如“人物”或“宾语补充说明”。这些句子可能是双宾语结构&#xff0c;也可能是宾语补足语结构。虽然两者都出现在动词后&#xff0c;但它们的功能和意义完全不同&#xff0c;本篇文章将会介绍一下小技巧…

实用指南:[Windows] 随手剪-视频合并工具 v0.12多种格式多段视频50多种转场效果

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

欧易-(OKX)交易所注册及KYC认证全流程指南

作为全球领先的加密货币交易平台,欧易(OKX)为用户提供安全便捷的数字资产交易服务。本文将详细介绍OKX的注册流程和KYC认证步骤,帮助您快速完成账户开通。 一、OKX注册流程下载安装OKX APP 您可以通过以下方式获取…