侧边栏壁纸
博主头像
云BLOG 博主等级

行动起来,活在当下

  • 累计撰写 318 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Debian12 AI 服务器 终极完整版脚本(顶级模型最终版)

Administrator
2025-12-22 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

Debian12 AI 服务器 终极完整版脚本(顶级模型最终版)

该版本补充 Claude 3.7 Sonnet、Meta 全系列顶级模型,优化量化策略(12-25B 默认 Q6/Q8、30B + 默认 Q4),适配大显存 / 硬盘环境,满足极致测试需求。

一、一键创建 + 执行最终版脚本

步骤 1:切换 root 权限(必做)

sudo -i

步骤 2:创建最终版脚本文件

#!/bin/bash
# Debian12 AI服务器终极完整版脚本(顶级模型最终版)
# 核心升级:补充Claude 3.7 Sonnet/Meta全系列+优化量化策略(12-25B Q6/Q8、30B+ Q4)
# 适配环境:大显存(RTX5060Ti 16G)+ 充足硬盘空间
# 
# ========== 使用手册 ==========
# 
# **一、 核心功能与特点**
# 
# 1.  **多端口并发服务**: 脚本默认配置了多组LM Studio远程推理端口(`LM_PORTS`)和对应的Open WebUI网页端口(`WEB_PORTS`)。
#     这允许多个模型实例并行运行,或为不同用户提供隔离的服务,提高了灵活性和可用性。
# 2.  **智能量化推荐**: 根据模型大小和您的硬件(RTX 5060 Ti 16G显存),脚本会推荐合适的量化级别(Q4, Q5, Q6, Q8),
#     在模型精度和显存占用之间取得平衡。
# 3.  **一键部署**: `system_init` 功能可以自动完成驱动、CUDA、Docker、LM Studio的安装和基本配置,并设置服务开机自启。
# 4.  **模型管理**: 提供下载、参数配置(上下文长度、批处理大小、显存分配等)、更新检查等功能。
# 5.  **系统监控与运维**: 包含服务状态查看、性能监控(GPU/CPU/内存)、日志查看、自动备份、性能告警(如GPU利用率过高)等功能。
# 
# **二、 重要配置项详解**
# 
# 1.  **`set -e`**: 这是一个重要的Shell选项,表示当脚本中的任何命令返回非零状态码(执行失败)时,脚本会立即退出。
#     这有助于在安装或配置过程中发现问题时及时停止,避免后续错误操作。
# 2.  **`LM_PORTS` (`("12345" "12346" "12347")`)**: 这是定义LM Studio远程推理服务监听端口的数组。脚本默认设置了三个端口 `12345`, `12346`, `12347`。
# 3.  **`WEB_PORTS` (`("8080" "8081" "8082")`)**: 这是定义Open WebUI服务监听端口的数组。脚本默认设置了三个端口 `8080`, `8081`, `8082`。
# 4.  **端口对应关系**: 脚本设计为 `LM_PORTS` 中的第N个端口与 `WEB_PORTS` 中的第N个端口形成一组服务。例如:
#     *   `LM_PORT[0]` (12345) 对应 `WEB_PORT[0]` (8080)
#     *   `LM_PORT[1]` (12346) 对应 `WEB_PORT[1]` (8081)
#     *   `LM_PORT[2]` (12347) 对应 `WEB_PORT[2]` (8082)
#     *   访问 `http://你的服务器IP:8080` 即可连接到运行在12345端口上的LM Studio模型。
# 5.  **`MODEL_DIR` (`$HOME/.cache/lm-studio/models`)**: 这是下载和存放模型文件的默认目录。
# 6.  **`BACKUP_DIR` (`/root/ai_model_backup`)**: 这是模型自动备份(每日执行,保留7天)的存放目录。
# 7.  **`ALERT_THRESHOLD` (`"90"`)**: 这是GPU利用率的告警阈值,单位为百分比。当GPU利用率持续高于此值时,系统会尝试发送邮件告警(需要mailutils配置好)。
# 
# **三、 端口选择建议**
# 
# *   **默认端口**: 脚本提供的默认端口 `LM_PORTS=("12345" "12346" "12347")` 和 `WEB_PORTS=("8080" "8081" "8082")` 是经过预设的,可以直接使用。
#     这些端口通常不会与其他常见服务冲突。
# *   **如何选择**:
#     *   如果你只需要一个AI服务实例,可以只关注第一组端口,即LM端口 `12345` 和Web端口 `8080`。
#     *   如果你需要运行多个模型或提供多个访问入口,可以保留这三组端口,或者根据需要添加更多组。
#     *   **注意事项**:
#         *   确保选择的端口在你的服务器上没有被其他服务占用。
#         *   如果你的服务器位于防火墙或路由器后面,需要在防火墙上放行这些端口(例如,如果使用UFW,脚本会在`system_init`中自动放行配置的端口)。
#         *   如果你想更改端口,直接修改脚本开头的 `LM_PORTS` 和 `WEB_PORTS` 数组即可。修改后需要重新运行 `system_init` 或手动管理(启动/重启)相应的服务。
# 
# **四、 `multi_port_manage` 函数中“添加新端口”的说明**
# 
# 在 `multi_port_manage` 函数的“5. 添加新端口”功能中,代码 `WEB_PORTS+=("$new_web_port")` 是正确的。
# 其目的是将用户输入的新的Web端口(`$new_web_port`)添加到 `WEB_PORTS` 数组中,与用户输入的新的LM端口(`$new_lm_port`)一起,形成一个新的服务端口对。
# 这样可以保证新添加的LM服务和Web服务能够正确地通过各自的端口进行通信和访问。
# 
# **总结**:
# 这份脚本是一个功能强大的AI模型部署工具。其核心在于多端口管理和智能量化。对于端口,直接使用默认的 `12345/12346/12347` (LM) 和 `8080/8081/8082` (Web) 是一个稳妥的选择,
# 它们满足了多实例并发的需求且通常无冲突。
set -e
# ========== 基础配置(可自定义,新手直接用默认值) ==========
# 多端口配置(新增/删减端口直接修改此数组)
LM_PORTS=("12345" "12346" "12347")  # 推荐保留3个端口,可扩展至更多
# 多端口Web界面配置(每个端口对应独立Web服务)
WEB_PORTS=("8080" "8081" "8082")    # 与LM_PORTS一一对应
LM_LOG_BASE="/var/log/lmstudio"
WEBUI_BASE_NAME="open-webui"
MODEL_DIR="$HOME/.cache/lm-studio/models"
BACKUP_DIR="/root/ai_model_backup"
ALERT_THRESHOLD="90"  # GPU利用率告警阈值(%)
# 模型更新接口(可替换为真实API实现自动更新)
UPDATE_CHECK_URL="https://api.lmstudio.ai/v1/models"
# 硬件配置(无需修改,适配5700G/RTX5060Ti/32G+充足硬盘)
CPU_MODEL="AMD Ryzen 7 5700G"
GPU_MODEL="RTX5060Ti 16G"
GPU_MEM="16GB"
SYSTEM_MEM="32GB DDR4"
DISK_SPACE="1TB+"  # 充足硬盘空间,支持高量化级别
# 创建必要目录
mkdir -p $MODEL_DIR $BACKUP_DIR $LM_LOG_BASE
# ========== 辅助函数:检查并安装必要依赖 ==========
ensure_dependencies() {
    echo -e "\033[33m[依赖检查] 正在检查必要命令...\033[0m"
    local missing_deps=()
    if ! command -v lms &> /dev/null; then
        echo -e "\033[33m[依赖检查] 'lms' 命令未找到,尝试安装 LM Studio...\033[0m"
        missing_deps+=("lmstudio")
    fi
    if ! command -v docker &> /dev/null; then
        echo -e "\033[33m[依赖检查] 'docker' 命令未找到,尝试安装 Docker...\033[0m"
        missing_deps+=("docker")
    fi
    # nvidia-smi 可能没有,但不是所有操作都必须,所以这里只检查不强制安装
    if ! command -v nvidia-smi &> /dev/null; then
        echo -e "\033[33m[依赖检查] 'nvidia-smi' 命令未找到。若需GPU监控,请确保NVIDIA驱动已安装。\033[0m"
    fi
    if [ ${#missing_deps[@]} -gt 0 ]; then
        echo -e "\033[33m[依赖检查] 发现缺失依赖: ${missing_deps[*]}\033[0m"
        read -p "是否尝试自动安装缺失的依赖 (Docker, LM Studio)?(y/N): " confirm_install
        if [[ $confirm_install =~ ^[Yy]$ ]]; then
            apt update
            # 安装 Docker
            if [[ " ${missing_deps[@]} " =~ " docker " ]]; then
                echo -e "\033[32m[安装] 正在安装 Docker...\033[0m"
                apt install -y docker.io docker-compose
                systemctl start docker
                systemctl enable docker
            fi
            # 安装 LM Studio
            if [[ " ${missing_deps[@]} " =~ " lmstudio " ]]; then
                echo -e "\033[32m[安装] 正在安装 LM Studio...\033[0m"
                # 安装基础依赖
                apt install -y wget curl git vim libvulkan1 mesa-vulkan-drivers libfuse2 build-essential software-properties-common apt-transport-https dirmngr jq
                # 下载并安装 LM Studio
                wget $(curl -s https://api.github.com/repos/lmstudio-ai/lmstudio/releases/latest | grep "browser_download_url.*amd64.deb" | cut -d '"' -f 4) -O lm-studio-latest.deb
                dpkg -i lm-studio-latest.deb
                apt install -f -y # 解决依赖
                rm -f lm-studio-latest.deb
            fi
            echo -e "\033[32m[安装] 依赖安装完成,正在重新检查...\033[0m"
        else
            echo -e "\033[31m❌ 用户取消安装依赖。请手动安装 Docker 和 LM Studio。\033[0m"
            exit 1
        fi
    fi
    # 再次检查
    local final_missing=()
    if ! command -v lms &> /dev/null; then
        final_missing+=("lms")
    fi
    if ! command -v docker &> /dev/null; then
        final_missing+=("docker")
    fi
    if [ ${#final_missing[@]} -gt 0 ]; then
        echo -e "\033[31m❌ 严重错误: 安装后仍有命令无法找到: ${final_missing[*]}\033[0m"
        echo -e "\033[31m    请检查安装过程是否有误,或手动安装后再运行脚本。\033[0m"
        exit 1
    fi
    echo -e "\033[32m[依赖检查] 所有必要命令均已准备就绪!\033[0m"
}
# ========== 核心函数0:智能量化推荐(优化版) ==========
quant_recommend() {
    local model_size=$1
    local quant_type=$2  # q4/q5/q6/q8,区分不同量化级别
    local gpu_mem=$GPU_MEM
    local recommend_quant=""
    # 提取数字部分(如30B→30,16B→16)
    local size_num=$(echo $model_size | grep -o '[0-9]\+')
    if [ -z "$size_num" ]; then
        recommend_quant="Q6_K"  # 默认值升级为Q6
        return
    fi
    # 智能推荐逻辑(适配RTX5060Ti 16G+充足硬盘)
    if [ $size_num -le 10 ]; then
        recommend_quant="Q8_0"  # 10B以下优先最高精度Q8
    elif [ $size_num -ge 11 ] && [ $size_num -le 25 ]; then
        if [ "$quant_type" = "q8" ]; then
            recommend_quant="Q8_0"  # 11-25B最高精度Q8(推荐)
        elif [ "$quant_type" = "q6" ]; then
            recommend_quant="Q6_K"  # 11-25B平衡精度Q6(默认)
        elif [ "$quant_type" = "q5" ]; then
            recommend_quant="Q5_K_M"  # Q5版本(仅测试)
        else
            recommend_quant="Q6_K"  # 默认Q6
        fi
    elif [ $size_num -ge 26 ] && [ $size_num -le 35 ]; then
        if [ "$quant_type" = "q6" ]; then
            recommend_quant="Q6_K"  # 26-35B Q6(显存紧张,仅测试)
        elif [ "$quant_type" = "q5" ]; then
            recommend_quant="Q5_K_M"  # Q5版本(仅测试)
        else
            recommend_quant="Q4_K_M"  # 26-35B适配Q4(推荐)
        fi
    else
        recommend_quant="Q4_K_M"  # 35B+默认Q4
    fi
    # 交互式选择(引导式设置,新手直接选5用推荐值)
    echo -e "\033[32m===== 智能量化推荐 =====\033[0m"
    local quant_note=""
    if [ "$quant_type" = "q5" ]; then
        quant_note="(⚠️ Q5版本:仅测试,不推荐日常使用)"
    elif [ "$quant_type" = "q4" ] && [ $size_num -le 25 ]; then
        quant_note="(⚠️ 11-25B不推荐Q4,建议选Q6/Q8)"
    elif [ "$quant_type" = "q8" ]; then
        quant_note="(✅ Q8版本:最高精度,推荐11-25B使用)"
    fi
    echo "模型规模:$model_size | GPU显存:$gpu_mem | 硬盘空间:$DISK_SPACE | 推荐量化级别:$recommend_quant $quant_note"
    echo "可选量化级别(精度从高到低):"
    echo "1. Q8_0(最高精度,显存占用最大,推荐11-25B)"
    echo "2. Q6_K(平衡精度/显存,11-25B默认,推荐)"
    echo "3. Q5_K_M(⚠️ 显存紧张,仅测试)"
    echo "4. Q4_K_M(适配大模型,推荐26-35B使用)"
    echo "5. 使用推荐值($recommend_quant,新手推荐)"
    read -p "输入量化级别编号(1-5): " quant_choice
    case $quant_choice in
        1) recommend_quant="Q8_0" ;;
        2) recommend_quant="Q6_K" ;;
        3) recommend_quant="Q5_K_M" ;;
        4) recommend_quant="Q4_K_M" ;;
        5) ;; # 使用推荐值
        *) 
            echo -e "\033[31m无效选择,自动使用推荐值:$recommend_quant\033[0m"
            sleep 1
            ;;
    esac
    echo $recommend_quant
}
# ========== 核心函数1:系统初始化(一站式部署) ==========
system_init() {
    clear
    echo -e "\033[34m===== 第一步:系统初始化(驱动/CUDA/多端口/Web)=====\033[0m"
    # 1. 系统更新+基础依赖(自动安装,无需手动操作)
    echo -e "\033[32m[1/9] 系统更新及基础依赖安装...\033[0m"
    apt update && apt upgrade -y
    apt install -y wget curl git vim libvulkan1 mesa-vulkan-drivers libfuse2 build-essential software-properties-common apt-transport-https dirmngr ufw docker.io docker-compose mailutils jq
    # 2. 禁用nouveau开源驱动(NVIDIA必做)
    echo -e "\033[32m[2/9] 禁用nouveau开源驱动...\033[0m"
    echo "blacklist nouveau" > /etc/modprobe.d/blacklist.conf
    echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist.conf
    update-initramfs -u
    # 3. 添加NVIDIA官方源+安装驱动+CUDA12.8
    echo -e "\033[32m[3/9] 安装NVIDIA驱动及CUDA12.8...\033[0m"
    curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/3bf863cc.pub | gpg --dearmor -o /usr/share/keyrings/nvidia-drivers.gpg
    echo "deb [signed-by=/usr/share/keyrings/nvidia-drivers.gpg] https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/ /" > /etc/apt/sources.list.d/nvidia-cuda.list
    apt update
    apt install -y nvidia-driver nvidia-cuda-toolkit
    # 4. 安装LM Studio(自动拉取最新版)
    echo -e "\033[32m[4/9] 安装最新版LM Studio...\033[0m"
    wget $(curl -s https://api.github.com/repos/lmstudio-ai/lmstudio/releases/latest | grep "browser_download_url.*amd64.deb" | cut -d '"' -f 4) -O lm-studio-latest.deb
    dpkg -i lm-studio-latest.deb && apt install -f -y && rm -f lm-studio-latest.deb
    # 5. 配置多端口+多Web界面开机自启
    echo -e "\033[32m[5/9] 配置多端口+多Web界面开机自启...\033[0m"
    # 清空原有定时任务
    sed -i '/lm-studio --remote-inference/d' /etc/crontab
    sed -i '/docker run.*open-webui/d' /etc/crontab
    # 多端口LM Studio API开机自启
    for port in "${LM_PORTS[@]}"; do
        echo "@reboot root nohup lm-studio --remote-inference --remote-port $port > $LM_LOG_BASE/lmstudio_$port.log 2>&1 &" >> /etc/crontab
    done
    # 多端口Web界面开机自启(与LM_PORTS一一对应)
    for i in "${!LM_PORTS[@]}"; do
        local lm_port=${LM_PORTS[$i]}
        local web_port=${WEB_PORTS[$i]}
        local webui_name="${WEBUI_BASE_NAME}_$lm_port"
        echo "@reboot root docker run -d --name $webui_name -p $web_port:8080 -e \"LMSTUDIO_BASE_URL=http://localhost:$lm_port\" --restart always ghcr.io/open-webui/open-webui:main" >> /etc/crontab
    done
    # 6. 系统优化(纯命令行+防火墙+性能调优)
    echo -e "\033[32m[6/9] 系统优化(纯命令行+防火墙)...\033[0m"
    systemctl set-default multi-user.target > /dev/null 2>&1 || true
    # 放行多端口+Web端口
    for port in "${LM_PORTS[@]}"; do
        ufw allow $port/tcp
    done
    for port in "${WEB_PORTS[@]}"; do
        ufw allow $port/tcp
    done
    ufw --force enable
    swapoff -a && echo "vm.swappiness=10" >> /etc/sysctl.conf && sysctl -p
    # 7. 性能告警脚本开机自启
    echo -e "\033[32m[7/9] 配置性能告警...\033[0m"
    sed -i '/GPU利用率告警/d' /etc/crontab
    echo "@reboot root /bin/bash -c 'while true; do GPU_UTIL=\$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits | awk '\''{print \$1}'\'''); if [ \$GPU_UTIL -ge $ALERT_THRESHOLD ]; then echo \"GPU利用率告警:\$GPU_UTIL%(阈值$ALERT_THRESHOLD%)\" | mail -s \"AI服务器GPU告警\" root; fi; sleep 60; done' &" >> /etc/crontab
    # 8. 自动备份+自动更新检查初始化
    echo -e "\033[32m[8/9] 初始化模型自动备份+自动更新检查...\033[0m"
    sed -i '/models_*.tar.gz/d' /etc/crontab
    # 每日0点备份模型(保留7天)
    echo "0 0 * * * root tar -zcf $BACKUP_DIR/models_$(date +\%Y\%m\%d).tar.gz $MODEL_DIR --exclude='*.tmp' && find $BACKUP_DIR -name 'models_*.tar.gz' -mtime +7 -delete" >> /etc/crontab
    # 每日9点检查模型更新(自动提示)
    echo "0 9 * * * root /bin/bash -c 'cd /root && /ai_server_ultimate_final.sh --auto-check-update' >> $LM_LOG_BASE/auto_update_check.log 2>&1" >> /etc/crontab
    # 9. 验证安装
    echo -e "\033[32m[9/9] 验证安装...\033[0m"
    nvidia-smi > /dev/null 2>&1 && echo "✅ NVIDIA驱动安装成功" || echo "❌ NVIDIA驱动安装失败"
    docker --version > /dev/null 2>&1 && echo "✅ Docker安装成功" || echo "❌ Docker安装失败"
    lm-studio --version > /dev/null 2>&1 && echo "✅ LM Studio安装成功" || echo "❌ LM Studio安装失败"
    echo -e "\033[32m系统初始化完成!重启后所有服务自动生效...\033[0m"
    read -p "按Enter键重启系统(必须重启)..."
    reboot
}
# ========== 核心函数2:启动LM Studio多端口+多Web API ==========
start_lm_multi_api() {
    echo -e "\033[32m[提示] 启动LM Studio多端口+多Web服务...\033[0m"
    # 启动多端口LM Studio API
    for port in "${LM_PORTS[@]}"; do
        if ! ps aux | grep -v grep | grep "lm-studio --remote-inference --remote-port $port" >/dev/null; then
            nohup lm-studio --remote-inference --remote-port $port > $LM_LOG_BASE/lmstudio_$port.log 2>&1 &
            echo "  LM Studio端口$port:已启动"
            sleep 2
        else
            echo "  LM Studio端口$port:已运行"
        fi
    done
    # 启动多端口Web界面
    for i in "${!LM_PORTS[@]}"; do
        local lm_port=${LM_PORTS[$i]}
        local web_port=${WEB_PORTS[$i]}
        local webui_name="${WEBUI_BASE_NAME}_$lm_port"
        if ! docker ps | grep $webui_name >/dev/null; then
            docker run -d --name $webui_name -p $web_port:8080 -e "LMSTUDIO_BASE_URL=http://localhost:$lm_port" --restart always ghcr.io/open-webui/open-webui:main
            echo "  Web界面端口$web_port(关联LM$lm_port):已启动"
        else
            echo "  Web界面端口$web_port(关联LM$lm_port):已运行"
        fi
    done
}
# ========== 核心函数3:模型下载(支持Q4/Q5/Q6/Q8全量化) ==========
download_model() {
    ensure_dependencies # 在下载模型前确保依赖存在
    local model_id=$1
    local model_name=$2
    local model_size=$3
    local quant_type=$4  # q4/q5/q6/q8
    # 智能量化推荐+交互式选择
    local quant_level=$(quant_recommend "$model_size" "$quant_type")
    echo -e "\033[32m开始下载:$model_name | 量化级别:$quant_level\033[0m"
    lms download --model $model_id --quantization $quant_level --save-path $MODEL_DIR
    echo -e "\033[32m$model_name 下载完成!\033[0m"
    # 配置模型运行参数(增强版+多端口绑定)
    config_model_params $model_name $quant_level
}
# ========== 核心函数4:自定义模型下载(新手友好指引) ==========
custom_model_download() {
    ensure_dependencies # 在下载模型前确保依赖存在
    clear
    echo -e "\033[34m===== 自定义模型下载(HuggingFace/镜像站)=====\033[0m"
    echo "📌 新手指引:"
    echo "   1. HuggingFace地址格式:用户名/模型名(如anthropic/Claude-3.7-Sonnet)"
    echo "   2. 镜像站地址格式:https://hf-mirror.com/用户名/模型名"
    echo "   3. 模型规模格式:8B/16B/30B(仅数字+B,如30B)"
    read -p "输入模型HuggingFace ID或镜像站链接: " custom_model_id
    read -p "输入模型规模(如8B/16B/30B): " custom_model_size
    read -p "选择量化版本(q8=最高精度/q6=平衡/q5=测试/q4=大模型,输入对应值): " custom_quant_type
    # 自动处理镜像站链接格式(新手无需手动修改)
    if [[ $custom_model_id == *"hf-mirror.com"* ]]; then
        custom_model_id=$(echo $custom_model_id | awk -F '/' '{print $(NF-1)"/"$NF}')
        echo -e "\033[32m自动解析镜像站链接为:$custom_model_id\033[0m"
    fi
    # 智能量化+下载
    local quant_level=$(quant_recommend "$custom_model_size" "$custom_quant_type")
    echo -e "\033[32m开始下载自定义模型:$custom_model_id | 量化级别:$quant_level\033[0m"
    lms download --model $custom_model_id --quantization $quant_level --save-path $MODEL_DIR
    echo -e "\033[32m自定义模型下载完成!\033[0m"
    # 配置运行参数
    config_model_params "自定义模型($custom_model_id)" $quant_level
}
# ========== 核心函数5:增强型模型运行参数配置 ==========
config_model_params() {
    local model_name=$1
    local quant_level=$2
    local target_port=""
    local target_web_port=""
    clear
    echo -e "\033[34m===== 增强型配置$model_name 运行参数 =====\033[0m"
    echo "🔗 多端口选择(每个端口对应独立推理+Web实例):"
    for i in "${!LM_PORTS[@]}"; do
        echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
    done
    read -p "选择模型绑定的端口编号(新手推荐1): " port_idx
    target_port=${LM_PORTS[$((port_idx-1))]}
    target_web_port=${WEB_PORTS[$((port_idx-1))]}
    # 智能推荐参数(适配5700G/RTX5060Ti+高量化级别)
    local ctx_length="4096"
    local batch_size="1024"
    local gpu_mem_alloc="15GB"
    local num_threads="8"  # 5700G 8核最优
    local temperature="0.7"
    local top_p="0.9"
    # 根据量化级别调整显存分配
    if [ "$quant_level" = "Q8_0" ]; then
        gpu_mem_alloc="14GB"
        ctx_length="2048"
        batch_size="512"
        echo -e "\033[33m⚠️ Q8量化版本:自动调整显存分配为14GB,保证精度\033[0m"
    elif [ "$quant_level" = "Q6_K" ]; then
        gpu_mem_alloc="14.5GB"
        ctx_length="3072"
        batch_size="768"
    elif [ "$quant_level" = "Q5_K_M" ]; then
        gpu_mem_alloc="13GB"
        echo -e "\033[33m⚠️ Q5量化版本:自动调整显存分配为13GB,避免溢出\033[0m"
    fi
    # 交互式配置(新手直接回车用推荐值)
    echo -e "\033[32m💡 智能推荐参数(基于$quant_level + 端口$target_port):\033[0m"
    read -p "上下文长度(推荐$ctx_length): " input_ctx
    read -p "批处理大小(推荐$batch_size): " input_batch
    read -p "GPU显存分配(推荐$gpu_mem_alloc): " input_gpu_mem
    read -p "CPU线程数(推荐$num_threads): " input_threads
    read -p "温度值(推荐$temperature): " input_temp
    read -p "Top-P值(推荐$top_p): " input_topp
    # 使用输入值或推荐值(新手回车即默认)
    ctx_length=${input_ctx:-$ctx_length}
    batch_size=${input_batch:-$batch_size}
    gpu_mem_alloc=${input_gpu_mem:-$gpu_mem_alloc}
    num_threads=${input_threads:-$num_threads}
    temperature=${input_temp:-$temperature}
    top_p=${input_topp:-$top_p}
    # 写入LM Studio配置文件(按端口区分)
    LM_CONFIG="$HOME/.config/lm-studio/config_$target_port.json"
    mkdir -p $(dirname $LM_CONFIG)
    cp $LM_CONFIG $LM_CONFIG.bak 2>/dev/null || true
    # 更新配置(JSON格式)
    jq --arg model "$model_name" --arg ctx "$ctx_length" --arg batch "$batch_size" \
       --arg gpu_mem "$gpu_mem_alloc" --arg threads "$num_threads" --arg temp "$temperature" \
       --arg topp "$top_p" --arg port "$target_port" --arg web_port "$target_web_port" \
       '.modelSettings[$model] = {
           contextLength: $ctx, 
           batchSize: $batch, 
           gpuMemoryAllocation: $gpu_mem,
           cpuThreads: $threads,
           temperature: $temp,
           topP: $topp,
           bindPort: $port,
           webPort: $web_port
       }' $LM_CONFIG 2>/dev/null || echo "{
           \"modelSettings\": {
               \"$model_name\": {
                   \"contextLength\": \"$ctx_length\",
                   \"batchSize\": \"$batch_size\",
                   \"gpuMemoryAllocation\": \"$gpu_mem_alloc\",
                   \"cpuThreads\": \"$num_threads\",
                   \"temperature\": \"$temperature\",
                   \"topP\": \"$top_p\",
                   \"bindPort\": \"$target_port\",
                   \"webPort\": \"$target_web_port\"
               }
           }
       }" > $LM_CONFIG
    echo -e "\033[32m✅ $model_name 运行参数配置完成!\033[0m"
    echo "📋 配置信息:"
    echo "   绑定LM端口:$target_port | 绑定Web端口:$target_web_port"
    echo "   上下文长度:$ctx_length | 批处理大小:$batch_size"
    echo "   GPU显存:$gpu_mem_alloc | CPU线程:$num_threads"
    echo "   温度值:$temperature | Top-P:$top_p"
    sleep 2
}
# ========== 核心函数6:模型更新检查(手动+自动) ==========
check_model_update() {
    # 自动检查模式(每日9点运行)
    if [ "$1" = "--auto" ]; then
        local models=($(ls -1 $MODEL_DIR | grep -v "tmp" | grep -v "bak" | grep -v ".tar.gz"))
        local update_count=0
        for model in "${models[@]}"; do
            local core_name=$(echo $model | awk -F '-' '{print $1"-"$2}' | sed 's/_/-/g')
            local update_available=$(curl -s $UPDATE_CHECK_URL/$core_name | jq -r '.updateAvailable // "false"')
            if [ "$update_available" = "true" ]; then
                echo "$(date +%Y-%m-%d\ %H:%M:%S) - ⚠️ $model 有新版本可用" >> $LM_LOG_BASE/auto_update_check.log
                update_count=$((update_count+1))
            fi
        done
        if [ $update_count -gt 0 ]; then
            echo "$(date +%Y-%m-%d\ %H:%M:%S) - 共有$update_count个模型可更新,请手动运行脚本选择6进行更新" >> $LM_LOG_BASE/auto_update_check.log
            echo "共有$update_count个模型可更新" | mail -s "AI服务器模型更新提示" root
        fi
        return 0
    fi
    # 手动检查模式(菜单操作)
    clear
    echo -e "\033[34m===== 模型更新检查(手动+自动提示)=====\033[0m"
    local models=($(ls -1 $MODEL_DIR | grep -v "tmp" | grep -v "bak" | grep -v ".tar.gz"))
    if [ ${#models[@]} -eq 0 ]; then
        echo -e "\033[31m❌ 无已下载模型,请先下载模型!\033[0m"
        sleep 2
        return 0
    fi
    # 列出模型供选择检查(新手可选0检查所有)
    echo "📋 已下载模型列表:"
    for i in "${!models[@]}"; do
        echo "$((i+1)). ${models[$i]}"
    done
    echo "0. 检查所有模型(新手推荐)"
    read -p "输入要检查更新的模型编号: " model_idx
    # 确定检查范围
    local check_models=()
    if [ $model_idx -eq 0 ]; then
        check_models=("${models[@]}")
    else
        check_models=("${models[$((model_idx-1))]}")
    fi
    # 检查更新(新手友好提示)
    for model in "${check_models[@]}"; do
        echo -e "\033[32m🔍 正在检查$model 更新...\033[0m"
        local core_name=$(echo $model | awk -F '-' '{print $1"-"$2}' | sed 's/_/-/g')
        local update_available=$(curl -s $UPDATE_CHECK_URL/$core_name | jq -r '.updateAvailable // "false"')
        if [ "$update_available" = "true" ] || [ "$update_available" = "" ]; then
            echo -e "\033[33m⚠️  $model 有新版本可用!\033[0m"
            read -p "是否立即更新该模型?(y/n,更新前自动备份): " update_confirm
            if [ "$update_confirm" = "y" ] || [ "$update_confirm" = "Y" ]; then
                # 自动备份旧模型(防止更新失败)
                echo -e "\033[32m📦 正在备份旧模型...\033[0m"
                mv $MODEL_DIR/$model $MODEL_DIR/${model}_old_$(date +%Y%m%d)
                # 重新下载最新版本
                local model_size=$(echo $model | grep -o '[0-9]\+B')
                local quant_type="q6"  # 默认用推荐的Q6版本更新
                local quant_level=$(quant_recommend "$model_size" "$quant_type")
                # 提取模型ID(简化处理)
                local model_id=$(echo $model | sed 's/ /_/g' | sed 's/(.*//g')
                lms download --model $model_id --quantization $quant_level --save-path $MODEL_DIR
                echo -e "\033[32m✅ $model 更新完成!旧模型备份为:${model}_old_$(date +%Y%m%d)\033[0m"
            fi
        else
            echo -e "\033[32m✅ $model 已是最新版本!\033[0m"
        fi
        sleep 1
    done
    echo -e "\033[32m✅ 模型更新检查完成!\033[0m"
    read -p "按Enter键返回菜单..."
}
# ========== 核心函数7:多端口推理+Web管理(新手友好) ==========
multi_port_manage() {
    ensure_dependencies # 在管理多端口前确保依赖存在
    clear
    echo -e "\033[34m===== 多端口推理+Web管理(新手友好)=====\033[0m"
    echo "🔧 当前配置:"
    echo "   LM端口:${LM_PORTS[*]} | Web端口:${WEB_PORTS[*]}"
    echo "   对应关系:LM12345→Web8080、LM12346→Web8081、LM12347→Web8082"
    echo "📌 操作菜单:"
    echo "1. 查看所有端口运行状态(新手常用)"
    echo "2. 重启指定端口服务(LM+Web)"
    echo "3. 停止指定端口服务(LM+Web)"
    echo "4. 绑定模型到指定端口(核心操作)"
    echo "5. 添加新端口(扩展功能)"
    echo "6. 返回主菜单"
    read -p "输入操作编号(新手推荐1): " port_choice
    case $port_choice in
        1)
            echo -e "\033[32m===== 多端口运行状态 =====\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                local lm_port=${LM_PORTS[$i]}
                local web_port=${WEB_PORTS[$i]}
                local webui_name="${WEBUI_BASE_NAME}_$lm_port"
                echo "📡 端口组$((i+1)):"
                echo "   LM端口$lm_port:$(ps aux | grep -v grep | grep "lm-studio --remote-inference --remote-port $lm_port" >/dev/null && "✅ 运行中" || "❌ 未运行")"
                echo "   Web端口$web_port:$(docker ps | grep $webui_name >/dev/null && "✅ 运行中" || "❌ 未运行")"
                echo "   LM日志:$LM_LOG_BASE/lmstudio_$lm_port.log"
                # 查看端口绑定的模型
                local config_file="$HOME/.config/lm-studio/config_$lm_port.json"
                if [ -f $config_file ]; then
                    local bound_models=$(jq -r '.modelSettings | keys[]' $config_file 2>/dev/null | head -1)
                    echo "   绑定模型:${bound_models:-无}"
                else
                    echo "   绑定模型:无"
                fi
                echo "   访问地址:http://服务器IP:$web_port"
                echo "-------------------------"
            done
            ;;
        2)
            echo -e "\033[32m===== 重启指定端口服务 =====\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
            done
            read -p "输入要重启的端口组编号: " port_idx
            local target_lm_port=${LM_PORTS[$((port_idx-1))]}
            local target_web_port=${WEB_PORTS[$((port_idx-1))]}
            local target_webui="${WEBUI_BASE_NAME}_$target_lm_port"
            # 重启LM Studio
            pkill -f "lm-studio --remote-inference --remote-port $target_lm_port" || true
            nohup lm-studio --remote-inference --remote-port $target_lm_port > $LM_LOG_BASE/lmstudio_$target_lm_port.log 2>&1 &
            # 重启Web界面
            docker restart $target_webui || true
            echo -e "\033[32m✅ 端口组$port_idx(LM$target_lm_port+Web$target_web_port)已重启!\033[0m"
            ;;
        3)
            echo -e "\033[32m===== 停止指定端口服务 =====\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
            done
            read -p "输入要停止的端口组编号: " port_idx
            local target_lm_port=${LM_PORTS[$((port_idx-1))]}
            local target_web_port=${WEB_PORTS[$((port_idx-1))]}
            local target_webui="${WEBUI_BASE_NAME}_$target_lm_port"
            # 停止LM Studio
            pkill -f "lm-studio --remote-inference --remote-port $target_lm_port" || true
            # 停止Web界面
            docker stop $target_webui || true
            echo -e "\033[32m✅ 端口组$port_idx(LM$target_lm_port+Web$target_web_port)已停止!\033[0m"
            ;;
        4)
            echo -e "\033[32m===== 绑定模型到指定端口 =====\033[0m"
            # 选择端口组(新手推荐1)
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
            done
            read -p "输入目标端口组编号(新手推荐1): " port_idx
            local target_port=${LM_PORTS[$((port_idx-1))]}
            # 选择模型
            local models=($(ls -1 $MODEL_DIR | grep -v "tmp" | grep -v "bak"))
            if [ ${#models[@]} -eq 0 ]; then
                echo -e "\033[31m❌ 无已下载模型!请先下载模型\033[0m"
                sleep 2
                return 0
            fi
            echo "📋 已下载模型:"
            for i in "${!models[@]}"; do
                echo "$((i+1)). ${models[$i]}"
            done
            read -p "输入要绑定的模型编号: " model_idx
            local selected_model=${models[$((model_idx-1))]}
            # 配置参数并绑定
            local model_size=$(echo $selected_model | grep -o '[0-9]\+B')
            local quant_type="q6"  # 默认用推荐的Q6版本
            local quant_level=$(quant_recommend "$model_size" "$quant_type")
            config_model_params $selected_model $quant_level
            echo -e "\033[32m✅ 模型$selected_model 已绑定到端口组$port_idx!\033[0m"
            echo "   访问地址:http://服务器IP:${WEB_PORTS[$((port_idx-1))]}"
            ;;
        5)
            echo -e "\033[32m===== 添加新端口(扩展功能)=====\033[0m"
            read -p "输入新的LM端口号(如12348): " new_lm_port
            read -p "输入新的Web端口号(如8083): " new_web_port
            # 检查端口是否已存在
            if [[ " ${LM_PORTS[@]} " =~ " $new_lm_port " ]]; then
                echo -e "\033[31m❌ LM端口$new_lm_port 已存在!\033[0m"
                sleep 2
                return 0
            fi
            if [[ " ${WEB_PORTS[@]} " =~ " $new_web_port " ]]; then
                echo -e "\033[31m❌ Web端口$new_web_port 已存在!\033[0m"
                sleep 2
                return 0
            fi
            # 添加新端口到数组
            LM_PORTS+=("$new_lm_port")
            WEB_PORTS+=("$new_web_port") # 修复:添加到WEB_PORTS数组 
	    # WEB_PORTS+=("$new_web_port") # 修复:添加到WEB_PORTS数组 # 可能这个错 WEB_PORTS+=("$new_lm_port") 
            # 放行端口
            ufw allow $new_lm_port/tcp
            ufw allow $new_web_port/tcp
            # 启动新端口服务
            nohup lm-studio --remote-inference --remote-port $new_lm_port > $LM_LOG_BASE/lmstudio_$new_lm_port.log 2>&1 &
            local new_webui="${WEBUI_BASE_NAME}_$new_lm_port"
            docker run -d --name $new_webui -p $new_web_port:8080 -e "LMSTUDIO_BASE_URL=http://localhost:$new_lm_port" --restart always ghcr.io/open-webui/open-webui:main
            echo -e "\033[32m✅ 新端口组添加完成!\033[0m"
            echo "   LM端口:$new_lm_port | Web端口:$new_web_port"
            echo "   访问地址:http://服务器IP:$new_web_port"
            ;;
        6)
            return 0
            ;;
        *)
            echo -e "\033[31m❌ 无效编号,请重新输入\033[0m"
            sleep 1
            ;;
    esac
    read -p "按Enter键返回多端口管理菜单..."
    multi_port_manage
}
# ========== 核心函数8:添加新模型到脚本(新手指引) ==========
add_new_model_to_script() {
    clear
    echo -e "\033[34m===== 添加新模型到脚本(新手友好指引)=====\033[0m"
    echo "📌 新手步骤指引(以添加Claude 3.7 Sonnet为例):"
    echo "1. 找到脚本中『model_menu』函数"
    echo "2. 在对应厂商分类下添加如下代码:"
    echo "   示例:"
    echo "   6. Claude 3.7 Sonnet(20B,推荐Q8_0)"
    echo "   然后在case中添加:"
    echo "   6) download_model \"anthropic/Claude-3.7-Sonnet\" \"Claude 3.7 Sonnet\" \"20B\" \"q8\" ;;"
    echo "3. 保存脚本后重新运行即可看到新模型选项"
    echo ""
    echo "📋 模型信息填写规范:"
    echo "   - download_model参数1:HuggingFace ID(必填)"
    echo "   - download_model参数2:模型显示名称(自定义)"
    echo "   - download_model参数3:模型规模(如20B,用于量化推荐)"
    echo "   - download_model参数4:量化类型(q8=最高精度/q6=平衡/q5=测试/q4=大模型)"
    echo ""
    echo "💡 快速定位方法:"
    echo "   运行:vim /ai_server_ultimate_final.sh"
    echo "   输入:/model_menu 回车(直接定位到模型菜单函数)"
    echo ""
    read -p "按Enter键返回主菜单..."
}
# ========== 一级菜单:主菜单(新手友好) ==========
main_menu() {
    # 自动更新检查模式(后台运行)
    if [ "$1" = "--auto-check-update" ]; then
        check_model_update --auto
        exit 0
    fi
    clear
    echo -e "\033[34m===== AI服务器终极完整版管理菜单(顶级模型最终版)=====\033[0m"
    echo "🔧 硬件配置:$CPU_MODEL | $GPU_MODEL | $SYSTEM_MEM | $DISK_SPACE"
    echo "🌐 多端口配置:LM${LM_PORTS[*]} → Web${WEB_PORTS[*]}"
    echo "📌 新增特性:Claude 3.7 Sonnet/Meta全系列+优化量化策略(12-25B Q6/Q8、30B+ Q4)"
    echo "📌 新手入门推荐流程:1→3→7→访问Web地址"
    echo ""
    echo "1. 全新部署(首次使用必选,全自动安装驱动/CUDA/多端口)"
    echo "2. 服务器运维管理(监控/备份/告警,日常维护)"
    echo "3. 顶级模型下载(含Claude/Meta/Google/DeepSeek全系列)"
    echo "4. 自定义模型下载(支持HuggingFace/镜像站)"
    echo "5. 模型运行参数配置(增强型,多端口绑定)"
    echo "6. 模型更新检查(手动+自动提示,一键更新)"
    echo "7. 多端口推理+Web管理(核心操作,绑定模型/访问)"
    echo "8. 添加新模型到脚本(新手指引,自定义扩展)"
    echo "9. 使用帮助手册(完整版,含所有功能说明)"
    echo "0. 退出脚本"
    echo -e "\033[34m=========================================================================\033[0m"
    read -p "输入操作编号(新手推荐1): " main_choice
    case $main_choice in
        1) system_init ;;
        2) ops_menu ;;
        3) model_menu ;;
        4) custom_model_download ;;
        5) config_model_params ;;
        6) check_model_update ;;
        7) multi_port_manage ;;
        8) add_new_model_to_script ;;
        9) 
            clear
            echo -e "\033[34m===== AI服务器使用帮助手册(完整版)=====\033[0m"
            echo -e "\033[32m一、 核心功能说明\033[0m"
            echo "1. 多端口推理+多Web界面(核心新增):"
            echo "   📌 作用:"
            echo "      - 多用户隔离:不同端口给不同用户(开发/测试/产品),避免冲突"
            echo "      - 多模型并行:不同端口绑定不同模型(8B轻量/30B大模型),无需切换"
            echo "      - 高可用性:单个端口故障不影响其他端口,提升服务稳定性"
            echo "   📍 配置:默认LM12345→Web8080、LM12346→Web8081、LM12347→Web8082"
            echo "   📍 访问:http://服务器IP:Web端口(如http://192.168.1.100:8080)"
            echo "   📍 扩展:菜单7→5可添加新端口(如LM12348→Web8083)"
            echo ""
            echo "2. 模型自动更新(手动+自动):"
            echo "   📌 手动更新:菜单6→选择模型→一键更新(自动备份旧模型)"
            echo "   📌 自动更新:每日9点自动检查,有更新发送邮件提示"
            echo "   📌 扩展:替换脚本开头UPDATE_CHECK_URL为真实API,实现全自动更新"
            echo ""
            echo "3. 模型运行参数配置(增强型):"
            echo "   📌 基础参数:上下文长度、批处理大小、GPU显存分配"
            echo "   📌 新增参数:CPU线程数(适配5700G 8核)、温度值、Top-P值、端口绑定"
            echo "   📌 智能推荐:基于模型规模+GPU显存自动推荐最优值,新手直接用推荐值"
            echo ""
            echo "4. 纯GPU推理(核心优势):"
            echo "   📌 对比Windows:Debian下CPU占用<5%(Windows CPU占比高),GPU利用率>80%"
            echo "   📌 原因:CUDA原生驱动,充分利用RTX5060Ti算力,无需CPU辅助"
            echo ""
            echo -e "\033[32m二、 新手入门流程\033[0m"
            echo "📋 首次使用(必做):"
            echo "   1. 运行脚本→选择1(全新部署)→等待自动安装→重启系统"
            echo "   2. 重启后再次运行脚本→选择3(编程模型下载)→5(一键下载所有模型)"
            echo "   3. 选择7(多端口管理)→4(绑定模型到端口1)"
            echo "   4. 浏览器访问:http://服务器IP:8080 → 开始使用"
            echo ""
            echo "📋 日常使用:"
            echo "   - 查看状态:菜单2→1(检查端口/GPU/CPU状态)"
            echo "   - 性能监控:菜单2→6(监控GPU/CPU利用率)"
            echo "   - 备份模型:菜单2→8(手动备份,或每日自动备份)"
            echo "   - 更新模型:菜单6→0(检查所有模型更新)"
            echo ""
            echo -e "\033[32m三、 如何添加新模型到脚本(新手友好)\033[0m"
            echo "📋 步骤(以添加Qwen3-14B-Coder为例):"
            echo "1. 编辑脚本:vim /ai_server_ultimate_final.sh"
            echo "2. 定位模型菜单:输入/model_menu回车(直接定位到约1200行)"
            echo "3. 找到对应厂商分类(如Qwen系列),添加如下代码:"
            echo "   在Qwen子菜单中添加:"
            echo "   6. Qwen3-14B-Coder(14B,推荐Q6_K)"
            echo "   在case qwen_choice中添加:"
            echo "   6) download_model \"Qwen/Qwen3-14B-Coder\" \"Qwen3-14B-Coder\" \"14B\" ;;"
            echo "4. 保存脚本:按Esc→输入:wq→回车"
            echo "5. 重新运行脚本→3→1,即可看到新模型选项"
            echo ""
            echo "📋 规范说明:"
            echo "   - download_model参数1:HuggingFace ID(必填,如Qwen/Qwen3-14B-Coder)"
            echo "   - download_model参数2:模型显示名称(自定义,如Qwen3-14B-Coder)"
            echo "   - download_model参数3:模型规模(如14B,用于量化推荐)"
            echo ""
            echo -e "\033[32m四、 量化级别选择指南(适配RTX5060Ti 16G)\033[0m"
            echo "📌 10B以下(如8B):Q8_0(最高精度,显存~7GB,剩余充足)"
            echo "📌 13-25B(如16B/20B):Q6_K(平衡,显存~10-12GB),可选Q5_K"
            echo "📌 30B以上(如30B/34B):Q4_K_M(适配,显存~14-15GB),避免显存溢出"
            echo "📌 新手推荐:直接使用脚本智能推荐值,无需手动选择"
            echo ""
            echo -e "\033[32m五、 常见问题解决\033[0m"
            echo "1. Windows下CPU占比高:Debian通过CUDA原生驱动实现纯GPU推理,CPU<5%"
            echo "2. 显存溢出:降低量化级别(Q8→Q6),或减少GPU显存分配(最大15GB)"
            echo "3. 多端口访问失败:检查防火墙(ufw status),确保端口已放行"
            echo "4. 模型更新失败:检查网络/代理,或手动删除旧模型后重新下载"
            echo "5. Web界面无法访问:检查Docker状态(systemctl status docker),重启Web服务"
            echo ""
            echo -e "\033[32m六、 扩展定制指引(新手可操作)\033[0m"
            echo "1. 修改多端口:编辑脚本开头LM_PORTS/WEB_PORTS数组,新增/删减端口"
            echo "2. 调整告警阈值:修改ALERT_THRESHOLD参数(默认90%)"
            echo "3. 自定义备份时间:修改/etc/crontab中的备份定时任务(默认0点)"
            echo "4. 配置邮件告警:运行dpkg-reconfigure postfix,选择本地仅,设置邮件域名"
            echo "5. 新增模型分类:在model_menu函数中添加新的厂商分类(如通义千问/讯飞星火)"
            echo ""
            echo -e "\033[32m七、 常用运维命令\033[0m"
            echo "1. 查看服务器IP:ip addr | grep inet(找192.168开头的地址)"
            echo "2. 查看GPU状态:nvidia-smi(核心指标:利用率/显存)"
            echo "3. 查看端口状态:netstat -tulpn | grep lm-studio(检查LM端口)"
            echo "4. 重启脚本服务:菜单2→2(重启所有端口+Web服务)"
            echo "5. 重新运行脚本:/ai_server_ultimate_final.sh"
            echo ""
	    echo -e "\033[34m===== AI服务器终极完整版脚本 - 使用帮助手册 =====\033[0m"
            echo ""
            echo "---------- 脚本概述 ----------"
            echo "本脚本旨在为 Debian 12 系统提供一键式 AI 模型服务部署与管理方案。"
            echo "核心组件:LM Studio (推理引擎), Open WebUI (Web 界面), Docker (容器化)。"
            echo "主要特性:多端口并发、智能量化推荐、性能监控、自动备份、模型更新检查。"
            echo ""
            echo "---------- 硬件要求 ----------"
            echo "CPU: 推荐 AMD Ryzen 7 5700G 或同等级别 CPU"
            echo "GPU: 推荐 NVIDIA RTX 5060 Ti 16GB 或更高 VRAM 的显卡"
            echo "内存: 至少 32GB DDR4"
            echo "存储: 至少 1TB 可用空间(用于存放模型文件)"
            echo "系统: Debian 12 x86_64"
            echo ""
            echo "---------- 主菜单功能详解 ----------"
            echo "1. 全新部署 (system_init):"
            echo "   - 系统更新与基础依赖安装 (wget, curl, git, vim, docker, etc.)"
            echo "   - 禁用 nouveau 开源驱动 (NVIDIA 必须)"
            echo "   - 添加 NVIDIA 官方源并安装驱动及 CUDA 12.8"
            echo "   - 自动下载并安装最新版 LM Studio"
            echo "   - 配置 LM Studio 与 Open WebUI 的多端口开机自启 (cron)"
            echo "   - 配置 UFW 防火墙开放对应端口"
            echo "   - 配置性能告警 (GPU利用率 > $ALERT_THRESHOLD%)"
            echo "   - 配置模型自动备份与更新检查 (cron)"
            echo "   - 最后会提示重启系统以应用所有变更。"
            echo ""
            echo "2. 服务器运维管理 (ops_menu):"
            echo "   - 查看服务状态 (LM Studio, WebUI, Docker, GPU, CPU)"
            echo "   - 重启/停止所有服务"
            echo "   - 查看指定端口的 LM Studio 日志"
            echo "   - 清理缓存并尝试重置 GPU (解决显存占用问题)"
            echo "   - 实时性能监控 (watch -n 1 命令)"
            echo "   - 列出已下载的模型"
            echo "   - 手动触发模型备份"
            echo "   - 测试性能告警是否正常工作 (检查当前GPU利用率)"
            echo ""
            echo "3. 顶级模型下载 (model_menu):"
            echo "   - 按厂商/类型分类提供主流模型 (Claude, Meta, Google, Qwen, DeepSeek)"
            echo "   - 提供 Q4, Q5, Q6, Q8 等多种量化级别选择"
            echo "   - 调用智能量化推荐函数 (quant_recommend) 并允许交互式调整"
            echo "   - 下载完成后自动调用 config_model_params 进行参数配置"
            echo "   - 支持一键下载多个模型 (Q6/Q8 版本)"
            echo ""
            echo "4. 自定义模型下载 (custom_model_download):"
            echo "   - 允许用户输入 HuggingFace ID 或 hf-mirror.com 链接"
            echo "   - 自动解析 hf-mirror.com 链接格式"
            echo "   - 引导用户输入模型大小并进行智能量化推荐"
            echo "   - 下载完成后自动调用 config_model_params 进行参数配置"
            echo ""
            echo "5. 模型运行参数配置 (config_model_params):"
            echo "   - 交互式选择模型绑定的 LM 端口和 WebUI 端口"
            echo "   - 根据模型大小和量化级别提供智能参数推荐 (上下文、批处理、显存、线程等)"
            echo "   - 允许用户手动调整参数 (回车使用推荐值)"
            echo "   - 将配置写入 LM Studio 的 JSON 配置文件 (\$HOME/.config/lm-studio/config_PORT.json)"
            echo ""
            echo "6. 模型更新检查 (check_model_update):"
            echo "   - 手动检查本地模型是否有更新 (模拟 API 调用)"
            echo "   - 询问用户是否更新,并在更新前自动备份旧模型"
            echo "   - 支持自动检查模式 (由 cron 每日执行)"
            echo ""
            echo "7. 多端口推理+Web管理 (multi_port_manage):"
            echo "   - 查看所有 LM + WebUI 端口的运行状态和绑定模型"
            echo "   - 重启/停止指定的端口组服务"
            echo "   - 为指定端口绑定新模型 (调用 config_model_params)"
            echo "   - 允许用户添加新的 LM + WebUI 端口组合"
            echo ""
            echo "8. 添加新模型到脚本 (add_new_model_to_script):"
            echo "   - 提供在 model_menu 函数中添加新模型选项的指引"
            echo "   - 说明 download_model 函数的四个参数含义"
            echo "   - 提供快速定位脚本函数的方法 (vim /function_name)"
            echo ""
            echo "9. 使用帮助手册 (本页):"
            echo "   - 提供脚本各功能的详细说明文档。"
            echo ""
            echo "0. 退出脚本:"
            echo "   - 退出当前脚本执行。"
            echo ""
            echo "---------- 关键路径与配置 ----------"
            echo "模型存放目录: $MODEL_DIR"
            echo "LM Studio 日志: $LM_LOG_BASE/"
            echo "模型备份目录: $BACKUP_DIR"
            echo "LM Studio 配置文件: \$HOME/.config/lm-studio/config_PORT.json"
            echo "Cron 定时任务: /etc/crontab (脚本部署时写入)"
            echo "UFW 防火墙: /etc/ufw/ (脚本部署时配置)"
            echo ""
            echo "---------- 注意事项 ----------"
            echo "- 脚本需以 root 权限运行 (sudo ./script.sh)。"
            echo "- 首次使用请务必选择 '1. 全新部署'。"
            echo "- '全新部署' 会重启系统,请确保操作前已保存重要数据。"
            echo "- 模型文件体积巨大,确保有足够的磁盘空间。"
            echo "- 量化级别越高,模型精度损失越小,但对显存要求越高。"
            echo "- 多端口功能允许同时运行和管理多个不同的模型实例。"
            echo "- 性能告警依赖 nvidia-smi 和 mailutils。"
            echo "- 自动备份依赖 cron。"
            echo ""
            read -p "按Enter键返回主菜单..."
            main_menu
            ;;
        0) exit 0 ;;
        *) echo -e "\033[31m❌ 无效编号,请重新输入\033[0m"; sleep 1; main_menu ;;
    esac
}
# ========== 二级菜单:服务器运维管理 ==========
ops_menu() {
    clear
    echo -e "\033[34m===== 服务器运维管理菜单 =====\033[0m"
    echo "📌 新手常用操作:1(查看状态)、6(性能监控)、8(手动备份)"
    echo "1. 查看服务状态(多端口LM/Web/GPU/CPU)"
    echo "2. 重启所有服务(多端口LM+Web)"
    echo "3. 停止所有服务"
    echo "4. 查看指定端口日志(排错用)"
    echo "5. 清理模型缓存+释放GPU显存"
    echo "6. 实时性能监控(GPU/CPU/内存,核心监控)"
    echo "7. 查看已下载模型列表"
    echo "8. 手动备份模型(保留7天,数据安全)"
    echo "9. 测试性能告警(GPU利用率阈值$ALERT_THRESHOLD%)"
    echo "10. 返回主菜单"
    echo -e "\033[34m===============================================================\033[0m"
    read -p "输入运维操作编号(新手推荐1): " ops_choice
    # 确保 docker 存在,nvidia-smi 根据情况处理
    if ! command -v docker &> /dev/null; then
        echo -e "\033[31m❌ 错误: 'docker' 命令未找到。请确保 Docker 已正确安装。\033[0m"
        exit 1
    fi
    case $ops_choice in
        1)
            echo -e "\033[32m=== 多端口服务状态 ===\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                local lm_port=${LM_PORTS[$i]}
                local web_port=${WEB_PORTS[$i]}
                local webui_name="${WEBUI_BASE_NAME}_$lm_port"
                echo "📡 端口组$((i+1)):"
                echo "   LM端口$lm_port:$(ps aux | grep -v grep | grep "lm-studio --remote-inference --remote-port $lm_port" >/dev/null && "✅ 运行中" || "❌ 未运行")"
                echo "   Web端口$web_port:$(docker ps | grep $webui_name >/dev/null && "✅ 运行中" || "❌ 未运行")"
            done
            echo "🐳 Docker:$(systemctl is-active docker | sed 's/active/✅ 运行中/' | sed 's/inactive/❌ 未运行/')"
            echo -e "\033[32m=== GPU状态(纯GPU推理,CPU占用<5%)===\033[0m"
            if command -v nvidia-smi &> /dev/null; then
                nvidia-smi | grep -E "GPU|Memory-Usage|Utilization"
            else
                echo -e "\033[33m⚠️  'nvidia-smi' 未找到,无法显示GPU状态。\033[0m"
            fi
            echo -e "\033[32m=== CPU状态 ===\033[0m"
            top -bn1 | grep -E 'Cpu.s*us|Mem' | head -2
            ;;
        2)
            echo -e "\033[32m=== 重启所有服务 ===\033[0m"
            for port in "${LM_PORTS[@]}"; do
                pkill -f "lm-studio --remote-inference --remote-port $port" || true
                nohup lm-studio --remote-inference --remote-port $port > $LM_LOG_BASE/lmstudio_$port.log 2>&1 &
                echo "✅ LM端口$port 已重启"
            done
            for i in "${!LM_PORTS[@]}"; do
                local webui_name="${WEBUI_BASE_NAME}_${LM_PORTS[$i]}"
                docker restart $webui_name || true
                echo "✅ Web端口${WEB_PORTS[$i]} 已重启"
            done
            echo -e "\033[32m✅ 所有服务重启完成!GPU利用率应>80%,CPU<5%\033[0m"
            ;;
        3)
            echo -e "\033[32m=== 停止所有服务 ===\033[0m"
            for port in "${LM_PORTS[@]}"; do
                pkill -f "lm-studio --remote-inference --remote-port $port" || true
                echo "✅ LM端口$port 已停止"
            done
            for i in "${!LM_PORTS[@]}"; do
                local webui_name="${WEBUI_BASE_NAME}_${LM_PORTS[$i]}"
                docker stop $webui_name || true
                echo "✅ Web端口${WEB_PORTS[$i]} 已停止"
            done
            echo -e "\033[32m✅ 所有服务已停止!\033[0m"
            ;;
        4)
            echo -e "\033[32m=== 查看指定端口日志 ===\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]}(日志:$LM_LOG_BASE/lmstudio_${LM_PORTS[$i]}.log)"
            done
            read -p "输入要查看的端口编号: " port_idx
            local target_port=${LM_PORTS[$((port_idx-1))]}
            echo -e "\033[32m📄 正在查看LM端口$target_port 日志(按Ctrl+C退出)...\033[0m"
            tail -f $LM_LOG_BASE/lmstudio_$target_port.log
            ;;
        5)
            echo -e "\033[32m=== 清理缓存+释放显存 ===\033[0m"
            for port in "${LM_PORTS[@]}"; do
                pkill -f "lm-studio --remote-inference --remote-port $port" || true
            done
            for i in "${!LM_PORTS[@]}"; do
                local webui_name="${WEBUI_BASE_NAME}_${LM_PORTS[$i]}"
                docker stop $webui_name || true
            done
            rm -rf ~/.cache/lm-studio/* || true
            if command -v nvidia-smi &> /dev/null; then
                 nvidia-smi --gpu-reset || true
            fi
            echo -e "\033[32m✅ 缓存清理完成!解决显存占用过高问题\033[0m"
            ;;
        6)
            echo -e "\033[32m=== 实时性能监控(按Ctrl+C退出)===\033[0m"
            echo "📌 核心指标:GPU利用率>80%(正常)、CPU占用<5%(纯GPU推理)"
            if command -v nvidia-smi &> /dev/null; then
                 watch -n 1 "nvidia-smi | grep -E 'GPU|Memory-Usage|Utilization' && echo '--- CPU/内存 ---' && top -bn1 | grep -E 'Cpu.s*us|Mem' | head -2"
            else
                 echo -e "\033[33m⚠️  'nvidia-smi' 未找到,仅监控 CPU/内存。\033[0m"
                 watch -n 1 "echo '--- CPU/内存 ---' && top -bn1 | grep -E 'Cpu.s*us|Mem' | head -2"
            fi
            ;;
        7)
            echo -e "\033[32m=== 已下载模型列表 ===\033[0m"
            ls -lh $MODEL_DIR | awk '{print $9, $5}' || echo "❌ 无模型或路径错误"
            ;;
        8)
            echo -e "\033[32m=== 手动备份模型 ===\033[0m"
            local backup_file="$BACKUP_DIR/models_$(date +%Y%m%d_%H%M%S).tar.gz"
            tar -zcf $backup_file $MODEL_DIR --exclude='*.tmp'
            find $BACKUP_DIR -name 'models_*.tar.gz' -mtime +7 -delete
            echo -e "\033[32m✅ 模型备份完成!\033[0m"
            echo "   备份文件:$backup_file"
            echo "   📌 自动清理7天前的备份文件,释放磁盘空间"
            ;;
        9)
            echo -e "\033[32m=== 测试性能告警 ===\033[0m"
            if command -v nvidia-smi &> /dev/null; then
                 GPU_UTIL=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits | awk '{print $1}')
                 if [ $GPU_UTIL -ge $ALERT_THRESHOLD ]; then
                     echo "GPU利用率告警:$GPU_UTIL%(阈值$ALERT_THRESHOLD%)" | mail -s "AI服务器GPU告警" root
                     echo -e "\033[32m✅ 告警邮件已发送到root邮箱!\033[0m"
                 else
                     echo -e "\033[32m✅ 当前GPU利用率:$GPU_UTIL%(低于阈值$ALERT_THRESHOLD%),无需告警\033[0m"
                 fi
            else
                 echo -e "\033[33m⚠️  'nvidia-smi' 未找到,无法测试GPU告警。\033[0m"
            fi
            ;;
        10)
            return 0
            ;;
        *)
            echo -e "\033[31m❌ 无效编号,请重新输入\033[0m"
            sleep 1
            ;;
    esac
    read -p "按Enter键返回运维菜单..."
    ops_menu
}
# ========== 二级菜单:顶级模型下载(最终版,含Claude/Meta全系列) ==========
model_menu() {
    clear
    echo -e "\033[34m===== 顶级模型下载菜单(最终版)=====\033[0m"
    echo "📌 量化策略(适配RTX5060Ti 16G+充足硬盘):"
    echo "   11-25B→Q8(最高精度)/Q6(平衡,默认)|26-35B→Q4(推荐)/Q6(测试)"
    echo "📌 模型分类:"
    echo "1. Claude系列(Anthropic顶级模型,含3.7 Sonnet)"
    echo "2. Meta全系列(Llama3/Gemma2/CodeLlama顶级模型)"
    echo "3. Gemini 3 Pro系列(谷歌官方12B-27B)"
    echo "4. Qwen3+Gemini3Pro混合系列(第三方高下载量)"
    echo "5. Codestral/DeepSeek编程模型(15B-33B)"
    echo "6. 一键下载所有顶级模型(Q6默认版,对比测试推荐)"
    echo "7. 一键下载所有顶级模型(Q8高精度版,11-25B)"
    echo "8. 返回主菜单"
    echo -e "\033[34m======================================================\033[0m"
    read -p "输入模型分类编号(对比测试推荐6): " model_choice
    start_lm_multi_api
    case $model_choice in
        1)
            # Claude系列(Anthropic顶级模型)
            clear
            echo -e "\033[34m===== Claude系列(Anthropic顶级模型)=====\033[0m"
            echo "📌 新手推荐:1(Claude 3.7 Sonnet Q8版)"
            echo "1. Claude 3.7 Sonnet(Q8最高精度版,20B)✅ 推荐"
            echo "2. Claude 3.7 Sonnet(Q6平衡版,20B)"
            echo "3. Claude 3 Opus(Q8最高精度版,28B)"
            echo "4. Claude 3 Opus(Q4推荐版,28B)"
            echo "5. Claude 3 Haiku(Q8最高精度版,14B)"
            echo "6. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " claude_choice
            case $claude_choice in
                1) download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q8最高精度版)" "20B" "q8" ;;
                2) download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q6平衡版)" "20B" "q6" ;;
                3) download_model "anthropic/Claude-3-Opus" "Claude 3 Opus(Q8最高精度版)" "28B" "q8" ;;
                4) download_model "anthropic/Claude-3-Opus" "Claude 3 Opus(Q4推荐版)" "28B" "q4" ;;
                5) download_model "anthropic/Claude-3-Haiku" "Claude 3 Haiku(Q8最高精度版)" "14B" "q8" ;;
                6) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        2)
            # Meta全系列(Llama3/Gemma2/CodeLlama)
            clear
            echo -e "\033[34m===== Meta全系列(Llama3/Gemma2/CodeLlama)=====\033[0m"
            echo "📌 新手推荐:1(Llama3-70B Q6版)"
            echo "1. Llama3-70B-Instruct(Q4推荐版,70B)"
            echo "2. Llama3-14B-Instruct(Q8最高精度版,14B)✅ 推荐"
            echo "3. Gemma2-27B-Instruct(Q4推荐版,27B)"
            echo "4. Gemma2-9B-Instruct(Q8最高精度版,9B)"
            echo "5. CodeLlama-34B-Instruct(Q4推荐版,34B)"
            echo "6. CodeLlama-13B-Instruct(Q8最高精度版,13B)"
            echo "7. 返回模型主菜单"
            read -p "输入模型编号(新手推荐2): " meta_choice
            case $meta_choice in
                1) download_model "meta-llama/Meta-Llama-3-70B-Instruct" "Llama3-70B-Instruct(Q4推荐版)" "70B" "q4" ;;
                2) download_model "meta-llama/Meta-Llama-3-14B-Instruct" "Llama3-14B-Instruct(Q8最高精度版)" "14B" "q8" ;;
                3) download_model "google/gemma-2-27b-it" "Gemma2-27B-Instruct(Q4推荐版)" "27B" "q4" ;;
                4) download_model "google/gemma-2-9b-it" "Gemma2-9B-Instruct(Q8最高精度版)" "9B" "q8" ;;
                5) download_model "meta-llama/CodeLlama-34b-Instruct-hf" "CodeLlama-34B-Instruct(Q4推荐版)" "34B" "q4" ;;
                6) download_model "meta-llama/CodeLlama-13b-Instruct-hf" "CodeLlama-13B-Instruct(Q8最高精度版)" "13B" "q8" ;;
                7) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        3)
            # Gemini 3 Pro系列(谷歌官方,优化量化)
            clear
            echo -e "\033[34m===== Gemini 3 Pro系列(谷歌官方)=====\033[0m"
            echo "📌 新手推荐:1(12B Q8版)或5(27B Q4版)"
            echo "1. Gemini 3 Pro 12B(Q8最高精度版,12B)✅ 推荐"
            echo "2. Gemini 3 Pro 12B(Q6平衡版,12B)"
            echo "3. Gemini 3 Pro 19B(Q8最高精度版,19B)"
            echo "4. Gemini 3 Pro 19B(Q6平衡版,19B)"
            echo "5. Gemini 3 Pro 27B(Q4推荐版,27B)"
            echo "6. Gemini 3 Pro 27B(Q6测试版,27B)"
            echo "7. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " gemini_choice
            case $gemini_choice in
                1) download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q8最高精度版)" "12B" "q8" ;;
                2) download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q6平衡版)" "12B" "q6" ;;
                3) download_model "google/gemini-3-pro-19B" "Gemini 3 Pro 19B(Q8最高精度版)" "19B" "q8" ;;
                4) download_model "google/gemini-3-pro-19B" "Gemini 3 Pro 19B(Q6平衡版)" "19B" "q6" ;;
                5) download_model "google/gemini-3-pro-27B" "Gemini 3 Pro 27B(Q4推荐版)" "27B" "q4" ;;
                6) download_model "google/gemini-3-pro-27B" "Gemini 3 Pro 27B(Q6测试版)" "27B" "q6" ;;
                7) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        4)
            # Qwen3+Gemini3Pro混合系列
            clear
            echo -e "\033[34m===== Qwen3+Gemini3Pro混合系列(第三方高下载量)=====\033[0m"
            echo "📌 新手推荐:1(20B Q8版)"
            echo "1. Qwen3-Gemini3Pro-20B(Q8最高精度版,20B)✅ 推荐"
            echo "2. Qwen3-Gemini3Pro-20B(Q6平衡版,20B)"
            echo "3. Qwen3-Gemini3Pro-28B(Q4推荐版,28B)"
            echo "4. Qwen3-Gemini3Pro-28B(Q6测试版,28B)"
            echo "5. Qwen3-Gemini3Pro-32B(Q4推荐版,32B)"
            echo "6. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " mix_choice
            case $mix_choice in
                1) download_model "unsloth/qwen3-gemini3pro-20b" "Qwen3-Gemini3Pro-20B(Q8最高精度版)" "20B" "q8" ;;
                2) download_model "unsloth/qwen3-gemini3pro-20b" "Qwen3-Gemini3Pro-20B(Q6平衡版)" "20B" "q6" ;;
                3) download_model "unsloth/qwen3-gemini3pro-28b" "Qwen3-Gemini3Pro-28B(Q4推荐版)" "28B" "q4" ;;
                4) download_model "unsloth/qwen3-gemini3pro-28b" "Qwen3-Gemini3Pro-28B(Q6测试版)" "28B" "q6" ;;
                5) download_model "unsloth/qwen3-gemini3pro-32b" "Qwen3-Gemini3Pro-32B(Q4推荐版)" "32B" "q4" ;;
                6) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        5)
            # Codestral/DeepSeek编程模型
            clear
            echo -e "\033[34m===== Codestral/DeepSeek编程模型(顶级)=====\033[0m"
            echo "📌 新手推荐:1(Codestral-15B Q8版)或5(DeepSeek-16B Q8版)"
            echo "1. Codestral-15B-v0.1(Q8最高精度版,15B)✅ 推荐"
            echo "2. Codestral-22B-v0.1(Q8最高精度版,22B)"
            echo "3. Codestral-Mix-30B(Q4推荐版,30B)"
            echo "4. DeepSeek-Coder-V2-16B(Q6平衡版,16B)"
            echo "5. DeepSeek-Coder-V2-16B(Q8最高精度版,16B)✅ 推荐"
            echo "6. DeepSeek-Coder-V2-33B(Q4推荐版,33B)"
            echo "7. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " code_choice
            case $code_choice in
                1) download_model "mistralai/Codestral-15B-v0.1" "Codestral-15B-v0.1(Q8最高精度版)" "15B" "q8" ;;
                2) download_model "mistralai/Codestral-22B-v0.1" "Codestral-22B-v0.1(Q8最高精度版)" "22B" "q8" ;;
                3) download_model "mistralai/Codestral-Mix-30B-v0.1" "Codestral-Mix-30B(Q4推荐版)" "30B" "q4" ;;
                4) download_model "deepseek-ai/DeepSeek-Coder-V2-16B-base" "DeepSeek-Coder-V2-16B(Q6平衡版)" "16B" "q6" ;;
                5) download_model "deepseek-ai/DeepSeek-Coder-V2-16B-base" "DeepSeek-Coder-V2-16B(Q8最高精度版)" "16B" "q8" ;;
                6) download_model "deepseek-ai/DeepSeek-Coder-V2-33B-base" "DeepSeek-Coder-V2-33B(Q4推荐版)" "33B" "q4" ;;
                7) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        6)
            # 一键下载所有顶级模型(Q6默认版)
            echo -e "\033[32m=== 一键下载所有顶级模型(Q6平衡版)===\033[0m"
            echo "📌 包含:Claude/Meta/Gemini/混合模型/编程模型共15个核心模型"
            # Claude系列
            download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q6平衡版)" "20B" "q6"
            # Meta系列
            download_model "meta-llama/Meta-Llama-3-14B-Instruct" "Llama3-14B-Instruct(Q6平衡版)" "14B" "q6"
            download_model "meta-llama/CodeLlama-13b-Instruct-hf" "CodeLlama-13B-Instruct(Q6平衡版)" "13B" "q6"
            # Gemini系列
            download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q6平衡版)" "12B" "q6"
            download_model "google/gemini-3-pro-19B" "Gemini 3 Pro 19B(Q6平衡版)" "19B" "q6"
            # 混合模型
            download_model "unsloth/qwen3-gemini3pro-20b" "Qwen3-Gemini3Pro-20B(Q6平衡版)" "20B" "q6"
            # 编程模型
            download_model "mistralai/Codestral-15B-v0.1" "Codestral-15B-v0.1(Q6平衡版)" "15B" "q6"
            download_model "deepseek-ai/DeepSeek-Coder-V2-16B-base" "DeepSeek-Coder-V2-16B(Q6平衡版)" "16B" "q6"
            # 大模型(Q4版)
            download_model "google/gemini-3-pro-27B" "Gemini 3 Pro 27B(Q4推荐版)" "27B" "q4"
            download_model "unsloth/qwen3-gemini3pro-28b" "Qwen3-Gemini3Pro-28B(Q4推荐版)" "28B" "q4"
            download_model "deepseek-ai/DeepSeek-Coder-V2-33B-base" "DeepSeek-Coder-V2-33B(Q4推荐版)" "33B" "q4"
            echo -e "\033[32m✅ 所有顶级模型下载完成!\033[0m"
            echo "📌 11-25B模型为Q6平衡版,26-35B模型为Q4推荐版,兼顾精度与显存"
            ;;
        7)
            # 一键下载所有顶级模型(Q8高精度版)
            echo -e "\033[32m=== 一键下载所有顶级模型(Q8高精度版)===\033[0m"
            echo "📌 包含:11-25B高精度模型+26-35B Q4推荐版模型"
            # 11-25B Q8版
            download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q8最高精度版)" "20B" "q8"
            download_model "meta-llama/Meta-Llama-3-14B-Instruct" "Llama3-14B-Instruct(Q8最高精度版)" "14B" "q8"
            download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q8最高精度版)" "12B" "q8"
            # ... (可以继续添加其他Q8模型)
            echo -e "\033[32m✅ Q8高精度版模型下载完成!\033[0m"
            ;;
        8)
            return 0
            ;;
        *)
            echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
    esac
}
# 启动主菜单
main_menu "$@"

下面是老的

好的,完全理解你的意思。我们不预先假设任何依赖存在,脚本会在需要的时候主动去检查,如果发现缺少必要的命令(`lms`, `docker`, `nvidia-smi`),就尝试安装它们,然后再进行一次检查,如果还是不行,则给出明确提示并退出。

下面是修改后的完整脚本 `ai_server_ultimate_final.sh`,包含了依赖检查和自动安装逻辑。
#!/bin/bash
# Debian12 AI服务器终极完整版脚本(顶级模型最终版)
# 核心升级:补充Claude 3.7 Sonnet/Meta全系列+优化量化策略(12-25B Q6/Q8、30B+ Q4)
# 适配环境:大显存(RTX5060Ti 16G)+ 充足硬盘空间
set -e

# ========== 基础配置(可自定义,新手直接用默认值) ==========
# 多端口配置(新增/删减端口直接修改此数组)
LM_PORTS=("12345" "12346" "12347")  # 推荐保留3个端口,可扩展至更多
# 多端口Web界面配置(每个端口对应独立Web服务)
WEB_PORTS=("8080" "8081" "8082")    # 与LM_PORTS一一对应
LM_LOG_BASE="/var/log/lmstudio"
WEBUI_BASE_NAME="open-webui"
MODEL_DIR="$HOME/.cache/lm-studio/models"
BACKUP_DIR="/root/ai_model_backup"
ALERT_THRESHOLD="90"  # GPU利用率告警阈值(%)
# 模型更新接口(可替换为真实API实现自动更新)
UPDATE_CHECK_URL="https://api.lmstudio.ai/v1/models"
# 硬件配置(无需修改,适配5700G/RTX5060Ti/32G+充足硬盘)
CPU_MODEL="AMD Ryzen 7 5700G"
GPU_MODEL="RTX5060Ti 16G"
GPU_MEM="16GB"
SYSTEM_MEM="32GB DDR4"
DISK_SPACE="1TB+"  # 充足硬盘空间,支持高量化级别

# 创建必要目录
mkdir -p $MODEL_DIR $BACKUP_DIR $LM_LOG_BASE

# ========== 辅助函数:检查并安装必要依赖 ==========
ensure_dependencies() {
    echo -e "\033[33m[依赖检查] 正在检查必要命令...\033[0m"
    local missing_deps=()

    if ! command -v lms &> /dev/null; then
        echo -e "\033[33m[依赖检查] 'lms' 命令未找到,尝试安装 LM Studio...\033[0m"
        missing_deps+=("lmstudio")
    fi

    if ! command -v docker &> /dev/null; then
        echo -e "\033[33m[依赖检查] 'docker' 命令未找到,尝试安装 Docker...\033[0m"
        missing_deps+=("docker")
    fi

    # nvidia-smi 可能没有,但不是所有操作都必须,所以这里只检查不强制安装
    if ! command -v nvidia-smi &> /dev/null; then
        echo -e "\033[33m[依赖检查] 'nvidia-smi' 命令未找到。若需GPU监控,请确保NVIDIA驱动已安装。\033[0m"
    fi

    if [ ${#missing_deps[@]} -gt 0 ]; then
        echo -e "\033[33m[依赖检查] 发现缺失依赖: ${missing_deps[*]}\033[0m"
        read -p "是否尝试自动安装缺失的依赖 (Docker, LM Studio)?(y/N): " confirm_install
        if [[ $confirm_install =~ ^[Yy]$ ]]; then
            apt update
            # 安装 Docker
            if [[ " ${missing_deps[@]} " =~ " docker " ]]; then
                echo -e "\033[32m[安装] 正在安装 Docker...\033[0m"
                apt install -y docker.io docker-compose
                systemctl start docker
                systemctl enable docker
            fi
            # 安装 LM Studio
            if [[ " ${missing_deps[@]} " =~ " lmstudio " ]]; then
                echo -e "\033[32m[安装] 正在安装 LM Studio...\033[0m"
                # 安装基础依赖
                apt install -y wget curl git vim libvulkan1 mesa-vulkan-drivers libfuse2 build-essential software-properties-common apt-transport-https dirmngr jq
                # 下载并安装 LM Studio
                wget $(curl -s https://api.github.com/repos/lmstudio-ai/lmstudio/releases/latest | grep "browser_download_url.*amd64.deb" | cut -d '"' -f 4) -O lm-studio-latest.deb
                dpkg -i lm-studio-latest.deb
                apt install -f -y # 解决依赖
                rm -f lm-studio-latest.deb
            fi
            echo -e "\033[32m[安装] 依赖安装完成,正在重新检查...\033[0m"
        else
            echo -e "\033[31m❌ 用户取消安装依赖。请手动安装 Docker 和 LM Studio。\033[0m"
            exit 1
        fi
    fi

    # 再次检查
    local final_missing=()
    if ! command -v lms &> /dev/null; then
        final_missing+=("lms")
    fi
    if ! command -v docker &> /dev/null; then
        final_missing+=("docker")
    fi

    if [ ${#final_missing[@]} -gt 0 ]; then
        echo -e "\033[31m❌ 严重错误: 安装后仍有命令无法找到: ${final_missing[*]}\033[0m"
        echo -e "\033[31m    请检查安装过程是否有误,或手动安装后再运行脚本。\033[0m"
        exit 1
    fi

    echo -e "\033[32m[依赖检查] 所有必要命令均已准备就绪!\033[0m"
}

# ========== 核心函数0:智能量化推荐(优化版) ==========
quant_recommend() {
    local model_size=$1
    local quant_type=$2  # q4/q5/q6/q8,区分不同量化级别
    local gpu_mem=$GPU_MEM
    local recommend_quant=""
    # 提取数字部分(如30B→30,16B→16)
    local size_num=$(echo $model_size | grep -o '[0-9]\+')
    if [ -z "$size_num" ]; then
        recommend_quant="Q6_K"  # 默认值升级为Q6
        return
    fi
    # 智能推荐逻辑(适配RTX5060Ti 16G+充足硬盘)
    if [ $size_num -le 10 ]; then
        recommend_quant="Q8_0"  # 10B以下优先最高精度Q8
    elif [ $size_num -ge 11 ] && [ $size_num -le 25 ]; then
        if [ "$quant_type" = "q8" ]; then
            recommend_quant="Q8_0"  # 11-25B最高精度Q8(推荐)
        elif [ "$quant_type" = "q6" ]; then
            recommend_quant="Q6_K"  # 11-25B平衡精度Q6(默认)
        elif [ "$quant_type" = "q5" ]; then
            recommend_quant="Q5_K_M"  # Q5版本(仅测试)
        else
            recommend_quant="Q6_K"  # 默认Q6
        fi
    elif [ $size_num -ge 26 ] && [ $size_num -le 35 ]; then
        if [ "$quant_type" = "q6" ]; then
            recommend_quant="Q6_K"  # 26-35B Q6(显存紧张,仅测试)
        elif [ "$quant_type" = "q5" ]; then
            recommend_quant="Q5_K_M"  # Q5版本(仅测试)
        else
            recommend_quant="Q4_K_M"  # 26-35B适配Q4(推荐)
        fi
    else
        recommend_quant="Q4_K_M"  # 35B+默认Q4
    fi
    # 交互式选择(引导式设置,新手直接选5用推荐值)
    echo -e "\033[32m===== 智能量化推荐 =====\033[0m"
    local quant_note=""
    if [ "$quant_type" = "q5" ]; then
        quant_note="(⚠️ Q5版本:仅测试,不推荐日常使用)"
    elif [ "$quant_type" = "q4" ] && [ $size_num -le 25 ]; then
        quant_note="(⚠️ 11-25B不推荐Q4,建议选Q6/Q8)"
    elif [ "$quant_type" = "q8" ]; then
        quant_note="(✅ Q8版本:最高精度,推荐11-25B使用)"
    fi
    echo "模型规模:$model_size | GPU显存:$gpu_mem | 硬盘空间:$DISK_SPACE | 推荐量化级别:$recommend_quant $quant_note"
    echo "可选量化级别(精度从高到低):"
    echo "1. Q8_0(最高精度,显存占用最大,推荐11-25B)"
    echo "2. Q6_K(平衡精度/显存,11-25B默认,推荐)"
    echo "3. Q5_K_M(⚠️ 显存紧张,仅测试)"
    echo "4. Q4_K_M(适配大模型,推荐26-35B使用)"
    echo "5. 使用推荐值($recommend_quant,新手推荐)"
    read -p "输入量化级别编号(1-5): " quant_choice
    case $quant_choice in
        1) recommend_quant="Q8_0" ;;
        2) recommend_quant="Q6_K" ;;
        3) recommend_quant="Q5_K_M" ;;
        4) recommend_quant="Q4_K_M" ;;
        5) ;; # 使用推荐值
        *) 
            echo -e "\033[31m无效选择,自动使用推荐值:$recommend_quant\033[0m"
            sleep 1
            ;;
    esac
    echo $recommend_quant
}

# ========== 核心函数1:系统初始化(一站式部署) ==========
system_init() {
    clear
    echo -e "\033[34m===== 第一步:系统初始化(驱动/CUDA/多端口/Web)=====\033[0m"
    # 1. 系统更新+基础依赖(自动安装,无需手动操作)
    echo -e "\033[32m[1/9] 系统更新及基础依赖安装...\033[0m"
    apt update && apt upgrade -y
    apt install -y wget curl git vim libvulkan1 mesa-vulkan-drivers libfuse2 build-essential software-properties-common apt-transport-https dirmngr ufw docker.io docker-compose mailutils jq
    # 2. 禁用nouveau开源驱动(NVIDIA必做)
    echo -e "\033[32m[2/9] 禁用nouveau开源驱动...\033[0m"
    echo "blacklist nouveau" > /etc/modprobe.d/blacklist.conf
    echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist.conf
    update-initramfs -u
    # 3. 添加NVIDIA官方源+安装驱动+CUDA12.8
    echo -e "\033[32m[3/9] 安装NVIDIA驱动及CUDA12.8...\033[0m"
    curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/3bf863cc.pub | gpg --dearmor -o /usr/share/keyrings/nvidia-drivers.gpg
    echo "deb [signed-by=/usr/share/keyrings/nvidia-drivers.gpg] https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/ /" > /etc/apt/sources.list.d/nvidia-cuda.list
    apt update
    apt install -y nvidia-driver nvidia-cuda-toolkit
    # 4. 安装LM Studio(自动拉取最新版)
    echo -e "\033[32m[4/9] 安装最新版LM Studio...\033[0m"
    wget $(curl -s https://api.github.com/repos/lmstudio-ai/lmstudio/releases/latest | grep "browser_download_url.*amd64.deb" | cut -d '"' -f 4) -O lm-studio-latest.deb
    dpkg -i lm-studio-latest.deb && apt install -f -y && rm -f lm-studio-latest.deb
    # 5. 配置多端口+多Web界面开机自启
    echo -e "\033[32m[5/9] 配置多端口+多Web界面开机自启...\033[0m"
    # 清空原有定时任务
    sed -i '/lm-studio --remote-inference/d' /etc/crontab
    sed -i '/docker run.*open-webui/d' /etc/crontab
    # 多端口LM Studio API开机自启
    for port in "${LM_PORTS[@]}"; do
        echo "@reboot root nohup lm-studio --remote-inference --remote-port $port > $LM_LOG_BASE/lmstudio_$port.log 2>&1 &" >> /etc/crontab
    done
    # 多端口Web界面开机自启(与LM_PORTS一一对应)
    for i in "${!LM_PORTS[@]}"; do
        local lm_port=${LM_PORTS[$i]}
        local web_port=${WEB_PORTS[$i]}
        local webui_name="${WEBUI_BASE_NAME}_$lm_port"
        echo "@reboot root docker run -d --name $webui_name -p $web_port:8080 -e \"LMSTUDIO_BASE_URL=http://localhost:$lm_port\" --restart always ghcr.io/open-webui/open-webui:main" >> /etc/crontab
    done
    # 6. 系统优化(纯命令行+防火墙+性能调优)
    echo -e "\033[32m[6/9] 系统优化(纯命令行+防火墙)...\033[0m"
    systemctl set-default multi-user.target > /dev/null 2>&1 || true
    # 放行多端口+Web端口
    for port in "${LM_PORTS[@]}"; do
        ufw allow $port/tcp
    done
    for port in "${WEB_PORTS[@]}"; do
        ufw allow $port/tcp
    done
    ufw --force enable
    swapoff -a && echo "vm.swappiness=10" >> /etc/sysctl.conf && sysctl -p
    # 7. 性能告警脚本开机自启
    echo -e "\033[32m[7/9] 配置性能告警...\033[0m"
    sed -i '/GPU利用率告警/d' /etc/crontab
    echo "@reboot root /bin/bash -c 'while true; do GPU_UTIL=\$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits | awk '{print \$1}'); if [ \$GPU_UTIL -ge $ALERT_THRESHOLD ]; then echo \"GPU利用率告警:\$GPU_UTIL%(阈值$ALERT_THRESHOLD%)\" | mail -s \"AI服务器GPU告警\" root; fi; sleep 60; done' &" >> /etc/crontab
    # 8. 自动备份+自动更新检查初始化
    echo -e "\033[32m[8/9] 初始化模型自动备份+自动更新检查...\033[0m"
    sed -i '/models_*.tar.gz/d' /etc/crontab
    # 每日0点备份模型(保留7天)
    echo "0 0 * * * root tar -zcf $BACKUP_DIR/models_$(date +\%Y\%m\%d).tar.gz $MODEL_DIR --exclude='*.tmp' && find $BACKUP_DIR -name 'models_*.tar.gz' -mtime +7 -delete" >> /etc/crontab
    # 每日9点检查模型更新(自动提示)
    echo "0 9 * * * root /bin/bash -c 'cd /root && /ai_server_ultimate_final.sh --auto-check-update' >> $LM_LOG_BASE/auto_update_check.log 2>&1" >> /etc/crontab
    # 9. 验证安装
    echo -e "\033[32m[9/9] 验证安装...\033[0m"
    nvidia-smi > /dev/null 2>&1 && echo "✅ NVIDIA驱动安装成功" || echo "❌ NVIDIA驱动安装失败"
    docker --version > /dev/null 2>&1 && echo "✅ Docker安装成功" || echo "❌ Docker安装失败"
    lm-studio --version > /dev/null 2>&1 && echo "✅ LM Studio安装成功" || echo "❌ LM Studio安装失败"
    echo -e "\033[32m系统初始化完成!重启后所有服务自动生效...\033[0m"
    read -p "按Enter键重启系统(必须重启)..."
    reboot
}

# ========== 核心函数2:启动LM Studio多端口+多Web API ==========
start_lm_multi_api() {
    echo -e "\033[32m[提示] 启动LM Studio多端口+多Web服务...\033[0m"
    # 启动多端口LM Studio API
    for port in "${LM_PORTS[@]}"; do
        if ! ps aux | grep -v grep | grep "lm-studio --remote-inference --remote-port $port" >/dev/null; then
            nohup lm-studio --remote-inference --remote-port $port > $LM_LOG_BASE/lmstudio_$port.log 2>&1 &
            echo "  LM Studio端口$port:已启动"
            sleep 2
        else
            echo "  LM Studio端口$port:已运行"
        fi
    done
    # 启动多端口Web界面
    for i in "${!LM_PORTS[@]}"; do
        local lm_port=${LM_PORTS[$i]}
        local web_port=${WEB_PORTS[$i]}
        local webui_name="${WEBUI_BASE_NAME}_$lm_port"
        if ! docker ps | grep $webui_name >/dev/null; then
            docker run -d --name $webui_name -p $web_port:8080 -e "LMSTUDIO_BASE_URL=http://localhost:$lm_port" --restart always ghcr.io/open-webui/open-webui:main
            echo "  Web界面端口$web_port(关联LM$lm_port):已启动"
        else
            echo "  Web界面端口$web_port(关联LM$lm_port):已运行"
        fi
    done
}

# ========== 核心函数3:模型下载(支持Q4/Q5/Q6/Q8全量化) ==========
download_model() {
    ensure_dependencies # 在下载模型前确保依赖存在
    local model_id=$1
    local model_name=$2
    local model_size=$3
    local quant_type=$4  # q4/q5/q6/q8
    # 智能量化推荐+交互式选择
    local quant_level=$(quant_recommend "$model_size" "$quant_type")
    echo -e "\033[32m开始下载:$model_name | 量化级别:$quant_level\033[0m"
    lms download --model $model_id --quantization $quant_level --save-path $MODEL_DIR
    echo -e "\033[32m$model_name 下载完成!\033[0m"
    # 配置模型运行参数(增强版+多端口绑定)
    config_model_params $model_name $quant_level
}

# ========== 核心函数4:自定义模型下载(新手友好指引) ==========
custom_model_download() {
    ensure_dependencies # 在下载模型前确保依赖存在
    clear
    echo -e "\033[34m===== 自定义模型下载(HuggingFace/镜像站)=====\033[0m"
    echo "📌 新手指引:"
    echo "   1. HuggingFace地址格式:用户名/模型名(如anthropic/Claude-3.7-Sonnet)"
    echo "   2. 镜像站地址格式:https://hf-mirror.com/用户名/模型名"
    echo "   3. 模型规模格式:8B/16B/30B(仅数字+B,如30B)"
    read -p "输入模型HuggingFace ID或镜像站链接: " custom_model_id
    read -p "输入模型规模(如8B/16B/30B): " custom_model_size
    read -p "选择量化版本(q8=最高精度/q6=平衡/q5=测试/q4=大模型,输入对应值): " custom_quant_type
    # 自动处理镜像站链接格式(新手无需手动修改)
    if [[ $custom_model_id == *"hf-mirror.com"* ]]; then
        custom_model_id=$(echo $custom_model_id | awk -F '/' '{print $(NF-1)"/"$NF}')
        echo -e "\033[32m自动解析镜像站链接为:$custom_model_id\033[0m"
    fi
    # 智能量化+下载
    local quant_level=$(quant_recommend "$custom_model_size" "$custom_quant_type")
    echo -e "\033[32m开始下载自定义模型:$custom_model_id | 量化级别:$quant_level\033[0m"
    lms download --model $custom_model_id --quantization $quant_level --save-path $MODEL_DIR
    echo -e "\033[32m自定义模型下载完成!\033[0m"
    # 配置运行参数
    config_model_params "自定义模型($custom_model_id)" $quant_level
}

# ========== 核心函数5:增强型模型运行参数配置 ==========
config_model_params() {
    local model_name=$1
    local quant_level=$2
    local target_port=""
    local target_web_port=""
    clear
    echo -e "\033[34m===== 增强型配置$model_name 运行参数 =====\033[0m"
    echo "🔗 多端口选择(每个端口对应独立推理+Web实例):"
    for i in "${!LM_PORTS[@]}"; do
        echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
    done
    read -p "选择模型绑定的端口编号(新手推荐1): " port_idx
    target_port=${LM_PORTS[$((port_idx-1))]}
    target_web_port=${WEB_PORTS[$((port_idx-1))]}
    # 智能推荐参数(适配5700G/RTX5060Ti+高量化级别)
    local ctx_length="4096"
    local batch_size="1024"
    local gpu_mem_alloc="15GB"
    local num_threads="8"  # 5700G 8核最优
    local temperature="0.7"
    local top_p="0.9"
    # 根据量化级别调整显存分配
    if [ "$quant_level" = "Q8_0" ]; then
        gpu_mem_alloc="14GB"
        ctx_length="2048"
        batch_size="512"
        echo -e "\033[33m⚠️ Q8量化版本:自动调整显存分配为14GB,保证精度\033[0m"
    elif [ "$quant_level" = "Q6_K" ]; then
        gpu_mem_alloc="14.5GB"
        ctx_length="3072"
        batch_size="768"
    elif [ "$quant_level" = "Q5_K_M" ]; then
        gpu_mem_alloc="13GB"
        echo -e "\033[33m⚠️ Q5量化版本:自动调整显存分配为13GB,避免溢出\033[0m"
    fi
    # 交互式配置(新手直接回车用推荐值)
    echo -e "\033[32m💡 智能推荐参数(基于$quant_level + 端口$target_port):\033[0m"
    read -p "上下文长度(推荐$ctx_length): " input_ctx
    read -p "批处理大小(推荐$batch_size): " input_batch
    read -p "GPU显存分配(推荐$gpu_mem_alloc): " input_gpu_mem
    read -p "CPU线程数(推荐$num_threads): " input_threads
    read -p "温度值(推荐$temperature): " input_temp
    read -p "Top-P值(推荐$top_p): " input_topp
    # 使用输入值或推荐值(新手回车即默认)
    ctx_length=${input_ctx:-$ctx_length}
    batch_size=${input_batch:-$batch_size}
    gpu_mem_alloc=${input_gpu_mem:-$gpu_mem_alloc}
    num_threads=${input_threads:-$num_threads}
    temperature=${input_temp:-$temperature}
    top_p=${input_topp:-$top_p}
    # 写入LM Studio配置文件(按端口区分)
    LM_CONFIG="$HOME/.config/lm-studio/config_$target_port.json"
    mkdir -p $(dirname $LM_CONFIG)
    cp $LM_CONFIG $LM_CONFIG.bak 2>/dev/null || true
    # 更新配置(JSON格式)
    jq --arg model "$model_name" --arg ctx "$ctx_length" --arg batch "$batch_size" \
       --arg gpu_mem "$gpu_mem_alloc" --arg threads "$num_threads" --arg temp "$temperature" \
       --arg topp "$top_p" --arg port "$target_port" --arg web_port "$target_web_port" \
       '.modelSettings[$model] = {
           contextLength: $ctx, 
           batchSize: $batch, 
           gpuMemoryAllocation: $gpu_mem,
           cpuThreads: $threads,
           temperature: $temp,
           topP: $topp,
           bindPort: $port,
           webPort: $web_port
       }' $LM_CONFIG 2>/dev/null || echo "{
           \"modelSettings\": {
               \"$model_name\": {
                   \"contextLength\": \"$ctx_length\",
                   \"batchSize\": \"$batch_size\",
                   \"gpuMemoryAllocation\": \"$gpu_mem_alloc\",
                   \"cpuThreads\": \"$num_threads\",
                   \"temperature\": \"$temperature\",
                   \"topP\": \"$top_p\",
                   \"bindPort\": \"$target_port\",
                   \"webPort\": \"$target_web_port\"
               }
           }
       }" > $LM_CONFIG
    echo -e "\033[32m✅ $model_name 运行参数配置完成!\033[0m"
    echo "📋 配置信息:"
    echo "   绑定LM端口:$target_port | 绑定Web端口:$target_web_port"
    echo "   上下文长度:$ctx_length | 批处理大小:$batch_size"
    echo "   GPU显存:$gpu_mem_alloc | CPU线程:$num_threads"
    echo "   温度值:$temperature | Top-P:$top_p"
    sleep 2
}

# ========== 核心函数6:模型更新检查(手动+自动) ==========
check_model_update() {
    # 自动检查模式(每日9点运行)
    if [ "$1" = "--auto" ]; then
        local models=($(ls -1 $MODEL_DIR | grep -v "tmp" | grep -v "bak" | grep -v ".tar.gz"))
        local update_count=0
        for model in "${models[@]}"; do
            local core_name=$(echo $model | awk -F '-' '{print $1"-"$2}' | sed 's/_/-/g')
            local update_available=$(curl -s $UPDATE_CHECK_URL/$core_name | jq -r '.updateAvailable // "false"')
            if [ "$update_available" = "true" ]; then
                echo "$(date +%Y-%m-%d\ %H:%M:%S) - ⚠️ $model 有新版本可用" >> $LM_LOG_BASE/auto_update_check.log
                update_count=$((update_count+1))
            fi
        done
        if [ $update_count -gt 0 ]; then
            echo "$(date +%Y-%m-%d\ %H:%M:%S) - 共有$update_count个模型可更新,请手动运行脚本选择6进行更新" >> $LM_LOG_BASE/auto_update_check.log
            echo "共有$update_count个模型可更新" | mail -s "AI服务器模型更新提示" root
        fi
        return 0
    fi
    # 手动检查模式(菜单操作)
    clear
    echo -e "\033[34m===== 模型更新检查(手动+自动提示)=====\033[0m"
    local models=($(ls -1 $MODEL_DIR | grep -v "tmp" | grep -v "bak" | grep -v ".tar.gz"))
    if [ ${#models[@]} -eq 0 ]; then
        echo -e "\033[31m❌ 无已下载模型,请先下载模型!\033[0m"
        sleep 2
        return 0
    fi
    # 列出模型供选择检查(新手可选0检查所有)
    echo "📋 已下载模型列表:"
    for i in "${!models[@]}"; do
        echo "$((i+1)). ${models[$i]}"
    done
    echo "0. 检查所有模型(新手推荐)"
    read -p "输入要检查更新的模型编号: " model_idx
    # 确定检查范围
    local check_models=()
    if [ $model_idx -eq 0 ]; then
        check_models=("${models[@]}")
    else
        check_models=("${models[$((model_idx-1))]}")
    fi
    # 检查更新(新手友好提示)
    for model in "${check_models[@]}"; do
        echo -e "\033[32m🔍 正在检查$model 更新...\033[0m"
        local core_name=$(echo $model | awk -F '-' '{print $1"-"$2}' | sed 's/_/-/g')
        local update_available=$(curl -s $UPDATE_CHECK_URL/$core_name | jq -r '.updateAvailable // "false"')
        if [ "$update_available" = "true" ] || [ "$update_available" = "" ]; then
            echo -e "\033[33m⚠️  $model 有新版本可用!\033[0m"
            read -p "是否立即更新该模型?(y/n,更新前自动备份): " update_confirm
            if [ "$update_confirm" = "y" ] || [ "$update_confirm" = "Y" ]; then
                # 自动备份旧模型(防止更新失败)
                echo -e "\033[32m📦 正在备份旧模型...\033[0m"
                mv $MODEL_DIR/$model $MODEL_DIR/${model}_old_$(date +%Y%m%d)
                # 重新下载最新版本
                local model_size=$(echo $model | grep -o '[0-9]\+B')
                local quant_type="q6"  # 默认用推荐的Q6版本更新
                local quant_level=$(quant_recommend "$model_size" "$quant_type")
                # 提取模型ID(简化处理)
                local model_id=$(echo $model | sed 's/ /_/g' | sed 's/(.*//g')
                lms download --model $model_id --quantization $quant_level --save-path $MODEL_DIR
                echo -e "\033[32m✅ $model 更新完成!旧模型备份为:${model}_old_$(date +%Y%m%d)\033[0m"
            fi
        else
            echo -e "\033[32m✅ $model 已是最新版本!\033[0m"
        fi
        sleep 1
    done
    echo -e "\033[32m✅ 模型更新检查完成!\033[0m"
    read -p "按Enter键返回菜单..."
}

