Explorar o código

历史问答删除功能实现、来源小标显示

songxy hai 2 meses
pai
achega
9f1134ef11

+ 1 - 1
ais_search_zj/web/public/config.js

@@ -10,7 +10,7 @@
       time: 12
       time: 12
     },
     },
     llm: {
     llm: {
-      kb_name: 'policy_zzst'  //kb_chat接口链接库
+      kb_name: 'policy'  //kb_chat接口链接库
     },
     },
     authToken: 'ZJUGIS-Authorization',
     authToken: 'ZJUGIS-Authorization',
     storage: {
     storage: {

+ 21 - 2
ais_search_zj/web/src/views/ai-home/index.scss

@@ -52,14 +52,33 @@
                   >.title {
                   >.title {
                     font-size: 14px;
                     font-size: 14px;
                     color: #666666;
                     color: #666666;
+                    padding-bottom: 5px;
                   }
                   }
                   >ul {
                   >ul {
-                    padding-left: 15px;
+                    margin-top: 15px;
+                    padding-left: 5px;
                     >li {
                     >li {
                       font-size: 15px;
                       font-size: 15px;
                       color: #222222;
                       color: #222222;
-                      padding: 8px 0px;
+                      padding: 8px;
                       cursor: pointer;
                       cursor: pointer;
+                      border-radius: 5px;
+                      margin: 4px 0px;
+                      width: 100%;
+                      display: flex;
+                      justify-content: space-between;
+                      >span {
+                        &:first-child {
+                          text-overflow: ellipsis;
+                          white-space: nowrap;
+                          overflow: hidden;
+                          flex: 1;
+                          margin-left: 5px;
+                        }
+                      }
+                      &.active,&:hover {
+                        background-color: #e5e5e5;
+                      }
                     }
                     }
                   }
                   }
                 }
                 }

+ 102 - 35
ais_search_zj/web/src/views/ai-home/index.vue

@@ -22,7 +22,17 @@
                     <li :key="index" v-if="session['datas'].length > 0">
                     <li :key="index" v-if="session['datas'].length > 0">
                       <span class="title">{{session['title']}}</span>
                       <span class="title">{{session['title']}}</span>
                       <ul>
                       <ul>
-                        <li v-for="(item, cindex) in session['datas']" :key="cindex" @click="switchSession(item)">{{item['tittle']}}</li>
+                        <li 
+                        v-for="(item, cindex) in session['datas']" 
+                        :key="cindex" 
+                        :class="{'active': item['id'] === cSessionId}" 
+                        @mouseenter="sessionDelId = item['id']"
+                        @mouseleave="sessionDelId = ''">
+                          <span @click="switchSession(item)">{{item['tittle']}}</span>
+                          <span v-if="sessionDelId === item['id']" @click="onSessionDeleteHandle(item['id'])">
+                              <DeleteOutlined />
+                          </span>
+                        </li>
                       </ul>
                       </ul>
                     </li>
                     </li>
                   </template>
                   </template>
@@ -364,9 +374,11 @@
 <script setup>
 <script setup>
 import {
 import {
   LoadingOutlined,
   LoadingOutlined,
+  DeleteOutlined,
   UpOutlined,
   UpOutlined,
   DownOutlined
   DownOutlined
 } from "@ant-design/icons-vue";
 } from "@ant-design/icons-vue";
+import { Modal } from 'ant-design-vue';
 import dayjs from 'dayjs';
 import dayjs from 'dayjs';
 import { fetchEventSource } from '@microsoft/fetch-event-source';
 import { fetchEventSource } from '@microsoft/fetch-event-source';
 import PDFViewer from '@/components/pdf/PdfCanvas.vue';
 import PDFViewer from '@/components/pdf/PdfCanvas.vue';
@@ -400,12 +412,15 @@ const historys = ref([])
 let historyIndex = -1;
 let historyIndex = -1;
 const cQuestion = ref('')
 const cQuestion = ref('')
 
 
