From 689aced342a8c6b41c1f7dcb7594e9fce387112b Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期三, 16 四月 2025 10:49:02 +0800
Subject: [PATCH] 聊天对接
---
src/api/request.js | 16 ++--
vue.config.js | 2
package-lock.json | 55 +++++++++++++
package.json | 1
src/views/Index.vue | 3
src/api/knowledge.js | 9 ++
src/components/AiChat.vue | 115 +++++++++++++++++++---------
src/components/Login.vue | 2
8 files changed, 153 insertions(+), 50 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 63ad5f1..4308e26 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"clipboard": "^2.0.11",
"core-js": "^3.8.3",
"element-ui": "^2.15.14",
+ "markdown-it": "^14.1.0",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
@@ -5405,7 +5406,6 @@
"version": "4.5.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -7773,6 +7773,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
"node_modules/loader-runner": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz",
@@ -8093,6 +8102,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/markdown-it": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz",
+ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.mjs"
+ }
+ },
+ "node_modules/markdown-it/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -8108,6 +8140,12 @@
"integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
"dev": true,
"license": "CC0-1.0"
+ },
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "license": "MIT"
},
"node_modules/media-typer": {
"version": "0.3.0",
@@ -9916,6 +9954,15 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
@@ -11461,6 +11508,12 @@
"node": ">= 0.6"
}
},
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "license": "MIT"
+ },
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.20.0.tgz",
diff --git a/package.json b/package.json
index 9362f0d..bdf6baa 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"clipboard": "^2.0.11",
"core-js": "^3.8.3",
"element-ui": "^2.15.14",
+ "markdown-it": "^14.1.0",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
diff --git a/src/api/knowledge.js b/src/api/knowledge.js
new file mode 100644
index 0000000..a80d658
--- /dev/null
+++ b/src/api/knowledge.js
@@ -0,0 +1,9 @@
+import axios from "./request";
+
+// 鑾峰彇鐭ヨ瘑搴撳垪琛�
+export const getKbList = () => {
+ return axios({
+ url: "knowledge_base/list_knowledge_bases",
+ method: "GET"
+ })
+}
diff --git a/src/api/request.js b/src/api/request.js
index b6d9702..b6b202c 100644
--- a/src/api/request.js
+++ b/src/api/request.js
@@ -4,7 +4,7 @@
const instance = axios.create({
baseURL: '/api/',
- timeout: 50000,
+ timeout: 500000,
// 涓嶆惡甯ookie
withCredentials: false,
headers: {
@@ -26,19 +26,19 @@
// 娣诲姞鍝嶅簲鎷︽埅鍣�
instance.interceptors.response.use(function (response) {
+ console.log("姝e父鍝嶅簲缁撴灉",response)
// 澶勭悊鑷畾涔夌姸鎬佺爜
- if(response.data.code === 200) {
+ if(response.status === 200) {
return response;
// 楠岃瘉鐮侀敊璇斁琛岋紝浠ヤ究鍒锋柊楠岃瘉鐮�
- } else if(response.data.code === 404) {
- Message.error(response.data.msg);
- } else if (response.data.code === 1998) {
- return response;
+ } else if(response.status === 404) {
+ Message.error(response.statusText);
} else {
- Message.error(response.data.msg);
- return Promise.reject(response.data.msg);
+ Message.error(response.statusText);
+ return Promise.reject(response.statusText);
}
}, function (error) {
+ console.log("閿欒鍝嶅簲缁撴灉",error)
// 澶勭悊http鐘舵�佺爜
if(error.response.data) {
error.message = error.response.data.msg;
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;
diff --git a/src/components/Login.vue b/src/components/Login.vue
index fcdaea1..48f24c9 100644
--- a/src/components/Login.vue
+++ b/src/components/Login.vue
@@ -39,7 +39,7 @@
name: "LoginView",
data() {
return {
- open: true,
+ open: false,
loginForm: {
username: '',
pwd: ''
diff --git a/src/views/Index.vue b/src/views/Index.vue
index d88fddf..670d93d 100644
--- a/src/views/Index.vue
+++ b/src/views/Index.vue
@@ -261,6 +261,9 @@
}
.right {
width: 1600px;
+ height: 100vh;
+ overflow-y: scroll;
+ position: relative;
}
.logo {
width: 100%;
diff --git a/vue.config.js b/vue.config.js
index e42232b..c78c8d6 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -4,7 +4,7 @@
devServer: {
proxy: {
"/api": {
- target: 'http://i-1.gpushare.com:10695/',//浠g悊鍦板潃 鍑℃槸浣跨敤/api
+ target: 'http://i-1.gpushare.com:52574/',//浠g悊鍦板潃 鍑℃槸浣跨敤/api
changeOrigin: true,//鍏佽璺ㄥ煙璇锋眰
secure: false,
pathRewrite: { //閲嶅啓璺緞 鏇挎崲璇锋眰鍦板潃涓殑鎸囧畾璺緞
--
Gitblit v1.8.0