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

Hd55169796643619 2024-09-06 08:33:02 阅读 99

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

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

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

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

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

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

<code> //请求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',code>

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,这样可以实现无缝拼接。

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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。