+const cSessionId = ref('')
+const sessionDelId = ref('')
 const isSessionNew = ref(true)
 const isSessionNew = ref(true)
 const startNewSessionHandle = () => {
 const startNewSessionHandle = () => {
   cQuestion.value = ''
   cQuestion.value = ''
   historys.value = []
   historys.value = []
   historyIndex = -1
   historyIndex = -1
   isSessionNew.value = true
   isSessionNew.value = true
+  cSessionId.value = ''
 }
 }
 
 
 const onKeydownHandle = (e) => {
 const onKeydownHandle = (e) => {
@@ -441,6 +456,7 @@ const onSendHandle = (status = true) => {
       streamMock: false,
       streamMock: false,
       msg: '',
       msg: '',
       originAnswer: '',
       originAnswer: '',
+      oDocs: '',
       docs: []
       docs: []
     }
     }
   })
   })
@@ -652,6 +668,7 @@ const quest = async (isFllow) => {
     originAnswer: '',
     originAnswer: '',
     streamMock: false,
     streamMock: false,
     streamMsg: '',
     streamMsg: '',
+    oDocs: '',
     docs: []
     docs: []
   };
   };
   activeIndex.value = 0;
   activeIndex.value = 0;
@@ -775,31 +792,31 @@ const handleKnowledgeResponse = (msg, id) => {
         });
         });
         timers.value = [];
         timers.value = [];
       }
       }
-        endTime.value = Date.now();
-        var time = ((endTime.value - startTime.value) / 1000).toFixed(0);
-        historys.value[historyIndex].currentResponse.hintTxt = `已深度思考(用时 ${time} 秒)`;
-        historys.value[historyIndex].currentResponse.time = time;
-        historys.value[historyIndex].currentResponse.loading = false;
-        aiLoading.value=true;
-        historys.value[historyIndex].currentResponse.originAnswer = rData.choices[0]?.delta?.content.replaceAll(
-          '\n',
-          `  \n`
+      endTime.value = Date.now();
+      var time = ((endTime.value - startTime.value) / 1000).toFixed(0);
+      historys.value[historyIndex].currentResponse.hintTxt = `已深度思考(用时 ${time} 秒)`;
+      historys.value[historyIndex].currentResponse.time = time;
+      historys.value[historyIndex].currentResponse.loading = false;
+      aiLoading.value=true;
+      historys.value[historyIndex].currentResponse.originAnswer = rData.choices[0]?.delta?.content.replaceAll(
+        '\n',
+        `  \n`
+      );
+      historys.value[historyIndex].currentResponse.msg = rData.choices[0]?.delta?.content.replaceAll('\n', `  \n`);
+      let num = getNum(historys.value[historyIndex].currentResponse.msg);
+      while (num) {
+        const docsNum = historys.value[historyIndex].currentResponse.docs.length;
+        historys.value[historyIndex].currentResponse.msg = historys.value[historyIndex].currentResponse.msg.replace(
+          `[[${num}]]`,
+          `<span onclick="window.openDocByIndex(${num}, ${id})" class="poi" style="    cursor: pointer; display: inline-block; width: 20px; height: 20px; font-size: 12px; line-height: 20px; text-align: center; margin: 0 5px; border-radius: 10px;background: #d0d5dd;    width: 20px;
+  height: 20px;
+  background: #FFFFFF;
+  border-radius: 4px 4px 4px 4px;
+  border: 1px solid #BACAE3;">${num}</span>`
         );
         );
-        historys.value[historyIndex].currentResponse.msg = rData.choices[0]?.delta?.content.replaceAll('\n', `  \n`);
-        let num = getNum(historys.value[historyIndex].currentResponse.msg);
-        while (num) {
-          const docsNum = historys.value[historyIndex].currentResponse.docs.length;
-          historys.value[historyIndex].currentResponse.msg = historys.value[historyIndex].currentResponse.msg.replace(
-            `[[${num}]]`,
-            `<span onclick="window.openDocByIndex(${num}, ${id})" class="poi" style="    cursor: pointer; display: inline-block; width: 20px; height: 20px; font-size: 12px; line-height: 20px; text-align: center; margin: 0 5px; border-radius: 10px;background: #d0d5dd;    width: 20px;
-    height: 20px;
-    background: #FFFFFF;
-    border-radius: 4px 4px 4px 4px;
-    border: 1px solid #BACAE3;">${num}</span>`
-          );
 
 
-          num = getNum(historys.value[historyIndex].currentResponse.msg);
-        }
+        num = getNum(historys.value[historyIndex].currentResponse.msg);
+      }
     } else {
     } else {
       
       
       aiLoading.value = false;
       aiLoading.value = false;
@@ -834,6 +851,7 @@ const handleKnowledgeResponse = (msg, id) => {
   }
   }
 
 
   if (!historys.value[historyIndex].currentResponse.docs.length) {
   if (!historys.value[historyIndex].currentResponse.docs.length) {
+    historys.value[historyIndex].currentResponse.oDocs = JSON.stringify(rData.docs)
     if (rData.docs && rData.docs.length) {
     if (rData.docs && rData.docs.length) {
       handleDocs(rData.docs);
       handleDocs(rData.docs);
     }
     }
@@ -1033,6 +1051,11 @@ const getNum = (str) => {
     return null;
     return null;
   }
   }
 };
 };
