hanyang пре 1 година
родитељ
комит
d3e0094453

+ 2 - 1
dist/i18n/lang-en.json

@@ -483,7 +483,8 @@
     "zoom_out": "Zoom Out",
     "full_screen": "Full Screen",
     "fit": "Fit",
-    "welcome": "Nice to meet you, how can I help?"
+    "welcome": "Nice to meet you, how can I help?",
+    "mindmap_title": "Mind Map"
   },
   "ai_search": {
     "placeholder": "Please enter search content",

+ 2 - 1
dist/i18n/lang-zh.json

@@ -484,7 +484,8 @@
     "zoom_out": "缩小",
     "full_screen": "全屏",
     "fit": "自适应",
-    "welcome": "很高兴见到你,有什么可以帮忙的?"
+    "welcome": "很高兴见到你,有什么可以帮忙的?",
+    "mindmap_title": "思维导图"
   },
   "ai_search": {
     "placeholder": "请输入搜索内容",

+ 7 - 2
public/i18n/lang-en.json

@@ -145,7 +145,11 @@
       "label_temp": "Temperature",
       "label_attend": "Attendance Penalty",
       "label_frequency": "Frequency Penalty",
-      "max_token_count": "Max Token Count"
+      "max_token_count": "Max Token Count",
+      "keyword_analysis": "Keyword Analysis",
+      "tts": "Text-to-Speech",
+      "multi_dialog": "Multi-Dialog Optimization",
+      "use_kg": "Use of Knowledge Graph"
     },
     "share": "Share",
     "share_way_tip": "Select the sharing method",
@@ -479,7 +483,8 @@
     "zoom_out": "Zoom Out",
     "full_screen": "Full Screen",
     "fit": "Fit",
-    "welcome": "Nice to meet you, how can I help?"
+    "welcome": "Nice to meet you, how can I help?",
+    "mindmap_title": "Mind Map"
   },
   "ai_search": {
     "placeholder": "Please enter search content",

+ 9 - 4
public/i18n/lang-zh.json

@@ -143,9 +143,13 @@
       "option_2": "精确",
       "option_3": "平衡",
       "label_temp": "温度",
-      "label_attend": "出席处罚",
-      "label_frequency": "频率处罚",
-      "max_token_count": "最大token数"
+      "label_attend": "存在处罚",
+      "label_frequency": "频率惩罚",
+      "max_token_count": "最大token数",
+      "keyword_analysis": "关键词分析",
+      "tts": "文本转语音",
+      "multi_dialog": "多轮对话优化",
+      "use_kg": "使用知识图谱"
     },
     "share": "分享",
     "share_way_tip": "选择分享方式",
@@ -480,7 +484,8 @@
     "zoom_out": "缩小",
     "full_screen": "全屏",
     "fit": "自适应",
