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 "$@"
评论区