<script setup lang='ts'>
|
import { computed, ref,watch } from 'vue'
|
import { useRoute } from 'vue-router'
|
import { useChat } from '../chat/hooks/useChat'
|
import { homeStore, useChatStore } from '@/store'
|
import { getInitChat, mlog, subModel,getSystemMessage , localSaveAny, canVisionModel
|
,isTTS, subTTS, file2blob, whisperUpload, getHistoryMessage, checkDisableGpt4, chatSetting, isCanBase64Model, } from '@/api'
|
//import { isNumber } from '@/utils/is'
|
import { useMessage } from "naive-ui";
|
import { t } from "@/locales";
|
|
const emit = defineEmits(['finished']);
|
const { addChat , updateChatSome } = useChat()
|
const chatStore = useChatStore()
|
const st=ref({uuid:'1002', index:-1, chatType:0, appId:'' });
|
const controller = ref<AbortController>( );;// new AbortController();
|
const dataSources = computed(() => chatStore.getChatByUuid(+st.value.uuid))
|
const ms= useMessage();
|
const textRz= ref<string[]>([]);
|
const goFinish= ( )=>{
|
//let dindex = st.value.index>=0? st.value.index : dataSources.value.length - 1;
|
//return ;
|
updateChatSome( +st.value.uuid, st.value.index , { dateTime: new Date().toLocaleString(),loading: false })
|
//scrollToBottom();
|
emit('finished');
|
|
homeStore.setMyData({act:'scrollToBottomIfAtBottom'});
|
mlog('🐞 goFinish2',st.value.uuid);
|
// setTimeout(() => {
|
|
// if(textRz.value.length>0 ) textRz.value = [];
|
// }, 200 );
|
}
|
|
const getMessage= async (start=1000,loadingCnt=3)=>{
|
return getHistoryMessage(dataSources.value,loadingCnt,start);
|
}
|
watch( ()=>textRz.value, (n)=>{
|
//mlog('🐞 textRz',n);
|
if(n.length==0) return ;
|
updateChatSome( +st.value.uuid, st.value.index , { dateTime: new Date().toLocaleString(),text: n.join('') })
|
//scrollToBottom();
|
homeStore.setMyData({act:'scrollToBottomIfAtBottom'})
|
//homeStore.setMyData({act:'scrollToBottom'})
|
},{deep:true})
|
const { uuid } = useRoute().params as { uuid: string }
|
watch(()=>homeStore.myData.act, async (n)=>{
|
|
if(n=='gpt.submit' || n=='gpt.whisper' ){
|
|
const dd:any = homeStore.myData.actData;
|
|
let uuid2 = dd.uuid?? uuid;
|
st.value.uuid = uuid2 ;
|
st.value.chatType = dd.chatType;
|
st.value.appId = dd.appId??'';
|
const chatSet = new chatSetting( +st.value.uuid );
|
const nGptStore = chatSet.getGptConfig();
|
mlog('gpt.submit', dd , dd.uuid, nGptStore ) ;
|
let model = nGptStore.model ;//gptConfigStore.myData.model
|
|
if(checkDisableGpt4( model )){
|
ms.error( t('mj.disableGpt4') );
|
return false;
|
}
|
|
let promptMsg = getInitChat(dd.prompt );
|
if( dd.fileBase64 && dd.fileBase64.length>0 ){
|
if( !canVisionModel(model) ) model='gpt-image';
|
|
try{
|
let images= await localSaveAny( JSON.stringify( dd.fileBase64) ) ;
|
mlog('key', images );
|
promptMsg.opt= {images:[images]}
|
}catch(e){
|
mlog('localSaveAny error',e);
|
}
|
}
|
if( n=='gpt.whisper'){
|
//model='whisper-1';
|
try{
|
let bb= await file2blob( dd.file );
|
// bb.blob
|
let lkey = await localSaveAny( bb ) ;
|
mlog('key', lkey );
|
promptMsg.opt= { lkey }
|
promptMsg.text='Loading...'
|
promptMsg.model='whisper-1';
|
if(dd.duration && dd.duration>0 ){
|
promptMsg.text=`${t('mj.lang')} ${dd.duration.toFixed(2)}s`;
|
}
|
addChat( +uuid2, promptMsg );
|
homeStore.setMyData({act:'scrollToBottom'});
|
}catch(e){
|
mlog('localSaveAny error',e);
|
ms.error( t('mj.noSupperChrom') );
|
return ;
|
}
|
|
try{
|
const formData = new FormData( );
|
formData.append('file',dd.file );
|
formData.append('model', 'whisper-1');
|
const whisper= await whisperUpload( formData);
|
mlog('whisper 内容>> ', whisper );
|
let opt={duration:0,...promptMsg.opt };
|
opt.duration= dd.duration??0;
|
updateChatSome( +uuid2, dataSources.value.length-1, {text:whisper.text,opt } );
|
dd.prompt= whisper.text;
|
//return ;
|
}catch(e){
|
updateChatSome( +uuid2, dataSources.value.length-1, {text:`${t('mj.fail')}:${e}` } );
|
return ;
|
}
|
|
}else{
|
addChat( +uuid2, promptMsg );
|
homeStore.setMyData({act:'scrollToBottom'});
|
}
|
|
let outMsg: Chat.Chat={
|
dateTime: new Date().toLocaleString(),
|
text: t('mj.thinking') ,//'思考中...',
|
loading: true,
|
inversion: false,
|
error: false,
|
conversationOptions: null,
|
requestOptions: { prompt: dd.prompt, options: { } },
|
uuid:+uuid2,
|
model ,
|
myid: `${Date.now()}`
|
}
|
// if(gptConfigStore.myData.gpts){
|
// outMsg.logo= gptConfigStore.myData.gpts.logo ;
|
// }
|
// const chatSet = new chatSetting( +st.value.uuid );
|
// const nGptStore = chatSet.getGptConfig() ;
|
//chatSet
|
if( nGptStore.gpts ){
|
outMsg.logo= nGptStore.gpts.logo ;
|
}
|
addChat( +uuid2, outMsg )
|
st.value.index= dataSources.value.length - 1;
|
if(textRz.value.length>=0) textRz.value = [ ];
|
|
homeStore.setMyData({act:'scrollToBottom'})
|
let historyMesg= await getMessage();
|
mlog('historyMesg', historyMesg );
|
//return ;
|
// let message= [ { "role": "system", "content": getSystemMessage( +uuid2) },
|
// ...historyMesg ];
|
let message= [...historyMesg ];
|
|
if( dd.fileBase64 && dd.fileBase64.length>0 ){
|
if(isCanBase64Model(model)){
|
let obj={
|
"role": "user",
|
"content": [] as any
|
}
|
obj.content.push({ "type": "text", "text": dd.prompt });
|
dd.fileBase64.forEach((f:any)=>{
|
obj.content.push({ "type": "image_url", "image_url": {url:f } });
|
});
|
message.push(obj);
|
}else{
|
let cc= dd.prompt;
|
//附件需要时远程的图片链接 或者文件 链接
|
let arr = dd.fileBase64.filter( (ff:string)=>ff.indexOf('http')>-1);
|
if(arr.length>0) cc = arr.join(' ')+' '+ cc ;
|
message.push({ "role": "user", "content": cc })
|
}
|
}else{
|
message.push({ "role": "user", "content": dd.prompt })
|
}
|
let opt={};
|
if( n=='gpt.whisper'){
|
opt= {
|
file: dd.file
|
}
|
}
|
|
submit(model,message,opt);
|
|
}else if(n=='abort'){
|
controller.value && controller.value.abort();
|
}else if(n=='gpt.resubmit'){
|
// if(checkDisableGpt4(gptConfigStore.myData.model)){
|
// ms.error( t('mj.disableGpt4') );
|
// return false;
|
// }
|
const dd:any = homeStore.myData.actData;
|
let uuid2 = dd.uuid?? uuid;
|
st.value.uuid = uuid2 ;
|
st.value.index = +dd.index;
|
|
mlog('gpt.resubmit', dd ) ;
|
let historyMesg= await getMessage( (+dd.index)-1,1 ); //
|
mlog('gpt.resubmit historyMesg', historyMesg );
|
let nobj = dataSources.value[ dd.index ];
|
//mlog('gpt.resubmit model', nobj.model );
|
let model = nobj.model as string
|
|
if(checkDisableGpt4( model )){
|
ms.error( t('mj.disableGpt4') );
|
return false;
|
}
|
//return ;
|
if(['whisper-1','midjourney'].indexOf(model)>-1){
|
ms.error( t('mj.noSuppertModel') );
|
return;
|
}
|
|
controller.value = new AbortController();
|
let message= [ { "role": "system", "content": getSystemMessage(+st.value.uuid ) },
|
...historyMesg ];
|
textRz.value=[];
|
|
submit(model, message);
|
|
}else if(n=='gpt.ttsv2'){
|
const actData:any = homeStore.myData.actData;
|
mlog('gpt.ttsv2',actData );
|
st.value.index= actData.index;
|
st.value.uuid= actData.uuid;
|
ms.info( t('mj.ttsLoading'));
|
const chatSet = new chatSetting( +st.value.uuid );
|
const nGptStore = chatSet.getGptConfig() ;
|
|
subTTS({model:'tts-1',input: actData.text , voice:nGptStore.tts_voice }).then(d=>{
|
ms.success( t('mj.ttsSuccess'));
|
mlog('subTTS',d );
|
//d.player.play();
|
//textRz.value.push('ok');
|
updateChatSome( +st.value.uuid, st.value.index
|
, {
|
dateTime: new Date().toLocaleString(),loading: false
|
|
,opt:{duration:d.duration,lkey:d.saveID }
|
});
|
// goFinish();
|
setTimeout(() => {
|
homeStore.setMyData({act:'playtts',actData:{ saveID:d.saveID} });
|
}, 100);
|
}).catch(e=>{
|
let emsg = (JSON.stringify( e.reason? JSON.parse( e.reason ):e,null,2));
|
if(e.message!='canceled' && emsg.indexOf('aborted')==-1 ) textRz.value.push("\n"+t('mjchat.failReason')+" \n```\n"+emsg+"\n```\n");
|
//goFinish();
|
});
|
}
|
})
|
|
const submit= (model:string, message:any[],opt?:any)=>{
|
mlog('提交Model', model );
|
const chatSet = new chatSetting( +st.value.uuid );
|
const nGptStore = chatSet.getGptConfig() ;
|
controller.value = new AbortController();
|
if(model=='whisper-1'){
|
|
//mlog('whisper-12323',opt );
|
const formData = new FormData( );
|
formData.append('file', opt.file );
|
formData.append('model', 'whisper-1');
|
|
//GptUploader('/v1/audio/transcriptions',formData).then(r=>{
|
whisperUpload( formData).then(r=>{
|
//mlog('语音识别成功', r );
|
textRz.value.push(r.text);
|
goFinish();
|
}).catch(e=>{
|
let emsg =( ( e.message?? JSON.stringify(e)) );
|
textRz.value.push("\n"+t('mj.failOcr')+":\n```\n"+emsg+"\n```\n");
|
goFinish();
|
});
|
return ;
|
}
|
else if( isTTS(model)){
|
let text = message[message.length-1].content;
|
mlog('whisper-tts', message[message.length-1] , text );
|
subTTS({model,input: text, voice:nGptStore.tts_voice }).then(d=>{
|
mlog('subTTS',d );
|
//d.player.play();
|
//textRz.value.push('ok');
|
updateChatSome( +st.value.uuid, st.value.index
|
, {
|
dateTime: new Date().toLocaleString(),loading: false
|
,text:'ok'
|
,opt:{duration:d.duration,lkey:d.saveID }
|
});
|
goFinish();
|
setTimeout(() => {
|
homeStore.setMyData({act:'playtts',actData:{ saveID:d.saveID} });
|
}, 100);
|
}).catch(e=>{
|
let emsg = (JSON.stringify( e.reason? JSON.parse( e.reason ):e,null,2));
|
if(e.message!='canceled' && emsg.indexOf('aborted')==-1 ) textRz.value.push("\n"+t('mjchat.failReason')+" \n```\n"+emsg+"\n```\n");
|
goFinish();
|
});
|
|
}else{
|
subModel( {message, model,
|
uuid: st.value.uuid //当前会话
|
,onMessage: (d) => {
|
mlog('🐞消息', d)
|
textRz.value.push(d.text)
|
},
|
onError: (e: any) => {
|
mlog('onError', e)
|
let emsg = (JSON.stringify(e.reason ? JSON.parse(e.reason) : e, null, 2))
|
//if(emsg=='{}' ) emsg= JSON.stringify(e );
|
if (e.message != 'canceled' && emsg.indexOf('aborted') == -1) textRz.value.push("\n" + t('mjchat.failReason') + "\n```\n" + emsg + "\n```\n")
|
goFinish()
|
},
|
signal: controller.value.signal,
|
kid: '',
|
chatType: st.value.chatType,
|
appId: st.value.appId
|
}).then(()=>goFinish() ).catch(e=>{
|
if(e.message!='canceled') textRz.value.push("\n"+t('mj.fail')+":\n```\n"+(e.reason??JSON.stringify(e,null,2)) +"\n```\n")
|
goFinish();
|
});
|
}
|
}
|
|
homeStore.setMyData({isLoader:false});
|
</script>
|
<template>
|
|
</template>
|