From 689aced342a8c6b41c1f7dcb7594e9fce387112b Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期三, 16 四月 2025 10:49:02 +0800 Subject: [PATCH] 聊天对接 --- src/components/AiChat.vue | 115 ++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/components/AiChat.vue b/src/components/AiChat.vue index e17ef15..6a3f58e 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" @@ -74,45 +77,29 @@ <script> import ClipboardJS from 'clipboard'; -import {sendKbMsg} from "@/api/chat"; +// import {sendKbMsg} from "@/api/chat"; import {Message} from "element-ui"; +const markdownIt = require('markdown-it')(); export default { name: 'AiChat', data() { return { + messages: [], // 鐢ㄤ簬椤甸潰灞曠ず鐨勫璇濆垪琛� netSearchEnable: false, - messages: [ - { - role: 'assistant', - content: '浣犲ソ锛佹垜鏄綘鐨� AI 鍔╂墜锛屾湁浠�涔堝彲浠ュ府浣犵殑鍚楋紵', - }, - { - role: 'user', - content: '浣犲ソ锛佹垜鏄綘鐨� AI 鍔╂墜锛屾湁浠�涔堝彲浠ュ府浣犵殑鍚楋紵', - }, - ], inputMessage: '', sendMsgForm: { query: "", mode: "local_kb", - kb_name: "samples", + kb_name: "SouthWest_Neclear_Develepment_KB", top_k: 3, score_threshold: 2, history: [ - { - "content": "鎴戜滑鏉ョ帺鎴愯鎺ラ緳锛屾垜鍏堟潵锛岀敓榫欐椿铏�", - "role": "user" - }, - { - "content": "铏庡ご铏庤剳", - "role": "assistant" - } ], stream: true, - model: "qwen:7b", + model: "Qwen25-32B-Instruct", temperature: 0.7, - max_tokens: 0, + max_tokens: 64, prompt_name: "default", return_direct: false }, @@ -121,6 +108,10 @@ }; }, methods: { + // md娓叉煋涓篽tml + getHtml(md) { + return markdownIt.render(md) + }, changeNetEnable() { this.netSearchEnable = ! this.netSearchEnable }, @@ -129,11 +120,9 @@ e.preventDefault(); // 闃绘榛樿鎹㈣琛屼负 }, handleMouseEnter(msgIndex) { - console.log("榧犳爣绉诲叆", msgIndex) this.msgIndex = msgIndex }, handleMouseLeave() { - console.log("榧犳爣绉婚櫎") this.msgIndex = null }, // 閲嶆柊鐢熸垚 @@ -176,18 +165,69 @@ role: 'user', content: this.inputMessage, }); + this.messages.push({ + role: 'assistant', + content: '' + }) this.sendMsgForm.query = this.inputMessage // 娓呯┖杈撳叆妗� this.inputMessage = ''; - sendKbMsg(this.sendMsgForm).then(res => { - console.log(res, "鎷垮埌鍥炲浜嗭紒锛�") - this.messages.push({ - role: 'assistant', - content: '杩欐槸涓�鏉� AI 鍥炲銆�', - }); - }) + const response = await fetch('/api/chat/kb_chat', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(this.sendMsgForm) + }); + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + + // eslint-disable-next-line no-constant-condition + while (true) { + const { done, value } = await reader.read(); + if (done) break; + console.log("缁撴潫寰幆") + const chunk = decoder.decode(value, { stream: false }); + const dataList = chunk.split('\r\n\r\n') + console.log("鑾峰彇鍒颁簡娴佸紡鍝嶅簲鏁版嵁", dataList) + if (dataList && dataList.length > 0) { + for (const data of dataList) { + if (data.startsWith("data: ")) { + const jsonStr = data.slice(6).trim(); + if (jsonStr) { + const json = JSON.parse(jsonStr); + if (json.docs && json.docs.length > 0) { + console.log("1", json) + json.docs.forEach(str => { + this.messages[this.messages.length - 1].content += str + // 寮哄埗Vue鏇存柊瑙嗗浘 + this.$forceUpdate(); + }) + } else if (json.choices && json.choices.length > 0) { + console.log("2", json) + json.choices.forEach(choice => { + this.messages[this.messages.length - 1].content += choice.delta.content + // 寮哄埗Vue鏇存柊瑙嗗浘 + this.$forceUpdate(); + }) + } + } + + } + } + } + + } + // sendKbMsg(this.sendMsgForm).then(res => { + // console.log(res, "鎷垮埌鍥炲浜嗭紒锛�") + // this.sendMsgForm.history.push({ + // role: 'assistant', + // content: JSON.parse(res.data).choices[0].message.content, + // }); + // }) }, + }, }; </script> @@ -229,9 +269,7 @@ .chat-messages { padding: 16px; margin-top: 14px; - overflow-y: auto; width: 800px; - height: 680px; } .message { @@ -280,9 +318,8 @@ } .chat-input { - padding: 16px; background-color: #fff; - width: 800px; + width: 100%; display: flex; flex-direction: row; justify-content: center; -- Gitblit v1.8.0