From 7c3871f72a04e3bb3466ed786d0b33d82d516741 Mon Sep 17 00:00:00 2001 From: li-shengren-123456 Date: Thu, 6 Mar 2025 12:04:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=89=8D=E7=AB=AFjson?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E6=8E=A5=E5=8F=A3conversation=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=B0=83=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/conversation.ts | 341 +++++++++--------- .../dialogue/components/DialogueAside.vue | 6 +- 2 files changed, 185 insertions(+), 162 deletions(-) diff --git a/src/store/conversation.ts b/src/store/conversation.ts index e88e686..b6d3390 100644 --- a/src/store/conversation.ts +++ b/src/store/conversation.ts @@ -24,23 +24,24 @@ import { ElMessageBox } from 'element-plus'; import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'; import { storeToRefs } from 'pinia'; import { Application } from 'src/apis/paths/type'; -import $bus from 'src/bus/index' +import $bus from 'src/bus/index'; +import { decode } from 'punycode'; const STREAM_URL = '/api/chat'; const newStreamUrl = 'api/chat'; let controller = new AbortController(); -export var txt2imgPath = ref(""); +export var txt2imgPath = ref(''); export var echartsObj = ref({}); export var echartsHas = ref(false); var excelPath = ref(''); const features = { max_tokens: 2048, context_num: 2, -} +}; function getCookie(name: string) { - let matches = document.cookie.match(new RegExp( - "(?:^|; )" + name.replace(/([.$?*|{}()\[\]\\/+^])/g, '\\$1') + "=([^;]*)" - )); + let matches = document.cookie.match( + new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()\[\]\\/+^])/g, '\\$1') + '=([^;]*)'), + ); return matches ? decodeURIComponent(matches[1]) : undefined; } @@ -79,11 +80,11 @@ export const useSessionStore = defineStore('conversation', () => { * 请求流式数据 * @param params * { -**/ + **/ const getStream = async ( params: { question: string; - user_selected_app?: any, + user_selected_app?: any; conversationId?: string; qaRecordId?: string; user_selected_flow?: string; @@ -91,7 +92,7 @@ export const useSessionStore = defineStore('conversation', () => { params?: any; type?: any; }, - ind?: number + ind?: number, ): Promise => { const language = localStorage.getItem('localeLang') === 'EN' ? 'en' : 'zh'; const { currentSelectedSession } = useHistorySessionStore(); @@ -108,11 +109,11 @@ export const useSessionStore = defineStore('conversation', () => { try { let resp; let pp = {}; - if(params.params && typeof params.params === 'object'){ + if (params.params && typeof params.params === 'object') { pp = params.params; - }else if(params.params && typeof params.params === 'string'){ + } else if (params.params && typeof params.params === 'string') { pp = Object(JSON.parse(params.params)); - }else{ + } else { pp = {}; } if (params.user_selected_flow) { @@ -129,13 +130,13 @@ export const useSessionStore = defineStore('conversation', () => { conversationId: params.conversationId, groupId: params.groupId, // record_id: params.qaRecordId, - app:{ - appId:params.user_selected_app[0], + app: { + appId: params.user_selected_app[0], flowId: params.user_selected_flow, params: pp, - auth:{}, + auth: {}, }, - features:features, + features: features, }), }); } else { @@ -148,7 +149,7 @@ export const useSessionStore = defineStore('conversation', () => { body: JSON.stringify({ app: { params: {}, - appId:params.user_selected_app[0], + appId: params.user_selected_app[0], flowId: params.user_selected_flow, }, question: params.question, @@ -156,10 +157,8 @@ export const useSessionStore = defineStore('conversation', () => { debug: true, }), }); - } - } - else if (params.user_selected_app) { + } else if (params.user_selected_app) { resp = await fetch(STREAM_URL, { signal: controller.signal, method: 'POST', @@ -172,18 +171,18 @@ export const useSessionStore = defineStore('conversation', () => { language, groupId: params.groupId, // record_id: params.qaRecordId, - app:{ - appId:params.user_selected_app[0], - flowId: "", + app: { + appId: params.user_selected_app[0], + flowId: '', params: pp, - auth:{}, + auth: {}, }, - features:features, + features: features, }), }); - } else if(false){ + } else if (false) { //写传参数情况 - }else { + } else { resp = await fetch(STREAM_URL, { signal: controller.signal, keepalive: true, @@ -196,13 +195,13 @@ export const useSessionStore = defineStore('conversation', () => { language, groupId: params.groupId, // record_id: params.qaRecordId, - app:{ - appId:"", - flowId: "", + app: { + appId: '', + flowId: '', params: {}, - auth:{}, + auth: {}, }, - features:features, + features: features, }), }); } @@ -225,6 +224,7 @@ export const useSessionStore = defineStore('conversation', () => { echartsObj.value = {}; txt2imgPath.value = ''; let workFlowId = ''; // 这里存储工作流调试对话的判断id + let addItem = ''; while (isEnd) { if (isPaused.value) { // 手动暂停输出 @@ -232,12 +232,7 @@ export const useSessionStore = defineStore('conversation', () => { break; } const { done, value } = await reader.read(); - const decodedValue = decoder.decode(value, { stream: true }); - const isLegal = judgeMessage(answerIndex, decodedValue); - if (!isLegal) { - isEnd = false; - break; - } + const decodedValue = addItem + decoder.decode(value, { stream: true }); if (done) { if (excelPath.value.length > 0) { @@ -254,81 +249,84 @@ export const useSessionStore = defineStore('conversation', () => { break; } // 这里删除了\n\n - const lines = decodedValue.split('\n\n').filter((line) => line.startsWith('data: {')); - lines.forEach((line) => { + const lines = decodedValue.split('\n\n').filter(line => line.startsWith('data: {')); + // 获取最后一个 + const lastLine = lines[lines.length - 1] || {}; + if (!judgeJson(lastLine.toString())) { + addItem = lastLine.toString(); + lines.splice(lines.length - 1, 1); + } else { + addItem = ''; + } + // pa + lines.forEach(line => { // 这里json解析 const message = Object(JSON.parse(line.replace(/^data:\s*/, '').trim())); - if( 'metadata' in message){ - if(conversationItem.metadata?.time item.id === message.flow?.stepId); if (target) { - target.data.output = message.content + target.data.output = message.content; target.status = message.flow?.stepStatus; // 工作流添加每阶段的时间耗时 target['costTime'] = message.metadata?.timeCost; - if(message.flow.step_status === "error"){ + if (message.flow.step_status === 'error') { conversationItem.flowdata.status = message.flow?.stepStatus; } } - } - else if(message["event"] === "flow.stop") { + } else if (message['event'] === 'flow.stop') { //时间流结束 let flow = message.content.flow; if (params.type) { @@ -338,41 +336,40 @@ export const useSessionStore = defineStore('conversation', () => { title: i18n.global.t('flow.flow_end'), progress: flow?.stepProgress, status: message.flow?.stepStatus, - display:true, - data:conversationItem?.flowdata?.data, + display: true, + data: conversationItem?.flowdata?.data, }; - }else if(message.content.type !== "schema"){ + } else if (message.content.type !== 'schema') { conversationItem.flowdata?.data[0].push({ - id:"end", - title:"end", - status:message.flow?.stepStatus, - data:{ - input:message.content, - } - }) + id: 'end', + title: 'end', + status: message.flow?.stepStatus, + data: { + input: message.content, + }, + }); conversationItem.flowdata = { id: flow?.stepId, title: i18n.global.t('flow.flow_end'), progress: flow?.stepProgress, - status:"success", - display:true, - data:conversationItem.flowdata.data, + status: 'success', + display: true, + data: conversationItem.flowdata.data, }; - if(message.content.type === 'chart'){ + if (message.content.type === 'chart') { conversationItem.echartsObj = message.content.data; } - }else{ + } else { conversationItem.paramsList = message.content.data; conversationItem.flowdata.title = i18n.global.t('flow.flow_params_error'); - conversationItem.flowdata.status = "error"; + conversationItem.flowdata.status = 'error'; conversationItem.paramsList = message.content.data; } - - } + } } }); // 将lines传递给workflow-以更新工作流节点的状态 - if(params.user_selected_flow && params.user_selected_app) { + if (params.user_selected_flow && params.user_selected_app) { $bus.emit('getNodesStatue', lines); } } @@ -416,11 +413,11 @@ export const useSessionStore = defineStore('conversation', () => { conversationId?: string; qaRecordId?: string; }, - ind?: number + ind?: number, ): Promise => { if (status === 401 || status === 403) { // 鉴权失败重发 - await toAuth() + await toAuth(); return false; } else if (status === 429) { throw new Error(`HTTP error, Rate limit exceeded`); @@ -430,13 +427,12 @@ export const useSessionStore = defineStore('conversation', () => { }; async function toAuth() { - const store = useAccountStore() + const store = useAccountStore(); if (qiankunWindow.__POWERED_BY_QIANKUN__) { - const url = await store.getAuthUrl('login') + const url = await store.getAuthUrl('login'); if (url) { - const redirectUrl = qiankunWindow.__POWERED_BY_QIANKUN__ ? `${url}&redirect_index=${location.href}` : url - if (redirectUrl) - window.location.href = redirectUrl + const redirectUrl = qiankunWindow.__POWERED_BY_QIANKUN__ ? `${url}&redirect_index=${location.href}` : url; + if (redirectUrl) window.location.href = redirectUrl; } } else { ElMessageBox.confirm(i18n.global.t('Login.unauthorized'), i18n.global.t('history.confirmation_message1'), { @@ -447,14 +443,12 @@ export const useSessionStore = defineStore('conversation', () => { closeOnClickModal: false, closeOnPressEscape: false, }).then(async () => { - const url = await store.getAuthUrl('login') + const url = await store.getAuthUrl('login'); if (url) { - const redirectUrl = qiankunWindow.__POWERED_BY_QIANKUN__ ? `${url}&redirect_index=${location.href}` : url - if (redirectUrl) - window.location.href = redirectUrl + const redirectUrl = qiankunWindow.__POWERED_BY_QIANKUN__ ? `${url}&redirect_index=${location.href}` : url; + if (redirectUrl) window.location.href = redirectUrl; } - } - ); + }); } } /** @@ -473,9 +467,12 @@ export const useSessionStore = defineStore('conversation', () => { const conversationItem = conversationList.value[answerIndex] as RobotConversationItem; conversationItem.flowdata.status = 'error'; } - if (errorMsg&&!(conversationList.value[ind] as RobotConversationItem).message[ - (conversationList.value[ind] as RobotConversationItem).currentInd - ]) { + if ( + errorMsg && + !(conversationList.value[ind] as RobotConversationItem).message[ + (conversationList.value[ind] as RobotConversationItem).currentInd + ] + ) { (conversationList.value[ind] as RobotConversationItem).message[ (conversationList.value[ind] as RobotConversationItem).currentInd ] = errorMsg; @@ -493,7 +490,7 @@ export const useSessionStore = defineStore('conversation', () => { * @param regenerateInd 重新生成的回答索引 */ const sendQuestion = async ( - groupId:string|undefined, + groupId: string | undefined, question: string, user_selected_app?: string[], regenerateInd?: number, @@ -509,13 +506,13 @@ export const useSessionStore = defineStore('conversation', () => { } if (regenerateInd) { // 重新生成,指定某个回答,修改默认索引 - (conversationList.value[regenerateInd] as RobotConversationItem).message.push('');//123 + (conversationList.value[regenerateInd] as RobotConversationItem).message.push(''); //123 (conversationList.value[regenerateInd] as RobotConversationItem).currentInd = - (conversationList.value[regenerateInd] as RobotConversationItem).message.length - 1;//123 + (conversationList.value[regenerateInd] as RobotConversationItem).message.length - 1; //123 } else { // 初次生成 ,创建一个问题和一个回答 const ind = conversationList.value.length - 1; - const a = new MessageArray() + const a = new MessageArray(); a.addItem('', '', 2); conversationList.value.push( { @@ -535,43 +532,43 @@ export const useSessionStore = defineStore('conversation', () => { groupId: '', conversationId: '', // createdAt: Date.now(), - } + }, ); } isAnswerGenerating.value = true; scrollBottom(); - if (user_selected_flow&&user_selected_app) { + if (user_selected_flow && user_selected_app) { await getStream( { question, qaRecordId, - user_selected_app:[...user_selected_app], + user_selected_app: [...user_selected_app], user_selected_flow, - groupId:groupId, - params:params||undefined, - type: type + groupId: groupId, + params: params || undefined, + type: type, }, - regenerateInd ?? undefined - ) + regenerateInd ?? undefined, + ); } else if (user_selected_app?.length) { await getStream( { question, qaRecordId, user_selected_app: [...user_selected_app], - groupId:groupId, - params:params||undefined, + groupId: groupId, + params: params || undefined, }, - regenerateInd ?? undefined - ) + regenerateInd ?? undefined, + ); } else { await getStream( { question, qaRecordId, - groupId:groupId, + groupId: groupId, }, - regenerateInd ?? undefined + regenerateInd ?? undefined, ); } }; @@ -579,7 +576,10 @@ export const useSessionStore = defineStore('conversation', () => { * 暂停流式返回 */ const pausedStream = async (cid?: number): Promise => { - const answerIndex = conversationList.value.findIndex((val) => val.cid === cid) !== -1 ? conversationList.value.findIndex((val) => val.cid === cid) : conversationList.value.length - 1; + const answerIndex = + conversationList.value.findIndex(val => val.cid === cid) !== -1 + ? conversationList.value.findIndex(val => val.cid === cid) + : conversationList.value.length - 1; isPaused.value = true; conversationList.value[answerIndex].message[0] += '暂停生成'; (conversationList.value[answerIndex] as RobotConversationItem).isFinish = true; @@ -590,21 +590,23 @@ export const useSessionStore = defineStore('conversation', () => { * 重新生成回答 * @param cid */ - const reGenerateAnswer = (cid: number, user_selected_app: any[],type?:string): void => { - const answerInd = conversationList.value.findIndex((val) => val.cid === cid); + const reGenerateAnswer = (cid: number, user_selected_app: any[], type?: string): void => { + const answerInd = conversationList.value.findIndex(val => val.cid === cid); const question = (conversationList.value[answerInd - 1] as UserConversationItem).message; const recordId = (conversationList.value[answerInd] as RobotConversationItem).recordId; let groupId = undefined; - if(type&&type === "params"){ + if (type && type === 'params') { groupId = undefined; - }else{ - groupId = (conversationList.value[answerInd] as RobotConversationItem).groupId?(conversationList.value[answerInd] as RobotConversationItem).groupId:""; + } else { + groupId = (conversationList.value[answerInd] as RobotConversationItem).groupId + ? (conversationList.value[answerInd] as RobotConversationItem).groupId + : ''; } (conversationList.value[answerInd] as RobotConversationItem).isFinish = false; if (!question) { return; } - sendQuestion(groupId, question, user_selected_app, answerInd, recordId,""); + sendQuestion(groupId, question, user_selected_app, answerInd, recordId, ''); }; // #region ----------------------------------------< pagenation >-------------------------------------- @@ -613,7 +615,7 @@ export const useSessionStore = defineStore('conversation', () => { * @param cid */ const prePage = (cid: number): void => { - const answerInd = conversationList.value.findIndex((val) => val.cid === cid); + const answerInd = conversationList.value.findIndex(val => val.cid === cid); if ((conversationList.value[answerInd] as RobotConversationItem).currentInd === 0) { return; } @@ -625,7 +627,7 @@ export const useSessionStore = defineStore('conversation', () => { * @param cid */ const nextPage = (cid: number): void => { - const answerInd = conversationList.value.findIndex((val) => val.cid === cid); + const answerInd = conversationList.value.findIndex(val => val.cid === cid); if ( conversationList.value[answerInd].message.length - 1 === @@ -635,7 +637,6 @@ export const useSessionStore = defineStore('conversation', () => { } (conversationList.value[answerInd] as RobotConversationItem).currentInd += 1; const index = (conversationList.value[answerInd] as RobotConversationItem).currentInd; - }; // #endregion @@ -650,26 +651,24 @@ export const useSessionStore = defineStore('conversation', () => { if (!_ && res) { conversationList.value = []; - res.result.records.forEach((record) => { - if ( - (conversationList.value as RobotConversationItem[]).find( - (i) => i.groupId === record.groupId - ) - ) { - const re = (conversationList.value as RobotConversationItem[]).find( - (i) => i.groupId === record.groupId - ); + res.result.records.forEach(record => { + if ((conversationList.value as RobotConversationItem[]).find(i => i.groupId === record.groupId)) { + const re = (conversationList.value as RobotConversationItem[]).find(i => i.groupId === record.groupId); re?.message.push(record.content.answer); - if (typeof (re?.message) !== 'string') { - re?.messageList.addItem(record.content.answer, record.id, typeof (record.is_like) === 'object' ? 2 : Number(record.is_like)); - if(re?.currentInd!==undefined){ + if (typeof re?.message !== 'string') { + re?.messageList.addItem( + record.content.answer, + record.id, + typeof record.is_like === 'object' ? 2 : Number(record.is_like), + ); + if (re?.currentInd !== undefined) { re.currentInd = re.currentInd + 1; } } return; } const a = new MessageArray(); - a.addItem(record.content.answer, record.id, typeof (record.is_like) === 'object' ? 2 : Number(record.is_like)); + a.addItem(record.content.answer, record.id, typeof record.is_like === 'object' ? 2 : Number(record.is_like)); conversationList.value.unshift( { cid: conversationList.value.length + 1, @@ -690,7 +689,7 @@ export const useSessionStore = defineStore('conversation', () => { conversationId: record.conversationId, groupId: record.groupId, metadata: record.metadata, - } + }, ); scrollBottom('auto'); }); @@ -698,7 +697,7 @@ export const useSessionStore = defineStore('conversation', () => { }; const comment = (cid: number, isSupport: boolean, index: number): void => { - const ind = conversationList.value.find((item) => item.cid === cid); + const ind = conversationList.value.find(item => item.cid === cid); // ind.message.items[index].is_like = isSupport; }; @@ -709,6 +708,27 @@ export const useSessionStore = defineStore('conversation', () => { await api.stopGeneration(); }; + // 判断string是否是json对象 + const judgeJson = (str) => { + if (!str) { + return false; + } + if (str.length < 8) { + return false; + } + const str3 = str.substr(6, str.length - 1); + try { + const obj = JSON.parse(str3); + if (typeof obj === 'object' && obj) { + return true; + } else { + return false; + } + } catch (e) { + return false; + } + }; + const cancel = () => { controller.abort(); }; @@ -738,6 +758,5 @@ export const useChangeThemeStore = defineStore('theme', () => { } return { theme, - } + }; }); - diff --git a/src/views/dialogue/components/DialogueAside.vue b/src/views/dialogue/components/DialogueAside.vue index 75c37a7..c01dba5 100644 --- a/src/views/dialogue/components/DialogueAside.vue +++ b/src/views/dialogue/components/DialogueAside.vue @@ -10,7 +10,7 @@ import { ElCollapseItem, ElTooltip, } from 'element-plus'; -import { computed, ref, watch } from 'vue'; +import { computed, onMounted, ref, watch } from 'vue'; import SessionCard from '@/components/sessionCard/SessionCard.vue'; import { useAccountStore, useHistorySessionStore, useSessionStore } from '@/store'; import { storeToRefs } from 'pinia'; @@ -110,6 +110,10 @@ function checkDate(date: string | Date): string { return 'else'; } +onMounted(() => { + getHistorySession(); +}) + const deletedSessionName = ref(''); const sessionList = ref(); /** -- Gitee