# ========== 核心函数7:多端口推理+Web管理(新手友好) ==========
multi_port_manage() {
    ensure_dependencies # 在管理多端口前确保依赖存在
    clear
    echo -e "\033[34m===== 多端口推理+Web管理(新手友好)=====\033[0m"
    echo "🔧 当前配置:"
    echo "   LM端口:${LM_PORTS[*]} | Web端口:${WEB_PORTS[*]}"
    echo "   对应关系:LM12345→Web8080、LM12346→Web8081、LM12347→Web8082"
    echo "📌 操作菜单:"
    echo "1. 查看所有端口运行状态(新手常用)"
    echo "2. 重启指定端口服务(LM+Web)"
    echo "3. 停止指定端口服务(LM+Web)"
    echo "4. 绑定模型到指定端口(核心操作)"
    echo "5. 添加新端口(扩展功能)"
    echo "6. 返回主菜单"
    read -p "输入操作编号(新手推荐1): " port_choice
    case $port_choice in
        1)
            echo -e "\033[32m===== 多端口运行状态 =====\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                local lm_port=${LM_PORTS[$i]}
                local web_port=${WEB_PORTS[$i]}
                local webui_name="${WEBUI_BASE_NAME}_$lm_port"
                echo "📡 端口组$((i+1)):"
                echo "   LM端口$lm_port:$(ps aux | grep -v grep | grep "lm-studio --remote-inference --remote-port $lm_port" >/dev/null && "✅ 运行中" || "❌ 未运行")"
                echo "   Web端口$web_port:$(docker ps | grep $webui_name >/dev/null && "✅ 运行中" || "❌ 未运行")"
                echo "   LM日志:$LM_LOG_BASE/lmstudio_$lm_port.log"
                # 查看端口绑定的模型
                local config_file="$HOME/.config/lm-studio/config_$lm_port.json"
                if [ -f $config_file ]; then
                    local bound_models=$(jq -r '.modelSettings | keys[]' $config_file 2>/dev/null | head -1)
                    echo "   绑定模型:${bound_models:-无}"
                else
                    echo "   绑定模型:无"
                fi
                echo "   访问地址:http://服务器IP:$web_port"
                echo "-------------------------"
            done
            ;;
        2)
            echo -e "\033[32m===== 重启指定端口服务 =====\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
            done
            read -p "输入要重启的端口组编号: " port_idx
            local target_lm_port=${LM_PORTS[$((port_idx-1))]}
            local target_web_port=${WEB_PORTS[$((port_idx-1))]}
            local target_webui="${WEBUI_BASE_NAME}_$target_lm_port"
            # 重启LM Studio
            pkill -f "lm-studio --remote-inference --remote-port $target_lm_port" || true
            nohup lm-studio --remote-inference --remote-port $target_lm_port > $LM_LOG_BASE/lmstudio_$target_lm_port.log 2>&1 &
            # 重启Web界面
            docker restart $target_webui || true
            echo -e "\033[32m✅ 端口组$port_idx(LM$target_lm_port+Web$target_web_port)已重启!\033[0m"
            ;;
        3)
            echo -e "\033[32m===== 停止指定端口服务 =====\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
            done
            read -p "输入要停止的端口组编号: " port_idx
            local target_lm_port=${LM_PORTS[$((port_idx-1))]}
            local target_web_port=${WEB_PORTS[$((port_idx-1))]}
            local target_webui="${WEBUI_BASE_NAME}_$target_lm_port"
            # 停止LM Studio
            pkill -f "lm-studio --remote-inference --remote-port $target_lm_port" || true
            # 停止Web界面
            docker stop $target_webui || true
            echo -e "\033[32m✅ 端口组$port_idx(LM$target_lm_port+Web$target_web_port)已停止!\033[0m"
            ;;
        4)
            echo -e "\033[32m===== 绑定模型到指定端口 =====\033[0m"
            # 选择端口组(新手推荐1)
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]} | Web端口${WEB_PORTS[$i]}"
            done
            read -p "输入目标端口组编号(新手推荐1): " port_idx
            local target_port=${LM_PORTS[$((port_idx-1))]}
            # 选择模型
            local models=($(ls -1 $MODEL_DIR | grep -v "tmp" | grep -v "bak"))
            if [ ${#models[@]} -eq 0 ]; then
                echo -e "\033[31m❌ 无已下载模型!请先下载模型\033[0m"
                sleep 2
                return 0
            fi
            echo "📋 已下载模型:"
            for i in "${!models[@]}"; do
                echo "$((i+1)). ${models[$i]}"
            done
            read -p "输入要绑定的模型编号: " model_idx
            local selected_model=${models[$((model_idx-1))]}
            # 配置参数并绑定
            local model_size=$(echo $selected_model | grep -o '[0-9]\+B')
            local quant_type="q6"  # 默认用推荐的Q6版本
            local quant_level=$(quant_recommend "$model_size" "$quant_type")
            config_model_params $selected_model $quant_level
            echo -e "\033[32m✅ 模型$selected_model 已绑定到端口组$port_idx!\033[0m"
            echo "   访问地址:http://服务器IP:${WEB_PORTS[$((port_idx-1))]}"
            ;;
        5)
            echo -e "\033[32m===== 添加新端口(扩展功能)=====\033[0m"
            read -p "输入新的LM端口号(如12348): " new_lm_port
            read -p "输入新的Web端口号(如8083): " new_web_port
            # 检查端口是否已存在
            if [[ " ${LM_PORTS[@]} " =~ " $new_lm_port " ]]; then
                echo -e "\033[31m❌ LM端口$new_lm_port 已存在!\033[0m"
                sleep 2
                return 0
            fi
            if [[ " ${WEB_PORTS[@]} " =~ " $new_web_port " ]]; then
                echo -e "\033[31m❌ Web端口$new_web_port 已存在!\033[0m"
                sleep 2
                return 0
            fi
            # 添加新端口到数组
            LM_PORTS+=("$new_lm_port")
            WEB_PORTS+=("$new_lm_port")
            # 放行端口
            ufw allow $new_lm_port/tcp
            ufw allow $new_web_port/tcp
            # 启动新端口服务
            nohup lm-studio --remote-inference --remote-port $new_lm_port > $LM_LOG_BASE/lmstudio_$new_lm_port.log 2>&1 &
            local new_webui="${WEBUI_BASE_NAME}_$new_lm_port"
            docker run -d --name $new_webui -p $new_web_port:8080 -e "LMSTUDIO_BASE_URL=http://localhost:$new_lm_port" --restart always ghcr.io/open-webui/open-webui:main
            echo -e "\033[32m✅ 新端口组添加完成!\033[0m"
            echo "   LM端口:$new_lm_port | Web端口:$new_web_port"
            echo "   访问地址:http://服务器IP:$new_web_port"
            ;;
        6)
            return 0
            ;;
        *)
            echo -e "\033[31m❌ 无效编号,请重新输入\033[0m"
            sleep 1
            ;;
    esac
    read -p "按Enter键返回多端口管理菜单..."
    multi_port_manage
}

