使用推流(streaming)让ChatGPT更丝滑 / ai #7

Words
266
Reading
2 min
Listen
Play
4y

https://ai.ilark.io

对比ChatGPT接受数据的方法是逐字逐字地传输,它得到第一个字就开始输出,这让用户体验更佳。相比,得到全部结果再一次输出,虽然时间都一样,但等待还是太煎熬了!一边输出一边看,这才是最佳打开方式嘛。

这种边看边输的方式其实就是现在的推流(streaming)模式,像现在的视频站、直播等,肯定都是用的数据流,都是边看边播的。ChatGPT API也是可以实现同样的功能的。

服务器端实现

//nodejs

try {
    res.setHeader('Cache-Control', 'no-cache')
    res.setHeader('Content-Type', 'text/event-stream')
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader('Connection', 'keep-alive')
    res.flushHeaders() // flush the headers to establish SSE with client

    const response = openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: query,
      max_tokens: 3000,
      temperature: 0.2,
      stream: true,    //推流模式打开
    }, { responseType: 'stream' })

    response.then(resp => {
      resp.data.on('data', data => {
          const lines = data.toString().split('\n').filter(line => line.trim() !== '')
          for (const line of lines) {
              const message = line.replace(/^data: /, '')
              if (message === '[DONE]') {
                // console.log(996, "done")
                  res.end()
                  return
              }
              let strTemp = getReg(message)
              if(strTemp != null){
                // console.log(1188, "strTemp", strTemp)
                res.write(strTemp)
              }
          }
      })
    })
  }

用户端

//浏览器

let query = [{role: "user", content: data.get('prompt')}]
let dataObj = {
     method: 'POST',
     headers: {
          'Content-Type': 'application/json',
     },
     body: JSON.stringify({
          query: query,
          })
}

const response = await fetch(url, dataObj)
let that = this
messageDiv.innerHTML = " "
if (response.ok) {  
let i = 0
let getStream = function (reader) {
     return reader.read().then(function (result) {
          // 如果数据已经读取完毕,直接返回
          if (result.done) {
               console.log(889, "result done")
               that.clickFlag = false
               clearInterval(loadInterval)  
               loading.textContent = ''
               return
          }
          // 取出本段数据(二进制格式)
          let chunk = result.value
          let text = that.utf8ArrayToStr(chunk)
          if(i === 0){
               text = text.replace(/\\n/g,'')  //去除首段换行
          } else{
               text = text.replace(/\\n/g,'
'
) } // console.log(5667, "i", i, text) // 将本段数据追加到网页之中 messageDiv.innerHTML += text i ++ // 递归处理下一段数据 return getStream(reader) }) } getStream(response.body.getReader())

用户端方面是折腾了许久,用axios尝试了半天 ,也是没搞定。用fetch也是尝试了半天,才发现可行。然后是慢慢完善,几天时间竟然就这样过去了!

折腾的结果还不赖,现在AI·Joe流畅了不少,再接再励,慢慢完善。

使用推流(streaming)让ChatGPT更丝滑 / ai #7 | Ecency