Skip to content

Quick Start.zh

sikkatu edited this page Oct 19, 2026 · 8 revisions

快速上手 — 4× RTX PRO 6000

English | Русский | 中文

从全新的 Debian 12 机器到可用的服务端点。先读三个必填参数 —— 启动脚本缺少它们会 拒绝启动,这是有意设计。

目标操作系统:Debian 12 (bookworm)。 命令同样适用于 Ubuntu 22.04/24.04(apt)。

启动脚本非有不可的三样东西

参数 为什么 怎么获得
IMAGE 必须以 sha256 digest 固定 —— 浮动标签被拒绝 步骤 3
MODEL_REVISION 模型按 id下载时必需(本地目录不需要) 模型的 commit SHA
API_KEY 即使 127.0.0.1 也必需 —— 只有 ALLOW_NO_AUTH=1 可跳过,且仅限回环 openssl rand -hex 24

0. 检查机器

  • 4× NVIDIA RTX PRO 6000(96 GB GDDR7),nvidia-smi 能看到全部四块
  • ≥ 1 TB 内存(冷库驻留在主机内存),≥ 2 TB NVMe 存模型 + 容器
  • Debian 12,root 或 sudo

1. 安装 Docker + NVIDIA Container Toolkit

# Docker (Debian 12)
sudo apt-get update && sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# NVIDIA Container Toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -fsSL https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker

# 验证:容器内必须打印 GPU 信息
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi

2. 获取配方仓库

git clone https://github.com/sikkatu/recipes.git ~/recipes
cd ~/recipes/rtx-pro-6000/mimo-v2.6-pro-hotsplit

后续所有命令都在这个目录执行 —— 不用反复猜 cd 路径。

3. 固定容器镜像(必填)

启动脚本拒绝浮动标签。解析一次 digest,处处使用:

export IMAGE="vllm/vllm-openai:<tag>"   # 用配方 README 指定的标签
# 注意:镜像未在目标硬件上验证 —— hotsplit 会替换 vLLM 内的模型文件,
# 因此 vLLM 的具体构建版本很重要。请把首次启动当作实验。
docker pull "$IMAGE"
export IMAGE="$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE")"
echo "$IMAGE"   # 必须以 @sha256:<digest> 结尾

4. 获取模型

这些命令在 Linux 主机(带四块 GPU 的机器)上执行,不要在 docker 容器内执行。 模型目录 是主机路径,启动脚本之后会以只读方式挂载它。

两个名称,两个不同的东西:

名称 是什么 示例
MODEL_ID 模型在 Hugging Face 上的地址 XiaomiMiMo/MiMo-V2.6-Pro-MOPD
MODEL_DIR 本机存放已下载文件的本地目录 /models/MiMo-V2.6-Pro-MOPD
MODEL_REVISION 模型版本的确切 commit SHA —— 下载和启动都用它 f3a9...(40 个十六进制字符)

MODEL_REVISION 标识版本。取得 SHA 不会下载模型。 注意:使用 MODEL_DIR 时启动脚本只挂载目录,不按 SHA 校验其内容 —— MODEL_REVISION 仅记录你下载的版本。要可复现地本地运行,请把版本字符串与文件放在一起 保存,并另行校验完整性。使用 MODEL_ID 时版本在下载时由启动脚本强制校验。下载是下面的步骤。启动时使用同一个 SHA,服务器加载的正是你验证过的那批文件。

方案 A —— 把整个模型仓库下载到本地目录(推荐)

# 1. 在独立的 Python 虚拟环境中安装 Hugging Face CLI(不用系统 Python)
python3 -m venv "$HOME/.venvs/hf-download"
source "$HOME/.venvs/hf-download/bin/activate"
python -m pip install --upgrade huggingface_hub

# 2. 模型 id 和目标目录
export MODEL_ID="XiaomiMiMo/MiMo-V2.6-Pro-MOPD"
export MODEL_DIR="/models/MiMo-V2.6-Pro-MOPD"

