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

当下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(""连接错误,请联系开发者")
  }

 响应数据如下:

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

第二种就是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)
  }

 解析输出数据如下:

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

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

你可能感兴趣的:(chatgpt,websocket)