# ========== 核心函数8:添加新模型到脚本(新手指引) ==========
add_new_model_to_script() {
    clear
    echo -e "\033[34m===== 添加新模型到脚本(新手友好指引)=====\033[0m"
    echo "📌 新手步骤指引(以添加Claude 3.7 Sonnet为例):"
    echo "1. 找到脚本中『model_menu』函数"
    echo "2. 在对应厂商分类下添加如下代码:"
    echo "   示例:"
    echo "   6. Claude 3.7 Sonnet(20B,推荐Q8_0)"
    echo "   然后在case中添加:"
    echo "   6) download_model \"anthropic/Claude-3.7-Sonnet\" \"Claude 3.7 Sonnet\" \"20B\" \"q8\" ;;"
    echo "3. 保存脚本后重新运行即可看到新模型选项"
    echo ""
    echo "📋 模型信息填写规范:"
    echo "   - download_model参数1:HuggingFace ID(必填)"
    echo "   - download_model参数2:模型显示名称(自定义)"
    echo "   - download_model参数3:模型规模(如20B,用于量化推荐)"
    echo "   - download_model参数4:量化类型(q8=最高精度/q6=平衡/q5=测试/q4=大模型)"
    echo ""
    echo "💡 快速定位方法:"
    echo "   运行:vim /ai_server_ultimate_final.sh"
    echo "   输入:/model_menu 回车(直接定位到模型菜单函数)"
    echo ""
    read -p "按Enter键返回主菜单..."
}

