diff --git a/changelog.md b/changelog.md index 6078a10571d037b74ead7304d773ceb3a1743444..c84a215ae04455378e10fd618f1e8e85a07a3542 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +## 1.2.5(2023-06-26) +- 修复 流式响应模式 因1.2.4更新引起的: + 1. 响应未完成时,“停止响应”按钮提前隐藏的问题。 + 2. 点击“停止响应”按钮,会延迟执行的问题。 + 3. 不自动滚动到最后一条消息的问题。 ## 1.2.4(2023-06-21) - 更新 改用optimizedMessage模式,即:收到AI响应的事件,基于message事件降频得到,使用此事件可以避免非常频繁的往客户端发送请求,导致部分情况下客户端处理消息卡顿。注意:云端新增于2023年6月21日,HBuilderX本地调试将于下次发版支持。 ## 1.2.3(2023-06-19) diff --git a/package.json b/package.json index 419b35e52e00643b67133df6ff57e64d8f866327..a39a454d8cde894fbd50e584862c74ca8b27eeee 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "id": "uni-ai-chat", "name": "uni-ai-chat", - "version": "1.2.4", + "version": "1.2.5", "description": "基于uni-ai的聊天示例项目,支持流式、支持前文总结,云端一体", "main": "main.js", "scripts": { diff --git a/pages/chat/SliceMsgToLastMsg.js b/pages/chat/SliceMsgToLastMsg.js index c2f4f7606bbd959834501921fbe647103e092e9b..acf9adae083faa5df72f2f60f2729bc6aef27ae1 100644 --- a/pages/chat/SliceMsgToLastMsg.js +++ b/pages/chat/SliceMsgToLastMsg.js @@ -1,32 +1,53 @@ export default class SliceMsgToLastMsg { constructor(arg) { - this.$ = arg + this.$ = arg + //分割显示的速度(毫秒) + this.t = 30 + // 要追加的消息的创建时间 + this.msgCreateTime = false + // 是否立即结束追加 + this.stopAction = false } // 所有待插入的消息数据 msgs = '' // 是否正在分割消息数据 sliceMsgIng = false - addMsg(msg) { + addMsg(msg) { // console.log('msg', msg); this.msgs += msg if (this.sliceMsgIng === false) { this.sliceMsg() } - } - sliceMsg() { + } + end(){ + this.stopAction = true + } + sliceMsg() { + if(this.stopAction === true){ + return //console.log('被终止'); + } this.sliceMsgIng = true let msg = this.msgs.slice(0, 1) // console.log('msg', msg); // 更新最后一条消息的内容 // console.log('this.$', this.$); - this.$.updateLastMsg(lastMsg => { + this.$.updateLastMsg(lastMsg => { + if(this.msgCreateTime && this.msgCreateTime != lastMsg.create_time){ + return //console.log('要追加的消息不存在了,停止'); + } + this.msgCreateTime = lastMsg.create_time lastMsg.content += msg - }) + }) + this.$.showLastMsg() this.msgs = this.msgs.slice(1) - if (this.msgs.length) { - setTimeout(() => { - this.sliceMsg(this.msgs) - }, 30); + if (this.msgs.length) { + if(this.t){ + setTimeout(() => { + this.sliceMsg(this.msgs) + }, this.t); + }else{ + this.sliceMsg(this.msgs) + } } else { this.sliceMsgIng = false } diff --git a/pages/chat/chat.vue b/pages/chat/chat.vue index e7186d49f84b7d6ef5c0783b52041164d0b0899a..7a6b6098c9f9ad3688d45960773d7eee6ce39a51 100644 --- a/pages/chat/chat.vue +++ b/pages/chat/chat.vue @@ -414,16 +414,17 @@ this.insufficientScore = false this.send() }, - //当消息涉及敏感 removeMsg(index) { - // 如果问题还在回答中需要先关闭 - if (this.sseIndex) { - this.closeSseChannel() - } - + // 成对删除,如果点中的是 ai 回答的内容,index -= 1 if (this.msgList[index].isAi) { index -= 1 } + + // 如果删除的就是正在问的,且问题还在回答中需要先关闭 + if (this.sseIndex && index == this.msgList.length - 2) { + this.closeSseChannel() + } + this.msgList.splice(index,2) }, async beforeSend() { @@ -573,7 +574,7 @@ // console.log('sseChannel',sseChannel); // 将多个字的文本,分割成单个字 分批插入到最末尾的消息中 - let sliceMsgToLastMsg = new SliceMsgToLastMsg(this) + this.sliceMsgToLastMsg = new SliceMsgToLastMsg(this) // 监听message事件 sseChannel.on('message', (message) => { // console.log('on message', message); @@ -584,10 +585,10 @@ this.msgList.push({ isAi: true, content: message, - create_time: Date.now() + create_time: Date.now() }) } else { - sliceMsgToLastMsg.addMsg(message) + this.sliceMsgToLastMsg.addMsg(message) // this.updateLastMsg(lastMsg => { // lastMsg.content += message // }) @@ -600,6 +601,8 @@ // 监听end事件,如果云端执行end时传了message,会在客户端end事件内收到传递的消息 sseChannel.on('end', (e) => { console.log('sse 结束',e) + // 更改“按字分割追加到最后一条消息“的时间间隔为0,即:一次性加载完(不再分割加载) + this.sliceMsgToLastMsg.t = 0 if(e && typeof e == 'object' && e.errCode){ let setLastAiMsgContent = (content)=>{ // console.log(content); @@ -792,7 +795,8 @@ if (sseChannel) { sseChannel.close() // 设置为 false 防止重复调用closeSseChannel时出错 - sseChannel = false + sseChannel = false + this.sliceMsgToLastMsg.end() } // 清空历史网络请求(调用云对象)任务 uniCoTaskList.clear() diff --git a/uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js b/uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js index 553c04dbc7592b8587b87b8bcc15c23d26969e37..00a16a96260d196727363d9e1418219838913399 100644 --- a/uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js +++ b/uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js @@ -270,7 +270,7 @@ module.exports = { let promiseAllRes = await Promise.all(promiseTaskList) - console.log('Promise.all promiseRes',promiseAllRes); + // console.log('Promise.all promiseRes',promiseAllRes); res = { data:{}, errCode:0 @@ -305,8 +305,8 @@ module.exports = { } = config // 如果客户端传了llmModel 就覆盖配置的model if (llmModel) { - if (llmModel.includes('gpt-') && (llm && llm.provider != "openai")) { - throw new Error('错误:LLM的provider不是openai,但model却选了' + llmModel + ';请参考文档:https://uniapp.dcloud.net.cn/uniCloud/uni-ai.html#chat-completion 中model参数的说明') + if (llmModel.includes('gpt-') && (llm && !["azure","openai"].includes(llm.provider))) { + throw new Error('错误:LLM的provider不是openai或azure,但model却选了' + llmModel + ';请参考文档:https://uniapp.dcloud.net.cn/uniCloud/uni-ai.html#chat-completion 中model参数的说明') } chatCompletionOptions.model = llmModel }