响应流数据,在本地云函数,测试没有问题,但在测试环境,线上去链接云端云函数,使用SSEChannel推送数据,当响应超过1分钟后,之后再响应大约三四秒种左右的时间,响应数据就会中断
- 发布:2023-06-21 18:30
- 更新:2023-06-25 09:30
- 阅读:326
SSEChannel的问题
云函数在执行超出1分钟后会被终止,如果有生成非常长的内容的需求可以考虑使用uni-ai计费网关。
流式响应需要云端持续从服务商接收数据并发送给客户端,这需要云函数一直保持运行。如果使用uni-ai计费网关则无需云函数保持运行,在请求发送给DCloud服务器后DCloud服务器会使用推送通道将结果通知给客户端,而云函数可以再继续处理下一个请求或者直接休眠,从而节省大量云函数资源(GBs)。
m***@163.com (作者)
您好,您答复的内容中有“无需云函数保持运行,在请求发送给DCloud服务器后DCloud服务器会使用推送通道将结果通知给客户端”,
这是我的云对象代码,我有使用推送通道将结果通知客户端的,
目前的问题是,大约63秒,64秒时,推送自己就停止了,
当我不使用推送通道的时候,打印是正常的。
let reply = ""
return new Promise(async (resolve, reject) => {
// 反序列化sseChannel
const channel = uniCloud.deserializeSSEChannel(sseChannel)
const res = await openai.createChatCompletion({
model: "gpt-3.5-turbo-16k",
messages,
presence_penalty: 0,
stream: true,
temperature: 0.5
}, {
responseType: "stream"
});
res.data.on("data", async (data) => {
try {
// 对每次推送的数据进行格式化, 得到的是 JSON 字符串、或者 [DONE] 表示流结束
let message = data.toString().trim()
message = message.replace('data: [DONE]', '');
// 将所有"data:"替换为",data:",确保每个"data:"前面都有逗号
message = message.replace(/data:/g, ",data:");
const occurrences = countOccurrences(message, 'data:');
if (occurrences == 1) {
//说明数据正常
message = message.replace(/^,data:/, '');
const parsed = JSON.parse(message);
if (parsed.choices[0].finish_reason == "stop") {
// 结束了
await channel.end()
// 返回处理结果
resolve({
errCode: 0,
"content": reply,
"role": "assistant"
})
} else {
const token = parsed.choices[0].delta.content
reply += token
console.log(token);
await channel.write(token)
}
} else {
//异常结构数据
let parts = message.split(",data:");
// 使用 map() 方法对每个部分进行处理并创建新的对象
let result = parts.map(part => {
if (part.trim() !== "") {
return JSON.parse(part.trim());
}
}).filter(Boolean)
for (let item of result) {
if (item.choices[0].finish_reason == "stop") {
// 结束了
await channel.end();
// 返回处理结果
resolve({
errCode: 0,
content: reply,
role: "assistant"
});
} else {
const token = item.choices[0].delta.content;
reply += token;
console.log(token);
await channel.write(token);
}
}
}
} catch (e) {
//TODO handle the exception
reject(e)
}
})
// 返回错误
res.data.on('error', async (error) => {
console.error('---error----', error)
reject(error)
})
})
m***@163.com (作者)
有采用uniapp官方的uni-ai-chat,也是存在这个问题,于是手写了下直接请求openai的方式,通过打印,发现问题出现在推送通道上,云函数超过一分钟,推送通道是可以保持继续执行的,但继续推送几秒钟后,直接就休止了(采用的model是“gpt-3.5-turbo-16k”),即不执行err的监听,也不执行end的监听。
2023-06-25 09:42
m***@163.com (作者)
客户端代码,是这样的, sseChannel.on('end', message => {
// 监听end事件,如果云端执行end时传了message,会在客户端end事件内收到传递的消息
console.log('on end', message)
this.status = 'no-more'
//执行SSE关闭事件
this.close()
})
2023-06-25 09:57