# 3. 创建目录并允许当前用户写入
sudo mkdir -p "$MODEL_DIR"
sudo chown "$USER:$(id -gn)" "$MODEL_DIR"

# 4. 获取当前模型版本的确切 commit SHA
export MODEL_REVISION="$(
  curl -fsSL "https://huggingface.co/api/models/$MODEL_ID" |
  python3 -c 'import json,sys; print(json.load(sys.stdin)["sha"])'
)"
if ! [[ "$MODEL_REVISION" =~ ^[0-9a-f]{40}$ ]]; then
  echo "ERROR: 无法获取有效的模型修订版 SHA" >&2
  exit 1
fi
echo "模型:    $MODEL_ID"
echo "修订版:  $MODEL_REVISION"
echo "目录:    $MODEL_DIR"

# 5. 下载前检查磁盘空间(模型有数百 GB)
df -h "$(dirname "$MODEL_DIR")"

# 6. 按该修订版下载整个模型仓库
hf download "$MODEL_ID" \
  --revision "$MODEL_REVISION" \
  --local-dir "$MODEL_DIR"

# 7. 验证下载(配置、权重索引、所有 shards、分词器、修订版)
test -s "$MODEL_DIR/config.json" || { echo "ERROR: 缺少 config.json" >&2; exit 1; }
find "$MODEL_DIR" -maxdepth 1 -type f -name '*.safetensors' -print -quit | grep -q . \
  || { echo "ERROR: 未找到 safetensors 文件" >&2; exit 1; }
