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

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

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

//使用WebSocket连接后端socket服务 注意此处wss 可以理解为https ws为http

socket = 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,实际使用需要调整,只是为大家提供一种思路,谢谢

文章链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: