From 40ca89fad509401c5ef9cb92f477a59830400131 Mon Sep 17 00:00:00 2001 From: "WIN-JHFT4D3SIVT\\caoxiaozhu" Date: Mon, 26 Jan 2026 14:33:00 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E4=BA=86=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E7=AB=AF=E5=8F=A3=E7=9A=84=E9=97=AE=E9=A2=98=202.=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=88=9B=E5=BB=BA=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E7=9A=84=E8=84=9A=E6=9C=AC=E5=92=8C=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E8=99=9A=E6=8B=9F=E7=8E=AF=E5=A2=83=E7=9A=84=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yaml | 5 +- create_venv.sh | 124 +++++++++++ delete_venv.sh | 55 +++++ requirements.txt | 3 + src/run.sh | 4 +- start_all.py | 304 ++++++++++++++++++++++++++ start_all.sh | 174 +++++++++++++++ web/favicon.ico | 1 + web/pages/custom-tool-create.html | 4 +- web/pages/dataset-create.html | 4 +- web/pages/dataset-preview.html | 6 +- web/pages/fine-tune-create.html | 4 +- web/pages/login.html | 4 +- web/pages/main.html | 7 +- web/pages/model-compare-chat.html | 4 +- web/pages/model-compare-create.html | 6 +- web/pages/model-compare-result.html | 4 +- web/pages/model-dimension-create.html | 4 +- web/pages/model-eval-create.html | 4 +- web/pages/model-eval.html | 4 +- web/pages/model-manage-create.html | 4 +- web/pages/model-manage.html | 4 +- web/start.sh | 21 +- 23 files changed, 714 insertions(+), 40 deletions(-) create mode 100644 create_venv.sh create mode 100644 delete_venv.sh create mode 100644 start_all.py create mode 100644 start_all.sh create mode 100644 web/favicon.ico diff --git a/config.yaml b/config.yaml index 08cab78..d67e24a 100644 --- a/config.yaml +++ b/config.yaml @@ -1,6 +1,6 @@ # 数据库配置 database: - host: "10.10.10.189" + host: "mysql" port: 3306 username: "root" password: "88116142" @@ -10,7 +10,8 @@ database: # 应用配置 app: host: "0.0.0.0" - port: 8080 + port: 7861 + web_port: 7863 debug: true # 密钥配置 diff --git a/create_venv.sh b/create_venv.sh new file mode 100644 index 0000000..b091293 --- /dev/null +++ b/create_venv.sh @@ -0,0 +1,124 @@ +#!/bin/bash +# YG_FT_Base 虚拟环境创建脚本 (Linux/Mac/WSL) +# 使用方法: bash create_venv.sh 或 ./create_venv.sh + +# 自动修复脚本换行符(如果是从 Windows 传来的文件) +if grep -q $'\r' "$0"; then + echo "检测到 Windows 换行符,自动修复中..." + sed -i 's/\r$//' "$0" + echo "修复完成,重新执行脚本..." + exec "$0" +fi + +echo "====================================" +echo "YG_FT_Base 虚拟环境创建脚本" +echo "====================================" +echo "" + +# 设置虚拟环境名称 +VENV_NAME="B_venv" + +# 检查 Python 版本 +echo "检查 Python 版本..." +if command -v python3 &> /dev/null; then + PYTHON_CMD="python3" + python3 --version +elif command -v python &> /dev/null; then + PYTHON_CMD="python" + python --version +else + echo "错误: 未找到 Python!请先安装 Python 3.10 或更高版本。" + exit 1 +fi + +# 检查并安装 python3-venv(仅限 Debian/Ubuntu 系统) +echo "" +echo "检查 python3-venv..." +if [ -f /etc/debian_version ]; then + echo "检测到 Debian/Ubuntu 系统" + if ! dpkg -l | grep -q python3-venv; then + echo "python3-venv 未安装,尝试安装..." + if [ -x "$(command -v apt)" ]; then + apt update && apt install -y python3-venv python3-pip + if [ $? -ne 0 ]; then + echo "警告: 安装 python3-venv 失败,请手动运行:" + echo " apt install python3-venv python3-pip" + echo "然后重新运行此脚本。" + exit 1 + fi + echo "python3-venv 安装成功!" + else + echo "错误: 未找到 apt 包管理器,请手动安装 python3-venv。" + exit 1 + fi + else + echo "python3-venv 已安装。" + fi +elif [ -f /etc/redhat-release ]; then + echo "检测到 RedHat/CentOS/Fedora 系统" + if ! rpm -qa | grep -q python3-virtualenv; then + echo "python3-virtualenv 未安装,尝试安装..." + if [ -x "$(command -v yum)" ]; then + yum install -y python3-virtualenv python3-pip + elif [ -x "$(command -v dnf)" ]; then + dnf install -y python3-virtualenv python3-pip + fi + fi +fi + +# 检查是否已存在虚拟环境 +if [ -d "$VENV_NAME" ]; then + echo "警告: 虚拟环境 '$VENV_NAME' 已存在!" + read -p "是否删除并重新创建? (y/n): " choice + if [[ "$choice" == "y" || "$choice" == "Y" ]]; then + echo "删除旧虚拟环境..." + rm -rf "$VENV_NAME" + else + echo "已取消操作。" + exit 0 + fi +fi + +# 创建虚拟环境 +echo "" +echo "创建虚拟环境..." +$PYTHON_CMD -m venv "$VENV_NAME" +if [ $? -ne 0 ]; then + echo "错误: 创建虚拟环境失败!" + exit 1 +fi +echo "虚拟环境创建成功!" + +# 激活虚拟环境并升级 pip +echo "" +echo "激活虚拟环境并升级 pip..." +source "$VENV_NAME/bin/activate" +python -m pip install --upgrade pip setuptools wheel +echo "pip 升级完成!" + +# 安装依赖 +echo "" +echo "安装项目依赖..." +if [ -f "requirements.txt" ]; then + pip install -r requirements.txt + if [ $? -eq 0 ]; then + echo "依赖安装成功!" + else + echo "警告: 依赖安装过程中出现一些问题。" + fi +else + echo "未找到 requirements.txt,跳过依赖安装。" +fi + +# 完成信息 +echo "" +echo "====================================" +echo "虚拟环境创建完成!" +echo "====================================" +echo "" +echo "激活虚拟环境:" +echo " source $VENV_NAME/bin/activate" +echo "" +echo "运行项目:" +echo " python src/main.py" +echo "" diff --git a/delete_venv.sh b/delete_venv.sh new file mode 100644 index 0000000..7fda17d --- /dev/null +++ b/delete_venv.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# 删除 YG_FT_Base 虚拟环境脚本 +# 使用方法: bash delete_venv.sh + +# 自动修复脚本换行符 +if grep -q $'\r' "$0"; then + echo "检测到 Windows 换行符,自动修复中..." + sed -i 's/\r$//' "$0" + echo "修复完成,重新执行脚本..." + exec "$0" +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +VENV_NAME="B_venv" +VENV_PATH="$SCRIPT_DIR/$VENV_NAME" + +echo "====================================" +echo "YG_FT_Base 虚拟环境删除脚本" +echo "====================================" +echo "" + +# 检查虚拟环境是否存在 +if [ ! -d "$VENV_PATH" ]; then + echo "虚拟环境 '$VENV_NAME' 不存在,无需删除。" + exit 0 +fi + +# 确认删除 +read -p "确定要删除虚拟环境 '$VENV_NAME' 吗?这将删除所有已安装的包。(y/n): " choice + +if [[ "$choice" != "y" && "$choice" != "Y" ]]; then + echo "已取消操作。" + exit 0 +fi + +# 删除虚拟环境 +echo "" +echo "🗑️ 删除虚拟环境..." +rm -rf "$VENV_PATH" + +if [ $? -eq 0 ]; then + echo "✅ 虚拟环境 '$VENV_NAME' 已删除!" +else + echo "❌ 删除失败,请检查权限。" + exit 1 +fi + +echo "" +echo "====================================" +echo "删除完成!" +echo "====================================" +echo "" +echo "如需重新创建虚拟环境,请运行:" +echo " bash create_venv.sh" +echo "" diff --git a/requirements.txt b/requirements.txt index 36b0360..0c1964c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,6 @@ flask-cors==4.0.0 pymysql==1.1.0 pyyaml==6.0.1 cryptography==41.0.7 +requests==2.31.0 +psutil==5.9.8 +werkzeug==3.0.1 diff --git a/src/run.sh b/src/run.sh index ab7959b..367b030 100644 --- a/src/run.sh +++ b/src/run.sh @@ -11,4 +11,6 @@ fi # 启动服务 echo "启动后端服务..." -python3 main.py +nohup python3 main.py & +# 日志会写入 logs/ 目录,同时输出到 stdout(Docker 日志可见) +echo "后端服务已在后台启动" diff --git a/start_all.py b/start_all.py new file mode 100644 index 0000000..cb1cfd6 --- /dev/null +++ b/start_all.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +YG_FT_Base 统一启动脚本 +同时启动后端 API 服务和 Web 静态服务器 + +使用方法: + python start_all.py start # 启动所有服务 + python start_all.py stop # 停止所有服务 + python start_all.py restart # 重启所有服务 + python start_all.py status # 查看服务状态 +""" +import os +import sys +import yaml +import signal +import subprocess +import time +from pathlib import Path + +# 获取脚本所在目录 +SCRIPT_DIR = Path(__file__).parent.absolute() +CONFIG_FILE = SCRIPT_DIR / "config.yaml" +WEB_DIR = SCRIPT_DIR / "web" + +# PID 文件路径 +API_PID_FILE = SCRIPT_DIR / ".api.pid" +WEB_PID_FILE = SCRIPT_DIR / ".web.pid" + + +def load_config(): + """加载配置文件""" + if not CONFIG_FILE.exists(): + print(f"❌ 配置文件不存在: {CONFIG_FILE}") + sys.exit(1) + + with open(CONFIG_FILE, 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) + + app_config = config.get('app', {}) + return { + 'api_port': app_config.get('port', 7861), + 'web_port': app_config.get('web_port', 7862) + } + + +def is_port_in_use(port): + """检查端口是否被占用""" + import socket + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + return s.connect_ex(('localhost', port)) == 0 + + +def get_pid(pid_file): + """获取 PID""" + if pid_file.exists(): + try: + return int(pid_file.read_text().strip()) + except: + return None + return None + + +def is_process_running(pid): + """检查进程是否在运行""" + try: + os.kill(pid, 0) + return True + except OSError: + return False + + +def kill_process(pid_file): + """杀死进程""" + pid = get_pid(pid_file) + if pid and is_process_running(pid): + try: + os.kill(pid, signal.SIGTERM) + time.sleep(0.5) + # 如果还在运行,强制杀死 + if is_process_running(pid): + os.kill(pid, signal.SIGKILL) + return True + except OSError: + pass + pid_file.unlink(missing_ok=True) + return False + + +def check_virtual_env(): + """检查虚拟环境是否存在""" + venv_path = SCRIPT_DIR / "B_venv" + if not venv_path.exists(): + print("⚠️ 虚拟环境不存在,请先运行 create_venv.sh 创建") + return False + return True + + +def start_api(): + """启动后端 API 服务""" + config = load_config() + api_port = config['api_port'] + + print("🚀 启动后端 API 服务...") + + if not check_virtual_env(): + return False + + if is_port_in_use(api_port): + print(f"❌ 端口 {api_port} 已被占用,后端服务可能已在运行") + return False + + venv_python = SCRIPT_DIR / "B_venv" / "bin" / "python" + main_py = SCRIPT_DIR / "src" / "main.py" + + if not venv_python.exists(): + venv_python = SCRIPT_DIR / "B_venv" / "Scripts" / "python.exe" # Windows + + if not main_py.exists(): + print(f"❌ 找不到主程序文件: {main_py}") + return False + + # 启动进程 + env = os.environ.copy() + env['PYTHONUNBUFFERED'] = '1' + + proc = subprocess.Popen( + [str(venv_python), str(main_py)], + cwd=str(SCRIPT_DIR), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + env=env + ) + + # 写入 PID + with open(API_PID_FILE, 'w') as f: + f.write(str(proc.pid)) + + # 等待服务启动 + time.sleep(2) + + if proc.poll() is not None: + print("❌ 后端服务启动失败") + API_PID_FILE.unlink(missing_ok=True) + return False + + print(f"✅ 后端服务已启动 (PID: {proc.pid}, 端口: {api_port})") + return True + + +def start_web(): + """启动 Web 静态服务器""" + config = load_config() + web_port = config['web_port'] + + print("🚀 启动 Web 静态服务器...") + + # 从项目根目录启动,这样 /lib/... 路径可以正确映射到 $PROJECT/lib/... + web_root = SCRIPT_DIR + + if not web_root.exists(): + print(f"❌ Web 目录不存在: {web_root}") + return False + + if is_port_in_use(web_port): + print(f"⚠️ 端口 {web_port} 已被占用,Web 服务可能已在运行") + return False + + # 使用 python 启动简单 HTTP 服务器(从项目根目录) + env = os.environ.copy() + env['PYTHONUNBUFFERED'] = '1' + + proc = subprocess.Popen( + [sys.executable, '-m', 'http.server', str(web_port)], + cwd=str(web_root), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + env=env + ) + + # 写入 PID + with open(WEB_PID_FILE, 'w') as f: + f.write(str(proc.pid)) + + time.sleep(1) + + if proc.poll() is not None: + print("❌ Web 服务启动失败") + WEB_PID_FILE.unlink(missing_ok=True) + return False + + print(f"✅ Web 服务已启动 (PID: {proc.pid}, 端口: {web_port})") + return True + + +def stop_all(): + """停止所有服务""" + print("🛑 停止所有服务...") + + # 停止后端服务 + if kill_process(API_PID_FILE): + print("✅ 后端服务已停止") + + # 停止 Web 服务 + if kill_process(WEB_PID_FILE): + print("✅ Web 服务已停止") + + # 清理残留进程 + subprocess.run(['pkill', '-f', 'src/main.py'], capture_output=True) + config = load_config() + subprocess.run(['pkill', '-f', f'http.server {config["web_port"]}'], capture_output=True) + + +def show_status(): + """显示服务状态""" + config = load_config() + api_port = config['api_port'] + web_port = config['web_port'] + + print("\n📊 服务状态:") + print("-" * 40) + + api_pid = get_pid(API_PID_FILE) + if api_pid and is_process_running(api_pid): + print(f"✅ 后端 API: 运行中 (PID: {api_pid}, 端口: {api_port})") + else: + print(f"❌ 后端 API: 未运行 (端口: {api_port})") + + web_pid = get_pid(WEB_PID_FILE) + if web_pid and is_process_running(web_pid): + print(f"✅ Web 服务: 运行中 (PID: {web_pid}, 端口: {web_port})") + else: + print(f"❌ Web 服务: 未运行 (端口: {web_port})") + + print("-" * 40) + print("\n🌐 访问地址:") + print(f" - 后端 API: http://localhost:{api_port}") + print(f" - Web 页面: http://localhost:{web_port}/web/pages/main.html") + print() + + +def main(): + if len(sys.argv) < 2: + print("用法: python start_all.py {start|stop|restart|status}") + print() + print("命令:") + print(" start - 启动所有服务") + print(" stop - 停止所有服务") + print(" restart - 重启所有服务") + print(" status - 查看服务状态") + sys.exit(1) + + command = sys.argv[1].lower() + + print("====================================") + print("YG_FT_Base 统一启动脚本 (Python版)") + print("====================================") + print() + + config = load_config() + print(f"📦 端口配置:") + print(f" - 后端 API: {config['api_port']}") + print(f" - Web 服务: {config['web_port']}") + print() + + if command == 'start': + start_api() + start_web() + print() + print("====================================") + print("所有服务已启动!") + print("====================================") + show_status() + + elif command == 'stop': + stop_all() + print("✅ 所有服务已停止") + + elif command == 'restart': + stop_all() + time.sleep(1) + start_api() + start_web() + print() + print("====================================") + print("所有服务已重启!") + print("====================================") + show_status() + + elif command == 'status': + show_status() + + else: + print(f"❌ 未知命令: {command}") + print("用法: python start_all.py {start|stop|restart|status}") + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/start_all.sh b/start_all.sh new file mode 100644 index 0000000..8e1d10d --- /dev/null +++ b/start_all.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# YG_FT_Base 统一启动脚本 +# 同时启动后端 API 服务和 Web 静态服务器 +# 使用方法: bash start_all.sh + +# 自动修复脚本换行符 +if grep -q $'\r' "$0"; then + echo "检测到 Windows 换行符,自动修复中..." + sed -i 's/\r$//' "$0" + echo "修复完成,重新执行脚本..." + exec "$0" +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +echo "====================================" +echo "YG_FT_Base 统一启动脚本" +echo "====================================" +echo "" + +# 读取配置 +CONFIG_FILE="$SCRIPT_DIR/config.yaml" +if [ -f "$CONFIG_FILE" ]; then + API_PORT=$(python3 -c "import yaml; print(yaml.safe_load(open('$CONFIG_FILE'))['app'].get('port', 7861))" 2>/dev/null) + WEB_PORT=$(python3 -c "import yaml; print(yaml.safe_load(open('$CONFIG_FILE'))['app'].get('web_port', 7862))" 2>/dev/null) + [ -z "$API_PORT" ] && API_PORT=7861 + [ -z "$WEB_PORT" ] && WEB_PORT=7862 +else + API_PORT=7861 + WEB_PORT=7862 +fi + +echo "📦 端口配置:" +echo " - 后端 API: $API_PORT" +echo " - Web 服务器: $WEB_PORT" +echo "" + +# 检查端口是否已被占用 +check_port() { + if lsof -i:$1 &> /dev/null || netstat -tuln | grep -q ":$1 " 2>/dev/null; then + return 1 + fi + return 0 +} + +# 启动后端 API 服务 +start_api() { + echo "🚀 启动后端 API 服务..." + if [ -f "requirements.txt" ]; then + if [ -d "B_venv" ]; then + source B_venv/bin/activate + else + echo "⚠️ 虚拟环境不存在,请先运行 create_venv.sh 创建" + return 1 + fi + fi + + # 检查端口 + if ! check_port $API_PORT; then + echo "❌ 端口 $API_PORT 已被占用,后端服务可能已在运行" + return 1 + fi + + python src/main.py & + API_PID=$! + echo "✅ 后端服务已启动 (PID: $API_PID, 端口: $API_PORT)" + echo "$API_PID" > /tmp/ygft_api.pid +} + +# 启动 Web 静态服务器 +start_web() { + echo "" + echo "🚀 启动 Web 静态服务器..." + cd "$SCRIPT_DIR/web" + + # 检查端口 + if ! check_port $WEB_PORT; then + echo "⚠️ 端口 $WEB_PORT 已被占用,Web 服务可能已在运行" + return 1 + fi + + python3 -m http.server $WEB_PORT & + WEB_PID=$! + echo "✅ Web 服务已启动 (PID: $WEB_PID, 端口: $WEB_PORT)" + echo "$WEB_PID" > /tmp/ygft_web.pid +} + +# 停止服务 +stop_all() { + echo "" + echo "🛑 停止所有服务..." + + if [ -f /tmp/ygft_api.pid ]; then + kill $(cat /tmp/ygft_api.pid) 2>/dev/null + rm /tmp/ygft_api.pid + echo "✅ 后端服务已停止" + fi + + if [ -f /tmp/ygft_web.pid ]; then + kill $(cat /tmp/ygft_web.pid) 2>/dev/null + rm /tmp/ygft_web.pid + echo "✅ Web 服务已停止" + fi + + # 清理可能残留的进程 + pkill -f "src/main.py" 2>/dev/null + pkill -f "http.server $WEB_PORT" 2>/dev/null +} + +# 显示状态 +status() { + echo "" + echo "📊 服务状态:" + echo "" + + if [ -f /tmp/ygft_api.pid ] && kill -0 $(cat /tmp/ygft_api.pid) 2>/dev/null; then + echo "✅ 后端 API: 运行中 (PID: $(cat /tmp/ygft_api.pid), 端口: $API_PORT)" + else + echo "❌ 后端 API: 未运行" + fi + + if [ -f /tmp/ygft_web.pid ] && kill -0 $(cat /tmp/ygft_web.pid) 2>/dev/null; then + echo "✅ Web 服务: 运行中 (PID: $(cat /tmp/ygft_web.pid), 端口: $WEB_PORT)" + else + echo "❌ Web 服务: 未运行" + fi + + echo "" + echo "🌐 访问地址:" + echo " - 后端 API: http://localhost:$API_PORT" + echo " - Web 页面: http://localhost:$WEB_PORT/pages/main.html" +} + +# 主菜单 +case "$1" in + start) + start_api + start_web + echo "" + echo "====================================" + echo "所有服务已启动!" + echo "====================================" + status + ;; + stop) + stop_all + echo "✅ 所有服务已停止" + ;; + restart) + stop_all + sleep 1 + start_api + start_web + echo "" + echo "====================================" + echo "所有服务已重启!" + echo "====================================" + status + ;; + status) + status + ;; + *) + echo "用法: $0 {start|stop|restart|status}" + echo "" + echo "命令:" + echo " start - 启动所有服务" + echo " stop - 停止所有服务" + echo " restart - 重启所有服务" + echo " status - 查看服务状态" + exit 1 + ;; +esac diff --git a/web/favicon.ico b/web/favicon.ico new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/web/favicon.ico @@ -0,0 +1 @@ + diff --git a/web/pages/custom-tool-create.html b/web/pages/custom-tool-create.html index 39e94f2..7a6ad81 100644 --- a/web/pages/custom-tool-create.html +++ b/web/pages/custom-tool-create.html @@ -253,11 +253,11 @@