参考文章:https://blog.csdn.net/qq_41298763/article/details/144560606
简单来说,就是我们持续接收,api持续响应,每次返回一部分数据(如一两个字),然后前端逐步展示,直到全部返回。
这样会比单次返回更加流畅,用户体验更好。
折腾了好久,最后感觉也没什么好说的,直接粘代码吧,都在代码里了。
fetch(`${apiUrl}/api/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestData)
})//post请求,requestData包含请求参数,比如message、stream
.then(response => {
const reader = response.body.getReader();
const textDecoder = new TextDecoder("utf-8");
//读取字节流,解码为utf-8字符串
//这两个工具不放入readStream是避免每次重新创建,可被重用
let fullResponse = ''; // 用于存储完整的 AI 回复内容
function readStream() {//这里只是把方法定义了,之后才是执行
reader.read().then(({ done, value }) => {
if (done) {
/*
Ai回复完成的逻辑
具体可以有启用输入栏,Ai下次回复换行之类
*/
return;
}
const chunk = textDecoder.decode(value, { stream: true });
const data = JSON.parse(chunk);
//接收字节流,解码为json数据
if (data.message) {
fullResponse += data.message.content; // 将内容逐字累加到 fullResponse
// 更新最后一条 AI 回复为最新内容
replaceLastAIMessage(`AI: ${fullResponse}`);
//这个逻辑我就不粘了,就是一个文本替换
}
readStream();//递归调用,继续读取字节流
});
}
readStream();//启动递归调用,开始读取字节流
})
遇到的问题
ai回复过慢
如果给了Ai过多系统消息,会加载的很慢,一场对话的开始需要将近1分钟,并且如果用户隔一段时间不回复,又会重新加载系统消息。
这个加载过程应该是在服务端也就是我自己的电脑上完成的,因为在不同gui调用同一个api不需要重新加载
ai历史记录的处理
这个历史记录应该既包含用户的消息,也包含ai的回复。
这个json上传的数据是一个数组,包含user和ai等的回复,我自己创建一个数组,然后每次把user和ai的回复推进数组,但发现一旦ai回复在数组里,ai就不回答了。
而使用‘ai:’这种方式明显效果不如隔壁,本地ai错以为每次对话都是新的开始。
也许的确是这样,但我们得让它把这种效果模拟出来。
没能有一个差强人意的效果,所以我先去了这一部分。
跨域请求
即使是同一个域名下的请求,也会遇到跨域问题,解决方法是:
- 后端设置响应头,允许跨域请求
res.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有来源访问
看着玩玩就好了,没试过,最好的办法还是得发送请求时避免跨域问题,比如说把文件挂载到本地服务器
更多:https://blog.csdn.net/jined/article/details/120693745
返回异常或错误
在浏览器控制台网络,刷新,打开标红的异常文件查看响应,有时候会详细标注错误,比如语法错误,格式错误
最后是一个流式返回的效果
此方悬停