-    "welcome": "很高兴见到你,有什么可以帮忙的?"
+    "welcome": "很高兴见到你,有什么可以帮忙的?",
+    "mindmap_title": "思维导图"
   },
   "ai_search": {
     "placeholder": "请输入搜索内容",

BIN
src/assets/chat/mind_map1.png


+ 3 - 1
src/modules/conversation-chat/DialogItem.vue

@@ -13,6 +13,7 @@
       :answer="answerInfo"
       :width="width"
       :answer_action_list="answer_action_list"
+      :loading_mind_map="loading_mind_map"
       @stop="handleStopChat"
       @retry="handleRetryChat"
       @select="handleSelectChat"
@@ -39,7 +40,8 @@ const props = defineProps({
   width: Number,
 
   answer_action_list: Array,
-  agent_id: String
+  agent_id: String,
+  loading_mind_map: Boolean
 });
 
 const emit = defineEmits(['stop', 'retry', 'select', 'edit', 'download', 'toSearchPage', 'toShowMindMap', 'send']);

+ 3 - 1
src/modules/conversation-chat/DialogList.vue

@@ -17,6 +17,7 @@
         :key="item.client_custom_unique_id"
         :answer_action_list="answer_action_list"
         :agent_id="agent_id"
+        :loading_mind_map="loading_mind_map"
         @select="handleSelectChat(item)"
         @edit="handleEditChat(item)"
         @download="handleDownload(item)"
@@ -72,7 +73,8 @@ const props = defineProps({
   /**
    * 控制滚动条展示
    * */
-  is_show_right_page: Boolean
+  is_show_right_page: Boolean,
+  loading_mind_map: Boolean
 });
 const emit = defineEmits(['edit', 'retry', 'toSearchPage', 'toShowMindMap', 'send']);
 

+ 48 - 4
src/modules/conversation-chat/dialog-input/InputActions.vue

@@ -28,6 +28,7 @@
         :disabled="disabled_knowledge"
         :placeholder="$t('conversation.knowledge_base')"
         :trigger-props="{ autoFitPopupMinWidth: true }"
+        style="height: 30px"
         v-model="base_list"
         multiple
         allow-clear
@@ -35,6 +36,10 @@
       >
         <a-option v-for="item in knowledge_list" :key="item.id" :label="item.name" :value="item.id"></a-option>
       </a-select>
+      <div class="switch-mind-map">
+        <a-switch v-model="show_mind_map" type="round" unchecked-color="var(--color-fill-3)" @change="handleChange" />
+        <span class="text">{{ $t('ai_search.mindmap_title') }}</span>
+      </div>
     </div>
     <div class="dialog-input-action-left" v-else></div>
 
@@ -168,13 +173,16 @@ const disabled_internet = ref(false);
 const disabled_knowledge = ref(false);
 const disabled_upload = ref(false);
 
+const show_mind_map = ref(true);
+
 // 深度思考
 const handleThinkChange = () => {
   is_deep_think.value = !is_deep_think.value;
   emit('actionConfig', {
     isDeep: is_deep_think.value ? 2 : 1,
     knowledgeId: base_list.value,
-    chatMode: is_connect_internet.value ? 2 : 1
+    chatMode: is_connect_internet.value ? 2 : base_list.value.length ? 3 : 1,
+    mind_map: show_mind_map.value
   });
 };
 // 联网搜索
@@ -194,7 +202,18 @@ const handleInternetChange = () => {
   emit('actionConfig', {
     isDeep: is_deep_think.value ? 2 : 1,
     knowledgeId: base_list.value,
-    chatMode: is_connect_internet.value ? 2 : 1
+    chatMode: is_connect_internet.value ? 2 : 1,
+    mind_map: show_mind_map.value
+  });
+};
+
+const handleChange = () => {
+  console.log('show_mind_map', show_mind_map.value);
+  emit('actionConfig', {
+    isDeep: is_deep_think.value ? 2 : 1,
+    knowledgeId: base_list.value,
+    chatMode: is_connect_internet.value ? 2 : base_list.value.length ? 3 : 1,
+    mind_map: show_mind_map.value
   });
 };
 
@@ -203,6 +222,7 @@ const base_list = ref([]);
  * 知识库
  * */
 const knowledge_list = ref([]);
+
 watch(
   () => base_list.value.length,
   (len) => {
@@ -216,7 +236,8 @@ watch(
     emit('actionConfig', {
       isDeep: is_deep_think.value ? 2 : 1,
       knowledgeId: base_list.value,
-      chatMode: base_list.value.length ? 3 : 1
+      chatMode: base_list.value.length ? 3 : 1,
+      mind_map: show_mind_map.value
     });
   },
   {
@@ -285,7 +306,7 @@ onMounted(() => {
   border: 1px solid var(--color-border-2);
   color: var(--color-text-2);
   border-radius: 8px;
-  background: var(color-bg-1);
+  /* background: var(color-bg-1); */
   .icon {
     width: 14px;
     margin-right: 3px;
@@ -355,6 +376,29 @@ onMounted(() => {
   text-align: center;
   line-height: 31px;
 }
+.switch-mind-map {
+  min-width: 130px;
+  height: 30px;
+  line-height: 30px;
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  margin-left: 10px;
+  color: var(--color-text-2);
+  .arco-switch-type-round {
+    width: 50px;
+    height: 30px;
+    line-height: 30px;
+    border-radius: 8px;
+  }
+}
+:deep(.arco-switch .arco-switch-handle) {
+  top: 7px;
+  border-radius: 50%;
+}
+/* :deep(.arco-switch-checked .arco-switch-handle) {
+  background-color: #f00;
+} */
 </style>
 
 <style>

+ 10 - 7
src/modules/conversation-content/DialogContent.vue

@@ -1,11 +1,5 @@
 <template>
   <div class="dialog-chat-answer-content" :style="custom_style">
-    <div class="mind-map" v-if="mind_map_btn">
-      <a-button class="mind-map-btn" @click="toShowMindMap">
-        <img width="14px" style="margin-right: 10px" src="../../assets/chat/mind-map.png" alt="" />
-        思维导图
-      </a-button>
-    </div>
     <DialogWebPage
       v-if="is_internet_search && internet_search.length"
       :internet_search="internet_search"
@@ -26,6 +20,14 @@
     </div>
 
     <div v-if="content.length !== 0 && !is_loading" v-html="content" class="answer-content-text" />
+    <div class="mind-map" v-if="mind_map_btn">
+      <a-button class="mind-map-btn" @click="toShowMindMap" :loading="loading_mind_map">
+        <img width="14px" style="margin-right: 10px" src="../../assets/chat/mind_map1.png" alt="" />
+        <!-- {{ $t('conversation.mindmap_title') }} -->
+        思维导图
+        <span v-if="!loading_mind_map" style="margin-left: 5px"> &gt; </span>
+      </a-button>
+    </div>
     <slot></slot>
   </div>
 </template>
@@ -71,7 +73,8 @@ const props = defineProps({
   deep_loading: Boolean,
   mind_map_btn: Boolean,
   // 对话状态: 0 1 2
-  answer_status: String
+  answer_status: Number,
+  loading_mind_map: Boolean
 });
 
 const emit = defineEmits(['toSearchPage', 'toShowMindMap']);

+ 2 - 2
src/modules/conversation-content/DialogWebPage.vue

@@ -7,7 +7,7 @@
     @click="toSearchPage"
   >
     <icon-check-circle class="icon" />
-    <span class="btn-text" :style="btn_text_style"> {{ buttonText }}</span>
+    <span class="btn-text"> {{ buttonText }}</span>
   </a-button>
   <a-button class="btn-right" v-if="show_internet_search" @click="handleShowChange">
     <icon-down />
@@ -36,7 +36,7 @@
 import { ref, computed, watch } from 'vue';
 const props = defineProps({
   internet_search: Array,
-  answer_status: String
+  answer_status: Number
 });
 const emit = defineEmits(['toSearchPage']);
 const internet_search_len = computed(() => {

+ 0 - 1
src/modules/conversation-dialog/format-anwser-string.js

@@ -29,7 +29,6 @@ export default function formatAnwserString(string) {
   if (!string) {
     return '';
   }
-
   let temp_str = replaceCode(string);
 
   /**

+ 8 - 6
src/modules/conversation-dialog/format-dialog-answer-from-history.js

@@ -20,7 +20,8 @@ function splitByThinkTag(inputString) {
     // 如果存在,使用split方法切割字符串
     const parts = inputString.split('</think>');
     // 返回切割后的两部分,第二部分之后可能还有内容,所以不需要额外处理
-    return [parts, parts.slice(1).join('</think>')];
+    // return [parts, parts.slice(1).join('</think>')];
+    return [parts[0], parts[1]];
   } else {
     // 如果不存在,返回一个包含原字符串的数组和一个空字符串
     return [inputString, ''];
@@ -70,14 +71,14 @@ export default function formatDialogAnswerFromHistory(item, agentInfo) {
     // 在回答进行展示时,会展示此数据
     client_custom_running_msg: '',
     client_custom_chat_message_id: item.id,
-    parent_id: item.parentId || '',
-    client_custom_item_mind_map: 1
+    parent_id: item.parentId || ''
   };
   if (item.isDeep && item.isDeep / 1 === 1) {
     history_item.answer = item.answer;
   } else if (item.isDeep && item.isDeep / 1 === 2) {
     history_item.answer = splitByThinkTag(item.answer)[1];
     history_item.deep_answer = splitByThinkTag(item.answer)[0];
+
     history_item.client_custom_chat_deep_loading = false;
     history_item.client_custom_item_think = true;
   }
@@ -217,9 +218,10 @@ export default function formatDialogAnswerFromHistory(item, agentInfo) {
       }
     });
   }
-  // 添加字段,历史记录中新增思维导图数据,有点话进行回显
-  if (item.mindMap) {
-    history_item.client_custom_item_mind_map = item.mindMap;
+  // 添加字段,历史记录中新增思维导图数据,有的话进行回显
+  console.log(item);
+  if (item.mindmap) {
+    history_item.client_custom_item_mind_map = item.mindmap;
   }
 
   // /**

+ 2 - 2
src/modules/conversation-dialog/format-dialog-answer-from-sse_receive_message.js

@@ -115,6 +115,7 @@ export default function formatDialogAnswerFromSseReceiveMessage(message_obj, pre
     client_custom_chat_message_id: '',
     deep_answer: '',
     parent_id: ''
+    // client_custom_item_mind_map: message_obj.isMindMap || false
     //   client_custom_item_think: false, // 是否有思考
     //   client_custom_item_think_content: '', //思考内容
     //   client_custom_item_internet: false, //是否联网
@@ -385,11 +386,10 @@ export default function formatDialogAnswerFromSseReceiveMessage(message_obj, pre
       }
     }
   }
-
   if (resType === 'message_end') {
     // 会话结束
     chat_status = 2;
-    currentMsg.client_custom_item_mind_map = 1;
+    currentMsg.client_custom_item_mind_map = message_obj.isMindMap || false;
     currentMsg.client_custom_chat_status = 2; // 次轮会话已结束
     currentMsg.client_custom_chat_type = 1; // 修改消息类型
     // currentMsg.client_custom_running_msg = ''; // 已结束:系统消息不再展示

+ 2 - 1
src/modules/conversation-dialog/format-dialog-question-by-history.js

@@ -34,6 +34,7 @@ export default function formatDialogQuestionByHistory(item, agentInfo) {
     client_custom_icon: icon_src,
 
     client_custom_unique_id: generateClientUniqueId(item.content),
-    question: item.content
+    question: item.content,
+    client_custom_upload_file_list: item.files
   };
 }

+ 6 - 3
src/modules/conversation-item/DialogAnswer.vue

@@ -124,7 +124,7 @@ const select_btn_visible = computed(() => {
 const answer_status = computed(() => {
   const answer = props.answer;
 
-  return answer.client_custom_chat_status;
+  return Number(answer.client_custom_chat_status);
 });
 
 /**
@@ -157,7 +157,6 @@ const system_message = computed(() => {
 const answer_html = computed(() => {
   const answer = props.answer;
   const str = answer.content;
-
   /**
    * 第一步处理位于:../conversation-dialogformat-dialog-answer-from-websocket_receive_message.js
    * 此处将websocket的答案数据进行第二步处理
@@ -224,8 +223,11 @@ const answer_html = computed(() => {
  * */
 const is_internet_search = computed(() => {
   const answer = props.answer;
+  if (answer.client_custom_item_internet && answer.client_custom_item_internet_list.length) {
+    return true;
+  }
 
-  return answer.client_custom_item_internet && answer.client_custom_item_internet_list;
+  return false;
 });
 /**
  * 联网搜索内容
@@ -246,6 +248,7 @@ const is_think = computed(() => {
 const deep_answer = computed(() => {
   const answer = props.answer;
   const str = answer.deep_answer;
+
   let answer_string = formatAnwserString(str);
   return answer_string;
 });

+ 13 - 1
src/modules/knowledge/ModalCreateKb.vue

@@ -1,5 +1,12 @@
 <template>
-  <a-modal v-model:visible="show_modal" :align-center="false" top="15vh" @ok="handleOk" @cancel="handleCancel">
+  <a-modal
+    v-model:visible="show_modal"
+    :align-center="false"
+    top="15vh"
+    :ok-loading="loading"
+    @ok="handleOk"
+    @cancel="handleCancel"
+  >
     <template #title> {{ $t('management.create_kb_title') }} </template>
     <div class="section">
       <div class="form-item">
@@ -58,6 +65,8 @@ const formInit = {
 };
 const form = ref(Object.assign({}, formInit));
 const show_modal = computed(() => props.visible);
+
+const loading = ref(false);
 const handleOk = () => {
   if (form.value.name.trim().length) {
     // TODO:添加知识库b
@@ -73,6 +82,7 @@ const handleCancel = () => {
   emit('update:visible', false);
 };
 const createKnowledgeBase = async () => {
+  loading.value = true;
   const { name, description } = form.value;
   const res = await createKb(name);
   if (res.data && res.data.kb_id) {
@@ -108,6 +118,8 @@ const createOwnKnowledgeBase = async (data) => {
     console.log('创建知识库失败', error);
     // 创建失败
     Message.error(t('management.create_fail'));
+  } finally {
+    loading.value = false;
   }
 };
 const handleSelectIcon = () => {

+ 175 - 21
src/modules/knowledge/rgflow/knowledgeLib/config.vue

@@ -58,18 +58,59 @@
               <a-option v-for="item in parser_ids" :key="item.value" :label="item.name" :value="item.value"></a-option>
             </a-select>
           </a-form-item>
+          <!-- 页面排名 -->
+          <a-form-item
+            field="slider"
+            tooltip="这用于提高相关性得分。所有检索到的块的相关性得分将加上此数字。 当您想首先搜索给定的知识库时,请设置比其他知识库更高的 pagerank 得分。"
+            label="页面排名"
+          >
+            <a-slider v-model="form.pagerank" :min="0" :max="2048" show-input />
+          </a-form-item>
+          <!-- 自动关键词 -->
+          <a-form-item
+            v-if="show_auto"
+            field="slider"
+            tooltip="在查询此类关键词时,为每个块提取 N 个关键词以提高其排名得分。在“系统模型设置”中设置的 LLM 将消耗额外的 token。您可以在块列表中查看结果。"
+            label="自动关键词"
+          >
+            <a-slider v-model="form.auto_keywords" :min="0" :max="2048" show-input />
+          </a-form-item>
+          <!-- 自动问题 -->
+          <a-form-item
+            v-if="show_auto"
+            field="slider"
+            tooltip="在查询此类问题时,为每个块提取 N 个问题以提高其排名得分。在“系统模型设置”中设置的 LLM 将消耗额外的 token。您可以在块列表中查看结果。如果发生错误,此功能不会破坏整个分块过程,除了将空结果添加到原始块。"
+            label="自动问题"
+          >
+            <a-slider v-model="form.auto_questions" :min="0" :max="2048" show-input />
+          </a-form-item>
           <!-- 块Token数 -->
-          <a-form-item field="slider" :label="$t('knowledgeLib.block_token_count')">
+          <a-form-item v-if="show_chunk_token_num" field="slider" :label="$t('knowledgeLib.block_token_count')">
             <a-slider v-model="form.chunk_token_num" :min="0" :max="2048" show-input />
           </a-form-item>
+          <!-- 分段标识符 -->
+          <a-form-item v-if="show_chunk_token_num" field="delimiter" label="分段标识符">
+            <a-input v-model="form.delimiter" />
+          </a-form-item>
           <!-- 布局识别 -->
-          <a-form-item :label="$t('knowledgeLib.label_layout')">
+          <a-form-item v-if="show_chunk_token_num" :label="$t('knowledgeLib.label_layout')">
             <a-space direction="vertical">
               <a-switch v-model="form.layout_recognize" size="small" />
             </a-space>
           </a-form-item>
+          <!-- 表格转HTML -->
+          <a-form-item
+            v-if="show_chunk_token_num"
+            label="表格转HTML"
+            tooltip="开启后电子表格会被解析为 HTML 表格,每张表格最多 256 行,否则会按行解析为键值对。"
+          >
+            <a-space direction="vertical">
+              <a-switch v-model="form.html4excel" size="small" />
+            </a-space>
+          </a-form-item>
+
           <!-- 使用召回增强RAPTOR策略 -->
-          <a-form-item field="raptor" :label="$t('knowledgeLib.use_strategy')">
+          <a-form-item v-if="show_RAPTOR_config" field="raptor" :label="$t('knowledgeLib.use_strategy')">
             <a-switch v-model="form.use_raptor" size="small" />
           </a-form-item>
           <div v-if="form.use_raptor">
@@ -108,6 +149,73 @@
               </a-button>
             </a-form-item>
           </div>
+          <!-- 提取知识图谱 -->
+          <a-form-item
+            v-if="show_graphrag"
+            label="提取知识图谱"
+            tooltip="文件分块后,所有块将用于知识图谱生成,这对多跳和复杂问题的推理大有帮助。"
+          >
+            <a-space direction="vertical">
+              <a-switch v-model="form.graphrag.graphrag" size="small" />
+            </a-space>
+          </a-form-item>
+          <div v-if="form.graphrag.graphrag">
+            <!-- 实体类型 -->
+            <a-form-item field="tags" label="实体类型">
+              <a-tag v-for="(tag, index) of form.tags" :key="tag" :closable="index !== 0" @close="handleRemove(tag)">
+                {{ tag }}
+              </a-tag>
+
+              <a-input
+                v-if="showInput"
+                ref="inputRef"
+                :style="{ width: '90px' }"
+                size="mini"
+                v-model.trim="inputVal"
+                @keyup.enter="handleAdd"
+                @blur="handleAdd"
+              />
+              <a-tag
+                v-else
+                :style="{
+                  width: '90px',
+                  backgroundColor: 'var(--color-fill-2)',
+                  border: '1px dashed var(--color-fill-3)',
+                  cursor: 'pointer'
+                }"
+                @click="handleEdit"
+              >
+                <template #icon>
+                  <icon-plus />
+                </template>
+                Add Tag
+              </a-tag>
+            </a-form-item>
+          </div>
+          <!-- 标签库 -->
+          <a-form-item
+            v-if="show_labels"
+            label="标签库"
+            tooltip="选择“标签”知识库有助于标记每个块。
+            对这些块的查询也将带有标签。
+            此过程将通过向数据集添加更多信息来提高检索的准确性,尤其是在存在大量块的情况下。
+            标签和关键字之间的区别:
+
+            标签是一个由用户定义和操作的封闭集,而关键字是一个开放集。
+            您需要在使用前上传带有样本的标签集。
+            关键字由 LLM 生成,这既昂贵又耗时。"
+          >
+            <a-select
+              :size="'large'"
+              v-model="form.labels"
+              :placeholder="$t('knowledgeLib.input_placeholder')"
+              :disabled="kbObj.chunk_num && kbObj.token_num"
+            >
+              <!-- <a-option v-for="(item, index) in mobileData" :key="item.name" :value="item.name">
+                {{ item.name }}
+              </a-option> -->
+            </a-select>
+          </a-form-item>
           <a-form-item>
             <div style="width: 100%; text-align: right">
               <a-space>
@@ -144,20 +252,28 @@ const scrollContainer = ref();
 const props = defineProps(['kbtenantInfo', 'kb_id']);
 const emit = defineEmits(['cancleConfig', 'saveConfig']);
 // 解析方法列表
-let parser_ids = props.kbtenantInfo.parser_ids
-  .split(',')
-  .map((item) => {
-    const [value1, value2] = item.split(':');
-    console.log(item);
-    return {
-      name: value2,
-      value: value1
-    };
-  })
-  ?.filter((item) => item.value !== 'picture')
-  ?.filter((item) => item.value !== 'audio')
-  ?.filter((item) => item.value !== 'email');
-console.log(parser_ids);
+// let parser_ids = props.kbtenantInfo.parser_ids
+//   .split(',')
+//   .map((item) => {
+//     const [value1, value2] = item.split(':');
+//     console.log(item);
+//     return {
+//       name: value2,
+//       value: value1
+//     };
+//   })
+//   ?.filter((item) => item.value !== 'picture')
+//   ?.filter((item) => item.value !== 'audio')
+//   ?.filter((item) => item.value !== 'email');
+
+let parser_ids = props.kbtenantInfo.parser_ids.split(',').reduce((acc, item) => {
+  const [value1, value2] = item.split(':');
+  if (value1 && value2 && ['General', 'Q&A', 'Table', 'Paper'].includes(value2)) {
+    acc.push({ name: value2, value: value1 });
+  }
+  return acc;
+}, []);
+
 let kbObj = reactive({});
 let avatarShow = ref(true);
 
@@ -168,7 +284,7 @@ const form = reactive({
   threshold: 0.32,
   max_cluster: 233,
   random_seed: 1500,
-  chunk_token_num: 384,
+  chunk_token_num: 128,
   use_raptor: false,
   pages: {},
   prompt:
@@ -177,8 +293,17 @@ const form = reactive({
   language: 'English',
   permission: '',
   embd_id: '',
-  parser_id: 'General',
-  layout_recognize: true
+  parser_id: 'naive',
+  layout_recognize: true,
+  pagerank: 0,
+  auto_keywords: 0,
+  auto_questions: 0,
+  delimiter: '\\n!?;。;!?',
+  labels: '',
+  html4excel: false,
+  graphrag: {
+    use_graphrag: false
+  }
 });
 const parsingIntroType = computed(() => {
   return form.parser_id;
@@ -215,9 +340,34 @@ const rules = computed(() => {
         required: true,
         message: t('knowledgeLib.config_form_rule.rule_3')
       }
+    ],
+    delimiter: [
+      {
+        required: true,
+        message: t('knowledgeLib.config_form_rule.rule_4')
+      }
     ]
   };
 });
+
+const show_auto = computed(() => {
+  return ['naive', 'manual', 'paper', 'book', 'laws', 'presentation', 'one'].includes(form.parser_id);
+});
+
+const show_chunk_token_num = computed(() => {
+  return ['naive'].includes(form.parser_id);
+});
+
+const show_labels = computed(() => {
+  return ['naive', 'qa', 'resume', 'manual', 'paper', 'book', 'laws', 'presentation', 'one'].includes(form.parser_id);
+});
+const show_RAPTOR_config = computed(() => {
+  return ['naive', 'manual', 'paper', 'book', 'laws', 'presentation'].includes(form.parser_id);
+});
+const show_graphrag = computed(() => {
+  return ['naive', 'manual', 'paper', 'book', 'laws', 'presentation', 'one'].includes(form.parser_id);
+});
+
 let visible = ref(false);
 const formRef = ref();
 const modelList = ref({});
@@ -252,7 +402,11 @@ const handleSubmit = async ({ values, errors }) => {
     parser_id: form.parser_id,
     parser_config: {
       chunk_token_num: form.chunk_token_num,
-      layout_recognize: form.layout_recognize
+      layout_recognize: form.layout_recognize,
+      pagerank: form.pagerank,
+      auto_keywords: form.auto_keywords,
+      auto_questions: form.auto_questions,
+      delimiter: formRef.delimiter
     },
     kb_id: kbObj.id
   };

+ 4 - 0
src/modules/knowledge/rgflow/knowledgeLib/index.vue

@@ -820,6 +820,10 @@ watch(
 onMounted(async () => {
   await knowledgeData();
 });
+onBeforeUnmount(() => {
+  clearInterval(interval);
+  interval = null;
+});
 </script>
 
 <style scoped lang="css">

+ 2 - 2
src/views/Xiaoshu.vue

@@ -43,8 +43,8 @@ const is_mounted = ref(false);
 
 const plugins = ref([]);
 
-// const xiaoshu_server_url = getConfigField('XIAOSHU_URL');
-const xiaoshu_server_url = 'http://192.168.20.119:9301';
+const xiaoshu_server_url = getConfigField('XIAOSHU_URL');
+// const xiaoshu_server_url = 'http://192.168.20.119:9301';
 const xiaoshu_websocket_url = getConfigField('WEBSOCKET_BASE_URL');
 const xiaoshu_api_base_url = getConfigField('API_BASE_URL');
 const xiaoshu_assets_url = getConfigField('ASSETS_BASE_URL');

+ 155 - 44
src/views/conversation/ConversationChatContainer.vue

@@ -36,6 +36,7 @@
               :suggestion="chat_suggestion"
               :answer_action_list="answer_action_list"
               :is_show_right_page="show_right"
+              :loading_mind_map="loading_mind_map"
               @share="handleChatShare"
               @edit="handleEditChat"
               @retry="handleRetryChat"
@@ -92,7 +93,7 @@
 
       <div class="conversation-chat-main-right" :style="style_conversation_chat_right">
         <div class="conversation-chat-expand" :style="style_conversation_chat_expand" v-if="is_show_right_page">
-          <div class="conversation-chat-mind-map" ref="fullScreen_mindMap">
+          <div class="conversation-chat-mind-map" :style="style_conversation_chat_mind_map" ref="fullScreen_mindMap">
             <!-- 全屏时显示的退出按钮 -->
             <button v-if="isFullScreen" class="exit-button" @click="exitFullScreen">X</button>
             <MindMap
@@ -103,7 +104,7 @@
               :svg_style="svg_style"
               @extend="extendMindMap"
             ></MindMap>
-            <div class="mind_map_error" v-if="mindMap_err.length">{{ mindMap_err }}</div>
+            <div class="mind_map_error" :style="style_map_error" v-if="mindMap_err.length">{{ mindMap_err }}</div>
 
             <div class="conversation-chat-mind-map-tools">
               <ConversationChatMindMapTools
@@ -117,10 +118,10 @@
               ></ConversationChatMindMapTools>
             </div>
           </div>
-          <div class="conversation-chat-mind-map-spin" v-if="loading_mind_map">
+          <div class="conversation-chat-mind-map-spin" :style="style_map_error" v-if="loading_mind_map">
             <a-spin tip="加载中..."></a-spin>
           </div>
-          <div class="conversation-chat-web-page" v-if="show_web_page">
+          <div class="conversation-chat-web-page" :style="style_conversation_chat_web_page" v-if="show_web_page">
             <ConversationChatWebPage :search_list="search_list" @toClose="closeWebPage"></ConversationChatWebPage>
           </div>
         </div>
@@ -186,6 +187,7 @@ import useScroll2Bottom from './use-scroll-bottom';
 import { IconEye } from '@arco-design/web-vue/es/icon';
 import { file, files } from 'jszip';
 import { getFileType } from '../../modules/form-dynamic/file-accept';
+import { value } from 'lodash-es';
 
 const props = defineProps({
   /**
@@ -329,6 +331,47 @@ const style_conversation_chat_list = computed(() => {
     };
   }
 });
+
+const style_conversation_chat_web_page = computed(() => {
+  if (!show_mind_map.value) {
+    return {
+      height: 100 + '%',
+      transition: 'all 0.2s ease',
+      marginTop: 0 + 'px'
+    };
+  } else {
+    return {
+      marginTop: 20 + 'px',
+      transition: 'all 0.2s ease',
+      height: 'calc(100 % - 380px)'
+    };
+  }
+});
+const style_conversation_chat_mind_map = computed(() => {
+  if (show_mind_map.value) {
+    return {
+      height: 330 + 'px',
+      transition: 'all 0.2s ease'
+    };
+  } else {
+    return {
+      display: 'none'
+    };
+  }
+});
+const style_map_error = computed(() => {
+  if (show_mind_map.value) {
+    return {
+      height: 330 + 'px',
+      transition: 'all 0.2s ease',
+      display: 'flex'
+    };
+  } else {
+    return {
+      display: 'none'
+    };
+  }
+});
 // ------------------------------------------------------------------
 // ------------------------------------------------------------------
 // ------------------------------------------------------------------
@@ -845,21 +888,40 @@ const closeWebPage = () => {
 };
 
 // 展示右侧页面按钮
-const show_right_page_btn = computed(() => {
-  return !show_word_viewer.value && !show_welcome.value;
-}); //控制右侧顶部按钮开关
+// const show_right_page_btn = computed(() => {
+//   if (chat_display_list.value.length) {
+//     const last_item = chat_display_list.value.at(-1);
+//     if (last_item.client_custom_item_internet && last_item.client_custom_item_internet_list.length) {
+//       return true;
+//     }
+//   }
+//   return false;
+// });
+
+//控制右侧顶部按钮开关
+const show_right_page_btn = ref(false);
 /**
  * 控制右侧显示/隐藏
+ * 展开 永远显示最后一项的网页和思维导图,如果二者都没有则,不显示
  * */
-
 const toggleRight = () => {
   is_show_right_page.value = !is_show_right_page.value;
   if (is_show_right_page.value) {
-    mindMap_content.value = mindMap_str.value;
-    setTimeout(() => {
+    const last = chat_display_list.value.at(-1);
+    if (last.client_custom_item_internet_list.length) {
+      show_web_page.value = true;
+      search_list.value = last.client_custom_item_internet_list;
+    }
+    if (last.client_custom_item_mind_map) {
       show_mind_map.value = true;
-    }, 200);
-    show_web_page.value = true;
+      console.log(last);
+      getMindMapData({ messageId: last.client_custom_chat_message_id.value, query: mindMap_txt.value }).then((res) => {
+        if (res.code / 1 === 200) {
+          mindMap_str.value = res.data.mindmap;
+          mindMap_content.value = res.data.mindmap;
+        }
+      });
+    }
   } else {
     show_mind_map.value = false;
     show_web_page.value = false;
@@ -1234,9 +1296,13 @@ const handleInputSubmit = async (options) => {
 };
 // 首页对话
 const toSubmitNewChat = async (options) => {
+  // 每次问答时,先隐藏右侧按钮
+  show_right_page_btn.value = false;
+  is_show_right_page.value = false;
+
   let ask_text = options.text; // 文本
   const ask_files = options.files; // 文件列表
-  const action_config = options.config; //是否深度思考,是否联网,是否选择知识库
+  const action_config = options.config; //是否深度思考,是否联网,是否选择知识库,是否生成思维导图
   target_action_config.value = options.config;
   let parent_id = '';
   if (chat_display_list.value.length) {
@@ -1248,8 +1314,18 @@ const toSubmitNewChat = async (options) => {
   if (options.parent_id) {
     parent_id = options.parent_id;
   }
+  console.log(target_action_config.value);
+  /**
+   *判断是否要生成思维导图
+   * 如果是生成思维导图,则将文本内容保存到mindMap_txt中,用于生成思维导图
+   * */
+  if (target_action_config.value.mind_map) {
+    mindMap_txt.value = options.text;
+  } else {
+    mindMap_txt.value = '';
+    show_mind_map.value = false;
+  }
 
-  mindMap_txt.value = options.text;
   // 用户选定的文件数量
   const file_total = ask_files.length;
   if (!ask_text) {
@@ -1323,13 +1399,13 @@ const search_list = ref([]);
 
 const toSearchPage = (item) => {
   search_list.value = [...item.client_custom_item_internet_list];
-  minMap_messageId.value = item.client_custom_chat_message_id;
+  // minMap_messageId.value = item.client_custom_chat_message_id;
   if (!is_show_right_page.value) {
     is_show_right_page.value = true;
     // if (!mindMap_content.value) {
     //   mindMap_err.value = '暂无内容';
     // }
-    toShowMindMap(item);
+    // toShowMindMap(item);
   }
   if (!show_web_page.value) {
     show_web_page.value = true;
@@ -1343,10 +1419,12 @@ const toShowMindMap = async (item) => {
       mindMap_content.value = res.data.mindmap;
       mindMap_err.value = '';
     } else {
-      (mindMap_content.value = ''), (mindMap_err.value = '暂无内容');
+      mindMap_content.value = '';
+      mindMap_err.value = '暂无内容';
     }
   } else {
-    (mindMap_content.value = ''), (mindMap_err.value = '暂无内容');
+    mindMap_content.value = '';
+    mindMap_err.value = '暂无内容';
   }
   is_show_right_page.value = true;
   minMap_messageId.value = item.client_custom_chat_message_id;
@@ -1354,6 +1432,37 @@ const toShowMindMap = async (item) => {
     show_mind_map.value = true;
   }, 200);
 };
+/**
+ * 生成思维导图的函数
+ *
+ * */
+const toGenerateMindMap = async () => {
+  // is_show_right_page.value = false;
+  loading_mind_map.value = true;
+  getMindMapData({ messageId: minMap_messageId.value, query: mindMap_txt.value })
+    .then((res) => {
+      if (res.code / 1 === 200) {
+        mindMap_str.value = res.data.mindmap;
+        mindMap_content.value = res.data.mindmap;
+        mindMap_err.value = '';
+        if (!res.data.mindmap) {
+          mindMap_err.value = '文本内容太少,不足以生成思维导图';
+        }
+      } else {
+        mindMap_err.value = '文本内容太少,不足以生成思维导图';
+      }
+    })
+    .catch((e) => {
+      mindMap_err.value = '文本内容太少,不足以生成思维导图';
+    })
+    .finally(() => {
+      loading_mind_map.value = false;
+
+      // setTimeout(() => {
+      //   show_mind_map.value = true;
+      // }, 200);
+    });
+};
 
 /**
  * sseOnMessage处理函数
@@ -1375,38 +1484,22 @@ const sseOnMessage = (ev) => {
     if (props.agent_id) {
       // return;
     } else {
-      is_show_right_page.value = true;
-      loading_mind_map.value = true;
-      getMindMapData({ messageId: minMap_messageId.value, query: mindMap_txt.value })
-        .then((res) => {
-          if (res.code / 1 === 200) {
-            mindMap_str.value = res.data.mindmap;
-            mindMap_content.value = res.data.mindmap;
-            mindMap_err.value = '';
-            if (!res.data.mindmap) {
-              mindMap_err.value = '文本内容太少,不足以生成思维导图,请重新尝试';
-            }
-          } else {
-            mindMap_err.value = '文本内容太少,不足以生成思维导图,请重新尝试';
-          }
-        })
-        .catch((e) => {
-          mindMap_err.value = '文本内容太少,不足以生成思维导图,请重新尝试';
-        })
-        .finally(() => {
-          loading_mind_map.value = false;
-
-          setTimeout(() => {
-            show_mind_map.value = true;
-          }, 200);
-        });
+      // 如果mimndMap_txt有值,则生成思维导图
+      res_data.isMindMap = target_action_config.value.mind_map;
+      if (mindMap_txt.value) {
+        toGenerateMindMap();
+      } else {
+      }
     }
   }
   if (res_data.event === 'node_finished' && res_data.data.title && res_data.data.title === 'SearXNG 搜索') {
     if (res_data.data.outputs?.json) {
       search_list.value = res_data.data.outputs.json;
       if (search_list.value.length) {
+        // 当有网页时,显示右侧按钮
+        show_right_page_btn.value = true;
         show_web_page.value = true;
+        is_show_right_page.value = true;
       }
     }
   }
@@ -1435,6 +1528,7 @@ const sseOnMessage = (ev) => {
   if (Object.keys(target_action_config.value)) {
     res_data.isDeep = target_action_config.value.isDeep / 1 === 2 ? true : false;
     res_data.isInternet = target_action_config.value.chatMode / 1 === 2 ? true : false;
+    res_data.isMindMap = target_action_config.value.mind_map;
   }
 
   /**
@@ -1442,8 +1536,9 @@ const sseOnMessage = (ev) => {
    *
 
    */
-
+  console.log(res_data, last_msg);
   const currentChat = formatDialogAnswerFromSseReceiveMessage(res_data, last_msg, props.CHAT_AGENT_INFOMATION);
+  // console.log(currentChat);
   const chat_status = currentChat.status;
 
   // 处理对话数据
@@ -1509,6 +1604,18 @@ const stopResponse = () => {
   scroll2ListBottom();
 };
 
+const toShowRightBtn = () => {
+  if (chat_display_list.value.length) {
+    const last_item = chat_display_list.value.at(-1);
+    if (last_item.mindmap) {
+      show_right_page_btn.value = true;
+    }
+    if (last_item.client_custom_item_internet && last_item.client_custom_item_internet_list.length) {
+      show_right_page_btn.value = true;
+    }
+  }
+};
+
 watch(
   () => props.agent_id,
   () => {
@@ -1641,6 +1748,9 @@ onMounted(() => {
           }
 
           chat_log_list.value = list;
+          console.log(chat_display_list.value);
+          // 处理最后一项是否有思维导图或者网页,有的话暂时右侧按钮
+          toShowRightBtn();
         } else {
           // 异常
           // TODO:处理异常
@@ -1793,6 +1903,7 @@ defineExpose({
   padding: 10px;
   border-radius: 12px;
   background-color: var(--color-bg-1);
+  box-sizing: border-box;
 }
 .conversation-chat-content {
   flex-grow: 1;

+ 1 - 1
vite.config.mjs

@@ -57,7 +57,7 @@ export default defineConfig(({ mode }) => {
           // target: 'http://192.168.20.119:11080',
           // target: 'http://smartai.com:8294/',
           target: 'http://192.168.20.119:28002/',
-          // target: 'http://smartai.com:8162/',
+          // target: 'http://47.96.40.148:8162/',
           changeOrigin: true,
           secure: false,
           ws: true,