VUE3和SpringBoot实现ChatGPT页面打字效果SSE流式数据展示

news/2024/5/20 10:28:10 标签: spring boot, 后端, ChatGPT, 大模型, SSE, SSE流式数据, OpenAI

在做这个功能之前,本人也是走了很多弯路(花了好几天才搞好),你能看到本篇博文,那你就是找对地方了。百度上很多都是使用SseEmitter这种方式,这种方式使用的是websocket,使用这种方式就搞复杂了,会为后面项目分布式布署上埋下坑,什么坑,下面会说明。要实现【VUE3和SpringBoot实现ChatGPT页面打字效果SSE流式数据展示】这种效果,其实就是要使用SSE这种协议,这种协议很简单。我们先明白websocket和sse有什么区别,说几个主要的区别(太细的自己百度,这不是本博文的重点)

1、SSE是一种基于HTTP的单向通信机制,用于服务器向客户端推送数据,是单向通信

2、WebSocket是一种全双工的通信协议,它通过在客户端和服务器之间建立持久连接,实现双向通信

3、使用SSE在SpringBoot端,就像平时写接口一样,不需要啥配置,不需要保存用户的连接Session,WebSocket在SpringBoot端配置太多,而且需要保存用户的连接session,保存连接seesion在分布式布署上就比较麻烦。

博文最后会有整个项目源代码下载地址,下载之后里面有两个文件夹,myserver是后端springboot的,myweb是vue3前端页面的,如下截图

一、先看效果

二、环境搭建

1、在使用之前,我们还是安装一个大模型,我们这里使用的是LmStudio工具,这里面可以下载阿里开源的通义千问的语言模型,而且是在windows操作,简单;

2、下载地址:https://releases.lmstudio.ai/windows/0.2.17/latest/LM-Studio-0.2.17-Setup.exe

3、安装之后,就是下载大模型(下载需要魔法上网),选择Qwen 1.5

4、启动大模型,按箭头顺序,大模型启动后端口是1234

三、后端服务SpringBoot实现

用idea打开myserver项目,直接运行ServerApplication这个类,关键代码如下:


        //构建请求对象
        ChatRequest chatRequest = new ChatRequest();
        chatRequest.setModel("qwen:latest");//设置模型
        chatRequest.setStream(true);//设置流式返回

        ReqMessage reqMessage = new ReqMessage();//设置请求消息,在此可以加入自己的prompt
        reqMessage.setRole("user");//用户消息
        reqMessage.setContent(message);//用户请求内容
        ArrayList<ReqMessage> messageList = new ArrayList<>();
        messageList.add(reqMessage);
        chatRequest.setMessages(messageList);//设置请求消息
        //构建请求json
        String paramJson = JSONUtil.toJsonStr(chatRequest);;

        Flux<String> response = webClient.post()
                .uri("/chat/completions")//请求uri
                .header("Authorization", "Bearer sk-**************")//设置成自己的key,获得key的方式可以在下文查看
                .header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE)//设置流式响应
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(paramJson))
                .retrieve()
                .bodyToFlux(String.class)
                .flatMap(res->{
                    if (StrUtil.equals("[DONE]",res)){//[DONE]是消息结束标识
                        return Flux.empty();
                    }
                    ObjectMapper objectMapper = new ObjectMapper();
                    try {
                        //System.out.println(res);
                        JsonNode jsonNode = objectMapper.readTree(res);
                        Answer aiAnswer = objectMapper.treeToValue(jsonNode, Answer.class);
                        List<Choices> choicesList = aiAnswer.getChoices();
                        Choices choices = choicesList.get(0);
                        Delta delta = choices.getDelta();
                        String json = objectMapper.writeValueAsString(delta);
                        System.out.println(json);
                        return Flux.just(json);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }

                    return Flux.empty();
                });

三、Vue3前端关键代码

1、打开myweb项目,先cmd命令,进入到当前目录执行如下命令

npm install

2、运行项目,执行如下命令

npm run dev

3、前端页面关键代码