# ========== 一级菜单:主菜单(新手友好) ==========
main_menu() {
    # 自动更新检查模式(后台运行)
    if [ "$1" = "--auto-check-update" ]; then
        check_model_update --auto
        exit 0
    fi
    clear
    echo -e "\033[34m===== AI服务器终极完整版管理菜单(顶级模型最终版)=====\033[0m"
    echo "🔧 硬件配置:$CPU_MODEL | $GPU_MODEL | $SYSTEM_MEM | $DISK_SPACE"
    echo "🌐 多端口配置:LM${LM_PORTS[*]} → Web${WEB_PORTS[*]}"
    echo "📌 新增特性:Claude 3.7 Sonnet/Meta全系列+优化量化策略(12-25B Q6/Q8、30B+ Q4)"
    echo "📌 新手入门推荐流程:1→3→7→访问Web地址"
    echo ""
    echo "1. 全新部署(首次使用必选,全自动安装驱动/CUDA/多端口)"
    echo "2. 服务器运维管理(监控/备份/告警,日常维护)"
    echo "3. 顶级模型下载(含Claude/Meta/Google/DeepSeek全系列)"
    echo "4. 自定义模型下载(支持HuggingFace/镜像站)"
    echo "5. 模型运行参数配置(增强型,多端口绑定)"
    echo "6. 模型更新检查(手动+自动提示,一键更新)"
    echo "7. 多端口推理+Web管理(核心操作,绑定模型/访问)"
    echo "8. 添加新模型到脚本(新手指引,自定义扩展)"
    echo "9. 使用帮助手册(完整版,含所有功能说明)"
    echo "0. 退出脚本"
    echo -e "\033[34m=========================================================================\033[0m"
    read -p "输入操作编号(新手推荐1): " main_choice

    case $main_choice in
        1) system_init ;;
        2) ops_menu ;;
        3) model_menu ;;
        4) custom_model_download ;;
        5) config_model_params ;;
        6) check_model_update ;;
        7) multi_port_manage ;;
        8) add_new_model_to_script ;;
        9) echo "使用帮助手册待完善..."; read -p "按Enter键返回..."; main_menu ;;
        0) exit 0 ;;
        *) echo -e "\033[31m❌ 无效编号,请重新输入\033[0m"; sleep 1; main_menu ;;
    esac
}

