From 7789aeaad9032763805da324d743bc664bddd2e8 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期五, 18 四月 2025 17:17:26 +0800
Subject: [PATCH] 改为对接java而不是直接调langchain

---
 src/components/AiChat.vue |  164 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 109 insertions(+), 55 deletions(-)

diff --git a/src/components/AiChat.vue b/src/components/AiChat.vue
index b372582..486e8cf 100644
--- a/src/components/AiChat.vue
+++ b/src/components/AiChat.vue
@@ -1,5 +1,5 @@
 <template>
-  <div style="position: relative;height:calc(100vh - 20px);width: 100%;display: flex;justify-content: center">
+  <div style="height:calc(100vh - 20px);width: 100%;display: flex;justify-content: center">
     <!-- 鑱婂ぉ娑堟伅鍒楄〃 -->
     <div class="chat-messages">
       <div
@@ -11,8 +11,11 @@
         <div class="avatar">
           <img :src="getAvatar(message.role)" alt="avatar" />
         </div>
-        <div class="content">
-          <div class="text" :ref="'msg' + index">{{ message.content }}</div>
+        <div v-if="!message.content && message.role == 'assistant'" v-loading="!message.content && message.role == 'assistant'">
+
+        </div>
+        <div v-else class="content">
+          <div class="text" :ref="'msg' + index" v-html="getHtml(message.content)"></div>
           <div v-if="message.role === 'assistant'">
             <div v-show="msgIndex === message" class="msg-op-list">
               <el-button class="copy" v-show="false"/>
@@ -37,7 +40,7 @@
 
     <!-- 杈撳叆妗� -->
     <div class="chat-input">
-      <div style="position: relative;width: 100%;box-sizing: border-box;">
+      <div style="position: relative;width: 800px;box-sizing: border-box;">
         <el-input
             v-model="inputMessage"
             type="textarea"
@@ -59,7 +62,7 @@
               </div>
             </div>
             <div class="send-but-warp">
-              <div class="send-but">
+              <div class="send-but" @click="sendMessage">
                 <svg t="1743144485359" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1261" width="36" height="36">
                   <path fill="#409eff" d="M512 85.333333c234.666667 0 426.666667 192 426.666667 426.666667s-192 426.666667-426.666667 426.666667S85.333333 746.666667 85.333333 512 277.333333 85.333333 512 85.333333z m-6.4 234.666667c-4.266667 2.133333-6.4 2.133333-12.8 8.533333l-153.6 153.6c-12.8 12.8-12.8 32 0 44.8 12.8 12.8 32 12.8 44.8 0l96-96V682.666667c0 17.066667 14.933333 32 32 32s32-14.933333 32-32V430.933333l96 96c12.8 12.8 32 12.8 44.8 0s12.8-32 0-44.8l-153.6-153.6c-6.4-6.4-8.533333-8.533333-12.8-8.533333s-8.533333-2.133333-12.8 0z" p-id="1262"></path>
                 </svg>
@@ -74,53 +77,46 @@
 
 <script>
 import ClipboardJS from 'clipboard';
-import {sendKbMsg} from "@/api/chat";
 import {Message} from "element-ui";
+const markdownIt = require('markdown-it')();
 
 export default {
   name: 'AiChat',
   data() {
     return {
+      chatId: null,
+      messages: [], // 鐢ㄤ簬椤甸潰灞曠ず鐨勫璇濆垪琛�
       netSearchEnable: false,
-      messages: [
-        {
-          role: 'assistant',
-          content: '浣犲ソ锛佹垜鏄綘鐨� AI 鍔╂墜锛屾湁浠�涔堝彲浠ュ府浣犵殑鍚楋紵',
-        },
-        {
-          role: 'user',
-          content: '浣犲ソ锛佹垜鏄綘鐨� AI 鍔╂墜锛屾湁浠�涔堝彲浠ュ府浣犵殑鍚楋紵',
-        },
-      ],
       inputMessage: '',
       sendMsgForm: {
         query: "",
         mode: "local_kb",
-        kb_name: "samples",
-        top_k: 3,
-        score_threshold: 2,
+        kbName: "SouthWest_Neclear_Develepment_KB",
+        topK: 3,
+        scoreThreshold: 2,
         history: [
-          {
-            "content": "鎴戜滑鏉ョ帺鎴愯鎺ラ緳锛屾垜鍏堟潵锛岀敓榫欐椿铏�",
-            "role": "user"
-          },
-          {
-            "content": "铏庡ご铏庤剳",
-            "role": "assistant"
-          }
+
         ],
         stream: true,
-        model: "qwen:7b",
-        temperature: 0.7,
-        max_tokens: 0,
-        prompt_name: "default",
-        return_direct: false
+        model: "Qwen25-32B-Instruct",
+        temperature: 1.15,
+        maxTokens: 512,
+        promptName: "default",
+        returnDirect: false
       },
       msgIndex: null,
-      msgRole: null
+      msgRole: null,
+      chunkRef: null, // ai鍥炵瓟涓存椂鏁版嵁
+      haveThinkStart: false, // ai鍥炵瓟鍝嶅簲鏁版嵁鏄惁鏈塼hink鏍囩
+      haveThinkEnd: false, // ai鍥炵瓟鍝嶅簲鏁版嵁鏄惁鏈塼hink鏍囩
+      controller: null, // ai鍥炵瓟璇锋眰鎺у埗鍣紝鍙互鏍规嵁涓氬姟涓柇璇锋眰
     };
   },
   methods: {
+    // md娓叉煋涓篽tml
+    getHtml(md) {
+      return markdownIt.render(md)
+    },
     changeNetEnable() {
       this.netSearchEnable = ! this.netSearchEnable
     },
@@ -129,11 +125,9 @@
       e.preventDefault(); // 闃绘榛樿鎹㈣琛屼负
     },
     handleMouseEnter(msgIndex) {
-      console.log("榧犳爣绉诲叆", msgIndex)
       this.msgIndex = msgIndex
     },
     handleMouseLeave() {
-      console.log("榧犳爣绉婚櫎")
       this.msgIndex = null
     },
     // 閲嶆柊鐢熸垚
@@ -167,27 +161,90 @@
       return roleNames[role];
     },
 
