diff --git a/src/components/dialoguePanel/DialogueFlow.vue b/src/components/dialoguePanel/DialogueFlow.vue
index 66816ebadaf3394fc329ba35e1c027330c7e22fa..e986a1511db9a6b30c5ca4f224ad5e36f33a6d19 100644
--- a/src/components/dialoguePanel/DialogueFlow.vue
+++ b/src/components/dialoguePanel/DialogueFlow.vue
@@ -289,7 +289,7 @@ watch(
-
+
{
revsionNumber: null,
organization: '',
user_sub: '', // 用户唯一标识
+ auto_execute: false,
});
/**
diff --git a/src/store/conversation.ts b/src/store/conversation.ts
index a462446d8314e66dd40e6949801debf30dbf7024..ed830a9d3e384bb7b535b2365d71f5915441f3d7 100644
--- a/src/store/conversation.ts
+++ b/src/store/conversation.ts
@@ -431,6 +431,7 @@ export const useSessionStore = defineStore('conversation', () => {
params: Record,
innerParams: Record,
fetchParams: Record,
+ isDebug: boolean,
) => {
await fetchEventSource(url, {
...fetchParams,
@@ -441,6 +442,7 @@ export const useSessionStore = defineStore('conversation', () => {
flowId: '',
params: innerParams || {},
},
+ ...(isDebug && { debug: isDebug }),
conversationId: params.conversationId,
features: features,
language: langStore.language,
@@ -520,6 +522,7 @@ export const useSessionStore = defineStore('conversation', () => {
},
ind?: number,
waitType?: string,
+ isDebug?: boolean,
): Promise => {
const { currentSelectedSession } = useHistorySessionStore();
params.conversationId = currentSelectedSession;
@@ -565,7 +568,9 @@ export const useSessionStore = defineStore('conversation', () => {
handleMsgDataShow(params, ev, conversationItem);
},
};
- if (params.user_selected_flow) {
+ if(isDebug){
+ await funcFetch.fetchAppNew(streamUrl, params, pp, fetchParams, isDebug);
+ } else if (params.user_selected_flow) {
// 之前的对话历史记录
await funcFetch.fetchHistory(streamUrl, params, pp, fetchParams);
} else if (params.user_selected_app) {
@@ -627,6 +632,7 @@ export const useSessionStore = defineStore('conversation', () => {
* @param params
* @param type
* @param waitType
+ * @param isDebug
*/
const sendQuestion = async (
groupId: string | undefined,
@@ -638,6 +644,7 @@ export const useSessionStore = defineStore('conversation', () => {
params?: any,
type?: any,
waitType?: string,
+ isDebug?: boolean,
): Promise => {
const { updateSessionTitle, currentSelectedSession } =
useHistorySessionStore();
@@ -713,7 +720,7 @@ export const useSessionStore = defineStore('conversation', () => {
if (waitType) {
getStreamParams = params;
}
- await getStream(getStreamParams, regenerateInd ?? undefined, waitType);
+ await getStream(getStreamParams, regenerateInd ?? undefined, waitType, isDebug);
};
/**
diff --git a/src/store/historySession.ts b/src/store/historySession.ts
index 9b702d5e0527149a8893773ea7da63ef157b9d70..6a0c5ea7293f560e761b5f486f2004b52f397c69 100644
--- a/src/store/historySession.ts
+++ b/src/store/historySession.ts
@@ -217,7 +217,8 @@ export const useHistorySessionStore = defineStore(
* 创建一个新的会话
*/
const generateSession = async (): Promise => {
- const [_, res] = await api.createSession(user_selected_app.value);
+ const appId = user_selected_app.value ?? '';
+ const [_, res] = await api.createSession(appId);
if (!_ && res) {
currentSelectedSession.value = res.result.conversationId;
await getHistorySession();
diff --git a/src/views/createapp/components/DebugApp.vue b/src/views/createapp/components/DebugApp.vue
index 80e3895b45fbd18e00e799fad7771bab4ffb8f8b..9110ef5ec244814f23c9895ac2b87fa338e81aed 100644
--- a/src/views/createapp/components/DebugApp.vue
+++ b/src/views/createapp/components/DebugApp.vue
@@ -20,7 +20,14 @@ import { fetchStream } from '@/utils/fetchStream';
import { useScrollBottom } from '@/hooks/useScrollBottom';
import dayjs from 'dayjs';
import { useRoute } from 'vue-router';
-
+import i18n from 'src/i18n';
+import DialoguePanel from 'src/components/dialoguePanel/DialoguePanel.vue';
+import type {
+ ConversationItem,
+ RobotConversationItem,
+} from 'src/views/dialogue/types';
+
+const { t } = i18n.global;
let isDebugSuccess = false;
interface DebugConfig {
@@ -59,17 +66,20 @@ const { currentSelectedSession, historySession } = storeToRefs(
const { generateSession, getHistorySession } = useHistorySessionStore();
async function initDebugSession() {
- const { conversationList } = useSessionStore();
- if (conversationList.length === 0) return;
await generateSession();
await getHistorySession();
currentSelectedSession.value = historySession.value[0].conversationId;
}
-async function deleteSession(id: string) {
+/**
+ * 删除会话
+ */
+async function toDeleteSession(id: string) {
+ // 先停止生成
+ stopStream();
const [, res] = await api.deleteSession({ conversationList: [id] });
if (res) {
- conversations.value = [];
+ currentSelectedSession.value = '';
}
}
@@ -90,207 +100,105 @@ const chatContainerRef = ref(null);
const { scrollToBottom } = useScrollBottom(chatContainerRef, {
threshold: 15,
});
+const { pausedStream } = useSessionStore();
+const isStreaming = ref(false);
+const stopStream = async () => {
+ pausedStream(Number(conversationList.value.length));
+};
+// 对话列表
+const { sendQuestion } = useSessionStore();
+const { conversationList, isAnswerGenerating, dialogueRef } = storeToRefs(
+ useSessionStore(),
+);
-const { conversations, setConversations } = useConversations();
-
-const { isStreaming, queryStream, stopStream } = useStream();
-
-function useStream() {
- const isStreaming = ref(false);
-
- let controller: AbortController;
-
- const queryStream = async (
- q: string,
- sessionId: string,
- lang: 'zh' | 'en' = 'zh',
- cId?: string,
- ) => {
- isStreaming.value = true;
-
- const headers = {};
- headers['Content-Type'] = 'application/json; charset=UTF-8';
- const token = localStorage.getItem('ECSESSION');
- if (token) headers['Authorization'] = `Bearer ${token}`;
-
- controller = new AbortController();
+/**
+ * 获取指定字段值
+ * @param item
+ */
+const getItem = (item: ConversationItem, field: string): T | undefined => {
+ if (field in item) {
+ return (item as RobotConversationItem)[field] as T;
+ }
+ return undefined;
+};
- const body = {
- question: q,
- conversationId: sessionId,
- app: {
- appId: route.query.appId as string,
- flowId: '',
- params: {},
- },
- language: lang,
- features: {
- context_num: 2,
- max_tokens: 2048,
- },
- };
- try {
- const resp = await fetch('/api/chat', {
- signal: controller.signal,
- method: 'POST',
- body: JSON.stringify(body),
- headers,
+/**
+ * @description 处理并过滤文件列表,将文件列表中的字段名统一为指定格式
+ * @param {ConversationItem} ConversationItem - 对话项对象
+ * @param {string} str - 字段名
+ * @returns {Array} 格式化后的文件列表
+ */
+const getFormatFileList = (ConversationItem, str) => {
+ let fileList: any = getItem(ConversationItem, str);
+ if (!fileList || fileList?.length === 0) return;
+ let newFileList: any = [];
+ fileList?.forEach((file) => {
+ if (file.associated === 'answer') {
+ newFileList.push({
+ documentId: file._id,
+ documentName: file.name,
+ documentAbstract: file.abstract,
+ documentType: file.type,
+ documentSize: file.size,
+ sourceUrl: file.sourceUrl,
+ documentOrder: file.order,
+ createdAt: file.created_at,
+ documentAuthor: file.author,
});
- if (!resp.ok) {
- isStreaming.value = false;
- conversations.value.push({
- id: '',
- question: q,
- answer: [
- {
- content: '系统错误,请稍后再试',
- },
- ],
- answerIndex: 0,
- role: 'assistant',
- });
- return;
- }
-
- for await (const chunk of fetchStream({
- readableStream: resp.body!,
- })) {
- if (!chunk.data) {
- break;
- }
- if (chunk.data.trim() === '[ERROR]') {
- isStreaming.value = false;
- const conversation =
- conversations.value[conversations.value.length - 1];
- conversation.answer[conversation.answerIndex].content =
- '系统错误,请稍后再试';
- break;
- }
- if (chunk.data.trim() === '[DONE]') {
- isStreaming.value = false;
- setTimeout(() => {
- scrollToBottom(true);
- }, 100);
- break;
- }
-
- let conversation = conversations.value.find((item) => item.id === cId);
-
- setConversations(chunk.data, q, conversation);
- }
- } catch (error) {
- console.log(error);
}
- };
-
- const stopStream = async () => {
- const [, res] = await api.stopGeneration();
- if (res) {
- isStreaming.value = false;
- controller.abort();
- const conversation = conversations.value[conversations.value.length - 1];
- if (conversation.answer[conversation.answerIndex].content === '') {
- conversation.answer[conversation.answerIndex].content = '对话已终止';
- return;
- }
- scrollToBottom(true);
- }
- };
-
- return { isStreaming, queryStream, stopStream };
-}
+ });
+ return newFileList;
+};
-function useConversations() {
- interface Conversation {
- id: string;
- question: string;
- answer: {
- content: string;
- metadata?: StreamMetadata;
- }[];
- answerIndex: number;
- role: 'user' | 'assistant';
- createdAt?: Date | number;
+const clearSuggestion = (index: number): void => {
+ if ('search_suggestions' in conversationList.value[index]) {
+ conversationList.value[index].search_suggestions = undefined;
}
+};
- type StreamEvent = 'text.add' | 'init' | 'input';
- interface StreamMetadata {
- inputTokens: number;
-
- outputTokens: number;
-
- timeCost: number;
- }
+const showFileSource = ref(false);
+const curFileList = ref>([]);
+const closeShowFileSource = () => {
+ showFileSource.value = false;
+};
+const openShowFileSource = (fileList: Array) => {
+ showFileSource.value = true;
+ curFileList.value = fileList;
+};
- interface StreamChunk {
- content: {
- text: string;
- };
- conversationId: string;
- event: StreamEvent;
- groupId: string;
- id: string;
- metadata: StreamMetadata;
- taskId: string;
+/**
+ * 发送消息
+ */
+const handleSendMessage = async (
+ groupId: string | undefined,
+ question: string,
+ user_selected_flow?: string,
+) => {
+ if (isAnswerGenerating.value) return;
+ const len = conversationList.value.length;
+ if (
+ len > 0 &&
+ !(conversationList.value[len - 1] as RobotConversationItem).isFinish
+ )
+ return;
+ dialogueInput.value = '';
+ if (!currentSelectedSession.value) {
+ await generateSession();
}
- const conversations = ref([]);
-
- const setConversations = (
- data: string,
- question: string,
- conversation?: Conversation,
- ) => {
- const { id, event, content, metadata } = JSON.parse(data) as StreamChunk;
-
- if (event === 'init') {
- if (conversation) {
- conversation.answer.push({
- content: '',
- });
- conversation.answerIndex = conversation.answer.length - 1;
- } else {
- conversations.value.push({
- id: id,
- question,
- answer: [
- {
- content: '',
- },
- ],
- answerIndex: 0,
- role: 'assistant',
- });
- }
- }
- if (event === 'text.add') {
- if (!isDebugSuccess) {
- isDebugSuccess = true;
- emits('success', true);
- }
- const c = conversations.value[conversations.value.length - 1];
- c.answer[c.answerIndex].content += content.text;
- c.answer[c.answerIndex].metadata = metadata;
- }
- scrollToBottom();
- };
-
- return { conversations, setConversations };
-}
-
-function onSend(q: string) {
- if (isStreaming.value) return;
- conversations.value.push({
- id: `user-${(conversations.value.length % 2) + 1}`,
- question: q,
- answer: [],
- answerIndex: 0,
- role: 'user',
- });
- scrollToBottom(true);
- queryStream(q, currentSelectedSession.value, language.value as 'zh' | 'en');
- dialogueInput.value = '';
-}
+ await sendQuestion(
+ undefined,
+ question,
+ route.query.appId as string,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ true,
+ );
+};
/**
* 处理鼠标事件
@@ -300,7 +208,7 @@ const handleKeydown = (event: KeyboardEvent) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
if (dialogueInput.value !== '') {
- onSend(dialogueInput.value);
+ handleSendMessage(undefined, dialogueInput.value);
}
}
};
@@ -335,8 +243,10 @@ watch(
() => props.visible,
() => {
if (!props.visible) {
- deleteSession(currentSelectedSession.value);
+ toDeleteSession(currentSelectedSession.value);
return;
+ } else {
+ conversationList.value = [];
}
initDebugSession();
},
@@ -348,7 +258,7 @@ watch(
class="mcp-debug-dialog"
:visible="visible"
:model-value="visible"
- title="调试"
+ :title="i18n.global.t('flow.debug')"
@close="emits('update:visible', false)"
align-center
destroy-on-close
@@ -361,7 +271,7 @@ watch(
-
MCP 服务
+
{{ $t('semantic.mcp_service') }}
-
+
- 你好,我是
+ {{ $t('main.describe1') }}
{{ config.name }}
- ,很高兴为您服务
+ {{ $t('main.describe2') }}
@@ -398,101 +308,38 @@ watch(
-
-
-
-
-
+ :messageArray="item.belong === 'robot' ? item.messageList : ''"
+ :is-finish="getItem(item, 'isFinish')"
+ :test="getItem(item, 'test')"
+ :metadata="getItem(item, 'metadata')"
+ :flowdata="getItem(item, 'flowdata')"
+ :created-at="item.createdAt"
+ :current-selected="item.currentInd"
+ :need-regernerate="item.cid === conversationList.slice(-1)[0].cid"
+ :user-selected-app="user_selected_app"
+ :search_suggestions="getItem(item, 'search_suggestions')"
+ :paramsList="getItem(item, 'paramsList')"
+ :fileList="item.files ?? getFormatFileList(item, 'document')"
+ @handleReport="handleReport"
+ @handleSendMessage="handleSendMessage"
+ @clearSuggestion="clearSuggestion(index)"
+ @openShowFileSource="openShowFileSource"
+ />
@@ -501,7 +348,7 @@ watch(
{{ $t('feedback.stop') }}
-
+
@@ -539,7 +384,7 @@ watch(
@@ -756,19 +601,9 @@ watch(
color: var(--o-text-color-primary);
font-size: 16px;
background-color: var(--o-bg-color-base);
- font-family:
- HarmonyOS_Sans_SC_Regular,
- system-ui,
- -apple-system,
- BlinkMacSystemFont,
- 'Segoe UI',
- Roboto,
- Oxygen,
- Ubuntu,
- Cantarell,
- 'Open Sans',
- 'Helvetica Neue',
- sans-serif;
+ font-family: HarmonyOS_Sans_SC_Regular, system-ui, -apple-system,
+ BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
+ 'Open Sans', 'Helvetica Neue', sans-serif;
&:focus {
outline: none;
diff --git a/src/views/dialogue/components/DialogueSession.vue b/src/views/dialogue/components/DialogueSession.vue
index ea2e7275f7dc7ba281ad64f80069c43d98f5d70c..409686050707f555c02083b102195ab194734fa5 100644
--- a/src/views/dialogue/components/DialogueSession.vue
+++ b/src/views/dialogue/components/DialogueSession.vue
@@ -31,6 +31,7 @@ import yamlSvg from '@/assets/svgs/yaml.svg';
import zipSvg from '@/assets/svgs/zip.svg';
import { ElMessage } from 'element-plus';
import { useAccountStore } from 'src/store';
+import { nextTick } from 'vue';
const autoExecuteRef = ref(
false);
const { userinfo } = storeToRefs(useAccountStore());
@@ -558,10 +559,11 @@ const getProviderLLM = async () => {
}
};
-const autoExecuteChange = (value) => {
+const autoExecuteChange = async (value) => {
autoExecuteRef.value = value;
+ await nextTick();
+ Object.assign(userinfo.value, { auto_execute: value });
api.updateUserInfo({ autoExecute: value });
- api.getPartAppConfgUser();
};
onMounted(() => {
@@ -661,7 +663,7 @@ watch(
watch(
() => app,
(val) => {
- if (app.value) {
+ if (app.value.appId) {
user_selected_app.value = app.value.appId;
}
},