diff --git a/run.sh b/run.sh new file mode 100644 index 00000000..357f618b --- /dev/null +++ b/run.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Function to stop the services +stop_services() { + echo "Stopping services..." + pkill -f "npm run server" + pkill -f "flask --app=api run" + exit +} + +# Trap signals to stop services +trap stop_services SIGINT SIGTERM + +# Start the frontend service +cd web +npm run server & + +# Start the backend service +cd ../src +flask --app=api run & + +# Wait for all background jobs to finish +wait diff --git a/src/api.py b/src/api.py index e2afe7fb..b12d389b 100644 --- a/src/api.py +++ b/src/api.py @@ -4,7 +4,7 @@ from flask import Flask, jsonify, Response, request from flask_cors import CORS from dotenv import load_dotenv from core import HistoryManager -from core import PreRetrieval +from core import Retriever from config import Config from models import select_model from utils.logging_config import setup_logger @@ -16,7 +16,7 @@ logger = setup_logger("server") config = Config("config/base.yaml") model = select_model(config) -pre_retrieval = PreRetrieval(config) +retriever = Retriever(config) apps = Flask(__name__)# 这段代码是为了解决跨域问题,Flask默认不支持跨域 @@ -39,27 +39,17 @@ def page_not_found(e): def chat_get(): return "Chat Get!" - @apps.route('/chat', methods=['POST']) def chat(): request_data = json.loads(request.data) query = request_data['query'] logger.debug(f"Web query: {query}") - external = "" - if config.enable_knowledge_base: - kb_res = pre_retrieval.search(query) - if kb_res: - kb_res = "\n".join([f"{r['id']}: {r['entity']['text']}" for r in kb_res]) - kb_res = f"知识库信息: {kb_res}" - external += kb_res - - if len(external) > 0: - query = f"以下是参考资料:\n\n\n {external} 请根据前面的知识回答:{query}" - + new_query, refs = retriever(query) history_manager = HistoryManager(request_data['history']) - messages = history_manager.add_user(query) + messages = history_manager.get_history_with_msg(new_query) + history_manager.add_user(query) logger.debug(f"Web history: {history_manager}") def generate_response(): @@ -68,14 +58,27 @@ def chat(): content += delta.content response_chunk = json.dumps({ "history": history_manager.update_ai(content), - "response": content + "response": content, + "refs": refs # TODO: 优化 refs,不需要每次都返回 }, ensure_ascii=False).encode('utf8') + b'\n' yield response_chunk return Response(generate_response(), content_type='application/json', status=200) +@apps.route('/call', methods=['POST']) +def call(): + request_data = json.loads(request.data) + query = request_data['query'] + logger.debug(f"Web query: {query}") + response = model.predict(query, stream=False) + + return jsonify({ + "response": response.content, + }) + + if __name__ == '__main__': print("Starting model...") apps.secret_key = os.urandom(24) - apps.run(host='0.0.0.0', port=8000, debug=False, threaded=True) \ No newline at end of file + apps.run(host='0.0.0.0', port=8000, debug=True, threaded=True) \ No newline at end of file diff --git a/src/cli.py b/src/cli.py index 351c03d4..a342846f 100644 --- a/src/cli.py +++ b/src/cli.py @@ -23,9 +23,7 @@ if __name__ == "__main__": break # 检索结果 - refs = retriever(query) - # 重新构建用户的输入 - query = retriever.construct_query(query, refs) + query, refs = retriever(query) messages = history_manager.add_user(query) response = model.predict(messages, stream=config.stream) diff --git a/src/core/history.py b/src/core/history.py index 02be4631..42075438 100644 --- a/src/core/history.py +++ b/src/core/history.py @@ -25,6 +25,12 @@ class HistoryManager(): self.add_ai(content) return self.messages + def get_history_with_msg(self, msg, role="user"): + """Get history with new message, but not append it to history.""" + history = self.messages[:] + history.append({"role": role, "content": msg}) + return history + def __str__(self): history_str = "" for message in self.messages: diff --git a/src/core/retriever.py b/src/core/retriever.py index a995ba38..93e56bed 100644 --- a/src/core/retriever.py +++ b/src/core/retriever.py @@ -47,4 +47,6 @@ class Retriever: raise NotImplementedError def __call__(self, query): - return self.retrieval(query) \ No newline at end of file + refs = self.retrieval(query) + query = self.construct_query(query, refs) + return query, refs \ No newline at end of file diff --git a/web/package-lock.json b/web/package-lock.json index 3f215a9c..5882e438 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -15,6 +15,7 @@ "echarts": "^5.4.2", "echarts-gl": "^2.0.9", "less": "^4.1.3", + "marked": "^13.0.2", "pinia": "^2.0.32", "vue": "^3.2.47", "vue-router": "^4.1.6" @@ -2153,6 +2154,17 @@ "semver": "bin/semver" } }, + "node_modules/marked": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.2.tgz", + "integrity": "sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", diff --git a/web/package.json b/web/package.json index 08311526..470c2647 100644 --- a/web/package.json +++ b/web/package.json @@ -18,6 +18,7 @@ "echarts": "^5.4.2", "echarts-gl": "^2.0.9", "less": "^4.1.3", + "marked": "^13.0.2", "pinia": "^2.0.32", "vue": "^3.2.47", "vue-router": "^4.1.6" diff --git a/web/public/jnu.png b/web/public/jnu.png new file mode 100644 index 00000000..3994f25b Binary files /dev/null and b/web/public/jnu.png differ diff --git a/web/src/App.vue b/web/src/App.vue index df62e07c..98240aef 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -1,79 +1,3 @@ - - - - diff --git a/web/src/assets/base.css b/web/src/assets/base.css index 733cd7d5..906ad372 100644 --- a/web/src/assets/base.css +++ b/web/src/assets/base.css @@ -34,6 +34,13 @@ --color-text: var(--vt-c-text-light-1); --section-gap: 160px; + + --main-color: #005f77; + --main-color-light: #007f96; + --main-color-dark: #004d5c; + --min-width: 400px; + --min-header-width: 80px; + --min-sider-width: 100px; } /* @media (prefers-color-scheme: dark) { diff --git a/web/src/assets/main.css b/web/src/assets/main.css index 2f6fe2cd..9005a704 100644 --- a/web/src/assets/main.css +++ b/web/src/assets/main.css @@ -1,10 +1,5 @@ @import './base.css'; -#app { - max-width: 1280px; - margin: 0 auto; - padding: 0 2rem; - - font-weight: normal; - /* height: 100vh; */ -} +:root { + --header-height: 60px; +} \ No newline at end of file diff --git a/web/src/components/ChatComponent.vue b/web/src/components/ChatComponent.vue new file mode 100644 index 00000000..fd37450f --- /dev/null +++ b/web/src/components/ChatComponent.vue @@ -0,0 +1,470 @@ + + + + + + diff --git a/web/src/layouts/AppLayout.vue b/web/src/layouts/AppLayout.vue new file mode 100644 index 00000000..f113e83d --- /dev/null +++ b/web/src/layouts/AppLayout.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/web/src/layouts/BlankLayout.vue b/web/src/layouts/BlankLayout.vue new file mode 100644 index 00000000..e537769d --- /dev/null +++ b/web/src/layouts/BlankLayout.vue @@ -0,0 +1,9 @@ + diff --git a/web/src/router/index.js b/web/src/router/index.js index e69a7e19..41507900 100644 --- a/web/src/router/index.js +++ b/web/src/router/index.js @@ -1,5 +1,6 @@ import { createRouter, createWebHistory } from 'vue-router' -import HomeView from '../views/HomeView.vue' +import AppLayout from '@/layouts/AppLayout.vue'; +import BlankLayout from '@/layouts/BlankLayout.vue'; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -7,21 +8,59 @@ const router = createRouter({ { path: '/', name: 'home', - component: HomeView, - meta: { keepAlive: true } + component: BlankLayout, + children: [ { + path: '', + name: 'home', + component: import('../views/HomeView.vue'), + meta: { keepAlive: true } + } + ] }, { path: '/chat', name: 'chat', - component: () => import('../views/ChatView.vue'), - meta: { keepAlive: true } + component: AppLayout, + children: [ + { + path: '', + name: 'Chat', + component: import('../views/ChatView.vue'), + meta: { keepAlive: true } + } + ] }, - // { - // path: '/knowledge', - // name: 'knowledge', - // component: () => import('../views/KnowledgeView.vue'), - // meta: { keepAlive: true } - // }, + { + path: '/knowledge', + name: 'knowledge', + component: AppLayout, + children: [ + { + path: '', + name: 'Knowledge', + component: import('../views/EmptyView.vue'), + meta: { keepAlive: true } + } + ] + }, + { + path: '/setting', + name: 'setting', + component: AppLayout, + children: [ + { + path: '', + name: 'setting', + component: import('../views/EmptyView.vue'), + meta: { keepAlive: true } + } + ] + }, + { + path: '/:pathMatch(.*)*', + name: 'NotFound', + component: () => import('../views/NotFoundView.vue') + } // { // path: '/kg', // name: 'knowledge-graph', diff --git a/web/src/views/ChatView.vue b/web/src/views/ChatView.vue index 95362ead..33fc5373 100644 --- a/web/src/views/ChatView.vue +++ b/web/src/views/ChatView.vue @@ -1,411 +1,200 @@ diff --git a/web/src/views/EmptyView.vue b/web/src/views/EmptyView.vue new file mode 100644 index 00000000..4f33ec24 --- /dev/null +++ b/web/src/views/EmptyView.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/web/src/views/HomeView.vue b/web/src/views/HomeView.vue index d868c38e..05aa8ce2 100644 --- a/web/src/views/HomeView.vue +++ b/web/src/views/HomeView.vue @@ -1,17 +1,24 @@ diff --git a/web/src/views/NotFoundView.vue b/web/src/views/NotFoundView.vue new file mode 100644 index 00000000..7764d1b6 --- /dev/null +++ b/web/src/views/NotFoundView.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/web/vite.config.js b/web/vite.config.js index 9f5b5578..b1f863c0 100644 --- a/web/vite.config.js +++ b/web/vite.config.js @@ -15,7 +15,7 @@ export default defineConfig({ server: { proxy: { '^/api': { - target: 'http://127.0.0.1:8000', + target: 'http://127.0.0.1:5000', // 5000端口是flask的Debug模式默认端口, 8000是非Debug模式默认端口 changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') }