Spring AI(4)——工具调用

工具调用也成为函数工具调用,是人工智能应用中的一个常见模式,通过函数调用允许模型与一组API或工具进行交互,从而增强其能力。

主要作用:

信息检索。此类别中的工具可用于从外部源检索信息,例如数据库、Web服务、文件系统或Web搜索引擎。其目的是增强模型的知识,使其能够回答其他方式无法回答的问题。例如,可以使用某个工具检索给定地点的当前天气、获取最新的新闻文章或查询数据库中的特定记录。

执行操作。本类工具可用于在软件系统中执行操作,例如发送电子邮件、在数据库中创建新记录、提交表单或触发工作流程。目标是自动化否则需要人工干预或明确编程的任务。例如,可以使用某个工具为与聊天机器人互动的客户预订航班,填写网页上的表单等。

执行流程:

1.当我们想让工具对大模型可用时,我们会将它的定义包含在聊天请求中。每个工具定义包括名称、描述和输入参数的模式。

2.当大模型决定调用工具时(注意:是否调用函数工具,由大模型做决定),它会发送一个响应,其中包含工具名称以及根据定义模式建模的输入参数。

3.我们的应用负责使用工具名称来识别并执行带有提供输入参数的工具。

4.工具调用的结果由应用处理。

5.应用将工具调用结果发送回大模型。

6.大模型根据工具调用的结果,结合上下文信息生成最终响应。

 

工具调用的是实现方式:

  • 方法作为工具

        Spring AI 提供内置支持,可以通过两种方式从方法中指定工具(即 ToolCallback):

        声明式方式,使用 @Tool 注解

        编程式方式,使用低级 MethodToolCallback 实现。

  • 函数作为工具

        Spring AI 提供内置支持,可以从函数中指定工具,既可以通过编程式使用低级 FunctionToolCallback 将函数式类型(FunctionSupplierConsumer 或 BiFunction)转换为工具实现

        还可以将工具定义为 Spring bean,并让 Spring AI 在运行时使用 ToolCallbackResolver 接口(通过 SpringBeanToolCallbackResolver 实现)动态解析它们

注意:本例主要演示@Tool声明式方式

定义工具类

public class MyTools {

    @Tool(name="getTodayDate", description = "获取今天日期信息")
    String getTodayDate() {
        System.out.println("获取当前日期时间");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }

}

大模型调用的工具通过@Tool 修饰,其包含如下4个属性:

  • name:工具的名称。如果未提供,将使用方法名称。AI 模型在调用工具时使用此名称进行识别。因此,同一类中不允许存在名称相同的两个工具。对于特定聊天请求,该名称在模型可用的所有工具中必须是唯一的。

  • description:工具的描述,模型可以使用此描述来理解何时以及如何调用该工具。如果未提供,将使用方法名称作为工具描述。但是,强烈建议提供详细描述,这对于模型理解工具目的及使用方法至关重要。未提供良好的描述可能导致模型在应该使用时未使用工具,或者使用错误。

  • returnDirect:工具结果是直接返回给客户端,还是传回给模型。默认值false,表示执行工具的结果需要再发送给大模型,大模型根据上下文返回组织后的信息。

  • resultConverter:用于将工具调用结果转换为自定义的String类型的数据,需要开发人员 重写ToolCallResultConverter 接口的方法实现,默认返回JSON格式的字符串。

通过ChatModel对象调用

    @GetMapping("/chat")
    public String chat(String message) {
        // 将指定类中@Tool修饰的方法转为ToolCallback对象
        ToolCallback[] dateTimeTools = ToolCallbacks.from(new MyTools());
        // 设置ChatOptions, 指定工具
        ChatOptions chatOptions = ToolCallingChatOptions.builder()
                .toolCallbacks(dateTimeTools)
                .build();
        // 提示词对象中指定工具
        Prompt prompt = new Prompt(message, chatOptions);
        // Prompt prompt = new Prompt(message);
        ChatResponse response = chatModel.call(prompt);
        System.out.println(response.getResult().getOutput().getText());
        return "success";
    }

提问内容:今天的日期

返回结果

从日志信息可以看到,内部调用了getTodayDate的方法。

提问内容:明天的日期

返回结果

从输出看到,返回了正确的结果。比如当前日期是5月13号,明天的日期是5月14号。

在这里我们再次强调下执行流程:

  • 大模型根据用户提出的问题确定是否需要调用工具
  • 如果需要调用,大模型返回需要调用哪个工具
  • 我们的应用执行对应的工具(默认spring ai内部封装的代码,帮助我们直接调用工具)
  • 将工具执行结果再次发给大模型
  • 大模型给出最终结果

通过ChatClient对象调用

    @GetMapping("/chat2")
    public String chat2(String message) {
        String answer = this.client
                .prompt(message)
                // 指定工具
                .tools(new MyTools())
                .call()
                .content();

        System.out.println(answer);

        return "success";
    }

上面的例子,我们是每次发送消息时都指定工具,这样子做更灵活。如果不想每次指定,我们可以通过defaultTools()方法为ChatClient指定默认工具:

    @Bean
    public ChatClient chatClient(ZhiPuAiChatModel chatModel) {
        return ChatClient
                .builder(chatModel)
                // 设置系统消息
                .defaultSystem("你是一个java架构师")
                // 指定默认工具
                .defaultTools(new MyTools())
                //配置日志相关的Advisor,需要开启日志级别以及配置 默认debug级别
                .defaultAdvisors(simpleLoggerAdvisor(),
                        MessageChatMemoryAdvisor.builder(chatMemory()).build())
                .build();
    }

如果即指定了默认工具,发送消息时也指定了工具,发送消息指定的工具生效。

returnDirect属性

