提交 81bba47a 编写于 作者: DCloud_JSON's avatar DCloud_JSON

1.0.3

- 新增 提供了商业化能力,与uni-ai对话消耗积分。积分可通过看[激励视频广告](https://uniapp.dcloud.net.cn/component/ad-rewarded-video.html)获得。
- 优化 根据配置的llm服务商以及是否开启流式响应,自动处理是否逐字返回
- 修复 llm服务商为openai时,内容换行位置不正确的问题
- 修复 消息发出后uni-ai回复未完成时,点击清空后没有终止会话,引起卡在ai正在回复中的问题
- 修复 流式响应模式 uni-ai回复的代码块不完整时 内容会出现多余的字符(<span class="cursor">|</span>)的问题
- 修复 服务端超时等错误时,客户端卡在ai正在回复中的问题
上级 2a5d4ce4
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
}); });
} }
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
if(adpid.config){ if(config.adpid){
uniCloud.initSecureNetworkByWeixin() uniCloud.initSecureNetworkByWeixin()
} }
// #endif // #endif
......
...@@ -225,6 +225,9 @@ module.exports = async (obj) => { ...@@ -225,6 +225,9 @@ module.exports = async (obj) => {
请参考文档:[云函数通过https访问其他服务器时出现“certificate has expired”](faq.md#lets-encrypt-cert) 请参考文档:[云函数通过https访问其他服务器时出现“certificate has expired”](faq.md#lets-encrypt-cert)
## 已知问题
- App-Vue3 使用highlight.js 因特殊正则引起报错,导致消息内容出错
## 其他 ## 其他
DCloud基于`uni-ai`提供了很多开源模板,除了本项目`uni-ai-chat`,还有: DCloud基于`uni-ai`提供了很多开源模板,除了本项目`uni-ai-chat`,还有:
......
## 1.0.3(2023-04-27)
- 新增 提供了商业化能力,与uni-ai对话消耗积分。积分可通过看[激励视频广告](https://uniapp.dcloud.net.cn/component/ad-rewarded-video.html)获得。
- 优化 根据配置的llm服务商以及是否开启流式响应,自动处理是否逐字返回
- 修复 llm服务商为openai时,内容换行位置不正确的问题
- 修复 消息发出后uni-ai回复未完成时,点击清空后没有终止会话,引起卡在ai正在回复中的问题
- 修复 流式响应模式 uni-ai回复的代码块不完整时 内容会出现多余的字符(<span class="cursor">|</span>)的问题
- 修复 服务端超时等错误时,客户端卡在ai正在回复中的问题
## 1.0.2(2023-04-26)
- 修改错误的HBuilderX版本要求的提示
## 1.0.1(2023-04-25) ## 1.0.1(2023-04-25)
- 新增内容安全识别 - 新增内容安全识别
- 不再提供stream设置ui,自动根据是否开通并启用uni-push设置 - 不再提供stream设置ui,自动根据是否开通并启用uni-push设置
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
<script> <script>
import MarkdownIt from '@/lib/markdown-it.min.js'; import MarkdownIt from '@/lib/markdown-it.min.js';
import hljs from "@/lib/highlight/highlight.min.js"; import hljs from "@/lib/highlight/highlight.min.js";
// import hljs from "highlight.js"; // import hljs from "highlight.js";
// import parseHtml from '@/lib/html-parser.js'; // import parseHtml from '@/lib/html-parser.js';
...@@ -94,7 +95,7 @@ ...@@ -94,7 +95,7 @@
if(this.md.split("```").length%2){ if(this.md.split("```").length%2){
return markdownIt.render(this.md + ' <span class="cursor">|</span>'); return markdownIt.render(this.md + ' <span class="cursor">|</span>');
}else{ }else{
return markdownIt.render(this.md) + ' <span class="cursor">|</span>'; return markdownIt.render(this.md) + ' \n <span class="cursor">|</span>';
} }
}, },
nodes() { nodes() {
......
...@@ -62,6 +62,9 @@ ...@@ -62,6 +62,9 @@
<script> <script>
import config from '@/config.js'; import config from '@/config.js';
const {adpid} = config const {adpid} = config
let sseChannel = false;
// 是否通过回调,当用户点击清空后应当跳过前一次请求的回调
let skip_callback = false;
export default { export default {
data() { data() {
return { return {
...@@ -76,6 +79,12 @@ ...@@ -76,6 +79,12 @@
}, },
computed: { computed: {
inputBoxDisabled() { inputBoxDisabled() {
console.log('inputBoxDisabled',{
"sseIndex":this.sseIndex,
"length":this.msgList.length,
"length2":this.msgList.length%2
});
if (this.sseIndex !== 0) { if (this.sseIndex !== 0) {
return true return true
} }
...@@ -180,6 +189,9 @@ ...@@ -180,6 +189,9 @@
}, },
updateLastMsg(param){ updateLastMsg(param){
let length = this.msgList.length let length = this.msgList.length
if(length === 0){
return
}
let lastMsg = this.msgList[length - 1] let lastMsg = this.msgList[length - 1]
if(typeof param == 'function'){ if(typeof param == 'function'){
...@@ -323,7 +335,7 @@ ...@@ -323,7 +335,7 @@
console.log('send to ai messages:', messages); console.log('send to ai messages:', messages);
let sseChannel = false;
if(this.stream){ if(this.stream){
sseChannel = new uniCloud.SSEChannel() // 创建消息通道 sseChannel = new uniCloud.SSEChannel() // 创建消息通道
// console.log('sseChannel',sseChannel); // console.log('sseChannel',sseChannel);
...@@ -338,7 +350,7 @@ ...@@ -338,7 +350,7 @@
this.showLastMsg() this.showLastMsg()
} else { } else {
this.updateLastMsg(lastMsg=>{ this.updateLastMsg(lastMsg=>{
lastMsg.content += "\n" + message lastMsg.content += message
}) })
this.showLastMsg() this.showLastMsg()
} }
...@@ -361,7 +373,7 @@ ...@@ -361,7 +373,7 @@
await sseChannel.open() // 等待通道开启 await sseChannel.open() // 等待通道开启
} }
skip_callback = false
const uniAiChat = uniCloud.importObject("uni-ai-chat",{ const uniAiChat = uniCloud.importObject("uni-ai-chat",{
customUI:true customUI:true
}) })
...@@ -373,6 +385,8 @@ ...@@ -373,6 +385,8 @@
this.updateLastMsg({state:100}) this.updateLastMsg({state:100})
if (!sseChannel) { if (!sseChannel) {
// console.log(res, res.reply); // console.log(res, res.reply);
// 判断长度,防止请求未返回时,历史对话已被清空。引起对话顺序错误 导致 对话输入框卡住
if(!skip_callback){
this.msgList.push({ this.msgList.push({
isAi: true, isAi: true,
content: res.data.reply, content: res.data.reply,
...@@ -381,10 +395,19 @@ ...@@ -381,10 +395,19 @@
insufficientPoints:res.data.insufficientPoints insufficientPoints:res.data.insufficientPoints
}) })
this.showLastMsg() this.showLastMsg()
}else{
console.log('用户点击了清空按钮,跳过前一次请求的回调',res.data.reply);
}
} }
}) })
.catch(e => { .catch(e => {
console.log(e); console.log(e);
let l = this.msgList.length
console.log(l,this.msgList[l-1]);
if(l && sseChannel && this.msgList[l-1].isAi){
this.sseIndex = 0
}
this.updateLastMsg({state:-100}) this.updateLastMsg({state:-100})
uni.showModal({ uni.showModal({
content: JSON.stringify(e.message), content: JSON.stringify(e.message),
...@@ -425,6 +448,11 @@ ...@@ -425,6 +448,11 @@
content: '本操作不可撤销', content: '本操作不可撤销',
complete: (e) => { complete: (e) => {
if (e.confirm) { if (e.confirm) {
if(sseChannel){
sseChannel.close()
}
skip_callback = true
this.sseIndex = 0
this.msgList = [] this.msgList = []
} }
} }
......
...@@ -174,7 +174,6 @@ module.exports = { ...@@ -174,7 +174,6 @@ module.exports = {
sseChannel = false, sseChannel = false,
llm llm
}) { }) {
const llmManager = uniCloud.ai.getLLMManager(llm) const llmManager = uniCloud.ai.getLLMManager(llm)
let res = await llmManager.chatCompletion({ let res = await llmManager.chatCompletion({
...chatCompletionOptions, ...chatCompletionOptions,
...@@ -186,18 +185,22 @@ module.exports = { ...@@ -186,18 +185,22 @@ module.exports = {
let reply = "" let reply = ""
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const channel = uniCloud.deserializeSSEChannel(sseChannel) const channel = uniCloud.deserializeSSEChannel(sseChannel)
// 判断如果是open-ai按字返回,否则按行返回
if(llm && llm.provider && llm.provider == "openai"){
res.on('message', async (message) => { res.on('message', async (message) => {
// await channel.write(message) reply += message
await channel.write(message)
// console.log('---message----', message) // console.log('---message----', message)
}) })
}else{
res.on('line', async (line) => { res.on('line', async (line) => {
await channel.write(reply? ("\n\n " + line) : line)
reply += line reply += line
await channel.write(line)
// console.log('---line----', line) // console.log('---line----', line)
}) })
}
res.on('end', async () => { res.on('end', async () => {
// console.log('---end----',reply) // console.log('---end----',reply)
messages.push({ messages.push({
"content": reply, "content": reply,
"role": "assistant" "role": "assistant"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册