-    // 鍙戦�佹秷鎭�
     async sendMessage() {
       if (this.inputMessage.trim() === '') return;
 
-      // 娣诲姞鐢ㄦ埛娑堟伅
-      this.messages.push({
-        role: 'user',
-        content: this.inputMessage,
-      });
-      this.sendMsgForm.query = this.inputMessage
-      // 娓呯┖杈撳叆妗�
-      this.inputMessage = '';
+      // 鍒濆鍖栫姸鎬�
+      this.chunkRef = '';
+      this.haveThinkStart = false;
+      this.haveThinkEnd = false;
+      this.controller = new AbortController();
 
-      sendKbMsg(this.sendMsgForm).then(res => {
-        console.log(res, "鎷垮埌鍥炲浜嗭紒锛�")
-        this.messages.push({
-          role: 'assistant',
-          content: '杩欐槸涓�鏉� AI 鍥炲銆�',
+      // 娣诲姞鐢ㄦ埛娑堟伅鍜屽崰浣嶅姪鐞嗘秷鎭�
+      this.messages.push(
+          { role: 'user', content: this.inputMessage },
+          { role: 'assistant', content: '' }
+      );
+      this.sendMsgForm.query = this.inputMessage;
+      this.inputMessage = '';
+      const assistantIndex = this.messages.length - 1;
+      try {
+        const response = await fetch('/api/chat/send/msg', {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/json',
+            "Accept": 'text/event-stream',
+            'Cache-Control': 'no-cache, no-transform'
+          },
+          signal: this.controller.signal,
+          body: JSON.stringify(this.sendMsgForm)
         });
-      })
-    },
+
+        if (!response.ok) throw new Error(`HTTP ${response.status}`);
+
+        const reader = response.body.getReader();
+        const decoder = new TextDecoder();
+        let jsonBuffer = '';
+
+        // eslint-disable-next-line no-constant-condition
+        while (true) {
+          const { done, value } = await reader.read();
+          if (done) {
+            this.sendMsgForm.history.push({ role: 'user', content: this.inputMessage })
+            this.sendMsgForm.history.push({ role: 'assistant', content: this.messages[assistantIndex].content })
+            break;
+          }
+
+          const chunk = decoder.decode(value, { stream: true });
+          const lines = chunk.split('\n');
+
+          for (const line of lines) {
+            if (!line.startsWith('data:')) continue;
+
+            const rawData = line.slice(5).trim();
+            if (rawData === '[DONE]') continue;
+
+            try {
+              jsonBuffer += rawData;
+              const data = JSON.parse(jsonBuffer);
+              jsonBuffer = '';
+              let content = '';
+              if (data.docs) {
+                for (let i = 0; i < data.docs.length; i++) {
+                  content += data.docs[i]
+                }
+              } else {
+                content = data?.choices?.[0]?.delta?.content || '';
+              }
+              if (!content) continue;
+              // 瀹炴椂鏇存柊
+              this.messages[assistantIndex].content += content;
+              this.messages[assistantIndex].content = this.messages[assistantIndex].content.replace(/<\/?think>/g, '');
+              await this.$nextTick();
+            } catch {
+              // JSON涓嶅畬鏁达紝绛夊緟涓嬫鏁版嵁
+              continue;
+            }
+          }
+        }
+      } catch (error) {
+        if (error.name !== 'AbortError') {
+          console.error('Request failed:', error);
+          this.messages[assistantIndex].content = '璇锋眰寮傚父';
+        }
+      }
+    }
+
   },
 };
 </script>
@@ -229,9 +286,7 @@
 .chat-messages {
   padding: 16px;
   margin-top: 14px;
-  overflow-y: auto;
   width: 800px;
-  height: 680px;
 }
 
 .message {
@@ -280,9 +335,8 @@
 }
 
 .chat-input {
-  padding: 16px;
   background-color: #fff;
-  width: 800px;
+  width: 100%;
   display: flex;
   flex-direction: row;
   justify-content: center;

--
Gitblit v1.8.0