工具结果是直接返回给客户端,还是传回给模型

在工具定义中,我们将returnDirect设置为true

 

public class MyTools {

    @Tool(name="getTodayDate", 
            description = "获取今天日期信息", 
            returnDirect = true)
    String getTodayDate() {
        System.out.println("获取当前日期时间");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }

}

提出的问题:明天的日期

返回结果:

通过返回内容,我们发现,设置 returnDirect=true后,只是返回了工具的调用结果,并没有将结果再次交给大模型。

大模型自动调用多次函数工具

public class MyTools {

    @Tool(description = "获取今天日期信息")
    String getTodayDate() {
        System.out.println("获取当前日期时间");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }

    @Tool(description = "根据指定日期获取天气情况")
    String getWeather(@ToolParam(description = "日期信息,格式为yyyy-MM-dd") String date) {
        System.out.println("获取指定日期的天气:" + date);
        return "晴天 35度";
    }

}

本例,我们设置了两个工具,一个用户获取当前日志,一个用于根据日期获取天气情况(给出模型的数据)。

提出问题:今天的天气

返回结果:

通过结果可以看出,大模型根据我们的提问,进行自动分析,内部调用了两次工具,返回了我们想要的结果。

提出问题:明天的天气

返回结果:

我们询问明天的天气,本意是想大模型得到明天的日期,然后返回天气,但是大模型只调用了获取天气的方法,日期随便给出。

修改提出的问题:查询天气时,需要先获取日期,然后根据日期查询。问题:明天的天气

返回结果:

返回结果符合我们的预期。

通过上面的例子,我们看到,是否调用函数工具由大模型决定,提示词描述的越准确,返回的结果也越精确。

 

 

 

### 如何在Spring中集成阿里云AI服务并实现前端工具交互 #### 1. 技术背景概述 Spring Cloud Alibaba AI 是一种将 Spring Cloud 生态与阿里巴巴的 AI 能力相结合的技术框架,旨在简化开发者构建智能化应用的过程[^2]。通过该框架,可以轻松地将自然语言处理、图像识别等功能嵌入到基于 Java 的微服务架构中。 此外,在现代开发实践中,Spring AI 提供了一套标准化 API 支持 LLM(大语言模型)、图像识别以及 NLP(自然语言处理)等核心功能[^3]。这使得开发者能够专注于业务逻辑设计,而无需过多关注底层技术细节。 --- #### 2. 环境准备 为了成功集成阿里云 AI 服务并与前端工具进行交互,需要满足以下条件: - **JDK 版本**: 推荐使用 JDK 17 或更高版本,并启用 ZGC 来优化 AI 模型推理性能。 - **Spring Boot 版本**: 使用 Spring Boot 3.2 及以上版本以获得更好的兼容性和扩展性。 - **构建工具**: Maven 或 Gradle 均可支持项目管理;本文示例采用 Maven 进行说明。 以下是典型的 `pom.xml` 文件中的依赖项配置: ```xml <dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Cloud Alibaba Dependency --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2023.x.x</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Aliyun SDK Core (for accessing AI services) --> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-sdk-core</artifactId> <version>4.x.x</version> </dependency> <!-- Optional: Actuator for health checks --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> ``` 上述代码片段展示了如何引入必要的依赖来支持 Spring Cloud Alibaba AI 和阿里云 SDK 核心库的功能。 --- #### 3. 后端接口开发 后端的主要职责在于封装对阿里云 AI 服务的调用逻辑,并提供 RESTful API 给前端消费。下面是一个简单的例子,展示如何创建一个用于在线聊天的应用程序接口: ##### 创建 Controller 类 ```java @RestController @RequestMapping("/api/chat") public class ChatController { @Autowired private AlipayClient alipayClient; // 注入阿里云客户端实例 /** * 处理来自前端的消息请求 */ @PostMapping("/message") public ResponseEntity<String> handleMessage(@RequestBody String message) { try { // 调用阿里云 AI 服务解析消息 String response = alipayClient.invokeChatService(message); return new ResponseEntity<>(response, HttpStatus.OK); // 返回响应给前端 } catch (Exception e) { return new ResponseEntity<>("Error processing request", HttpStatus.INTERNAL_SERVER_ERROR); } } } ``` 此部分实现了接收从前端发送过来的数据包,并将其传递至阿里云 AI 平台进行进一步分析和生成回复的操作流程[^1]。 --- #### 4. 前端工具对接 对于前端而言,可以通过 AJAX 请求或者 WebSocket 实现与后端服务器之间的实时通信。这里给出一个基础样例,利用 JavaScript 发送 POST 请求获取结果: ```javascript async function sendMessageToBackend() { const userInput = document.getElementById('userInput').value; const url = '/api/chat/message'; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: userInput }) }).then(response => response.json()) .then(data => { console.log('Response from server:', data); displayMessageOnUI(data.text); }); } function displayMessageOnUI(text) { const chatBox = document.getElementById('chatBox'); chatBox.innerHTML += `<div>${text}</div>`; } ``` 这段脚本定义了一个函数用来捕获用户的输入内容并向指定 URL 地址发起异步 HTTP 请求,最后把接收到的信息显示出来。 --- #### 5. 安全注意事项 当涉及到敏感数据传输时,请务必采取适当的安全措施保护用户隐私权不受侵犯。例如设置 HTTPS 加密连接防止中间人攻击行为发生;合理控制访问权限范围仅允许授权人员操作特定资源等等。 --- ### 总结 综上所述,借助于 Spring Cloud Alibaba AI 框架及其相关组件的支持下,我们可以较为便捷高效地完成整个系统的搭建工作——从初始化环境直至部署上线运行阶段均能保持较高水准的一致性和稳定性表现^。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值