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

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

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

//使用WebSocket连接后端socket服务注意此处wss 可以理解为httpsws为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).contentconsole.log('gpt 响应内容为',content)} catch (err) {switch (event.data) {case "[INTERRUPTED]":case "[MODEL_TIMEOUT]":case "TEMPERATURE_THRESHOLD":case "[TOKENS]":console.log("gpt 响应中断或者超时")event.target.close()breakcase "[DONE]":console.log("gpt 响应结束了")event.target.close()breakdefault: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,//此处可以携带你需要的headerstoken: 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()beakcase "[TOKENS]":case "[DONE]": console.log("gpt回复完毕")event.target.close()breakdefault:const content = JSON.parse(data).contentconsole.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" />调用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,实际使用需要调整,只是为大家提供一种思路,谢谢