|
@@ -353,7 +353,7 @@
|
|
type="checkbox"
|
|
type="checkbox"
|
|
id="inferenceModelId"
|
|
id="inferenceModelId"
|
|
v-model="inferenceModel"
|
|
v-model="inferenceModel"
|
|
- @change="handleInferenceModel"
|
|
|
|
|
|
+
|
|
class="toggle-input"
|
|
class="toggle-input"
|
|
/>
|
|
/>
|
|
<label
|
|
<label
|
|
@@ -562,6 +562,11 @@
|
|
}"
|
|
}"
|
|
:style="{ width: rightMenuWidth + 'px' }"
|
|
:style="{ width: rightMenuWidth + 'px' }"
|
|
>
|
|
>
|
|
|
|
+ <div v-if="inferenceModel">
|
|
|
|
+ <div style="height: 91vh;overflow: auto;" class="file-list" v-html="formatted_data">
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
<!-- 修改收缩按钮的位置和样式 -->
|
|
<!-- 修改收缩按钮的位置和样式 -->
|
|
<!-- <div
|
|
<!-- <div
|
|
class="collapse-button"
|
|
class="collapse-button"
|
|
@@ -584,48 +589,9 @@
|
|
@touchstart="startResize"
|
|
@touchstart="startResize"
|
|
></div>
|
|
></div>
|
|
|
|
|
|
- <!-- 修改折叠按钮的样式和行为 -->
|
|
|
|
- <!-- <div
|
|
|
|
- class="collapse-button"
|
|
|
|
- :class="{ 'menu-expanded': !isRightMenuCollapsed }"
|
|
|
|
- :style="!isRightMenuCollapsed ? { left: `-20px` } : {}"
|
|
|
|
- @click="toggleRightMenu"
|
|
|
|
- >
|
|
|
|
- <img
|
|
|
|
- :src="isRightMenuCollapsed ? leftIcon : rightIcon"
|
|
|
|
- alt="toggle"
|
|
|
|
- class="collapse-icon"
|
|
|
|
- />
|
|
|
|
- </div> -->
|
|
|
|
<div class="right-menu-content">
|
|
<div class="right-menu-content">
|
|
<!-- 添加 Tab 切换 -->
|
|
<!-- 添加 Tab 切换 -->
|
|
- <!-- <div class="right-menu-tabs">
|
|
|
|
- <div
|
|
|
|
- class="tab-item"
|
|
|
|
- :class="{ active: activeTab === 'search' }"
|
|
|
|
- @click="activeTab = 'search'"
|
|
|
|
- >
|
|
|
|
- <FileSearchOutlined />
|
|
|
|
- <span>搜索</span>
|
|
|
|
- </div>
|
|
|
|
- <div
|
|
|
|
- class="tab-item"
|
|
|
|
- :class="{ active: activeTab === 'knowledge' }"
|
|
|
|
- @click="activeTab = 'knowledge'"
|
|
|
|
- >
|
|
|
|
- <DatabaseOutlined />
|
|
|
|
- <span>知识库</span>
|
|
|
|
- </div>
|
|
|
|
- <div
|
|
|
|
- class="tab-item"
|
|
|
|
- :class="{ active: activeTab === 'preview' }"
|
|
|
|
- @click="activeTab = 'preview'"
|
|
|
|
- >
|
|
|
|
- <FileOutlined />
|
|
|
|
- <span>文档预览</span>
|
|
|
|
- </div>
|
|
|
|
- </div> -->
|
|
|
|
-
|
|
|
|
|
|
+
|
|
<!-- 搜索面板 -->
|
|
<!-- 搜索面板 -->
|
|
<div v-show="activeTab === 'search'" class="panel-container">
|
|
<div v-show="activeTab === 'search'" class="panel-container">
|
|
<!-- <div class="search-header">
|
|
<!-- <div class="search-header">
|
|
@@ -772,6 +738,8 @@
|
|
/>
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
+
|
|
|
|
+
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
@@ -903,6 +871,8 @@ const enableKnowledgeSearch = ref(false);
|
|
const knowledgeResults = ref([]);
|
|
const knowledgeResults = ref([]);
|
|
const knowledgeTotal = ref(0);
|
|
const knowledgeTotal = ref(0);
|
|
const isKnowledgeLoading = ref(false);
|
|
const isKnowledgeLoading = ref(false);
|
|
|
|
+const formatted_data = ref('')
|
|
|
|
+
|
|
|
|
|
|
// 推理模式
|
|
// 推理模式
|
|
const inferenceModel = ref(false);
|
|
const inferenceModel = ref(false);
|
|
@@ -1447,14 +1417,13 @@ const sendMessage = async () => {
|
|
}else{
|
|
}else{
|
|
// 构建请求参数
|
|
// 构建请求参数
|
|
const requestData = {
|
|
const requestData = {
|
|
- message: currentMessage,
|
|
|
|
- user_id: "13365429324",
|
|
|
|
- session_id: session_id.value || "",
|
|
|
|
-
|
|
|
|
|
|
+ query: currentMessage,
|
|
|
|
+ /* user_id: "13365429324",
|
|
|
|
+ session_id: session_id.value || "", */
|
|
};
|
|
};
|
|
|
|
|
|
// 发送初始请求获取SSE URL
|
|
// 发送初始请求获取SSE URL
|
|
- const response = await fetch(`${import.meta.env.VITE_BASE_AI_API}/api/agents/chat/multimodal/`, {
|
|
|
|
|
|
+ const response = await fetch(`${import.meta.env.VITE_BASE_AI_API}/api/agents/database/`, {
|
|
method: 'POST',
|
|
method: 'POST',
|
|
headers: {
|
|
headers: {
|
|
'Authorization': `JWT ${token}`,
|
|
'Authorization': `JWT ${token}`,
|
|
@@ -1469,193 +1438,24 @@ const sendMessage = async () => {
|
|
|
|
|
|
// 获取SSE URL
|
|
// 获取SSE URL
|
|
const responseData = await response.json();
|
|
const responseData = await response.json();
|
|
- console.log(responseData)
|
|
|
|
- const sseUrl = responseData.data.sse_url;
|
|
|
|
-
|
|
|
|
- if (!sseUrl) {
|
|
|
|
- throw new Error('未获取到SSE URL');
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 建立SSE连接
|
|
|
|
- const sseUrlWithToken = `${import.meta.env.VITE_BASE_AI_API}${sseUrl}${sseUrl.includes('?') ? '&' : '?'}token=JWT ${encodeURIComponent(token)}`;
|
|
|
|
- console.log('SSE连接URL:', sseUrlWithToken);
|
|
|
|
-
|
|
|
|
- const eventSource = new EventSource(sseUrlWithToken, {
|
|
|
|
- withCredentials: true // 启用跨域认证
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // 处理SSE消息
|
|
|
|
- eventSource.onmessage = (event) => {
|
|
|
|
- try {
|
|
|
|
- console.log('收到SSE消息:', event.data);
|
|
|
|
- const data = JSON.parse(event.data);
|
|
|
|
-
|
|
|
|
- switch(data.type) {
|
|
|
|
- case 'connected':
|
|
|
|
- // 更新session_id
|
|
|
|
- if (data.session_id) {
|
|
|
|
- session_id.value = data.session_id;
|
|
|
|
- console.log('已连接,会话ID:', data.session_id);
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case 'thinking_step':
|
|
|
|
- // 更新临时消息的内容
|
|
|
|
- const lastMessage = messages.value[messages.value.length - 1];
|
|
|
|
- if (lastMessage && lastMessage.id === tempAiMessage.id) {
|
|
|
|
- // 初始化thinking steps数组(如果不存在)
|
|
|
|
- if (!lastMessage.thinkingSteps) {
|
|
|
|
- lastMessage.thinkingSteps = [];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- let stepContent = '';
|
|
|
|
- let stepType = data.data.step_type;
|
|
|
|
-
|
|
|
|
- // 根据step_type处理不同类型的思考步骤
|
|
|
|
- switch(data.data.step_type) {
|
|
|
|
- case 'start':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'request_analysis':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'knowledge_search':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'search_error':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'intent_analysis':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'intent_result':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'model_call':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'response_generation':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'text_analysis':
|
|
|
|
- stepContent = ` ${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'planning':
|
|
|
|
- stepContent = ` ${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'execution':
|
|
|
|
- stepContent = `${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'result':
|
|
|
|
- stepContent = ` ${data.data.content}`;
|
|
|
|
- break;
|
|
|
|
- case 'conclusion':
|
|
|
|
- if (data.data.metadata && data.data.metadata.final_content) {
|
|
|
|
- // 添加最后一个thinking step
|
|
|
|
- lastMessage.thinkingSteps.push({
|
|
|
|
- type: 'conclusion',
|
|
|
|
- content: `✨ 完成: ${data.data.content}`
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // 创建最终的AI消息
|
|
|
|
- const aiMessage = reactive({
|
|
|
|
- id: Date.now() + 2,
|
|
|
|
- role: "assistant",
|
|
|
|
- content: data.data.metadata.final_content,
|
|
|
|
- displayContent: "",
|
|
|
|
- audioData: null,
|
|
|
|
- thinkingSteps: lastMessage.thinkingSteps // 保留thinking steps
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // 替换临时消息
|
|
|
|
- const msgIndex = messages.value.findIndex(msg => msg.id === tempAiMessage.id);
|
|
|
|
- if (msgIndex !== -1) {
|
|
|
|
- messages.value.splice(msgIndex, 1, aiMessage);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 显示打字效果
|
|
|
|
- typeMessage(aiMessage);
|
|
|
|
- return;
|
|
|
|
- } else if (data.data.content) {
|
|
|
|
- // 根据内容是否包含某些关键词来决定显示的emoji
|
|
|
|
- let emoji = '💭'; // 默认emoji
|
|
|
|
- if (data.data.content.includes('分析')) {
|
|
|
|
- emoji = '🔍';
|
|
|
|
- } else if (data.data.content.includes('规划')) {
|
|
|
|
- emoji = '📋';
|
|
|
|
- } else if (data.data.content.includes('执行')) {
|
|
|
|
- emoji = '⚙️';
|
|
|
|
- } else if (data.data.content.includes('完成')) {
|
|
|
|
- emoji = '✨';
|
|
|
|
- }
|
|
|
|
- stepContent = `${emoji} ${data.data.content}`;
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 添加新的thinking step
|
|
|
|
- if (stepContent) {
|
|
|
|
- lastMessage.thinkingSteps.push({
|
|
|
|
- type: stepType,
|
|
|
|
- content: stepContent
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // 更新显示内容
|
|
|
|
- lastMessage.content = "AI正在思考中...";
|
|
|
|
- lastMessage.displayContent = "AI正在思考中...";
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- /* case 'idle_timeout':
|
|
|
|
- console.log('连接空闲超时,关闭连接');
|
|
|
|
- eventSource.close();
|
|
|
|
- // 移除临时消息
|
|
|
|
- messages.value = messages.value.filter(msg => msg.id !== tempAiMessage.id);
|
|
|
|
- // 添加提示消息
|
|
|
|
- messages.value.push({
|
|
|
|
- id: Date.now() + 2,
|
|
|
|
- role: "assistant",
|
|
|
|
- content: "连接超时,请重试",
|
|
|
|
- displayContent: "连接超时,请重试",
|
|
|
|
- });
|
|
|
|
- break; */
|
|
|
|
-
|
|
|
|
- case 'session_ended':
|
|
|
|
- console.log('会话结束');
|
|
|
|
- eventSource.close();
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case 'heartbeat':
|
|
|
|
- // 忽略心跳消息
|
|
|
|
- console.log('收到心跳消息');
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- console.log('未处理的消息类型:', data.type);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- } catch (error) {
|
|
|
|
- console.error('处理SSE消息失败:', error);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // 处理SSE错误
|
|
|
|
- eventSource.onerror = (error) => {
|
|
|
|
- console.error('SSE连接错误:', error);
|
|
|
|
- eventSource.close();
|
|
|
|
-
|
|
|
|
- // 移除临时消息
|
|
|
|
- messages.value = messages.value.filter(msg => msg.id !== tempAiMessage.id);
|
|
|
|
-
|
|
|
|
- // 添加错误消息
|
|
|
|
- messages.value.push({
|
|
|
|
- id: Date.now() + 2,
|
|
|
|
- role: "assistant",
|
|
|
|
- content: "连接出错,请重试",
|
|
|
|
- displayContent: "连接出错,请重试",
|
|
|
|
- });
|
|
|
|
- };
|
|
|
|
|
|
+ console.log(responseData)//.result.summary
|
|
|
|
+ // 移除临时消息
|
|
|
|
+ messages.value = messages.value.filter(
|
|
|
|
+ (msg) => msg.id !== tempAiMessage.id
|
|
|
|
+ );
|
|
|
|
+ formatted_data.value = responseData.result.html
|
|
|
|
+ const messageContent = responseData.result.summary
|
|
|
|
+ // 创建新的AI消息
|
|
|
|
+ const aiMessage = reactive({
|
|
|
|
+ id: Date.now() + 2,
|
|
|
|
+ role: "assistant",
|
|
|
|
+ content: messageContent,
|
|
|
|
+ displayContent: "",
|
|
|
|
+ audioData: null,
|
|
|
|
+ });
|
|
|
|
+ messages.value.push(aiMessage);
|
|
|
|
+ // 显示打字效果
|
|
|
|
+ await typeMessage(aiMessage);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2131,11 +1931,29 @@ const updateCollapsedState = () => {
|
|
(activeTab.value === 'preview' && attachedFiles.value.length > 0)
|
|
(activeTab.value === 'preview' && attachedFiles.value.length > 0)
|
|
)); */
|
|
)); */
|
|
});
|
|
});
|
|
- // 推理模式
|
|
|
|
|
|
+ /* // 推理模式
|
|
const handleInferenceModel = () => {
|
|
const handleInferenceModel = () => {
|
|
inferenceModel.value = !inferenceModel.value;
|
|
inferenceModel.value = !inferenceModel.value;
|
|
- };
|
|
|
|
-
|
|
|
|
|
|
+ }; */
|
|
|
|
+ watch(inferenceModel, (newValue) => {
|
|
|
|
+ console.log('推理模式状态:', newValue);
|
|
|
|
+ if (newValue) {
|
|
|
|
+ // 打开右侧窗口
|
|
|
|
+ rightMenuWidth.value = 450;
|
|
|
|
+ isRightMenuCollapsed.value = false;
|
|
|
|
+ if (document.querySelector('.chat')) {
|
|
|
|
+ document.querySelector('.chat').style.right = `${rightMenuWidth.value}px`;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ // 关闭右侧窗口
|
|
|
|
+ rightMenuWidth.value = 0;
|
|
|
|
+ isRightMenuCollapsed.value = true;
|
|
|
|
+ if (document.querySelector('.chat')) {
|
|
|
|
+ document.querySelector('.chat').style.right = `${rightMenuWidth.value}px`;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
// 修改知识库搜索开关处理方法
|
|
// 修改知识库搜索开关处理方法
|
|
const handleKnowledgeToggle = (event) => {
|
|
const handleKnowledgeToggle = (event) => {
|
|
if (event.target.checked) {
|
|
if (event.target.checked) {
|