一比一实现ChatGPT流式接口前端显示效果(打字机效果)【对比几种不同的流式实现方案】
吉吉安 2024-06-21 13:03:02 阅读 89
前端实现GPT或者其他大模型的流式推送的数据接收可以通过EventSource
、Axios
、或者基于EventSource实现的@microsoft/fetch-event-source
插件库;
GPT官方是基于原生EventSource实现的流式数据接收,我们作为个人开发使用可以使用Axios或者使用@microsoft/fetch-event-source插件库,后两种可以携带header并且操作接口请求参数格式较为自由
话不多说,直接开始(注:以下代码基于vue)
方案一 EventSource
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
import { fetchEventSource } from '@microsoft/fetch-event-source';
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 } }); },
通过 fetchEventSource(url, {...})
发送 SSE 请求。传递给 fetchEventSource
的参数包括请求的方法、头部信息、请求体、信号等onopen(response)
:建立连接时的回调函数。onmessage(msg)
:接收到数据时的回调函数。由于 SSE 是流式传输,所以这个回调函数会被多次调用。在这个回调函数中,首先检查是否发生了用户手动取消请求的情况,然后根据消息的类型进行相应的处理onclose()
:正常结束连接时的回调函数。onerror(err)
:连接出现异常时的回调函数。在 onmessage
回调函数中,根据接收到的消息进行相应的处理。如果消息类型为空字符串,则表示连接正常,对数据进行解析和处理;如果消息类型为 ‘close’,则表示连接错误
axios方案暂时先不写了,还是更推荐上面两种正儿八经的SSE推送接收方案,希望各位都能用上接的大模型,
也可以直接访问我的半公益网站使用GPT,点我嗷…(呸,又一次广告…)
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。