# 权重索引中列出的每个 shard 都必须存在且非空
if ls "$MODEL_DIR"/*.index.json >/dev/null 2>&1; then
  python3 -c '
import json, sys, pathlib
idx = next(pathlib.Path(sys.argv[1]).glob("*.index.json"))
shards = sorted(set(json.load(open(idx))["weight_map"].values()))
missing = [s for s in shards if not (pathlib.Path(sys.argv[1]) / s).is_file()
           or (pathlib.Path(sys.argv[1]) / s).stat().st_size == 0]
if missing:
    print("ERROR: 缺失或为空的 shards:", missing, file=sys.stderr); sys.exit(1)
print(f"shards 正常:{len(shards)} 个文件({idx.name})")
' "$MODEL_DIR" || exit 1
fi
# 分词器文件(至少一个标准名称)
for f in tokenizer.json tokenizer_config.json; do
  test -s "$MODEL_DIR/$f" || { echo "ERROR: 缺少分词器文件 $f" >&2; exit 1; }
done
# 把修订版保存在文件旁边 —— MODEL_DIR 启动时不会校验它
echo "$MODEL_REVISION" > "$MODEL_DIR/REVISION.txt"
echo "下载完成:"
ls -lah "$MODEL_DIR"

不指定文件列表的 hf download 会下载整个仓库(权重、config.json、分词器、索引)—— 比手动挑文件更可靠,不会漏掉某个文件。如果模型需要授权,先执行 hf auth login。公开模型 无需登录。

这些检查验证 config.json、权重索引中列出的每个 shard(存在且非零大小)以及分词器文件。 但它们不校验字节:要逐字节完整性,请用模型作者发布的哈希值(若有)运行 sha256sum。 使用 MODEL_DIR 时启动脚本在加载时不会比对目录与 MODEL_REVISION —— 保存的 REVISION.txt 是你自己保留的记录;需要可复现性时请核对它。

方案 B —— 让启动脚本把模型下载到 Hugging Face cache

启动脚本也能按 MODEL_ID 拉取到默认 HF 缓存(~/.cache/huggingface),但此时 MODEL_REVISION(40 个十六进制字符)必填 —— 启动脚本拒绝分支名。用同样的方法取得 SHA (上面第 4 步),改为导出 MODEL_ID 和 MODEL_REVISION(而不是 MODEL_DIR),然后启动 服务器。下载的文件位于 ~/.cache/huggingface/hub/models--<org>--<name>/snapshots/<SHA>/ —— 服务器加载的就是这个 快照目录。注意:缓存不会随回退一起删除(见 manage.sh clean-cache)。

5. 生成 API 密钥(必填)

export API_KEY="$(openssl rand -hex 24)"

纯回环调试可以用 ALLOW_NO_AUTH=1 BIND=127.0.0.1 代替 —— 其他任何绑定都必须有密钥。

6. 首次运行 —— 安全基线(原版 vLLM + UVA)

从未改动的基线和小上下文开始:

export IMAGE="vllm/vllm-openai:<tag>@sha256:<64-hex-digest>"   # 来自步骤 3
export API_KEY="$(openssl rand -hex 24)"                       # 来自步骤 5
export MAX_MODEL_LEN=16384 CPU_OFFLOAD_GB=96
bash scripts/run-tp4-uva.sh
bash scripts/check-tp4-api.sh   # 等待 /v1/models,发送一次 chat 请求(使用 $API_KEY)

基线健康后才试 hotsplit(尚未在目标 4-GPU 主机上验证):

# 先停止 UVA 基线 —— 两者都用 --network host 和同一端口
docker stop mimo-pro-tp4-uva && docker rm mimo-pro-tp4-uva
export HOTSPLIT_DYNAMIC=0          # 先 static
bash scripts/run-tp4-hotsplit.sh
bash scripts/check-hotsplit-tp4.sh mimo-pro-tp4-hotsplit static

然后是 dynamic 实验(单独一次运行):

docker stop mimo-pro-tp4-hotsplit && docker rm mimo-pro-tp4-hotsplit
HOTSPLIT_DYNAMIC=1 bash scripts/run-tp4-hotsplit.sh
bash scripts/check-hotsplit-tp4.sh mimo-pro-tp4-hotsplit dynamic expect-progress

7. 怎么读检查脚本

  • check-hotsplit-tp4.sh <container> static —— 所有 rank 期望 dynamic_hook=INACTIVE; 某个 rank 缺 hotsplit done 就是 FAIL。
  • check-hotsplit-tp4.sh <container> dynamic —— 每个 rank 期望 dynamic_hook=ACTIVE。 真实流量后加 expect-progress(第 3 个参数或 EXPECT_PROGRESS=1):零进度即 FAIL 并返回非零退出码,而不是静默 WARN。 真实流量后 hotsplit dynamic update 计数必须非零;生成之前计数为零是正常的 —— 它 什么也证明不了。

日常命令(scripts/manage.sh)

首次成功启动后,不必再记 docker 参数和环境变量:

./manage.sh status      # 容器、GPU、API 可达性 —— 一屏看清
./manage.sh logs        # 跟随服务器日志
./manage.sh stop        # 停止并删除服务器容器
./manage.sh start       # 再次启动(HOTSPLIT_DYNAMIC 取自 env 或 tp4.env)
./manage.sh restart     # stop + start,采纳修改后的 tp4.env
./manage.sh update      # git pull + 重启
./manage.sh rollback    # 容器级回退(只删除容器)
./manage.sh clean-cache # 显示 HF 缓存大小,仅在明确确认后删除
./manage.sh check       # hotsplit 验证,模式跟随 HOTSPLIT_DYNAMIC

manage.sh 是配方启动脚本的薄封装 —— 如果你创建了 ./tp4.env(复制 tp4.env.example)它会 加载,而已导出的环境变量优先于文件。

已知的坑(来自真实评审)

  • 热门预算(HOTSPLIT_HOT_GIB)是每 rank 的。留空 = “使用原版放置所用的 GPU 常驻 专家字节数”,不是 “装下整个专家库” —— 整个库装不进一张卡。算术见 模型与几何结构。
  • HOTSPLIT_VRAM_RESERVE_GIB=2 是下限,不是承诺。 长上下文和高并发需要更多 —— 用配方 RUNNING.md 的流程实测。
  • 模型补丁(PATCH_MODEL_FILES=1)启动前按 patches/MANIFEST.sha256 验证 —— 不要直接改补丁文件。

完整测量流程:配方的 RUNNING.md 和 FAQ。

Clone this wiki locally