+const getNumAll = (str) => {
+  return Array.from(str.matchAll(/\[\[(\d+)\]\]/g), match => {
+      return parseInt(match[1])
+  });
+}
 
 
 const sessionId = ref('');
 const sessionId = ref('');
 const sessionCreate = () => {
 const sessionCreate = () => {
@@ -1046,6 +1069,20 @@ const sessionCreate = () => {
     }
     }
   });
   });
 }
 }
+const sessionDelete = (id) => {
+  const sendData = {
+    id
+  }
+  ManagerAPI.delete(sendData).then((res) => {
+    if (res.data) {
+      initSessionLists();
+    }
+  });
+}
+const getSessionList = async (times) => {
+  const res = await ManagerAPI.list(userStore.user.syUser.Id, times);
+  return res.data
+}
 const sessionLists = reactive([
 const sessionLists = reactive([
   {
   {
     title: '今天',
     title: '今天',
@@ -1072,13 +1109,12 @@ const sessionLists = reactive([
     datas: []
     datas: []
   }
   }
 ])
 ])
-const sessionList = async (times) => {
-  const res = await ManagerAPI.list(userStore.user.syUser.Id, times);
-  return res.data
+const initSessionLists = () => {
+  sessionLists.forEach(async (session) => {
+    session['datas'] = await getSessionList(session['times'])
+  })
 }
 }
-sessionLists.forEach(async (session) => {
-  session['datas'] = await sessionList(session['times'])
-})
+initSessionLists();
 const getQuestionList = async (chatId) => {
 const getQuestionList = async (chatId) => {
   const res = await ManagerAPI.getQuestionList({
   const res = await ManagerAPI.getQuestionList({
     chatId
     chatId
@@ -1086,30 +1122,59 @@ const getQuestionList = async (chatId) => {
   return res.data
   return res.data
 }
 }
 const switchSession = async (item) => {
 const switchSession = async (item) => {
+  cSessionId.value = sessionId.value = item['id']
+  isSessionNew.value = false;
   const results = await getQuestionList(item['id'])
   const results = await getQuestionList(item['id'])
   historys.value = []
   historys.value = []
   results.forEach((item) => {
   results.forEach((item) => {
+    let nums = getNumAll(item['answer']);
+    let msg = item['answer'];
+    const id = questHistories.value.length;
+    nums.forEach(num => {
+      msg = msg.replace(
+            `[[${num}]]`,
+            `<span onclick="window.openDocByIndex(${num}, ${id})" class="poi" style="    cursor: pointer; display: inline-block; width: 20px; height: 20px; font-size: 12px; line-height: 20px; text-align: center; margin: 0 5px; border-radius: 10px;background: #d0d5dd;    width: 20px;
+    height: 20px;
+    background: #FFFFFF;
+    border-radius: 4px 4px 4px 4px;
+    border: 1px solid #BACAE3;">${num}</span>`
+        )
+    })
+    const docs = JSON.parse(item['answerSources']) || []
     historys.value.push({
     historys.value.push({
       question: item['question'],
       question: item['question'],
       dsChecked: true,
       dsChecked: true,
       sourceVisible: false,
       sourceVisible: false,
       currentResponse: {
       currentResponse: {
+        id,
         loading: false,
         loading: false,
         hintTxt: `已深度思考(用时 ${item['thinkTime']} 秒)`,
         hintTxt: `已深度思考(用时 ${item['thinkTime']} 秒)`,
-        msg: item['answer'],
-        docs: item['answerSources'] || []
+        msg: msg,
+        docs: docs
       }
       }
     })
     })
+    activeIndex.value = 5
     historyIndex = results.length - 1;
     historyIndex = results.length - 1;
+    handleDocs(docs)
   })
   })
 }
 }
+const onSessionDeleteHandle = (id) => {
+  Modal.confirm({
+    content: () => '确定删除该条记录,删除将无法恢复!',
+    onOk () {
+      sessionDelete(id);
+    },
+    cancelText: '取消',
+    okText: '确定',
+  });
+}
 // 埋点采集数据
 // 埋点采集数据
 const collectQuestion = () => {
 const collectQuestion = () => {
-  const { question, originAnswer, docs, time, keywords = [] } = historys.value[historyIndex].currentResponse;
+  const { question, originAnswer, oDocs, time, keywords = [] } = historys.value[historyIndex].currentResponse;
   const param = {
   const param = {
     question,
     question,
     answer: originAnswer,
     answer: originAnswer,
-    answerSources: docs,
+    answerSources: oDocs,
     thinkTime: time,
     thinkTime: time,
     questionType: askType.value === 'zcfg' ? '政策法规' : '土地市场',
     questionType: askType.value === 'zcfg' ? '政策法规' : '土地市场',
     keywords: Array.isArray(keywords) ? keywords.join(',') : keywords,
     keywords: Array.isArray(keywords) ? keywords.join(',') : keywords,
@@ -1125,7 +1190,9 @@ const collectQuestion = () => {
   ManagerAPI.collect(param).then((res) => {
   ManagerAPI.collect(param).then((res) => {
     if (res.data) {
     if (res.data) {
       // 记录日志,用来反馈
       // 记录日志,用来反馈
-      historys.value[historyIndex].currentResponse.logId = res.data;
+      sessionLists.forEach(async (session) => {
+        session['datas'] = await getSessionList(session['times'])
+      })
     }
     }
   });
   });
 };
 };

+ 4 - 4
ais_search_zj/web/vite.config.js

@@ -41,8 +41,8 @@ export default defineConfig({
     cors: true,
     cors: true,
     proxy: {
     proxy: {
       '/server': {
       '/server': {
-        // target: 'http://localhost:9999/',
-          target: 'http://10.249.6.132:8528/aisKnowledge',
+        target: 'http://localhost:9999/',
+          // target: 'http://10.249.6.132:8528/aisKnowledge',
           // target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           // target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           changeOrigin: true,
           changeOrigin: true,
           rewrite: function (path) { return path.replace(/^\/server/, ''); }
           rewrite: function (path) { return path.replace(/^\/server/, ''); }
@@ -56,14 +56,14 @@ export default defineConfig({
       },
       },
       '/aisChat': {
       '/aisChat': {
         // target: 'http://localhost:9999/',
         // target: 'http://localhost:9999/',
-          target: 'http://10.249.6.132:8528/aisChat',
+          target: 'https://zjugpt.com/llm',
           // target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           // target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           changeOrigin: true,
           changeOrigin: true,
           rewrite: function (path) { return path.replace(/^\/aisChat/, ''); }
           rewrite: function (path) { return path.replace(/^\/aisChat/, ''); }
       },
       },
       '/aiServer': {
       '/aiServer': {
         // target: 'http://localhost:9999/',
         // target: 'http://localhost:9999/',
-          target: 'http://10.249.6.132:8528/aiServer',
+          target: 'https://zjugpt.com/llm',
           // target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           // target: 'https://zdzy.zrzyt.zj.gov.cn/aisKnowledge',
           changeOrigin: true,
           changeOrigin: true,
           rewrite: function (path) { return path.replace(/^\/aiServer/, ''); }
           rewrite: function (path) { return path.replace(/^\/aiServer/, ''); }