SpringAI框架搭建连续对话聊天
SpringAI框架实现连续对话聊天
- 什么是SpringAI
- 如何实现SpringAI的连续聊天。
- 依赖jar包的选择
- 配置文件
- spring的自动配置
- 实现聊天功能的WEB接口
什么是SpringAI
此处纯属我个人理解,从刚开始ChatGPT爆红网络,到现在各大AI模型百花齐放,AI在训练和使用上似乎一直是python的特权。现在spring终于放大招了,出了一个SpringAI框架,我们使用的Java语言也可以实现AI的使用了。并且SpringAI框架的出现,定义了一套标准接口,我们不用去学各个大模型厂商提供的SDK怎么用了,只需要学习SpringAI就可以适配所有已接入的大模型。
本次先记录下如何实现连续聊天(AI可以通过聊天记录的上下文,给出最合适的答案),MCP服务及客户端的实现、文转图的实现,我们随后就发布。有兴趣的同学可以订阅专栏或者关注我。
如何实现SpringAI的连续聊天。
本次的功能实现,用的是阿里的通义大模型,需要提前申请好大模型的密钥。密钥创建的传送门:https://bailian.console.aliyun.com/?tab=model#/api-key
依赖jar包的选择
spring boot的版本使用3.5.0以上,我使用的是3.5.5
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>1.0.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 阿里云通义集成模块 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- 提供web服务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 提供响应式的流服务,对客户端相应速度快 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
配置文件
使用application.yml进行配置
server:
port: 8080
spring:
application:
name: chat-gpt
ai:
dashscope:
api-key: sk-xxxxxxxxxxxxxxxxxxxxxxxxx
spring的自动配置
SpringAI框架在对象创建、方法调用,大量用了链式调用去实现,一定得习惯这种方式。很多类是没有公共的构造方法的。
package com.zhangzz.ai.core.config;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* SpringAI配置类,用于配置ChatClient和ChatMemory。
*/
@Configuration
public class SpringAIConfig
{
/**
* 保存历史聊天记录的Bean对象,使用的是线程安全的Map保存,也可自己实现接口ChatMemory,持久化到数据库等。
* @return ChatMemory
*/
@Bean
public ChatMemory getChatMemory() {
return MessageWindowChatMemory.builder().maxMessages(100).build();
}
/**
* 将通义大模型接入ChatClient
* @param model 阿里通义模型
* @return ChatClient
*/
@Bean
public ChatClient getChatClient(DashScopeChatModel model) {
return ChatClient.builder(model).build();
}
}
- ChatMemory接口,该接口是用来记录与AI大模型每次的聊天记录的,便于AI大模型每次生成的内容是基于之前的聊天历史问的,不会出现答非所问的情况。Spring默认提供了一个实现类,基于线程安全的Map去做存储的。相当于存储在内存里,个人比较推荐重新实现ChatMemory接口,使用Mongdb去做存储,大数据量检索速度还快。
- ChatClient 接口,是文本生成的重要接口,我们的文本聊天基本上都是用这个接口实现的。
实现聊天功能的WEB接口
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.util.Map;
import java.util.Objects;
@RestController
@RequestMapping("/ai")
public class ChatController
{
@Autowired
private ChatClient chatClient;
@Autowired
private DashScopeChatModel model;
@Autowired
private ChatMemory chatMemory;
@PostMapping("/tongYiChat")
public Map<
String,Object> tongYiChat(@RequestParam(value="message")String message){
String tabId = "newTab1";
//例如此处用户新开的聊天窗口ID。以此ID作为标识,将每次的聊天记录保存
MessageChatMemoryAdvisor chatMemoryAdvisor = MessageChatMemoryAdvisor.builder(chatMemory).conversationId(tabId).build();
ChatResponse response = chatClient.
prompt(new Prompt(message)).//用户的提问信息
advisors(chatMemoryAdvisor).//聊天记录保存器,此处为保存聊天记录到内存中。
call().chatResponse();
return Map.of("result", Objects.requireNonNullElse(response, "error"));
}
/**
* 响应式输出,避免客户端等待时间太长
* @param message 用户输入的消息
* @return 聊天流
*/
@PostMapping("/chatStream")
public Flux<
String> chatStream(@RequestParam(value="message")String message){
return chatClient.prompt(new Prompt(message)).stream().content();
}
Controller的Advisor,类似于springAOP,会在调用AI大模型的前、后,或环绕通知里,做一些业务。例如下面实现的连续对话的MessageChatMemoryAdvisor ,会在发起AI大模型请求前,将历史聊天读取出来,一起发送给AI大模型。
如下图:
启动服务,使用postman进行测试
1.接口“/tongYiChat”的结果
2.接口“/chatStream”的结果
此处若想实现响应式的流,还需要去前端实现,通过和后端建议长连接来进行持续输出(就和文言一心一样,AI的结果是一点一点输出的页面的,而不是一下子全部显示在页面,那样用户会等待的太久)
浙公网安备 33010602011771号