使用uni.request封装大模型流式返回

7 阅读1分钟

最近小程序要对接AI大模型,微信小程序里面的流式返回对接有几个坑:

1、微信小程序需要启动enableChunked: true, 启用分块传输模式 返回的数据类型是arraybuffer

2、返回的数据分块需要自己拼接(ps:比如一个id是一个完整的字符串,i 字符在上一个分块,d在下一个分块)

3、arraybuffer需要转成字符串,原生的转换方法紧在调试器有效,不支持真机

下面是完整代码

import utf8Array2Str from 'utf8array2str' // 处理二进制数据(兼容Uint8Array/ArrayBuffer)
 
export default function (url, data = {}, method = 'POST', sseCallback, failCallback) {
 
  let header = {
    Accept: 'text/event-stream',
    token: uni.getStorageSync('access_token')
  }
  const abort = () => {
    failCallback && failCallback()
  }
  const requestTask = uni.request({
    url,
    method,
    header,
    data,
    enableChunked: true, // 启用分块传输模式
    responseType: 'arraybuffer',
    success: (res) => {
      console.log('响应结束')
    },
    fail: (error) => {
      console.log('错误处理', error)
      failCallback && failCallback()
    }
  })
 
  let lastText = ''
 
  requestTask.onChunkReceived((res) => {
    // 第一步:获取 字符串 数组
    const data = new Uint8Array(res.data)
    const responseText = lastText + utf8Array2Str(data)
    let arr = responseText.split('\n\n');
 
    let lastIndex = arr.length - 1
    // 第二步:是否可以直接进行解析
    try {
      // 判断是否可以全部解析完成
      arr.every(item => JSON.parse(item.replace(/^data:/, '')))
    } catch (error) {
      // 如果报错截取最后一项
      lastText = arr[lastIndex]
      arr = arr.filter((_, i) => i !== lastIndex)
    }
 
    for (let i = 0; i < arr.length; i++) {
      const item = arr[i]
      const jsonData = item.replace(/^\s+/, '').replace(/^data:/, '')
      // 下面大家根据自己的业务逻辑处理正常响应
    }
  })
  return {
    abort
  }
}