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 | 162 ++++++++++++++++++++++++++++++++++++------------------
1 files changed, 108 insertions(+), 54 deletions(-)
diff --git a/src/components/AiChat.vue b/src/components/AiChat.vue
index e17ef15..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"
@@ -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