一比一实现ChatGPT流式接口前端显示效果(打字机效果)【对比几种不同的流式实现方案】

前端实现GPT或者其他大模型的流式推送的数据接收可以通过EventSource、Axios、或者基于EventSource实现的@microsoft/fetch-event-source插件库;

GPT官方是基于原生EventSource实现的流式数据接收,我们作为个人开发使用可以使用Axios或者使用@microsoft/fetch-event-source插件库,后两种可以携带header并且操作接口请求参数格式较为自由

话不多说,直接开始(注:以下代码基于vue)

方案一 EventSource

javascript 复制代码
sendSSEMessage() {
      // 只有当eventSource不存在时才创建新的EventSource连接
      if (!this.eventSource) {
        this.messages.push({text: this.inputText, isMine: true});
        this.messages.push({text: "", isMine: false});

        // 创建新的EventSource连接
        this.eventSource = new EventSource('http://127.0.1.1:8383/completions?messages='+this.inputText);

        // 设置消息接收的回调函数
        this.eventSource.onmessage = (event) => {
          const data = JSON.parse(event.data);
          this.messages[this.messages.length - 1].text += data.choices[0].delta.content;
        };

        // 可选:监听错误事件,以便在出现问题时能够重新连接或处理错误
        this.eventSource.onerror = (event) => {
          console.error("EventSource failed:", event);
          this.eventSource.close(); // 关闭出错的连接
          this.eventSource = null; // 重置eventSource变量,允许重建连接
        };
      }
    }

异常处理和重连

处理连接中断或其他异常也是至关重要的。你可能需要在失去连接时尝试重新连接,或者至少提醒用户当前的连接状态。这可以通过监听EventSource的错误事件并采取适当的行动来实现。

如果需要携带header或者其他参数可以考虑使用更完善的插件库@microsoft/fetch-event-source,我自己开发的GPT4.0网站也是基于这个插件库实现的,

这里给自己网站打个广告--->>欢迎各位看官老爷点击这里参观

--重回正题--

方案二 @microsoft/fetch-event-source插件库(更好用的SSE库)

1.首先从@microsoft/fetch-event-source中引入fetchEventSource

javascript 复制代码
import { fetchEventSource } from '@microsoft/fetch-event-source';
javascript 复制代码
   async sseSendStream(){
   			let that = this
            let token = "获取token";
            let tokens = "Bearer" + ' ' + token;

            let params =  {
                "model": that.gptmodel,
                "stream": true,
                "convGroupId": that.convGroupId,
                "parentConvId": that.convId,
                "request": that.inputText,
            }
            that.inputText = ""; //发送请求前将输入清空
            return new Promise((resolve, reject) => {
                try {
                    let concateContent = "";
                    fetchEventSource(url, {
                        method: 'post',
                        headers: {
                            'Content-Type': 'application/json',
                            "Accept": "text/event-stream",
                            "Authorization": tokens,
                        },
                        responseType: 'text/event-stream',
                        body: JSON.stringify(params),
                        signal: that.controller.signal,
                        openWhenHidden: true,
                        async onopen(response) {//建立连接的回调},
                        onmessage(msg) {//接收一次数据段时回调,因为是流式返回,所以这个回调会被调用多次
                            if(msg.event==''){
                                //进行连接正常的操作
                                try{
                                    const dataObj = JSON.parse(msg.data)
                                    // 检查数据块是否包含有效的content字段
                                    if (dataObj) {
                                        // 将content字段的值拼接到结果字符串中
                                        concateContent += dataObj.choices[0].delta.content;
                                        that.dialogueList[that.dialogueList.length - 1].text = concateContent
                                    }
                                }catch (e){
                                }
                            }else if (msg.event === 'close') {
                                //连接错误的操作
                                reject('close error')
                            }
                        },
                        onclose() {//正常结束的回调
                           //在这里写一些GPT回答结束后的一些操作
                        },
                        onerror(err) {//连接出现异常回调
                            // 取消请求
                            reject(err); // 发生错误,拒绝 Promise
                            throw err
                        },
                    })
                } catch (e) {
                    reject(e); // 拒绝 Promise
                }
            });
        },
  1. 通过 fetchEventSource(url, {...}) 发送 SSE 请求。
  2. 传递给 fetchEventSource 的参数包括请求的方法、头部信息、请求体、信号等
  3. onopen(response):建立连接时的回调函数。
  4. onmessage(msg):接收到数据时的回调函数。由于 SSE 是流式传输,所以这个回调函数会被多次调用。在这个回调函数中,首先检查是否发生了用户手动取消请求的情况,然后根据消息的类型进行相应的处理
  5. onclose():正常结束连接时的回调函数。
  6. onerror(err):连接出现异常时的回调函数。
  7. 在 onmessage 回调函数中,根据接收到的消息进行相应的处理。如果消息类型为空字符串,则表示连接正常,对数据进行解析和处理;如果消息类型为 'close',则表示连接错误

axios方案暂时先不写了,还是更推荐上面两种正儿八经的SSE推送接收方案,希望各位都能用上接的大模型,

也可以直接访问我的半公益网站使用GPT,点我嗷...(呸,又一次广告...)

相关推荐
小陈不好吃8 分钟前
equals 与 hashCode 的契约关系:从 HashMap 到 Lombok 注解
java·hashmap·lombok
Angeldream1239 分钟前
第 4 章 医学影像预处理
图像处理·人工智能·python·医学影像·医学影像处理
Web3&Basketball12 分钟前
实测Gemini4Argon:ERQA 87%登顶长程任务榜
数据库·python·大模型·多模态·gemini·长上下文·推理优化
Data analyse45614 分钟前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai25 分钟前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
把我格子衫拿来28 分钟前
医学影像重采样:spacing 改了,为什么模型位置也跟着错了?
python·dicom·医学影像·simpleitk·重采样
打工仔折腾 AI35 分钟前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战
wuyk55544 分钟前
PyQt6-第05讲-QtDesigner工作流与ui文件
python·ui·pyqt
Want5951 小时前
Python跳动的爱心②
开发语言·python·数学建模
田里的水稻1 小时前
PyTorch_TensorBoard展示
人工智能·pytorch·python·深度学习·神经网络