ChatGPT 前端流式数据如何处理?本文提供三种方案为你揭开疑惑【websocket、SSE、fetch Stream]

zero笨小孩 2024-06-11 15:33:02 阅读 60

当下chatGPT如此火热,很多开发者都想部署一个 自己的gpt站点,本文不细致讨论gpt部署,只是着重总结一下博主在接入gpt时对于内容流失输出的解决方案,【代码质量并不高,感兴趣的小伙伴可以简单参考】

第一种也是我个人比较推荐的方案:websocket

各个平台兼容性也比较友好,且支持小程序【小程序需要使用其内部自动的socket API,详情请参考其官方文档】

//使用WebSocket连接后端socket服务 注意此处wss 可以理解为https ws为httpsocket = new WebSocket("ws://chat.xxx.saybot.net/websocket/" + userStore.uid)//监听onopen 成功触发表示连接socket服务成功 socket.onopen = function () { console.log("😄您已成功接入websocket服务,开始解决你的问题") socket.send("") }//收到消息事件 gpt响应会不断触发onmessage事件,其事件对象中会有流失输出的内容 socket.onmessage = function (event) { try { const content = JSON.parse(event.data).content console.log('😄gpt 响应内容为',content) } catch (err) { switch (event.data) { case "[INTERRUPTED]": case "[MODEL_TIMEOUT]": case "TEMPERATURE_THRESHOLD": case "[TOKENS]": console.log("😄gpt 响应中断或者超时") event.target.close() break case "[DONE]": console.log("😄gpt 响应结束了") event.target.close() break default: console.log("😄message error", err) break } } } //连接关闭事件 socket.onclose = function (event) { console.log("😄您已断开") } //发生了错误事件 socket.onerror = function (e) { console.log(""连接错误,请联系开发者") }

 响应数据如下:

第二种就是SSE方案,

SSE方案和websocket类似,但其存在一个比较大的”遗憾“就是不支持小程序

npm  i event-source-polyfill    //首先需要下载改库到项目                

const eventSource = new EventSourcePolyfill("http:/xxxxxx/createSse", { headers: { uid: userStore.uid, //此处可以携带你需要的headers token: localStorage.getItem("accessToken") } })eventSource.onopen = event => { console.log("SSE 连接成功, 开始请求数据") } eventSource.onmessage = async event => { const { data, lastEventId } = event switch (lastEventId) { case "[INTERRUPTED]": case "[MODEL_TIMEOUT]": case "TEMPERATURE_THRESHOLD": console.log("😄gpt 回复超时或中断") event.target.close() beak case "[TOKENS]": case "[DONE]": console.log("😄gpt 回复完毕") event.target.close() break default: const content = JSON.parse(data).content console.log("😄gpt 回复:",content) break } } eventSource.onerror = event => { console.log("😄gpt onerror :",event) }

 解析输出数据如下:

 

第三种方案就是strem流式方案

通过fetch 请求,获取stream流式数据,相对比较麻烦不推荐

export const postMessage = async data => { const res = await fetch("http://xxxxx/talkByStream", { method: "POST", headers: { "Content-Type": "application/json", token: userStore.token }, body: JSON.stringify(data) }) if (res.status && res.status !== 200) { console.log('error',res) } return res?.body?.getReader(); //getReader()可以让调用者更方便字符内容的处理}

调用fetch请求const reader = await postMessage({ conversation: messageListToConversation(messageList.value), userMessage: { role: "user", content }, temperature: 0.9}) reader.read().then(async ({ value, done }) => { if (done) { return } let text = new TextDecoder().decode(value) const responseStatus = text.match(REGEXP_FINISH_STATUS) const matchs = text.match(REGEXP_CONTENT_ARR) for (let i = 0; i < matchs?. length; i++) { let [, content] = matchs[i].match(REGEXP_CONTENT) content = content.replace(/\\n/g, "\n") await sleep(90) //睡眠函数 console.log(content ) } }

以上方案仅供参考,只是一个基础demo,实际使用需要调整,只是为大家提供一种思路,谢谢



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。