目录
1.介绍
工作原理
2.SpringAl开发
2.1工具调用的流程:
2.2工具使用
2.21工具定义
2.2.2使用工具
2.2.3主流开发工具
2.2.4集中注册
2.2.5正式使用工具
工具调用理解为让Al大模型借助外部工具来完成他自己做不到的事情
工具可以是任何东西,比如网页搜索、对外部 API 的调用、访问外部数据、或执行特定的代码等。
比如用户提问 “帮我查询上海最新的天气”,AI 本身并没有这些知识,它就可以调用 “查询天气工具”,来完成任务。
目前工具调用技术发展的已经比较成熟了,几乎所有主流的、新出的 AI 大模型和 AI 应用开发平台都支持工具调用。
工作原理
其实,工具调用的工作原理非常简单,并不是 AI 服务器自己调用这些工具、也不是把工具的代码发送给 AI 服务器让它执行,它只能提出要求,表示 “我需要执行 XX 工具完成任务”。而真正执行工具的是我们自己的应用程序,执行后再把结果告诉 AI,让它继续工作。
- 1.工具定义:程序告诉Al你可以使用这些工具,并描述每个工具功能和所需参数
- 2.工具选择:Al在对话中判断需要使用某个工具,并准备号响应的参数
- 3.返回意图:Al返回我想使用xx工具,参数是xxx的信息
- 4.工具执行:我们的程序接收请求,执行相应的工具操作
- 5.结果返回:程序将工具执行的结果发回给Al
- 6.继续对话:Al根据工具返回的结果,生成最终回答给用户
通过上述流程,我们会发现,程序需要和 AI 多次进行交互、还要能够执行对应的工具,怎么实现这些呢?我们当然可以自主开发,不过还是更推荐使用 Spring AI、LangChain 等开发框架。此外,有些 AI 大模型服务商也提供了对应的 SDK,都能够简化代码编写。
只学习基于Methods方法来定义工具,Methods方式更容易编写,更容易理解,支持的参数和返回类型更多。
1)Methods 模式:通过 @Tool 注解定义工具,通过 tools 方法绑定工具
class WeatherTools { @Tool(description = "Get current weather for a location") public String getWeather(@ToolParam(description = "The city name") String city) { return "Current weather in " + city + ": Sunny, 25°C"; } } // 使用方式 ChatClient.create(chatModel) .prompt("What's the weather in Beijing?") .tools(new WeatherTools()) .call();
2.21工具定义
SpringAl提供了两种定义工具的方法——注解式和编程式。
1)注解式:只需使用
@Tool
注解标记普通 Java 方法,就可以定义工具了,简单直观。每个工具最好都添加详细清晰的描述,帮助 AI 理解何时应该调用这个工具。对于工具方法的参数,可以使用
@ToolParam
注解提供额外的描述信息和是否必填。class WeatherTools { @Tool(description = "获取指定城市的当前天气情况") String getWeather(@ToolParam(description = "城市名称") String city) { // 获取天气的实现逻辑 return "北京今天晴朗,气温25°C"; } }
2)编程式:如果想在运行时动态创建工具,可以选择编程式来定义工具,更灵活。
class WeatherTools { String getWeather(String city) { // 获取天气的实现逻辑 return "北京今天晴朗,气温25°C"; } }
2.2.2使用工具
定义好工具后,SpringAl提供了多种灵活的方式将工具提供给ChatClient,让Al能够在需要时调用这些工具。
1)按需使用:这是最简单的方式,直接在构建 ChatClient 请求时通过 tools() 方法附加工具。这种方式适合只在特定对话中使用某些工具的场景。
String response = ChatClient.create(chatModel) .prompt("北京今天天气怎么样?") .tools(new WeatherTools()) // 在这次对话中提供天气工具 .call() .content();
2)全局使用:如果某些工具需要在所有对话中都可以用,可以在构建ChatClient时注册默认工具。这样,这些工具将对从同一个ChatClient发起的所有对话可用。
ChatClient chatClient = ChatClient.builder(chatModel) .defaultTools(new WeatherTools(), new TimeTools()) // 注册默认工具 .build();
3)更底层的使用方式:除了给Chatclient绑定工具外,也可以给更底层的ChatModel绑定工具,适合需要更精细控制的场景。
// 先得到工具对象 ToolCallback[] weatherTools = ToolCallbacks.from(new WeatherTools()); // 绑定工具到对话 ChatOptions chatOptions = ToolCallingChatOptions.builder() .toolCallbacks(weatherTools) .build(); // 构造 Prompt 时指定对话选项 Prompt prompt = new Prompt("北京今天天气怎么样?", chatOptions); chatModel.call(prompt);
总结:在使用工具时,SpringAl会自动处理工具调用的全过程:从Al大模型决定调用工具=》到执行工具具体方法=>再到将结果返回给模型=>最后模型基于工具结果生成最终回答。这整个过程对开发者来说是透明的,我们只需专注于实现工具的业务逻辑即可。
2.2.3主流开发工具
首先,工具的本质就是一种插件。能不自己写的插件,就尽量不要自己写。我们可以直接在网上找一些优秀的工具实现,比如 Spring AI Alibaba 官方文档 中提到了社区插件。
虽然文档里只提到了屈指可数的插件数,但我们可以顺藤摸瓜,在 GitHub 社区找到官方提供的更多 工具源码,包含大量有用的工具!比如翻译工具、网页搜索工具、爬虫工具、地图工具等:
这种搜集资源的能力,希望大家也能够掌握,尤其是学新技术的时候,即使官方文档写的不够清晰完善,我们也可以从开源社区中获取到一手信息。
2.2.4集中注册
开发好了这么多工具类后,结合我们自己的需求,可以给Al一次性提供所有工具,让它自己决定何时调用。所有我们可以创建工具注册类,方便统一管理和绑定所有工具。
@Configuration public class ToolRegistration { @Value("${search-api.api-key}") private String searchApiKey; @Bean public ToolCallback[] allTools() { FileOperationTool fileOperationTool = new FileOperationTool(); WebSearchTool webSearchTool = new WebSearchTool(searchApiKey); WebScrapingTool webScrapingTool = new WebScrapingTool(); ResourceDownloadTool resourceDownloadTool = new ResourceDownloadTool(); TerminalOperationTool terminalOperationTool = new TerminalOperationTool(); PDFGenerationTool pdfGenerationTool = new PDFGenerationTool(); return ToolCallbacks.from( fileOperationTool, webSearchTool, webScrapingTool, resourceDownloadTool, terminalOperationTool, pdfGenerationTool ); } }
可别小瞧这段代码,其实它暗含了好几种设计模式:
- 1.工厂模式:allTools()方法作为一个工厂方法,负责创建和配置多个工具实例,然后将它们包装成统一的数组返回。这符合工厂模式的核心思想-集中创建对象并隐藏创建细节。
- 2.依赖注入模式:通过@Value注解注入配置值,以及创建号的工具通过Spring容器注入到需要它们的组件中。
- 3.注册模式:该类作为一个中央注册点,集中管理和注册所有可用的工具,使它们能够被系统其他部分统一访问。
- 适配器模式的应用:ToolCallbacks.from 方法可以看作是一种适配器,它将各种不同的工具类转换为统一的 ToolCallback 数组,使系统能够以一致的方式处理它们。
有了这个注册类,如果需要添加或移除工具,只需修改这一个类即可,更利于维护。
2.2.5正式使用工具
@Resource private ToolCallback[] allTools; public String doChatWithTools(String message, String chatId) { ChatResponse response = chatClient .prompt() .user(message) .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId) .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)) // 开启日志,便于观察效果 .advisors(new MyLoggerAdvisor()) .tools(allTools) .call() .chatResponse(); String content = response.getResult().getOutput().getText(); log.info("content: {}", content); return content; }
好了,以上就是关于springAl的工具使用特性,SpringAl也非常贴心的集成了工具调用的方法,关于工具可以去github上查找别人现成的,能不自己开发就不自己开发!