uni.request流式(Stream)请求,实现打印机效果

最近使用 扣子 - 开发指南 (coze.cn) 和 智谱AI开放平台 开发小程序AI导诊和用药对话指南。

开发的过程中也是走了不少坑,下面就来聊聊走了哪些坑。

坑1 :coze试了v2和v3的接口,两个接口请求还是有点差别的,v2拿到了botId和accessToken可以直接请求不需要做任何处理,v3还需要多一步,先创建会话,在开发指南上有接口,需要先请求创建会话,拿到createdId在接口后拼接,注意,createdId是拼接到接口后的,最开始没仔细看官网就犯了这个错误!!

坑2(响应的格式) :第一次开发不知道流式请求响应的内容是markdown格式,找了一天怎么渲染!!最后还是朋友的朋友提醒markdown,一个简短的markdown让我茅塞断开。

可以查询对应的插件做页面展示,我这里使用的是zero-markdown-view,主要是因为有事件,可以处理自己的逻辑,图片可以放大预览,当然里面也有很有问题我就不在这多说了

下面代码是一个发送后 请求的整体流程

    //请求ai接口
    bindChunkTest() {
      let that = this;
      this.aiApimsg=[{
        role: 'user',
        content: this.content,
        content_type: 'text',
      }]
      let params = {
        bot_id: this.yonghuObj.botId,
        user_id: this.userId,
        additional_messages: this.aiApimsg,
        stream: true,
      };
      let message = '';
      let messageObj = {};
      this.shengChengObj = {};
      let imageUrl = '';
      this.isSendLoading = true;
      this.requestTask = uni.request({
        url: 'https://api.coze.cn/v3/chat?conversation_id='+that.createdId,
        timeout: 30000,
        responseType: 'arraybuffer',
        method: 'POST',
        enableChunked: true,
        data: params,
        header: {
          'content-type': 'application/json',
          Authorization: `Bearer ${this.yonghuObj.accessToken}`, // 添加token到header中
        },

        success(res) {
          that.$set(that, 'renderedText', '');
          that.talkList.push(messageObj);
          console.log(res,'resresresres')
        },
        complete() {
          that.isSendLoading = false;
        },
      });

      this.requestTask.onChunkReceived(function (response) {
        const arrayBuffer = response.data;
        const uint8Array = new Uint8Array(arrayBuffer);
        // 使用TextDecoder对Uint8Array进行解码为字符串
         const str = new TextEncoding.TextDecoder('utf-8').decode(uint8Array);
        let regex =str.replace(/data:|event:conversation\.message\.delta|event:conversation\.message|event:conversation\.chat\.completed|event:conversation\.chat\.created|event:conversation\.chat\.in_progress/gm,'');
        let a = '[' + regex + ']';
        let b = a
          .replace(/\s*/g, '')
          .replace(/\}\s*{/g, '},{')
          .replace('event:done"[DONE]"', '');
        try {
          let data = JSON.parse(b);
          data.forEach((item) => {
            if (item &&  item.type === 'answer') {
              message += item.content;
              that.$set(that, 'renderedText', message);
              let htmlString = '';
              // 判断markdown中代码块标识符的数量是否为偶数
              if (message.split('```').length % 2) {
                let content = message;
                if (content[content.length - 1] != '\n') {
                  content += '\n';
                }
                htmlString = content;
              } else {
                htmlString = message;
              }
              that.$set(that, 'renderedText', htmlString);
              messageObj = {
                ...item,
                content: htmlString,
                image: imageUrl,
                contentCopy: message,
              };
              that.shengChengObj = Object.assign({}, messageObj);
            }
          });
        } catch (e) {
          console.error('JSON.parse error:', e, b);
        }
      });
    },

坑3(转化响应内容):返回的内容使用下面代码转完之后如下图,需要拿到content内容,(我用的是v2接口的截图,v3因为需求问题我又改成了非流式)

为了拿到响应的文字,需要进行JSON.parse的转化,转化过程中各种报错,因为相应的内容有很多不符合JSON.parse转化格式,而且有的时候一突 突出来,每个接口返回内容还不一样,所以需要根据返回的内容使用javaScript的方法进行处理,我这里使用的是正则和replace

坑4(内容拼接):因为对话模式是数组格式,在数组中实现打印机效果需要push,push有个问题就是会有多条,还需要各种处理,所以我就用了另一个办法,使用renderedText变量进行拼接,当onChunkReceived在在输出的时候,页面显示renderedText变量,当响应完成,在走到success时,对完成的那一条进行push,这样可以实现无缝拼接。

以上就是整个请求的流程所遇见的问题,欢迎来讨论,有没有更简单的方法!!

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值