前两天对接微信小程序ai的时候用到了stream流式请求。
先说一下个人理解的流式请求是什么吧,流式请求就是持续接收数据的请求,一般用post。
一般在传输大文件或者大数据,实时数据传输等等场景,这种方式可以节省内存。
这篇文章就是用到了实时数据传输,把ai回复的文字实时展示在客户端,可以实现打字机的效果。
我这里用的是硅基流动的api接口。
//声明一个接收二进制的变量,utf-8表示接收utf-8的编码。后续要这个变量来接收数据和转换数据
const utf8Decoder = new TextDecoder('utf-8')
//1:用uni.request发送请求,再声明一个变量接收它。
const requestTsk = uni.request({
url: url,
method: 'POST',
//开启分块传输数据,这个一定要开,不开的话后续无法进行。
enableChunked: true,
header: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + apiKey,
//这个请求头告诉服务器前端要接收stream的数据流。可写可不写。
'Accept': 'text/event-stream'
},
data: {
//模型配置
model: SILICONFLOW_CONFIG.model,
//对话列表
messages: apiMessages,
max_tokens: SILICONFLOW_CONFIG.maxTokens,
// 这个是硅基流动开启stream的配置,只做参考。
stream: true
},
success: (_res: UniNamespace.RequestSuccessCallbackResult) => {
//3.这个success回调表示流式请求已经结束,这里只做 UTF-8 解码收尾 + 空内容兜底 + 关 loading
//这里是最后再转码一次,由于一个中文汉字占3个字节,
所以有可能导致utf8Decoder里最后不是的一整个中文,可能是最后一个中文的一个字节,
由于解码器在收到不是完整中文字节的时候会先暂存字节,所以就会导致最后这个字节还处于暂存状态,
这行代码的意思就是让解码器把最后的一个字节吐出来,
然后再按照utf-8的标准解析为正常的文本字符串。stream: false是声明流式请求结束。
const tail = utf8Decoder.decode(new Uint8Array(0), { stream: false })
},
fail: (err: UniNamespace.GeneralCallbackResult) => {
// 请求失败:有占位则改占位,否则新追加一条错误 AI 消息
const msg = (err.errMsg != null && err.errMsg.length > 0) ? err.errMsg : '网络请求失败,请检查网络与 API 配置'
if (streamMsgId > 0) {
updateMessageById(streamMsgId, (prev) => {
return {
id: prev.id,
text: msg,
sender: prev.sender,
timestamp: prev.timestamp,
showThinking: false,
reasoning: undefined,
reasoningExpanded: undefined
}
})
} else {
appendAIMessage(msg)
}
uni.showToast({ title: msg, icon: 'none' })
isTyping.value = false
isAwaitingReply.value = false
scrollToBottom()
}
})
2.监听分块传输的数据流,
requestTsk.onChunkReceived((res) => {
if (res.data == null) return
let chunkText = ''
//由于用的是ts,这里先做一层声明,其实不写也行,这么写只不过是更加规范一些,而且提前已经断言了res.data是ArrayBuffer类型。
const uint8Array = new Uint8Array(res.data as ArrayBuffer)
//用decode把二进制数据转换为正常文本。stream:true表示这是一个持续的数据流。
chunkText = utf8Decoder.decode(uint8Array, { stream: true })
//这里log出来的chunkText就是解析完的纯文本请求数据,例如:"data:xxx",真正的数据还要根据情况后续自己去解析。
console.log(chunkText,'侦听流式二进制数据')
})

255

被折叠的 条评论
为什么被折叠?



