evalstone/scripts/deploy_evalscope.sh

365 lines
12 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ============================================================
# EvalScope 完整部署脚本
# 用法: bash deploy_evalscope.sh [OPTIONS] <BASE_DIR> [TOKEN]
# 示例:
# bash deploy_evalscope.sh /data1/sora
# bash deploy_evalscope.sh --download-swe /data1/sora
#
# 断点续传:已加载的镜像/tar 包会记录在 <BASE_DIR>/evalscope/docker/.deploy_checkpoint
# 重复执行时会自动跳过,避免二次加载。
# ============================================================
set -euo pipefail
# --------------------------------------------------
# 1. 参数解析
# --------------------------------------------------
DOWNLOAD_SWE=0
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--download-swe)
DOWNLOAD_SWE=1
shift
;;
--help|-h)
echo "用法: bash deploy_evalscope.sh [OPTIONS] <BASE_DIR> [TOKEN]"
echo "选项:"
echo " --download-swe 同时下载 SWE-Bench 镜像包(默认不下载,体积很大)"
echo " -h, --help 显示帮助"
exit 0
;;
-*)
echo "未知选项: $1"
echo "使用 --help 查看用法"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1")
shift
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}"
BASE_DIR="${1:-/data1/sora}" # 基础目录,默认 /data1/sora
DEFAULT_TOKEN="ms-3d554a39-6e07-496d-8022-0b0ee64a6389"
MODELSCOPE_TOKEN="${2:-$DEFAULT_TOKEN}"
# 派生路径
EVALSCOPE_DIR="$BASE_DIR/evalscope"
DOCKER_DIR="$EVALSCOPE_DIR/docker"
IMAGES_DIR="$DOCKER_DIR/images"
CONTAINERD_DIR="$DOCKER_DIR/containerd"
SWE_IMAGES_DIR="$DOCKER_DIR/swe_images"
DATASETS_DIR="$EVALSCOPE_DIR/datasets"
CHECKPOINT_FILE="$DOCKER_DIR/.deploy_checkpoint"
# 断点:记录/检查已加载的镜像或 tar 包
mark_loaded() {
local key="$1"
mkdir -p "$DOCKER_DIR"
touch "$CHECKPOINT_FILE"
if ! grep -qx "$key" "$CHECKPOINT_FILE" 2>/dev/null; then
echo "$key" >> "$CHECKPOINT_FILE"
fi
}
is_loaded() {
local key="$1"
if [ -f "$CHECKPOINT_FILE" ] && grep -qx "$key" "$CHECKPOINT_FILE" 2>/dev/null; then
return 0
fi
return 1
}
# --------------------------------------------------
# 2. 安装依赖
# --------------------------------------------------
echo "==> 安装 modelscope..."
pip install modelscope
# --------------------------------------------------
# 3. 登录 ModelScope
# --------------------------------------------------
if [ -n "$MODELSCOPE_TOKEN" ]; then
echo "==> 登录 ModelScope..."
modelscope login --token "$MODELSCOPE_TOKEN"
fi
# --------------------------------------------------
# 4. 下载数据集
# --------------------------------------------------
echo "==> 下载 evalscope 数据集..."
mkdir -p "$DATASETS_DIR"
python3 -c "
from modelscope.hub.snapshot_download import snapshot_download
snapshot_download(
'SoraAmami/evalscope-datasets',
repo_type='dataset',
cache_dir='$EVALSCOPE_DIR',
local_dir='$DATASETS_DIR'
)
"
# --------------------------------------------------
# 5. 下载 Docker 镜像包
# --------------------------------------------------
echo "==> 下载 evalscope Docker 镜像..."
mkdir -p "$DOCKER_DIR"
python3 -c "
from modelscope.hub.file_download import model_file_download
model_file_download(
model_id='SoraAmami/evalscope-docker',
file_path='evalscope-complete-py312.tar.gz',
local_dir='$DOCKER_DIR'
)
"
# --------------------------------------------------
# 6. 配置 Docker 和 containerd 数据目录
# --------------------------------------------------
echo "==> 配置 Docker 和 containerd..."
# 停止服务
sudo systemctl stop docker.socket 2>/dev/null || true
sudo systemctl stop docker 2>/dev/null || true
sudo systemctl stop containerd 2>/dev/null || true
# 创建数据目录
mkdir -p "$IMAGES_DIR"
mkdir -p "$CONTAINERD_DIR"
# 配置 Docker
echo "==> 写入 Docker 配置..."
sudo tee /etc/docker/daemon.json <<EOF
{
"data-root": "$IMAGES_DIR",
"features": {
"containerd-snapshotter": true
},
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1ms.run",
"https://hub.rat.dev",
"https://docker.1panel.live",
"https://dockerproxy.com",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.mirrors.sjtug.sjtu.edu.cn",
"https://docker.nju.edu.cn",
"https://docker.mirrors.tuna.tsinghua.edu.cn"
]
}
EOF
# 配置 containerd
echo "==> 写入 containerd 配置..."
sudo tee /etc/containerd/config.toml <<EOF
root = "$CONTAINERD_DIR"
state = "/run/containerd"
EOF
# 重启服务
sudo systemctl reset-failed docker.service 2>/dev/null || true
sudo systemctl start containerd
sudo systemctl start docker
# --------------------------------------------------
# 7. 加载 evalscope 环境镜像
# --------------------------------------------------
echo "==> 加载 evalscope Docker 镜像..."
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -qx "evalscope-complete-py312:latest"; then
echo "evalscope-complete-py312:latest 已存在,跳过加载"
elif is_loaded "evalscope-complete-py312.tar.gz"; then
echo "evalscope-complete-py312.tar.gz 已加载过checkpoint跳过加载"
else
docker load -i "$DOCKER_DIR/evalscope-complete-py312.tar.gz"
mark_loaded "evalscope-complete-py312.tar.gz"
fi
# --------------------------------------------------
# 8. 克隆代码仓库到根目录
# --------------------------------------------------
echo "==> 克隆 evalscope 代码..."
if [ -f "$EVALSCOPE_DIR/bash/run.py" ]; then
echo "代码已存在于 $EVALSCOPE_DIR,跳过克隆"
else
echo "正在克隆代码到 $EVALSCOPE_DIR ..."
tmp_backup="$BASE_DIR/.evalscope_deploy_backup_$(date +%s)"
mkdir -p "$tmp_backup"
# 保留已有的 datasets/ 和 docker/,其余清空后克隆
for item in "$EVALSCOPE_DIR"/* "$EVALSCOPE_DIR"/.[!.]* "$EVALSCOPE_DIR"/..?*; do
[ -e "$item" ] || continue
basename_item=$(basename "$item")
case "$basename_item" in
.|..|.git) continue ;;
datasets|docker)
mv "$item" "$tmp_backup/$basename_item" ;;
*)
rm -rf "$item" ;;
esac
done
git clone "https://git.meta-stone.net/sora/evalstone.git" "$EVALSCOPE_DIR"
# 恢复 datasets/ docker/
for item in "$tmp_backup"/* "$tmp_backup"/.[!.]* "$tmp_backup"/..?*; do
[ -e "$item" ] || continue
basename_item=$(basename "$item")
[ "$basename_item" = "." ] || [ "$basename_item" = ".." ] && continue
if [ -e "$EVALSCOPE_DIR/$basename_item" ]; then
continue
fi
mv "$item" "$EVALSCOPE_DIR/$basename_item"
done
rm -rf "$tmp_backup" 2>/dev/null || true
fi
# --------------------------------------------------
# 9. 准备 sandbox 镜像
# --------------------------------------------------
echo "==> 准备 sandbox 镜像..."
SANDBOX_IMAGES_DIR="$DOCKER_DIR/sandbox_images"
mkdir -p "$SANDBOX_IMAGES_DIR"
# 从 ModelScope 下载预打包的 sandbox 镜像(不再使用 docker pull避免 DockerHub 限速)
download_sandbox_image_from_modelscope() {
local file="$1"
if [ -f "$SANDBOX_IMAGES_DIR/$file" ]; then
echo "sandbox 镜像包 $file 已存在,跳过下载"
return 0
fi
echo "==> 从 ModelScope 下载 $file ..."
python3 -c "
from modelscope.hub.file_download import model_file_download
model_file_download(
model_id='SoraAmami/evalscope-sandbox-images',
file_path='$file',
local_dir='$SANDBOX_IMAGES_DIR'
)
" && return 0
echo "警告:从 ModelScope 下载 $file 失败"
return 1
}
load_sandbox_image() {
local file="$1"
local expected_image="$2"
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -qx "$expected_image"; then
echo "镜像 $expected_image 已存在,跳过加载"
return 0
fi
if is_loaded "$file"; then
echo "镜像包 $file 已加载过checkpoint跳过加载"
return 0
fi
if [ -f "$SANDBOX_IMAGES_DIR/$file" ]; then
echo "==> 加载 $file ..."
docker load -i "$SANDBOX_IMAGES_DIR/$file"
mark_loaded "$file"
return 0
fi
return 1
}
# 9.1 bigcodebench-sandbox:latest
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -qx "bigcodebench-sandbox:latest"; then
echo "bigcodebench-sandbox:latest 已存在,跳过"
else
if ! load_sandbox_image "bigcodebench-sandbox.tar.gz" "bigcodebench-sandbox:latest"; then
download_sandbox_image_from_modelscope "bigcodebench-sandbox.tar.gz" && \
load_sandbox_image "bigcodebench-sandbox.tar.gz" "bigcodebench-sandbox:latest"
fi
fi
# 9.2 python:3.11-slim
if docker images --format '{{.Repository}}:{{.Tag}}' | grep -qx "python:3.11-slim"; then
echo "python:3.11-slim 已存在,跳过"
else
if ! load_sandbox_image "python-3.11-slim.tar.gz" "python:3.11-slim"; then
download_sandbox_image_from_modelscope "python-3.11-slim.tar.gz" && \
load_sandbox_image "python-3.11-slim.tar.gz" "python:3.11-slim"
fi
fi
# --------------------------------------------------
# 10. 下载 SWE-Bench 镜像包(默认不下载,需加 --download-swe
# --------------------------------------------------
if [ "$DOWNLOAD_SWE" -eq 1 ]; then
echo "==> 下载 SWE-Bench 镜像包..."
mkdir -p "$SWE_IMAGES_DIR"
modelscope download \
--repo-type dataset \
--local_dir "$SWE_IMAGES_DIR" \
SoraAmami/swe-bench-verified-images || echo "警告SWE-Bench 镜像下载失败"
else
echo "==> 跳过 SWE-Bench 镜像包下载(如需下载请加 --download-swe"
fi
# --------------------------------------------------
# 11. 加载 SWE-Bench 镜像(如果存在)
# --------------------------------------------------
if [ -d "$SWE_IMAGES_DIR" ] && ls "$SWE_IMAGES_DIR"/swebench_batch_*.tar.gz 1>/dev/null 2>&1; then
echo "==> 加载 SWE-Bench 镜像..."
TARS=("$SWE_IMAGES_DIR"/swebench_batch_*.tar.gz)
TOTAL=${#TARS[@]}
echo "共找到 $TOTAL 个镜像包"
IDX=0
LOADED_COUNT=0
SKIPPED_COUNT=0
for TAR in "${TARS[@]}"; do
IDX=$((IDX + 1))
BASENAME=$(basename "$TAR")
if is_loaded "$BASENAME"; then
echo "[$IDX/$TOTAL] 跳过(已加载过): $BASENAME"
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
continue
fi
echo "[$IDX/$TOTAL] 加载 $BASENAME ..."
docker load -i "$TAR"
mark_loaded "$BASENAME"
LOADED_COUNT=$((LOADED_COUNT + 1))
done
echo "SWE-Bench 镜像加载完成:本次加载 $LOADED_COUNT 个,跳过 $SKIPPED_COUNT 个,已加载 $(docker images | grep -c '^swebench/' || true)"
else
echo "跳过 SWE-Bench 镜像加载(未找到镜像包)"
fi
# --------------------------------------------------
# 12. 验证部署
# --------------------------------------------------
echo ""
echo "========================================"
echo "部署完成!"
echo "========================================"
echo "基础目录: $BASE_DIR"
echo "EvalScope: $EVALSCOPE_DIR"
echo "数据集: $DATASETS_DIR"
echo "Docker 数据: $IMAGES_DIR"
echo "Containerd: $CONTAINERD_DIR"
echo ""
echo "Docker Root Dir:"
docker info 2>/dev/null | grep "Docker Root Dir" || echo "Docker 未运行"
echo ""
echo "已加载镜像:"
docker images | grep -E "evalscope|swebench|bigcodebench|python" || true
echo ""
echo "运行 EvalScope:"
echo " cd $EVALSCOPE_DIR"
echo " docker run -it --rm \\"
echo " --network host \\"
echo " -v $EVALSCOPE_DIR:/opt/evalscope \\"
echo " -v /var/run/docker.sock:/var/run/docker.sock \\"
echo " evalscope-complete-py312:latest \\"
echo " bash"
echo "========================================"