Download docs/AUTODL_SETUP.md from keryszhan/harbor-qwen-grpo-experiment: direct link, hf CLI and curl.
- Browser
- Download file 51.8 kB
-
https://huggingface.co/spaces/keryszhan/harbor-qwen-grpo-experiment/resolve/main/docs/AUTODL_SETUP.md
- Command line
-
hf download hf://spaces/keryszhan/harbor-qwen-grpo-experiment/docs/AUTODL_SETUP.md
-
curl -L -o AUTODL_SETUP.md https://huggingface.co/spaces/keryszhan/harbor-qwen-grpo-experiment/resolve/main/docs/AUTODL_SETUP.md
AutoDL 准备、验收与后续执行顺序
当前状态(2026-08-30):项目已完成统一64K P0并阶段性归档;腾讯云CVM、云硬盘和相关计费资源已经释放,原k3s/BuildKit/sandbox不在线。本文是历史安装与未来重建手册;旧EIP、KubeConfig、PVC、端口转发和AutoDL公网映射均不得假设仍然有效。历史运行中需要设置
NCCL_P2P_DISABLE=1规避Direct P2P死锁。
本文的环境安装与验收命令仍适用;涉及ACK/ACR的旧资源名称只用于理解方案演进。AutoDL只运行训练、Harbor/rLLM/verl和k3s控制客户端,不安装Docker、kubeadm、kubelet或本地Kubernetes集群。
flowchart LR
subgraph Mac["💻 Mac:管理与镜像准备"]
M1["✅ 项目源码与配置"]
M2["✅ Docker 构建环境"]
M3["✅ ACK 管理员 KubeConfig"]
M4["⏭️ 镜像 SWE 基础镜像"]
end
subgraph Aliyun["☁️ 阿里云"]
ACR["✅ ACR 镜像仓库"]
subgraph ACK["✅ ACK 集群"]
API["✅ 公网 API Server"]
RBAC["✅ RAM + Kubernetes RBAC"]
BK["✅ Rootful BuildKit"]
PVC["✅ 100 GiB 构建缓存"]
POD["🟡 SWE 任务 Pod"]
end
end
subgraph AutoDL["🖥️ AutoDL GPU"]
ENV["✅ Conda / Harbor / rLLM"]
DATA["✅ SWE-Smith 100 条"]
VLLM["✅ vLLM + Qwen2.5-Coder-7B"]
GW["✅ 公网模型 Gateway"]
TUNNEL["✅ BuildKit Tunnel"]
CANARY["🟡 单任务 Canary"]
end
M2 --> ACR
M3 --> API
ENV --> CANARY
DATA --> CANARY
CANARY --> API
API --> POD
POD --> BK
BK --- PVC
TUNNEL --> BK
POD --> GW
GW --> VLLM
M4 --> ACR
ACR -.下一步替代 Docker Hub.-> BK
classDef done fill:#d9f7e5,stroke:#21a366,color:#123;
classDef partial fill:#fff2cc,stroke:#d6a100,color:#123;
classDef next fill:#dcecff,stroke:#3478c9,color:#123;
class M1,M2,M3,ACR,API,RBAC,BK,PVC,ENV,DATA,VLLM,GW,TUNNEL done;
class POD,CANARY partial;
class M4 next;
1.Mac 生成并上传源码包--done
在 Mac 项目根目录执行:
make mac-preflight
make prepare-sources
make package-autodl
生成:
output/bundles/harbor-qwen-grpo-autodl-source.tar.gz
output/bundles/harbor-qwen-grpo-autodl-source.tar.gz.sha256
同时上传压缩包和 .sha256 文件到 AutoDL。源码包会排除 .env、.secrets、日志、状态、输出和 Git 元数据,不包含任何凭证。
2. AutoDL 校验和解压--done
在上传文件所在目录执行:
cd /root/autodl-tmp
sha256sum harbor-qwen-grpo-autodl-source.tar.gz
tar -xzf harbor-qwen-grpo-autodl-source.tar.gz
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
校验文件由 Mac 生成,第二列可能记录 Mac 上的绝对路径;因此这里只读取第一列哈希值,再校验 AutoDL 当前目录中的压缩包。
预期校验结果:
harbor-qwen-grpo-autodl-source.tar.gz: OK
如果 Mac 重新执行了 make prepare-sources 或修改了本项目源码,应重新打包、上传并校验,不能只覆盖零散文件。
3. Conda 环境准备--done
选择已经能够正常使用 A800、NVIDIA 驱动、CUDA 和 PyTorch 的 AutoDL 基础镜像。项目要求 Python 3.12;这里的“3.12”指 Python 版本,不是 PyTorch 版本。
清理缓存和坏残留
set -euo pipefail
echo "== before =="
df -h /
du -h --max-depth=1 /root | sort -hr | head -30
du -h --max-depth=1 /root/miniconda3 | sort -hr | head -30 || true
du -h --max-depth=1 /root/.cache | sort -hr | head -30 || true
echo "== clean pip/conda caches =="
python -m pip cache purge || true
conda clean -a -y || true
echo "== clean common build/runtime caches =="
rm -rf /root/.cache/pip
rm -rf /root/.cache/torch
rm -rf /root/.cache/triton
rm -rf /tmp/pip-* /tmp/tmp*
echo "== clean broken pip leftovers =="
rm -rf /root/miniconda3/lib/python3.12/site-packages/~orch*
rm -rf /root/miniconda3/lib/python3.12/site-packages/~umpy*
rm -rf /root/miniconda3/envs/harbor-grpo/lib/python3.12/site-packages/~orch*
rm -rf /root/miniconda3/envs/harbor-grpo/lib/python3.12/site-packages/~umpy*
echo "== after =="
df -h /
du -h --max-depth=1 /root | sort -hr | head -30
du -h --max-depth=1 /root/miniconda3 | sort -hr | head -30 || true
先查看当前环境:
source /root/miniconda3/etc/profile.d/conda.sh
conda env list
python --version
nvidia-smi
python -c 'import torch; print(torch.__version__, torch.version.cuda, torch.cuda.is_available(), torch.cuda.device_count())'
若 AutoDL 预装环境已是 Python 3.12 且 PyTorch 能访问全部 GPU,优先克隆该已验证环境。将下面的 <源环境名> 替换为 conda env list 中实际可用的环境名:
source /root/miniconda3/etc/profile.d/conda.sh
conda create -n harbor-grpo --clone base -y
conda activate harbor-grpo
不要为了切换 Python 小版本直接覆盖基础环境中已经验证的 PyTorch/CUDA 组合。如果基础环境不是 Python 3.12,应换用匹配镜像,或另建经过 CUDA 验证的环境后再继续。
在激活环境后安装项目依赖:
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
source /root/miniconda3/etc/profile.d/conda.sh
conda activate harbor-grpo
set -a
source .env
set +a
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda install -c conda-forge make gettext openssl curl tmux -y
# kubectl 1.36.1:
KUBECTL_VERSION=v1.36.1
KUBECTL_BASE="https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64"
curl -fL -o /tmp/kubectl "${KUBECTL_BASE}/kubectl"
curl -fL -o /tmp/kubectl.sha256 "${KUBECTL_BASE}/kubectl.sha256"
echo "$(cat /tmp/kubectl.sha256) /tmp/kubectl" | sha256sum --check
install -m 0755 /tmp/kubectl "$CONDA_PREFIX/bin/kubectl"
kubectl version --client
# buildctl v0.20.2:
BUILDKIT_VERSION=v0.20.2
BUILDKIT_BASE=https://github.com/moby/buildkit/releases/download
BUILDKIT_FILE=buildkit-${BUILDKIT_VERSION}.linux-amd64.tar.gz
BUILDKIT_URL=${BUILDKIT_BASE}/${BUILDKIT_VERSION}/${BUILDKIT_FILE}
curl -fL -o /tmp/buildkit.tgz "$BUILDKIT_URL"
tar -xzf /tmp/buildkit.tgz -C /tmp
tar -xzf buildkit-v0.20.2.linux-amd64.tar.gz -C /tmp
install -m 0755 /tmp/bin/buildctl "$CONDA_PREFIX/bin/buildctl"
buildctl --version
# crane 示例固定为 v0.20.3;下载后应在 GitHub Release 页面核对 SHA-256:
CRANE_VERSION=v0.20.3
CRANE_BASE=https://github.com/google/go-containerregistry/releases/download
CRANE_FILE=go-containerregistry_Linux_x86_64.tar.gz
CRANE_URL=${CRANE_BASE}/${CRANE_VERSION}/${CRANE_FILE}
curl -fL -o /tmp/crane.tgz "$CRANE_URL"
tar -xzf /tmp/crane.tgz -C /tmp crane
tar -xzf go-containerregistry_Linux_x86_64.tar.gz -C /tmp crane
install -m 0755 /tmp/crane "$CONDA_PREFIX/bin/crane"
crane version
# 工具总检:
for cmd in conda python pip kubectl buildctl crane curl openssl make envsubst tmux; do
command -v "$cmd" || exit 1
done
cp .env.example .env
pip install "https://github.com/adithyaxx/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu13torch2.11cxx11abiTRUE-cp312-cp312-linux_x86_64.whl"
手动下载flash_attn-2.8.1+cu12torch2.8cxx11abiFALSE-cp312-cp312-linux_x86_64.whl
pip install flash_attn-2.8.1+cu12torch2.8cxx11abiFALSE-cp312-cp312-linux_x86_64.whl
SKIP_FLASH_ATTN=1 make install-conda
5. AutoDL 本地验收(ACK 尚未创建也可以完成)
5.1 源码完整性--done
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
test -f Makefile && echo 'PASS: Makefile'
test -f .env.example && echo 'PASS: .env.example'
test -d scripts && echo 'PASS: scripts'
test -d upstream/harbor && echo 'PASS: upstream/harbor'
test -d upstream/rllm && echo 'PASS: upstream/rllm'
test -f .env && echo "PASS: .env"
五项都必须显示 PASS。
5.2 Conda、Python及依赖--done
source /root/miniconda3/etc/profile.d/conda.sh
conda activate harbor-grpo
echo "$CONDA_DEFAULT_ENV"
which python
python --version
python -m pip --version
python -m pip check
验收标准:
- 环境名为
harbor-grpo; - Python 为 3.12.x;
which python指向当前 Conda 环境;pip check不报告依赖冲突。
验证项目导入:
PYTHONPATH="$PWD/src:$PWD/upstream/rllm:${PYTHONPATH:-}" python - <<'PY'
import harbor
import rllm
import verl
import harbor_qwen_grpo_experiment
print("PASS: Harbor, rLLM, verl and project imports")
PY
5.3 GPU及真实 CUDA 运算--done
nvidia-smi
nvidia-smi --query-gpu=index,name,memory.total,driver_version --format=csv
python - <<'PY'
import torch
print("torch:", torch.__version__)
print("torch CUDA build:", torch.version.cuda)
print("CUDA available:", torch.cuda.is_available())
print("GPU count:", torch.cuda.device_count())
for i in range(torch.cuda.device_count()):
print(i, torch.cuda.get_device_name(i))
assert torch.cuda.is_available(), "PyTorch cannot access CUDA"
x = torch.randn(2048, 2048, device="cuda")
y = x @ x
torch.cuda.synchronize()
print("PASS: CUDA matrix multiplication", y.mean().item())
PY
验收标准:
CUDA available: True;- 显示预期的 4 或 8 张 A800;
- CUDA 矩阵计算完成,无驱动、CUDA或显存错误。
5.4 命令及架构--done
for cmd in conda python pip kubectl buildctl crane curl openssl make envsubst tmux; do
if command -v "$cmd" >/dev/null 2>&1; then
printf 'PASS: %-10s %s\n' "$cmd" "$(command -v "$cmd")"
else
printf 'FAIL: %s\n' "$cmd"
fi
done
uname -m
kubectl version --client
buildctl --version
crane version
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
source /root/miniconda3/etc/profile.d/conda.sh
conda activate harbor-grpo
python --version
python - <<'PY'
import torch
import flash_attn
import vllm
import transformers
print("torch:", torch.__version__)
print("torch CUDA:", torch.version.cuda)
print("vllm:", vllm.__version__)
print("transformers:", transformers.__version__)
print("CUDA available:", torch.cuda.is_available())
print("GPU count:", torch.cuda.device_count())
print("flash-attn:", flash_attn.__version__)
PY
python -m pip check
验收标准:全部命令显示 PASS,uname -m 为 x86_64,三个客户端能够输出版本。AutoDL 上缺少 docker 和 git 是本方案的正常状态。
5.5 公网、DNS及 ACR--done
curl -I --connect-timeout 10 https://www.aliyun.com
getent hosts ${ACR_PUBLIC_REGISTRY_HOST}
curl -I --connect-timeout 10 \
https://${ACR_PUBLIC_REGISTRY_HOST}/v2/
curl -4 --connect-timeout 10 https://ifconfig.me
echo
curl -sS -o /dev/null \
--connect-timeout 10 \
-w 'Aliyun: http=%{http_code} remote_ip=%{remote_ip} tls_verify=%{ssl_verify_result}\n' \
https://www.aliyun.com/
getent ahostsv4 \
${ACR_PUBLIC_REGISTRY_HOST}
curl -sS -o /dev/null \
--connect-timeout 10 \
-w 'ACR: http=%{http_code} remote_ip=%{remote_ip} tls_verify=%{ssl_verify_result}\n' \
https://${ACR_PUBLIC_REGISTRY_HOST}/v2/
printf 'AutoDL public IPv4: '
curl -4 -sS --connect-timeout 10 https://ifconfig.me/ip
echo
这组结果说明 AutoDL 到阿里云的公网出站网络验证已经通过。
| 检查项 | 结果 | 含义 |
|---|---|---|
| 阿里云公网访问 | 403 |
网络、DNS、TCP、TLS 均正常;403 是网站/WAF拒绝 curl 请求,不是网络故障 |
| ACR DNS | 47.95.181.38 |
解析正常 |
ACR /v2/ |
401 |
完全符合预期:Registry 可达,但请求未携带认证 |
| TLS | tls_verify=0 |
两个 HTTPS 站点的证书校验正常 |
| AutoDL 出口 IP | 36.140.113.200 |
已获得当前公网出口地址 |
所以当前链路成立:
AutoDL
→ 公网出口 36.140.113.200
→ 阿里云公网
→ 北京 ACR 47.95.181.38:443
Aliyun 403 不需要处理。阿里云门户可能根据 User-Agent、数据中心出口 IP 或 WAF 策略拒绝命令行访问;它已经证明连接成功。
ACR 401 是最佳预期结果,表示:
DNS成功 → TCP成功 → TLS成功 → Registry服务成功 → 缺少登录凭证
注意 36.140.113.200 不一定是长期固定 IP。AutoDL 实例重启、迁移或网络调整后应重新执行:
curl -4 -sS https://ifconfig.me/ip
不要永久假设它不会变化。
5.6 ACK 创建前验收结论
以下全部通过,AutoDL 本地准备才算完成:
- 源码包 SHA-256 为
OK; - 项目与两个上游源码目录齐全;
- Conda、Python 3.12、依赖导入和
pip check通过; - 4/8 张 A800 全部可见,CUDA 计算通过;
- 必需命令齐全且为 Linux AMD64;
- AutoDL 能访问公网和 ACR;
- 已记录当前 AutoDL 出口 IP。
ACK 尚未创建时,不能执行或不要求通过:
kubectl cluster-info
make autodl-ack-network
make buildkit-tunnel
make buildkit-status
make network-smoke
make preflight
5.7 设置目录&下载模型&验证--done
设置模型和缓存目录
mkdir -p /root/autodl-tmp/models
mkdir -p /root/autodl-tmp/cache/huggingface
mkdir -p /root/autodl-tmp/logs
# export HF_HOME=/root/autodl-tmp/cache/huggingface
export MODEL_DIR=/root/autodl-tmp/models/Qwen2.5-Coder-7B-Instruct
export MODELSCOPE_CACHE="/root/autodl-tmp/cache/modelscope"
export MODEL_ID="Qwen/Qwen2.5-Coder-7B-Instruct"
mkdir -p "$MODEL_DIR" "$MODELSCOPE_CACHE"
df -h /root/autodl-tmp
确保下载前至少有40GB可用空间,最好扩容到100GB以上。
安装官方Hugging Face下载工具:
conda activate harbor-grpo
python -m pip install -U modelscope
modelscope --version
# python -m pip install -U huggingface_hub
下载固定revision:
modelscope download \
--model "$MODEL_ID" \
--revision master \
--local_dir "$MODEL_DIR"
#hf download Qwen/Qwen2.5-Coder-7B-Instruct \
--revision c03e6d358207e414f1eca0bb1891e29f1db0e242 \
--local-dir "$MODEL_DIR"
验证:
du -sh "$MODEL_DIR"
test -f "$MODEL_DIR/config.json" &&
test -f "$MODEL_DIR/model.safetensors.index.json" &&
echo "PASS: model files"
验证tokenizer:
python - <<'PY'
from transformers import AutoTokenizer
path = "/root/autodl-tmp/models/Qwen2.5-Coder-7B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(path, local_files_only=True)
print("PASS:", tokenizer.__class__.__name__, tokenizer.vocab_size)
PY
5.8 生成模型API Token--done
mkdir -p /root/.config/harbor-qwen-grpo
chmod 700 /root/.config/harbor-qwen-grpo
umask 077
openssl rand -hex 32 > /root/.config/harbor-qwen-grpo/model-api-key
chmod 600 /root/.config/harbor-qwen-grpo/model-api-key
将文件中的值填入AutoDL项目.env:
CANARY_MODEL_API_KEY=<读取 /root/.config/harbor-qwen-grpo/model-api-key 的内容>
不要把Token写入Qwen Code的settings.json。Qwen Code官方推荐通过环境变量或envKey读取凭证。
在6008启动单卡vLLM
进入tmux:
tmux new -s vllm-canary
在tmux内执行:
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
source /root/miniconda3/etc/profile.d/conda.sh
conda activate harbor-grpo
export MODEL_DIR=/root/autodl-tmp/models/Qwen2.5-Coder-7B-Instruct
export MODEL_NAME=Qwen2.5-Coder-7B-Instruct
export MODEL_API_KEY="$(tr -d '\r\n' < /root/.config/harbor-qwen-grpo/model-api-key)"
CUDA_VISIBLE_DEVICES=0 vllm serve "$MODEL_DIR" \
--served-model-name "$MODEL_NAME" \
--host 0.0.0.0 \
--port 6008 \
--dtype bfloat16 \
--max-model-len 32768 \
--max-num-seqs 2 \
--gpu-memory-utilization 0.85 \
--enable-auto-tool-choice \
--tool-call-parser hermes \
--api-key "$MODEL_API_KEY"
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
source /root/miniconda3/etc/profile.d/conda.sh
conda activate harbor-grpo
set -a
source .env
set +a
exec vllm serve "$KLEAR_MODEL_PATH" \
--served-model-name "$KLEAR_SERVED_MODEL_NAME" \
--host 0.0.0.0 \
--port 6008 \
--api-key "$CANARY_MODEL_API_KEY" \
--max-model-len 65536 \
--max-num-seqs "${KLEAR_VLLM_MAX_NUM_SEQS:-4}" \
--max-num-batched-tokens "${KLEAR_VLLM_MAX_NUM_BATCHED_TOKENS:-32768}" \
--gpu-memory-utilization "${KLEAR_VLLM_GPU_MEMORY_UTILIZATION:-0.90}" \
--enable-chunked-prefill \
--enable-prefix-caching
看到服务启动完成后,按Ctrl-b再按d离开tmux,但不停止服务。
查看:
tmux ls
tmux attach -t vllm-canary
5.8.1 预构建 mini-swe-agent-plus 运行镜像
使用Plus前先确认BuildKit tunnel正常,然后构建并推送固定运行镜像:
make buildkit-status
make agent-runtime-build
.env必须包含:
MINI_SWE_AGENT_PLUS_RUNTIME_SCHEMA=v3
ACK_MINI_SWE_AGENT_PLUS_BASE_IMAGE=${ACK_REGISTRY_PREFIX}/infra-mini-swe-agent-plus:${MINI_SWE_AGENT_PLUS_VERSION}
ACK_MINI_SWE_AGENT_PLUS_IMAGE=${ACK_REGISTRY_PREFIX}/infra-mini-swe-agent-plus:${MINI_SWE_AGENT_PLUS_VERSION}-${MINI_SWE_AGENT_PLUS_RUNTIME_SCHEMA}
构建从Registry中已验收的固定revision旧镜像增量生成v3,不重新访问GitHub或PyPI。
Canary任务Pod通过initContainer复制自包含的Python 3.12与Plus环境,
Plus启动后恢复任务原有Python环境,任务命令继续使用任务镜像自带的python3。Harbor安装
阶段只进行本地命令、固定revision和运行时schema检查,不访问GitHub或PyPI。
5.9 本地接口验收--done
export MODEL_API_KEY="$(tr -d '\r\n' < /root/.config/harbor-qwen-grpo/model-api-key)"
curl --fail --silent --show-error \
-H "Authorization: Bearer $MODEL_API_KEY" \
http://127.0.0.1:6008/v1/models |
python -m json.tool
基础生成测试:
curl --fail --silent --show-error \
http://127.0.0.1:6008/v1/chat/completions \
-H "Authorization: Bearer $MODEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-Coder-7B-Instruct",
"messages": [
{
"role": "user",
"content": "Write a Python function that returns the nth Fibonacci number."
}
],
"temperature": 0.2,
"max_tokens": 512
}' |
python -m json.tool
同时观察:
watch -n 1 nvidia-smi
5.10 从Mac验证AutoDL公网入口--done
复制AutoDL控制台6008对应地址后,在Mac执行:
6008公网地址 https://uu242790-b362-d570d0a7.nma1.seetacloud.com:8448
export CANARY_URL='https://uu242790-b362-d570d0a7.nma1.seetacloud.com:8448/v1'
read -s MODEL_API_KEY
curl --fail --silent --show-error \
-H "Authorization: Bearer $MODEL_API_KEY" \
"$CANARY_URL/models" |
python3 -m json.tool
验收标准:
- DNS能够解析;
- TLS/HTTP连接成功;
- 返回模型列表;
- 不带Token时返回401;
- 带Token时返回200;
- 模型名称与
.env的MODEL_NAME完全一致。
如果Mac无法访问,不要创建ACK;ACK同样无法访问该入口。
5.11安装并测试Qwen Code--done
检查Node:
git clone https://gitee.com/mirrors/nvm.git /root/.nvm
cd /root/.nvm
git checkout v0.40.3
export NVM_DIR="$HOME/.nvm"
source "$NVM_DIR/nvm.sh"
export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node
nvm install 22
nvm use 22
node -v
npm -v
项目固定Qwen Code 0.16.2:
npm config set registry https://registry.npmmirror.com
npm install -g @qwen-code/qwen-code@0.16.2
qwen --version
预期 qwen --version:
0.16.2
连接本地vLLM:
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
export OPENAI_API_KEY="$(tr -d '\r\n' < /root/.config/harbor-qwen-grpo/model-api-key)"
export OPENAI_BASE_URL=http://127.0.0.1:6008/v1
export OPENAI_MODEL=Qwen/Qwen2.5-Coder-7B-Instruct
qwen \
--auth-type openai \
--model "$OPENAI_MODEL" \
--openai-api-key "$OPENAI_API_KEY" \
--openai-base-url "$OPENAI_BASE_URL" \
--approval-mode plan \
--prompt "Read README.md, Makefile, and scripts/50_train_grpo.sh. Explain this project in 5 bullets. Do not guess."
首轮只用plan验证模型连接和工具格式。真正的Harbor Sandbox自动执行时才切换到yolo,并使用Qwen Code的任务超时限制。
ACK Sandbox 的 Qwen Code 安装路径
ACK Sandbox 不复用 AutoDL 主机上的 Node.js。每个任务环境会独立安装或检测 Qwen Code。由于 ACK 到 raw.githubusercontent.com 可能连接后长期无响应,必须启用:
APPLY_QWEN_PREINSTALL_PATCH=1
补丁行为如下:
- 已存在指定版本 Qwen Code:直接跳过安装。
- ACK 未预装:从
nodejs.org安装固定 Node.js 22.17.0,再从 npm 安装QWEN_CODE_VERSION。 - Docker/Daytona:继续使用 Harbor 原始 NVM 安装方式。
运行 Canary 前,可从 ACK Pod 验证 nodejs.org 和 npm;不再要求 ACK 访问 raw.githubusercontent.com。正式批量训练仍建议使用 docker/qwen-code-overlay.Dockerfile 预装依赖,以减少每条轨迹的启动时间和外网波动。
6. .env 与凭证分工
源码包不包含 .env。Mac 和 AutoDL 各自执行:
cp .env.example .env
chmod 600 .env
两台机器的 .env 不是同一个文件:路径项必须填写各自机器上的绝对路径,“凭证分工”同时说明三件事:
- 凭证在哪里生成。
- 凭证长期保存在哪里。
- 哪个组件在运行时使用它。
不是所有凭证都需要“上传”。
| 凭证 | 生成/获取位置 | 保存位置 | 是否传输 |
|---|---|---|---|
| ACR用户名和固定密码 | 阿里云ACR控制台 | Mac的.secrets/acr/ |
Mac通过ack-prepare写入ACK Secret;不传AutoDL |
| ACK管理员KubeConfig | ACK控制台 | Mac | 从ACK下载到Mac,不上传回ACK |
| ACK运行KubeConfig | ACK控制台/RBAC | AutoDL | 从ACK下载到AutoDL,权限应低于管理员 |
| BuildKit CA证书 | Mac | Mac、AutoDL、ACK | CA证书可分发 |
| BuildKit CA私钥 | Mac | 只保留在Mac | 绝不上传AutoDL或ACK |
| BuildKit server证书/私钥 | Mac | Mac、ACK Secret | 通过ack-prepare传到ACK,不传AutoDL |
| BuildKit client证书/私钥 | Mac | Mac、AutoDL | 安全复制到AutoDL,不传Sandbox |
| 模型Gateway Token | AutoDL配置 | AutoDL的.env |
请求模型时使用,不应长期写入任务目录 |
.env |
Mac和AutoDL分别创建 | 各自本机 | 不互相整体复制,也不上传ACK |
数据流可以理解为:
阿里云ACK
│
├── 下载管理员KubeConfig ──→ Mac
└── 下载受限KubeConfig ────→ AutoDL
Mac
├── ACR用户名/密码 ─────────→ ACK imagePullSecret
├── BuildKit CA+server证书 ─→ ACK Kubernetes Secret
└── CA+client证书 ──────────→ AutoDL
AutoDL
├── 使用受限KubeConfig访问ACK
├── 使用client证书连接BuildKit
└── 保存模型Gateway Token
具体目录建议
Mac:
harbor-qwen-grpo-experiment/
├── .env
└── .secrets/
├── acr/
│ ├── username
│ └── password
└── buildkit/
├── ca.pem
├── ca-key.pem
├── server-cert.pem
├── server-key.pem
├── client-cert.pem
└── client-key.pem
AutoDL只需要:
/root/ack-public-kubeconfig.yaml
/root/.config/harbor-qwen-grpo/buildkit/ca.pem
/root/.config/harbor-qwen-grpo/buildkit/client-cert.pem
/root/.config/harbor-qwen-grpo/buildkit/client-key.pem
项目目录/.env
ACK里最终保存:
harbor-qwen-grpo namespace
└── acr-pull:ACR拉取凭证
harbor-qwen-build namespace
├── acr-pull:ACR拉取/推送凭证
└── buildkit-server-tls:CA、server-cert、server-key
关键安全边界:
- AutoDL不要保存ACR固定密码。
- AutoDL不要使用
ack-admin管理员KubeConfig,应使用harbor-runner受限KubeConfig。 ca-key.pem永远只留在Mac。- 不要把整个
.secrets目录打包上传。 - Mac和AutoDL分别维护自己的
.env,因为KubeConfig和证书路径不同。 - 所有KubeConfig、私钥、密码文件执行:
chmod 600 <文件>
所以,“上传到对应资源”只适用于部分凭证;KubeConfig的方向恰好相反,它是从ACK下载到Mac或AutoDL。
7. ACK 双用户授权、KubeConfig与双端验收
本项目使用两个独立RAM用户,不能共用KubeConfig:
| RAM用户 | 使用位置 | RAM系统策略 | Kubernetes RBAC | 用途 |
|---|---|---|---|---|
ack-admin |
Mac | AliyunCSFullAccess |
仅当前实验集群的管理员 | 初始化namespace、Secret和BuildKit,执行集群运维 |
harbor-runner |
AutoDL | AliyunCSReadOnlyAccess |
两个项目namespace的开发人员 | 创建任务Pod/Job、exec、读取日志、端口转发及项目Secret |
若用户还持有PowerUserAccess,应解除该策略。harbor-runner不能授予集群管理员,
AutoDL也不能复制或使用ack-admin的KubeConfig。
7.1 前置网络条件--done
获取公网KubeConfig前,ACK API Server必须已启用公网访问。若使用CLB监听ACL白名单, 至少保留以下来源:
100.104.0.0/16 # ACK管控网段
10.20.0.0/16 # 本项目VPC网段
<Mac出口IPv4>/32 51.195.241.248
<AutoDL出口IPv4>/32. 36.140.113.200
Mac和AutoDL可分别执行以下命令获取当前出口IPv4:
curl -4 -sS https://ifconfig.me/ip
echo
AutoDL重启后出口IP可能变化;连接突然超时时,应先复查出口IP和ACL。
7.2 创建RAM登录凭证和系统权限--done
使用阿里云主账号进入RAM控制台 -> 身份管理 -> 用户:
- 为
ack-admin保留AliyunCSFullAccess。 - 为
harbor-runner保留AliyunCSReadOnlyAccess。 - 在各用户的
认证管理 -> 登录信息中启用控制台登录并设置密码。
RAM控制台密码不能查看明文;忘记时只能由主账号重置。它不是ACR固定密码、AccessKey、
KubeConfig或服务器登录密码,也不写入项目.env。
7.3 授权顺序--done
权限和namespace存在先后依赖,按以下顺序操作:
- 主账号进入
ACK控制台 -> 授权管理 -> RAM用户 -> ack-admin -> 管理权限。 - 为
ack-admin添加当前harbor-qwen-grpo-experiment集群、全部namespace、预置角色管理员。 - 使用
ack-admin登录ACK控制台,获取它自己的长期公网KubeConfig。 - Mac使用管理员KubeConfig创建
harbor-qwen-grpo和harbor-qwen-build。 - 主账号回到授权管理,为
harbor-runner添加两条权限:harbor-qwen-grpo:开发人员;harbor-qwen-build:开发人员。
- 使用
harbor-runner登录ACK控制台,获取它自己的长期公网KubeConfig。
KubeConfig由当前登录身份签发。不能用主账号下载一份后同时复制给Mac和AutoDL, 也不能把管理员KubeConfig改名后当作运行KubeConfig。
7.4 Mac管理员KubeConfig--done
将ack-admin的公网KubeConfig保存为:
/Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml
设置权限并验证:
chmod 600 /Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml
kubectl --kubeconfig /Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml \
config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
kubectl --kubeconfig /Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml \
cluster-info
kubectl --kubeconfig /Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml \
get nodes -o wide
kubectl --kubeconfig /Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml \
auth can-i '*' '*' --all-namespaces
API地址应为ACK公网端点,节点应为Ready,最后一条应返回yes。
若尚未创建namespace,可幂等执行:
ADMIN_KUBECONFIG=/Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml
kubectl --kubeconfig "${ADMIN_KUBECONFIG}" create namespace harbor-qwen-grpo \
--dry-run=client -o yaml | kubectl --kubeconfig "${ADMIN_KUBECONFIG}" apply -f -
kubectl --kubeconfig "${ADMIN_KUBECONFIG}" create namespace harbor-qwen-build \
--dry-run=client -o yaml | kubectl --kubeconfig "${ADMIN_KUBECONFIG}" apply -f -
Mac的.env填写管理员文件及其实际context:
KUBECONFIG_PATH=/Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml
KUBE_CONTEXT=<该文件的current-context>
实际context可用以下命令取得:
kubectl --kubeconfig /Users/keryszhang/.kube/harbor-qwen-grpo/ack-admin-public.yaml \
config current-context
7.5 AutoDL运行KubeConfig--done
将harbor-runner的公网KubeConfig保存为:
/root/ack-public-kubeconfig.yaml
设置权限、确认公网端点并验收命名空间权限:
chmod 600 /root/ack-public-kubeconfig.yaml
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml config get-contexts
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml \
config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml get --raw=/version
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i create pods -n harbor-qwen-grpo
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i create jobs.batch -n harbor-qwen-grpo
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i create pods/exec -n harbor-qwen-grpo
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i get pods/log -n harbor-qwen-grpo
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i get secrets -n harbor-qwen-grpo
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i create pods/portforward -n harbor-qwen-build
kubectl --kubeconfig /root/ack-public-kubeconfig.yaml auth can-i get secrets -n harbor-qwen-build
上述auth can-i检查应全部返回yes。harbor-runner采用命名空间级最小权限,以下结果正常:
kubectl cluster-info -> 可能因不能列出kube-system Service而返回Forbidden
kubectl get nodes -> 因不能读取集群级Node而返回Forbidden
kubectl get namespace -> 因不能读取集群级Namespace而返回Forbidden
不要为了消除这些提示而扩大权限。AutoDL的.env只保存文件路径和实际context:
KUBECONFIG_PATH=/root/ack-public-kubeconfig.yaml
KUBE_CONTEXT=<该文件的current-context>
7.6 项目网络验收--done
先在Mac完成make ack-prepare,使两个namespace内的镜像拉取Secret存在;然后把更新后的
项目脚本同步到AutoDL并执行:
make autodl-ack-network
该命令检查AutoDL公网出口、ACR公网端点、ACK API /version、Pod/Job/exec/log/
port-forward/Secret权限,以及ack-prepare创建的镜像拉取Secret。
失败时按以下顺序排查:
- AutoDL出口IP是否仍在ACK API Server ACL中。
- AutoDL
.env中的KUBECONFIG_PATH和KUBE_CONTEXT是否匹配运行KubeConfig。 - Mac是否已执行
make ack-prepare。 harbor-runner是否仅对两个正确namespace获得开发人员权限。- 是否误将Mac管理员KubeConfig或旧KubeConfig复制到了AutoDL。
8. BuildKit 通道、Gateway 与全量预检
BuildKit在ACK中使用moby/buildkit:v0.20.2 rootful镜像和privileged容器。ACK托管
节点可能将/proc/sys/user/max_user_namespaces设置为0,rootless镜像会因此以
failed to start the child退出。Builder必须放在独立CPU节点池,不与业务负载混部;
它不挂载宿主机Docker socket,缓存仅写入专用PVC。
8.1 BuildKit PVC StorageClass--done
ACK集群可能安装多个StorageClass但不设置默认项。BuildKit缓存PVC必须显式配置:
ACK_BUILDKIT_STORAGE_CLASS=alicloud-disk-topology-alltype
ACK_BUILDKIT_CACHE_SIZE=100Gi
ACK_BUILDKIT_GC_KEEP_STORAGE=80000000000
alicloud-disk-topology-alltype使用WaitForFirstConsumer,会在Pod确定调度节点和可用区后
创建可用云盘,适合测试集群。可用StorageClass可由Mac管理员查询:
ACK_BUILDKIT_GC_KEEP_STORAGE传给BuildKit v0.20.2的
--oci-worker-gc-keepstorage,必须填写纯数字字节数;80000000000表示80GB,不能写成
80GB。
kubectl --kubeconfig "$KUBECONFIG_PATH" --context "$KUBE_CONTEXT" \
get storageclass -o wide
若旧buildkit-cache一直为Pending,事件显示no storage class is set,说明该PVC在
创建时没有StorageClass。storageClassName不能在现有PVC上修改;确认PVC从未绑定且没有
数据后,删除并由make buildkit-up重建:
kubectl --kubeconfig "$KUBECONFIG_PATH" --context "$KUBE_CONTEXT" \
delete pvc buildkit-cache -n harbor-qwen-build
make buildkit-up
8.2 AutoDL 放置客户端证书--done
在Mac项目目录执行:
cd /Users/keryszhang/Documents/Tool-using-agent-rl/harbor-qwen-grpo-experiment
make buildkit-certs
生成目录:
.secrets/buildkit/
├── ca.pem
├── ca-key.pem
├── server-cert.pem
├── server-key.pem
├── client-cert.pem
└── client-key.pem
分工如下:
ca.pem:Mac、ACK、AutoDL都需要server-cert.pem、server-key.pem:Mac通过make ack-prepare写入ACKclient-cert.pem、client-key.pem:安全上传到AutoDLca-key.pem:只留在Mac,不能上传
在AutoDL创建目录:
mkdir -p /root/.config/harbor-qwen-grpo/buildkit
chmod 700 /root/.config/harbor-qwen-grpo/buildkit
通过AutoDL文件上传功能,把以下三个Mac文件上传过去:
ca.pem
client-cert.pem
client-key.pem
然后执行:
chmod 600 /root/.config/harbor-qwen-grpo/buildkit/*.pem
AutoDL的.env填写:
BUILDKIT_CA_CERT_PATH=/root/.config/harbor-qwen-grpo/buildkit/ca.pem
BUILDKIT_CLIENT_CERT_PATH=/root/.config/harbor-qwen-grpo/buildkit/client-cert.pem
BUILDKIT_CLIENT_KEY_PATH=/root/.config/harbor-qwen-grpo/buildkit/client-key.pem
这些证书必须来自同一次make buildkit-certs。不要分别在Mac和AutoDL生成两套。同时保持:
ACK_BUILDKIT_ADDRESS=tcp://127.0.0.1:1234
ACK_BUILDKIT_LOCAL_PORT=1234
ACK_BUILDKIT_SERVER_NAME=127.0.0.1
8.3 启动长期端口转发--done
在AutoDL独立 tmux 窗口运行:
(服务器上保持后台终端会话的工具,make buildkit-tunnel是一个需要持续运行的前台进程。如果SSH或网页终端断开,普通终端中的进程可能退出;放进tmux后,断开连接它仍会继续运行。)
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
set -a
source .env
set +a
source /root/miniconda3/etc/profile.d/conda.sh
conda activate harbor-grpo
tmux new -s buildkit
make buildkit-tunnel
使用 Ctrl-b d 脱离 tmux。另一个终端验证:
make buildkit-status
buildkit-tunnel 会循环重连,但网络断开时正在进行的单次构建仍可能失败。10题 Canary 的并发固定为 2;长期高并发应改为固定 EIP 的安全构建中继。
脱离但不停止:
先按 Ctrl-b,再按 d
查看:
tmux ls
重新进入:
tmux attach -t buildkit
停止时,在窗口里按Ctrl-C,或者:
tmux kill-session -t buildkit
AutoDL实例关机后tmux也会停止,重新开机需要重新启动隧道。
8.4 BuildKit 实际构建验收--done
make buildkit-status只能证明客户端可列出远端worker。启动Canary前,还需要验证构建上下文
上传、Dockerfile执行和OCI导出链路:
make buildkit-smoke
该命令使用临时目录生成一个不访问网络的scratch镜像,经AutoDL本机mTLS tunnel交给ACK
BuildKit构建,再把OCI归档流回AutoDL并验证index.json。无论成功或失败,临时上下文和输出
都会删除;它不会推送镜像,也不会修改现有PVC内容之外的正常BuildKit缓存。
成功标志:
BuildKit smoke build passed; temporary context and OCI output were removed.
8.5 模型 Gateway--done
AutoDL 个人账号使用控制台提供的 6006(测试) 或 6008(正式) 公网映射,<公网地址>是ACK Pod能够访问的AutoDL模型服务公网入口。
AutoDL无需自己购买域名。实例运行后,平台自动把容器内的6006和6008映射为公网地址。
操作顺序:
- AutoDL控制台进入对应实例。
- 确认“自定义服务”中:
- 在实例详情或“自定义服务”入口点击对应端口的“复制地址”。
- 得到类似:
https://u39-xxxx.nmb2.seetacloud.com:8443
这是完整公网入口;不能把AutoDL SSH地址或内网IP填进去。AutoDL官方说明6006/6008会映射成可访问的“域名+端口”。
AutoDL当前实例将rLLM Gateway的 127.0.0.1:6006 和Canary vLLM的
127.0.0.1:6008 映射为两个不同的公网 HTTPS origin:
cd /root/autodl-tmp/harbor-qwen-grpo-experiment
test -f .env || cp .env.example .env
chmod 600 .env
nano .env
MODEL_NAME=ricdomolm/mini-coder-4b
CANARY_MODEL_BASE_URL=https://uu242790-9c17-e7970d4a.nma1.seetacloud.com:8448/v1
CANARY_MODEL_API_KEY=<从受限密钥文件读取,不在文档中记录明文>
RLLM_GATEWAY_PORT=6006
RLLM_GATEWAY_PUBLIC_URL=https://u242790-9c17-e7970d4a.nma1.seetacloud.com:8448
CANARY_MODEL_BASE_URL:ACK Sandbox在10题Canary中直接请求vLLM。RLLM_GATEWAY_PUBLIC_URL:正式GRPO中,ACK Sandbox请求rLLM Gateway;只填写公网 origin,不带/v1,rLLM 会为每个 rollout 自动追加/sessions/<id>/v1。RLLM_GATEWAY_PORT:rLLM Gateway在AutoDL容器内部监听的端口,不是公网映射端口号。- 必须验证 Authorization、
/v1/models、流式响应及30/60/120分钟长连接。实例重启后重新确认公网地址。Canary 成功但长连接不稳定时,应使用带固定 EIP 的阿里云 ECS HTTPS 中继。
8.6 从 ACK 反向验证 Gateway--done
在AutoDL执行:
make network-smoke
它实际执行的路径是:
AutoDL上的kubectl
→ 请求ACK API创建临时Pod
→ ACK临时Pod从ACR拉取infra-curl镜像
→ ACK临时Pod请求AutoDL公网Gateway
→ 验证/models
→ 删除临时Pod
预期输出:
ACK Pod can reach the GPU model gateway.
8.7 全量预检--done
保持 buildkit-tunnel 在 tmux 中运行,然后执行:
make preflight
预期输出:
Preflight passed.
9. 从当前状态开始的跨平台执行顺序
阶段 A:ACK 创建前,可并行--done
| 工作线 | 执行位置 | 操作 | 当前依赖 | 结果 |
|---|---|---|---|---|
| A1 | AutoDL | 完成第5节本地验收,记录出口 IP | 已上传源码包 | done |
| A2 | Mac | 再次确认两个基础镜像已在 ACR,执行 make buildkit-certs |
.env 和 OpenSSL |
Certificate request self-signature ok subject=CN=harbor-gpu-controller BuildKit mTLS certificates created: /Users/keryszhang/Documents/Tool-using-agent-rl/harbor-qwen-grpo-experiment/.secrets/buildkit Set the five BUILDKIT_*_PATH values in .env to these files. |
| A3 | AutoDL | 启动并验证本地模型服务;准备6006/6008公网映射 | GPU和Conda环境 | done |
| A4 | AutoDL | 可选执行 make pull 预取 SWE-smith 数据 |
make install-conda 已通过 |
Done. Use 'rllm dataset info /root/.rllm/datasets/swesmith 100 examples swesmith' to view details. fields: task_id, task_path, instruction, question, ground_truth, harbor_task_name, harbor_task_digest, harbor_category, data_source |
| A5 | 阿里云控制台 | 最后复核ACK测试版配置、余额和计费项 | VPC、交换机、ACR已就绪 | done |
A1~A5可以并行。此阶段不要运行 make ack-prepare、make buildkit-up 或任何需要 Kubernetes API 的命令。
阶段 B:创建 ACK,主体串行--done
- 阿里云创建测试版 ACK 集群并等待“运行中”。
- 阿里云开启 API Server 公网访问;ACL加入当前 AutoDL 出口 IP并保留ACK要求的系统网段。
- 按第7节先为
ack-admin配置当前集群管理员权限并获取其公网KubeConfig。 - 不把KubeConfig内容粘贴到项目文档;只记录受限文件路径、context和验证命令。
- Mac创建两个项目namespace后,为
harbor-runner配置两条namespace级开发人员权限并获取其公网KubeConfig。 - Mac管理员执行
kubectl cluster-info和kubectl get nodes -o wide;AutoDL受限账户执行kubectl get --raw=/version及命名空间级auth can-i检查。
步骤2和3可在集群运行后并行;步骤4依赖权限完成;步骤5依赖KubeConfig、ACL和RBAC都生效。
阶段 C:初始化 ACK,必须按顺序--done
Mac 更新
.env中的KUBECONFIG_PATH、KUBE_CONTEXT和证书路径。Mac 执行:
make ack-prepareMac 执行:
make buildkit-upAutoDL 更新自己的
.env、放置 KubeConfig 和 BuildKit客户端证书。AutoDL 执行:
make autodl-ack-network
make autodl-ack-network 依赖 make ack-prepare 已经创建两个 namespace,因此不能提前运行。make buildkit-tunnel 依赖 make buildkit-up 已经部署 BuildKit,因此也不能提前运行。
阶段 D:联调,可部分并行--done
- AutoDL 在 tmux 中运行
make buildkit-tunnel。 - AutoDL 运行
make buildkit-status。 - AutoDL 模型 Gateway 保持运行。?
- AutoDL 运行
make network-smoke,验证 ACK Pod → AutoDL Gateway。 - AutoDL 运行
make preflight。
步骤1和3可并行准备;步骤2依赖步骤1;步骤4依赖 Gateway、ACK namespace、ACR Secret及网络同时就绪;步骤5是最终汇总门槛。
阶段 E:Canary 与训练,严格串行放行
Oracle 阶段在 AutoDL .env 中设置 CURATION_ORACLE_VERIFIER_TIMEOUT_SEC=480 和
CURATION_ALLOW_SHORTFALL=true。单任务 verifier 超时后由 ingest 拒绝,不阻断同批 Oracle;
冻结集允许少于目标 100 条。
Canary 前必须完成 Oracle、dataset-freeze 和 dataset-register;make canary 从
TRAIN_DATASET_NAME 的冻结 validation split 确定性选题。任务 Dockerfile 依赖的
SWE-Smith 基础镜像需已同步到 ACR。执行:
make canary
make canary报错解决:
- 将 SWE-Smith 基础镜像同步到 ACR 公网仓库。
- 解决 BuildKit 访问 ACR 私网认证地址超时的问题。
- 制作离线基础镜像,解决构建阶段无法获取 Git 分支的问题。
- 解决 ACK Sandbox 无法访问 GitHub、导致 Qwen Code 安装超时的问题。
- Canary 首次完整跑通 Agent 和 Verifier:
Trials=1,Exceptions=0,但奖励为0。 - 检查轨迹后发现只有用户和模型回复,没有实际工具调用。
- 分别测试工具调用:
tool_choice=required:成功生成结构化tool_calls。tool_choice=auto:失败,只输出 Markdown 包裹的普通 JSON。
当前基模的问题并非完全不能调用工具,而是不能在自动模式下可靠遵循工具调用协议。Qwen2.5-Coder-7B 更擅长代码生成,但工具格式遵循能力较弱:它把调用内容写进普通文本,而没有输出 Hermes 能识别的 <tool_call> 结构。
Qwen Code 必须使用自动模式,让模型自主决定何时调用工具、何时结束。因此,强制 required 虽能通过测试,却不能支撑真实的长程代码任务。当前基模不适合直接进入10条任务测试和GRPO训练。
项目现已把默认 harness 切换为 mini-swe-agent 文本动作模式,绕开原生 function calling。将以下配置补充到 AutoDL .env:
HARBOR_AGENT=mini-swe-agent
MINI_SWE_AGENT_VERSION=2.3.0
MINI_SWE_AGENT_CONFIG_FILE=configs/agents/mini-swe-agent-text.yaml
MINI_SWE_AGENT_MAX_TOKENS=2048
MINI_SWE_AGENT_STEP_LIMIT=100
MINI_SWE_AGENT_COST_LIMIT=0
ACK_POD_READY_TIMEOUT_SEC=480
CANARY_TASKS=1
CANARY_CONCURRENCY=1
CANARY_MAX_RETRIES=1
mini-swe-agent-plus使用独立旧版CLI适配。32768上下文下把单步输出限制为896;实测
1024输出预算与31745输入token合计32769,会超过模型上限:
MINI_SWE_AGENT_PLUS_MAX_TOKENS=896
CANARY_TASKS=10
CANARY_CONCURRENCY=4
CANARY_MAX_RETRIES=0
scripts/lib.sh遵循标准dotenv优先级:调用方显式导出的变量优先于.env。因此也可用
CANARY_TASKS=10 CANARY_CONCURRENCY=4 CANARY_MAX_RETRIES=0 make canary临时覆盖,不需要反复改写.env。
重新上传源码包后依次执行:
make preflight
make network-smoke
make canary
单任务通过标准:Exceptions=0,轨迹包含多轮 agent 与 Shell observation,verifier 文件完整。reward 可以为 0,但不能只有普通文本回答。
mini-swe-agent 的任务仓库固定为 /testbed。每个动作都在新 Shell 中执行,不能依赖上一步设置的 REPO_PATH 等临时变量;命令应使用相对路径或显式以 cd /testbed && 开头。当前文本动作配置最多执行 100 步;达到步数或上下文上限时按正常 rollout 截断并继续 verifier。
只有满足以下条件才执行 make train:
- 10/10任务均能创建Sandbox并结束;
- 10/10均有可解析ATIF轨迹;
- 10/10均有verifier reward,reward可以为0但不能缺失;
- BuildKit没有异常重启或持续断线;
- 无Sandbox OOM、Gateway/API超时和残留Pod/Job;
- 资源峰值、单任务时长和费用可接受。
通过后:
make train
10. 2026-08-11当前AutoDL交接状态
CVM侧已经完成:
oracle_total=1440
oracle_accepted=981
train/validation/test=350/75/75
repositories=77/70
freeze_ready=true
正式导出包为 swesmith-20260808-v2-poc-curated.tar.gz,大小29377680字节,SHA-256为 8ce630ad5850c1b0456802cb26230257bb7a0b4ca76be50b643534c3248ced05。AutoDL已完成import、register和status,结果为350/75/75;Canary与单卡GRPO smoke均已完成。
已验证的单卡GRPO smoke配置:
TRAIN_NNODES=1
TRAIN_N_GPUS_PER_NODE=1
TRAIN_TENSOR_PARALLEL_SIZE=1
TRAIN_GPU_MEMORY_UTILIZATION=0.35
TRAIN_MODEL_DTYPE=bf16
TRAIN_ENABLE_SLEEP_MODE=false
TRAIN_FREE_CACHE_ENGINE=false
TRAIN_PARAM_OFFLOAD=false
TRAIN_OPTIMIZER_OFFLOAD=false
TRAIN_REF_PARAM_OFFLOAD=false
TRAIN_MODEL_DTYPE=bf16让训练模型直接以BF16加载;TRAIN_GPU_MEMORY_UTILIZATION=0.35将单卡rollout vLLM占用从约40GiB降至可完成backward的范围。CPU offload默认关闭;只有实测显存不足时才逐项启用。
单卡smoke峰值训练显存分配约42.70GiB并完成 training/global_step=1。两卡初次初始化异常的根因不是FSDP:原始 all_reduce 在Direct P2P/CUMEM路径同样死锁。当前机器先在 .env 设置:
NCCL_P2P_DISABLE=1
该配置后,两卡隔离测试通过:
make fsdp2-smoke
该命令输出 FSDP2_SMOKE_PASSED;随后传统FSDP1两卡完整GRPO也完成4/4 rollout、backward、optimizer step、权重同步和global step 1,峰值分配/预留约38.29/39.91GiB。因此无需为了通信故障把完整训练迁移到FSDP2。注意 NCCL_P2P_DISABLE=1 仅用于已复现Direct P2P死锁的机器。
现阶段质量诊断使用 TRAIN_TASK_IDS 精确选择train任务,TRAIN_SMOKE_GROUP_SIZE、TRAIN_SMOKE_PARALLEL_TASKS、TRAIN_SMOKE_AGENT_STEP_LIMIT 和 TRAIN_SMOKE_SESSION_TIMEOUT_SEC 缩短A/B;每次smoke自动创建带UTC run ID的独立experiment/checkpoint/episode目录。rank 32在默认 dummy_dtensor 路径产生2048-token乱码,改用 TRAIN_ROLLOUT_LOAD_FORMAT=safetensors 后已恢复合法动作。正式训练前必须得到非零学习信号,并验证实际LoRA更新后的再次同步。
11. 五卡分离PPO环境(已完成40步验收)
PPO已在AutoDL完成4卡trainer加1卡独立vLLM的40K训练验收。本节固定与现有AutoDL/GRPO不同的资源门槛;公共的模型路径、Gateway、BuildKit和ACK配置继续复用前文。
- actor/critic trainer使用单机4×80GB FSDP,rollout使用另1×80GB运行唯一TP=1 vLLM;五张卡必须同时空闲。
- 已验证训练边界为40K、900秒、并发8。历史6卡colocated尝试会随world size复制vLLM,不能用作分离拓扑替代品。
- 启动前停止独立Canary
vllm serve,并确认没有其他Ray、训练、Canary或Oracle作业占用GPU/ACK。 - critic使用独立value head、optimizer和BF16 model-only checkpoint;actor只保存LoRA adapter,参数和optimizer offload按已验证配置启用,reference KL关闭。
- PPO入口继续复用现有preflight,不新增PPO专用目标;训练模式只跳过必须已停止的独立Canary vLLM存活探测,其余Python、Kubernetes、RBAC、Registry和BuildKit门禁保持启用。两卡
make fsdp2-smoke的历史结果不能替代四卡门禁。 - 末步已验证actor adapter约177.5MiB、critic约14.11GiB;每次新运行仍须检查系统内存、磁盘、每rank显存和checkpoint体积。
PPO特有参数、验收和故障记录见PPO_TRAINING_RUNBOOK.md。