const abortController = new AbortController();
  eventSource.value = fetchEventSource('http://localhost:8080/ck/chat?message='+sendMsg.value,
      {
        method: "GET",
        signal: abortController.signal,
        openWhenHidden: true,
        onmessage(event) {
          let res = event.data;
          console.log(res)
          if(res!='[DONE]'&&res!=null){
            let data = JSON.parse(event.data);
            let content = data.content
            console.log('content=='+content)
            if(content!=null&&content.indexOf('\n')!=-1){
              let text = tableRightData.value[tableRightData.value.length - 1].content + content
              content = DOMPurify.sanitize(marked.parse(text))
              tableRightData.value[tableRightData.value.length - 1].content = content
              tableRightData.value.push({"role": "assistant", "content": '', "showPhoto": false, "error": null});
            }else if(content!=null&&content!=''){
              tableRightData.value[tableRightData.value.length - 1].content += content
            }
          }
          nextTick(()=>{
            //滚动条置最下面
            const container = rightContainerRef.value
            container.scrollTop = container.scrollHeight
          })
        },
        onclose() {
          console.log('结束了***************************')
          deleteBlankRow()
          // eventSource.close();
          eventSource.value = null; // 重置eventSource变量,允许重建连接
          console.log('结束了2*****************')
          abortController.abort();


        },
        onerror(event){
          console.log("EventSource failed:", event);
          abortController.abort();
          eventSource.value.close(); // 关闭出错的连接
          eventSource.value = null; // 重置eventSource变量,允许重建连接
        }
      }
  );

四、源代码下载:

下载地址:百度网盘 请输入提取码


http://www.niftyadmin.cn/n/5470429.html

相关文章

HaDoop学习1

第一章 读时模式&#xff08;Read-Time Schema&#xff09;- 写时模式&#xff08;Write-Time Schema&#xff09; 通常与模式演变&#xff08;Schema Evolution&#xff09;相关 即在数据表结构发生变化时&#xff0c;已经存在的数据如何适应新的模式&#xff1f; 【读时模…

C语言 | Leetcode C语言题解之3题无重复字符的最长子串

题目&#xff1a; 题解&#xff1a; int lengthOfLongestSubstring(char * s) {//类似于hash的思想//滑动窗口维护int left 0;int right 0;int max 0;int i,j;int len strlen(s);int haveSameChar 0;for(i 0; i < len ; i ){if(left < right){ //检测是否出现重…

VR版GPT可以在苹果Vision Pro上开发一个

特色:相比于基于文本的GPT,Noda的AI语音助手能够响应语音提示,在3D VR中创建思维导图。 1. 产品概述:一款空间计算生产力应用,集成了AIGC功能,旨在提升个人和团队的创意思维体验。 2. 产品功能: - AI辅助头脑风暴:通过智能建议和连接生成创新想法,利用AI进行利弊分析…

最优控制理论笔记 - 01数学准备

目录 一、向量和矩阵的微分 1. 向量对标量的导数 2. 矩阵对标量的导数 2.1 矩阵对标量的导数的运算公式 2.2 标量函数对向量的导数&#xff1a; 2.3 向量函数对向量的导数 二、函数极值的问题 三、有约束条件的函数极值问题 四、n元函数的Taylor 一、向量和矩阵的微分 …

【VSCode】修改插件地址

不想放在原始C盘下面C:\Users\{用户}\.vscode\extensions为了后续存储空间考虑&#xff0c;想通过添加环境变量创建名为VSCODE_EXTENSIONS的环境变量&#xff0c;内容指向vs Code扩展所在目录即可 直接配置环境变量&#xff0c;不要在有空格的文件夹下面 变量名称&#xff1a;…

[UTCTF 2024] crypto 部分

RSA-256 RSA签到太简单了 N 77483692467084448965814418730866278616923517800664484047176015901835675610073 e 65537 c 43711206624343807006656378470987868686365943634542525258065694164173101323321 p,q1025252665848145091840062845209085931,755752167715513324…

程序员延寿指南:科学延寿 20 年 | 开源日报 No.214

geekan/HowToLiveLonger Stars: 28.7k License: Unlicense HowToLiveLonger 是一个程序员延寿指南项目。 该项目旨在提供关于如何延长寿命的指南&#xff0c;特别是针对程序员群体。该项目包括术语、目标、关键结果、分析、行动和证据等内容&#xff0c;涵盖了各种与健康相关的…

使用STM32 MCU模拟实现PPS+TOD授时信号

简介 PPSTOD是授时信号的一种&#xff0c;用来传递准确的时间信息。 PPS&#xff0c;Pulse Per Second&#xff0c;是每秒一次的脉冲信号&#xff0c;其上升沿表示整秒的时刻。TOD&#xff0c;Time of Day&#xff0c;是时间信息。是跟随在每个PPS信号后的由串口发出的一句报…