# ========== 二级菜单:服务器运维管理 ==========
ops_menu() {
    clear
    echo -e "\033[34m===== 服务器运维管理菜单 =====\033[0m"
    echo "📌 新手常用操作:1(查看状态)、6(性能监控)、8(手动备份)"
    echo "1. 查看服务状态(多端口LM/Web/GPU/CPU)"
    echo "2. 重启所有服务(多端口LM+Web)"
    echo "3. 停止所有服务"
    echo "4. 查看指定端口日志(排错用)"
    echo "5. 清理模型缓存+释放GPU显存"
    echo "6. 实时性能监控(GPU/CPU/内存,核心监控)"
    echo "7. 查看已下载模型列表"
    echo "8. 手动备份模型(保留7天,数据安全)"
    echo "9. 测试性能告警(GPU利用率阈值$ALERT_THRESHOLD%)"
    echo "10. 返回主菜单"
    echo -e "\033[34m===============================================================\033[0m"
    read -p "输入运维操作编号(新手推荐1): " ops_choice
    # 确保 docker 存在,nvidia-smi 根据情况处理
    if ! command -v docker &> /dev/null; then
        echo -e "\033[31m❌ 错误: 'docker' 命令未找到。请确保 Docker 已正确安装。\033[0m"
        exit 1
    fi
    case $ops_choice in
        1)
            echo -e "\033[32m=== 多端口服务状态 ===\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                local lm_port=${LM_PORTS[$i]}
                local web_port=${WEB_PORTS[$i]}
                local webui_name="${WEBUI_BASE_NAME}_$lm_port"
                echo "📡 端口组$((i+1)):"
                echo "   LM端口$lm_port:$(ps aux | grep -v grep | grep "lm-studio --remote-inference --remote-port $lm_port" >/dev/null && "✅ 运行中" || "❌ 未运行")"
                echo "   Web端口$web_port:$(docker ps | grep $webui_name >/dev/null && "✅ 运行中" || "❌ 未运行")"
            done
            echo "🐳 Docker:$(systemctl is-active docker | sed 's/active/✅ 运行中/' | sed 's/inactive/❌ 未运行/')"
            echo -e "\033[32m=== GPU状态(纯GPU推理,CPU占用<5%)===\033[0m"
            if command -v nvidia-smi &> /dev/null; then
                nvidia-smi | grep -E "GPU|Memory-Usage|Utilization"
            else
                echo -e "\033[33m⚠️  'nvidia-smi' 未找到,无法显示GPU状态。\033[0m"
            fi
            echo -e "\033[32m=== CPU状态 ===\033[0m"
            top -bn1 | grep -E 'Cpu.s*us|Mem' | head -2
            ;;
        2)
            echo -e "\033[32m=== 重启所有服务 ===\033[0m"
            for port in "${LM_PORTS[@]}"; do
                pkill -f "lm-studio --remote-inference --remote-port $port" || true
                nohup lm-studio --remote-inference --remote-port $port > $LM_LOG_BASE/lmstudio_$port.log 2>&1 &
                echo "✅ LM端口$port 已重启"
            done
            for i in "${!LM_PORTS[@]}"; do
                local webui_name="${WEBUI_BASE_NAME}_${LM_PORTS[$i]}"
                docker restart $webui_name || true
                echo "✅ Web端口${WEB_PORTS[$i]} 已重启"
            done
            echo -e "\033[32m✅ 所有服务重启完成!GPU利用率应>80%,CPU<5%\033[0m"
            ;;
        3)
            echo -e "\033[32m=== 停止所有服务 ===\033[0m"
            for port in "${LM_PORTS[@]}"; do
                pkill -f "lm-studio --remote-inference --remote-port $port" || true
                echo "✅ LM端口$port 已停止"
            done
            for i in "${!LM_PORTS[@]}"; do
                local webui_name="${WEBUI_BASE_NAME}_${LM_PORTS[$i]}"
                docker stop $webui_name || true
                echo "✅ Web端口${WEB_PORTS[$i]} 已停止"
            done
            echo -e "\033[32m✅ 所有服务已停止!\033[0m"
            ;;
        4)
            echo -e "\033[32m=== 查看指定端口日志 ===\033[0m"
            for i in "${!LM_PORTS[@]}"; do
                echo "$((i+1)). LM端口${LM_PORTS[$i]}(日志:$LM_LOG_BASE/lmstudio_${LM_PORTS[$i]}.log)"
            done
            read -p "输入要查看的端口编号: " port_idx
            local target_port=${LM_PORTS[$((port_idx-1))]}
            echo -e "\033[32m📄 正在查看LM端口$target_port 日志(按Ctrl+C退出)...\033[0m"
            tail -f $LM_LOG_BASE/lmstudio_$target_port.log
            ;;
        5)
            echo -e "\033[32m=== 清理缓存+释放显存 ===\033[0m"
            for port in "${LM_PORTS[@]}"; do
                pkill -f "lm-studio --remote-inference --remote-port $port" || true
            done
            for i in "${!LM_PORTS[@]}"; do
                local webui_name="${WEBUI_BASE_NAME}_${LM_PORTS[$i]}"
                docker stop $webui_name || true
            done
            rm -rf ~/.cache/lm-studio/* || true
            if command -v nvidia-smi &> /dev/null; then
                 nvidia-smi --gpu-reset || true
            fi
            echo -e "\033[32m✅ 缓存清理完成!解决显存占用过高问题\033[0m"
            ;;
        6)
            echo -e "\033[32m=== 实时性能监控(按Ctrl+C退出)===\033[0m"
            echo "📌 核心指标:GPU利用率>80%(正常)、CPU占用<5%(纯GPU推理)"
            if command -v nvidia-smi &> /dev/null; then
                 watch -n 1 "nvidia-smi | grep -E 'GPU|Memory-Usage|Utilization' && echo '--- CPU/内存 ---' && top -bn1 | grep -E 'Cpu.s*us|Mem' | head -2"
            else
                 echo -e "\033[33m⚠️  'nvidia-smi' 未找到,仅监控 CPU/内存。\033[0m"
                 watch -n 1 "echo '--- CPU/内存 ---' && top -bn1 | grep -E 'Cpu.s*us|Mem' | head -2"
            fi
            ;;
        7)
            echo -e "\033[32m=== 已下载模型列表 ===\033[0m"
            ls -lh $MODEL_DIR | awk '{print $9, $5}' || echo "❌ 无模型或路径错误"
            ;;
        8)
            echo -e "\033[32m=== 手动备份模型 ===\033[0m"
            local backup_file="$BACKUP_DIR/models_$(date +%Y%m%d_%H%M%S).tar.gz"
            tar -zcf $backup_file $MODEL_DIR --exclude='*.tmp'
            find $BACKUP_DIR -name 'models_*.tar.gz' -mtime +7 -delete
            echo -e "\033[32m✅ 模型备份完成!\033[0m"
            echo "   备份文件:$backup_file"
            echo "   📌 自动清理7天前的备份文件,释放磁盘空间"
            ;;
        9)
            echo -e "\033[32m=== 测试性能告警 ===\033[0m"
            if command -v nvidia-smi &> /dev/null; then
                 GPU_UTIL=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits | awk '{print $1}')
                 if [ $GPU_UTIL -ge $ALERT_THRESHOLD ]; then
                     echo "GPU利用率告警:$GPU_UTIL%(阈值$ALERT_THRESHOLD%)" | mail -s "AI服务器GPU告警" root
                     echo -e "\033[32m✅ 告警邮件已发送到root邮箱!\033[0m"
                 else
                     echo -e "\033[32m✅ 当前GPU利用率:$GPU_UTIL%(低于阈值$ALERT_THRESHOLD%),无需告警\033[0m"
                 fi
            else
                 echo -e "\033[33m⚠️  'nvidia-smi' 未找到,无法测试GPU告警。\033[0m"
            fi
            ;;
        10)
            return 0
            ;;
        *)
            echo -e "\033[31m❌ 无效编号,请重新输入\033[0m"
            sleep 1
            ;;
    esac
    read -p "按Enter键返回运维菜单..."
    ops_menu
}

# ========== 二级菜单:顶级模型下载(最终版,含Claude/Meta全系列) ==========
model_menu() {
    clear
    echo -e "\033[34m===== 顶级模型下载菜单(最终版)=====\033[0m"
    echo "📌 量化策略(适配RTX5060Ti 16G+充足硬盘):"
    echo "   11-25B→Q8(最高精度)/Q6(平衡,默认)|26-35B→Q4(推荐)/Q6(测试)"
    echo "📌 模型分类:"
    echo "1. Claude系列(Anthropic顶级模型,含3.7 Sonnet)"
    echo "2. Meta全系列(Llama3/Gemma2/CodeLlama顶级模型)"
    echo "3. Gemini 3 Pro系列(谷歌官方12B-27B)"
    echo "4. Qwen3+Gemini3Pro混合系列(第三方高下载量)"
    echo "5. Codestral/DeepSeek编程模型(15B-33B)"
    echo "6. 一键下载所有顶级模型(Q6默认版,对比测试推荐)"
    echo "7. 一键下载所有顶级模型(Q8高精度版,11-25B)"
    echo "8. 返回主菜单"
    echo -e "\033[34m======================================================\033[0m"
    read -p "输入模型分类编号(对比测试推荐6): " model_choice
    start_lm_multi_api
    case $model_choice in
        1)
            # Claude系列(Anthropic顶级模型)
            clear
            echo -e "\033[34m===== Claude系列(Anthropic顶级模型)=====\033[0m"
            echo "📌 新手推荐:1(Claude 3.7 Sonnet Q8版)"
            echo "1. Claude 3.7 Sonnet(Q8最高精度版,20B)✅ 推荐"
            echo "2. Claude 3.7 Sonnet(Q6平衡版,20B)"
            echo "3. Claude 3 Opus(Q8最高精度版,28B)"
            echo "4. Claude 3 Opus(Q4推荐版,28B)"
            echo "5. Claude 3 Haiku(Q8最高精度版,14B)"
            echo "6. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " claude_choice
            case $claude_choice in
                1) download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q8最高精度版)" "20B" "q8" ;;
                2) download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q6平衡版)" "20B" "q6" ;;
                3) download_model "anthropic/Claude-3-Opus" "Claude 3 Opus(Q8最高精度版)" "28B" "q8" ;;
                4) download_model "anthropic/Claude-3-Opus" "Claude 3 Opus(Q4推荐版)" "28B" "q4" ;;
                5) download_model "anthropic/Claude-3-Haiku" "Claude 3 Haiku(Q8最高精度版)" "14B" "q8" ;;
                6) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        2)
            # Meta全系列(Llama3/Gemma2/CodeLlama)
            clear
            echo -e "\033[34m===== Meta全系列(Llama3/Gemma2/CodeLlama)=====\033[0m"
            echo "📌 新手推荐:1(Llama3-70B Q6版)"
            echo "1. Llama3-70B-Instruct(Q4推荐版,70B)"
            echo "2. Llama3-14B-Instruct(Q8最高精度版,14B)✅ 推荐"
            echo "3. Gemma2-27B-Instruct(Q4推荐版,27B)"
            echo "4. Gemma2-9B-Instruct(Q8最高精度版,9B)"
            echo "5. CodeLlama-34B-Instruct(Q4推荐版,34B)"
            echo "6. CodeLlama-13B-Instruct(Q8最高精度版,13B)"
            echo "7. 返回模型主菜单"
            read -p "输入模型编号(新手推荐2): " meta_choice
            case $meta_choice in
                1) download_model "meta-llama/Meta-Llama-3-70B-Instruct" "Llama3-70B-Instruct(Q4推荐版)" "70B" "q4" ;;
                2) download_model "meta-llama/Meta-Llama-3-14B-Instruct" "Llama3-14B-Instruct(Q8最高精度版)" "14B" "q8" ;;
                3) download_model "google/gemma-2-27b-it" "Gemma2-27B-Instruct(Q4推荐版)" "27B" "q4" ;;
                4) download_model "google/gemma-2-9b-it" "Gemma2-9B-Instruct(Q8最高精度版)" "9B" "q8" ;;
                5) download_model "meta-llama/CodeLlama-34b-Instruct-hf" "CodeLlama-34B-Instruct(Q4推荐版)" "34B" "q4" ;;
                6) download_model "meta-llama/CodeLlama-13b-Instruct-hf" "CodeLlama-13B-Instruct(Q8最高精度版)" "13B" "q8" ;;
                7) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        3)
            # Gemini 3 Pro系列(谷歌官方,优化量化)
            clear
            echo -e "\033[34m===== Gemini 3 Pro系列(谷歌官方)=====\033[0m"
            echo "📌 新手推荐:1(12B Q8版)或5(27B Q4版)"
            echo "1. Gemini 3 Pro 12B(Q8最高精度版,12B)✅ 推荐"
            echo "2. Gemini 3 Pro 12B(Q6平衡版,12B)"
            echo "3. Gemini 3 Pro 19B(Q8最高精度版,19B)"
            echo "4. Gemini 3 Pro 19B(Q6平衡版,19B)"
            echo "5. Gemini 3 Pro 27B(Q4推荐版,27B)"
            echo "6. Gemini 3 Pro 27B(Q6测试版,27B)"
            echo "7. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " gemini_choice
            case $gemini_choice in
                1) download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q8最高精度版)" "12B" "q8" ;;
                2) download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q6平衡版)" "12B" "q6" ;;
                3) download_model "google/gemini-3-pro-19B" "Gemini 3 Pro 19B(Q8最高精度版)" "19B" "q8" ;;
                4) download_model "google/gemini-3-pro-19B" "Gemini 3 Pro 19B(Q6平衡版)" "19B" "q6" ;;
                5) download_model "google/gemini-3-pro-27B" "Gemini 3 Pro 27B(Q4推荐版)" "27B" "q4" ;;
                6) download_model "google/gemini-3-pro-27B" "Gemini 3 Pro 27B(Q6测试版)" "27B" "q6" ;;
                7) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        4)
            # Qwen3+Gemini3Pro混合系列
            clear
            echo -e "\033[34m===== Qwen3+Gemini3Pro混合系列(第三方高下载量)=====\033[0m"
            echo "📌 新手推荐:1(20B Q8版)"
            echo "1. Qwen3-Gemini3Pro-20B(Q8最高精度版,20B)✅ 推荐"
            echo "2. Qwen3-Gemini3Pro-20B(Q6平衡版,20B)"
            echo "3. Qwen3-Gemini3Pro-28B(Q4推荐版,28B)"
            echo "4. Qwen3-Gemini3Pro-28B(Q6测试版,28B)"
            echo "5. Qwen3-Gemini3Pro-32B(Q4推荐版,32B)"
            echo "6. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " mix_choice
            case $mix_choice in
                1) download_model "unsloth/qwen3-gemini3pro-20b" "Qwen3-Gemini3Pro-20B(Q8最高精度版)" "20B" "q8" ;;
                2) download_model "unsloth/qwen3-gemini3pro-20b" "Qwen3-Gemini3Pro-20B(Q6平衡版)" "20B" "q6" ;;
                3) download_model "unsloth/qwen3-gemini3pro-28b" "Qwen3-Gemini3Pro-28B(Q4推荐版)" "28B" "q4" ;;
                4) download_model "unsloth/qwen3-gemini3pro-28b" "Qwen3-Gemini3Pro-28B(Q6测试版)" "28B" "q6" ;;
                5) download_model "unsloth/qwen3-gemini3pro-32b" "Qwen3-Gemini3Pro-32B(Q4推荐版)" "32B" "q4" ;;
                6) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        5)
            # Codestral/DeepSeek编程模型
            clear
            echo -e "\033[34m===== Codestral/DeepSeek编程模型(顶级)=====\033[0m"
            echo "📌 新手推荐:1(Codestral-15B Q8版)或5(DeepSeek-16B Q8版)"
            echo "1. Codestral-15B-v0.1(Q8最高精度版,15B)✅ 推荐"
            echo "2. Codestral-22B-v0.1(Q8最高精度版,22B)"
            echo "3. Codestral-Mix-30B(Q4推荐版,30B)"
            echo "4. DeepSeek-Coder-V2-16B(Q6平衡版,16B)"
            echo "5. DeepSeek-Coder-V2-16B(Q8最高精度版,16B)✅ 推荐"
            echo "6. DeepSeek-Coder-V2-33B(Q4推荐版,33B)"
            echo "7. 返回模型主菜单"
            read -p "输入模型编号(新手推荐1): " code_choice
            case $code_choice in
                1) download_model "mistralai/Codestral-15B-v0.1" "Codestral-15B-v0.1(Q8最高精度版)" "15B" "q8" ;;
                2) download_model "mistralai/Codestral-22B-v0.1" "Codestral-22B-v0.1(Q8最高精度版)" "22B" "q8" ;;
                3) download_model "mistralai/Codestral-Mix-30B-v0.1" "Codestral-Mix-30B(Q4推荐版)" "30B" "q4" ;;
                4) download_model "deepseek-ai/DeepSeek-Coder-V2-16B-base" "DeepSeek-Coder-V2-16B(Q6平衡版)" "16B" "q6" ;;
                5) download_model "deepseek-ai/DeepSeek-Coder-V2-16B-base" "DeepSeek-Coder-V2-16B(Q8最高精度版)" "16B" "q8" ;;
                6) download_model "deepseek-ai/DeepSeek-Coder-V2-33B-base" "DeepSeek-Coder-V2-33B(Q4推荐版)" "33B" "q4" ;;
                7) model_menu ;;
                *) echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
            esac
            ;;
        6)
            # 一键下载所有顶级模型(Q6默认版)
            echo -e "\033[32m=== 一键下载所有顶级模型(Q6平衡版)===\033[0m"
            echo "📌 包含:Claude/Meta/Gemini/混合模型/编程模型共15个核心模型"
            # Claude系列
            download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q6平衡版)" "20B" "q6"
            # Meta系列
            download_model "meta-llama/Meta-Llama-3-14B-Instruct" "Llama3-14B-Instruct(Q6平衡版)" "14B" "q6"
            download_model "meta-llama/CodeLlama-13b-Instruct-hf" "CodeLlama-13B-Instruct(Q6平衡版)" "13B" "q6"
            # Gemini系列
            download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q6平衡版)" "12B" "q6"
            download_model "google/gemini-3-pro-19B" "Gemini 3 Pro 19B(Q6平衡版)" "19B" "q6"
            # 混合模型
            download_model "unsloth/qwen3-gemini3pro-20b" "Qwen3-Gemini3Pro-20B(Q6平衡版)" "20B" "q6"
            # 编程模型
            download_model "mistralai/Codestral-15B-v0.1" "Codestral-15B-v0.1(Q6平衡版)" "15B" "q6"
            download_model "deepseek-ai/DeepSeek-Coder-V2-16B-base" "DeepSeek-Coder-V2-16B(Q6平衡版)" "16B" "q6"
            # 大模型(Q4版)
            download_model "google/gemini-3-pro-27B" "Gemini 3 Pro 27B(Q4推荐版)" "27B" "q4"
            download_model "unsloth/qwen3-gemini3pro-28b" "Qwen3-Gemini3Pro-28B(Q4推荐版)" "28B" "q4"
            download_model "deepseek-ai/DeepSeek-Coder-V2-33B-base" "DeepSeek-Coder-V2-33B(Q4推荐版)" "33B" "q4"
            echo -e "\033[32m✅ 所有顶级模型下载完成!\033[0m"
            echo "📌 11-25B模型为Q6平衡版,26-35B模型为Q4推荐版,兼顾精度与显存"
            ;;
        7)
            # 一键下载所有顶级模型(Q8高精度版)
            echo -e "\033[32m=== 一键下载所有顶级模型(Q8高精度版)===\033[0m"
            echo "📌 包含:11-25B高精度模型+26-35B Q4推荐版模型"
            # 11-25B Q8版
            download_model "anthropic/Claude-3.7-Sonnet" "Claude 3.7 Sonnet(Q8最高精度版)" "20B" "q8"
            download_model "meta-llama/Meta-Llama-3-14B-Instruct" "Llama3-14B-Instruct(Q8最高精度版)" "14B" "q8"
            download_model "google/gemini-3-pro-preview-12B" "Gemini 3 Pro 12B(Q8最高精度版)" "12B" "q8"
            # ... (可以继续添加其他Q8模型)
            echo -e "\033[32m✅ Q8高精度版模型下载完成!\033[0m"
            ;;
        8)
            return 0
            ;;
        *)
            echo -e "\033[31m❌ 无效编号\033[0m"; sleep 1; model_menu ;;
    esac
}

# 启动主菜单
main_menu "$@"

0

评论区