快速开始
本节完成 Wall-OSS-0.5 环境和权重准备。所有命令默认在 wall-x/ 仓库根目录执行,所有 /path/to/ 路径均需替换为本地真实路径。
本节完成 Wall-OSS-0.5 环境和权重准备。所有命令默认在 wall-x/ 仓库根目录执行,所有 /path/to/* 路径均需替换为本地真实路径。
官方部署教程:
环境搭建
# 1. 创建并激活环境
conda create --name wallx python=3.10 -y
conda activate wallx# 2. 安装基础依赖
pip install -r requirements.txt
pip install "dmuon @ git+https://github.com/X-Square-Robot/dmuon.git"# 3. 安装 LeRobot
git clone https://github.com/huggingface/lerobot.git
cd lerobot
git checkout v0.4.4
pip install --no-deps -e .
cd ../4. 安装 wall-x
export CUDA_HOME=/usr/local/cuda-12.8 # 改成你 nvcc 所在根目录,cuda 建议 12.8,和 torch 版本匹配
export PATH="$CUDA_HOME/bin:PATH"
which nvcc && nvcc --version
MAX_JOBS=8 pip install --no-build-isolation -e .# 5.安装 flash-attn
export FLASH_ATTN_CUDA_ARCHS=$(python -c 'import torch; print(f"{torch.cuda.get_device_capability()[0]}{torch.cuda.get_device_capability()[1]}")')
MAX_JOBS=4 pip install flash-attn==2.8.3 --no-build-isolationflash-attn 不在 requirements.txt,但是是硬依赖(joint.py 无条件 import is_flash_attn_greater_or_equal_2_10)
下载 Wall-OSS-0.5 权重
HuggingFace 下载相关
网络问题
如果 HuggingFace 网络有问题,可以
export HF_ENDPOINT=https://hf-mirror.com
hf download <repo_id> --local-dir <your-path>Wall-OSS-0.5 基于 Qwen2.5-VL-3B 构建,微调&推理必须下载模型权重 和qwen 权重 两套文件
maniparena 数据集下载(如有必要)
需在网页申请 dataset access 权限,并提供 HF read token
--local-dir 指到已存在的目录时,连不上远程的 hub 会把目录原样返回,打印绿勾和 exit 0,看起来完全成功但其实一个文件都没下。
还有超过 1000 个文件的仓库必然踩翻页坑,镜像返回的 Link: next 是绝对的 huggingface.co 地址,从第二页开始全是 Errno 101,只能自己枚举文件逐个 hf_hub_download
脚本:
"""Download every file in a Hub repo without snapshot_download pagination.
hf-mirror's tree API returns absolute huggingface.co Link: next headers after
the first 1000 files. dataset_info().siblings is a complete path list and
hf_hub_download honors HF_ENDPOINT.
Usage:
HF_ENDPOINT=https://hf-mirror.com HF_HUB_DISABLE_XET=1 HF_TOKEN=... \
python workspace/download_hf_siblings.py \
--repo-id ManipArena/maniparena-dataset \
--repo-type dataset \
--local-dir /path/to/dir
"""
from __future__ import annotations
import argparse
import os
import sys
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
from huggingface_hub import dataset_info, hf_hub_download, model_info
def list_files(repo_id: str, repo_type: str) -> list[str]:
info_fn = dataset_info if repo_type == "dataset" else model_info
info = info_fn(repo_id)
if not info.siblings:
raise RuntimeError(f"{repo_id}: empty siblings list")
return [s.rfilename for s in info.siblings]
def already_have(local_dir: Path, filename: str) -> bool:
path = local_dir / filename
return path.is_file() and path.stat().st_size > 0
def fetch(repo_id: str, repo_type: str, filename: str, local_dir: str, retries: int) -> str:
last: Exception | None = None
for attempt in range(retries):
try:
return hf_hub_download(
repo_id,
filename,
repo_type=repo_type,
local_dir=local_dir,
)
except Exception as exc: # noqa: BLE001
last = exc
time.sleep(min(2**attempt, 16))
raise RuntimeError(f"{filename}: {type(last).__name__} {last}") from last
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--repo-id", required=True)
parser.add_argument("--repo-type", default="dataset", choices=["dataset", "model"])
parser.add_argument("--local-dir", required=True)
parser.add_argument("--workers", type=int, default=8)
parser.add_argument("--retries", type=int, default=4)
args = parser.parse_args()
local_dir = Path(args.local_dir)
local_dir.mkdir(parents=True, exist_ok=True)
files = list_files(args.repo_id, args.repo_type)
pending = [f for f in files if not already_have(local_dir, f)]
print(
f"{args.repo_id}: {len(files)} files, {len(files) - len(pending)} already present, "
f"{len(pending)} to fetch",
flush=True,
)
if not pending:
print(f"OK {args.repo_id} -> {local_dir}", flush=True)
return
done = 0
errors: list[str] = []
t0 = time.time()
with ThreadPoolExecutor(max_workers=args.workers) as pool:
futures = {
pool.submit(fetch, args.repo_id, args.repo_type, f, str(local_dir), args.retries): f
for f in pending
}
for future in as_completed(futures):
try:
future.result()
except Exception as exc: # noqa: BLE001
errors.append(str(exc))
done += 1
if done % 100 == 0 or done == len(pending):
dt = time.time() - t0
print(
f" {done}/{len(pending)} errors={len(errors)} {dt:.0f}s",
flush=True,
)
if errors:
print(f"FAILED {len(errors)} files, first: {errors[0]}", flush=True)
sys.exit(1)
print(f"OK {args.repo_id} -> {local_dir}", flush=True)
if __name__ == "__main__":
main()模型页面:
推荐使用命令行:
huggingface-cli download X-Square-Robot/wall-oss-0.5 --local-dir /path/to/wall-oss-0.5也可以使用 Python
from huggingface_hub import snapshot_download
snapshot_download(
"X-Square-Robot/wall-oss-0.5",
local_dir="/path/to/wall-oss-0.5",
)下载后至少确认:
| 核心文件 | 作用 |
|---|---|
| config.json | 模型架构配置,对应训练 YAML 中的 model.config_path |
| model.safetensors | 预训练权重,对应 checkpoint.resume_from |
| tokenizer / processor 系列文件 | 模型推理和数据预处理必需文件 |
下载 Qwen2.5-VL-3B-Instruct
Wall-OSS-0.5 基于 Qwen2.5-VL-3B 构建。训练和推理还需要处理器文件:
huggingface-cli download Qwen/Qwen2.5-VL-3B-Instruct --local-dir /path/to/Qwen2.5-VL-3B-Instruct在训练配置中将 model.processor_path 和 model.pretrained_path 指向该目录。
快速检查
-
Python 环境可激活;
-
wall-x、dmuon 和 LeRobot 安装成功;
-
config.json 与 model.safetensors 完整;
-
Qwen2.5-VL-3B-Instruct 处理器目录完整;
-
GPU、CUDA 和 PyTorch 可用;
-
所有配置路径均已替换。
核心资源
| 资源 | 用途 |
|---|---|
| workspace/example/libero.yml | LIBERO 单臂仿真微调 |
| workspace/example/maniparena_example.yml | 真机双臂微调与部署 |
| scripts/compute_norm_stats.py | 生成数据集归一化统计 |
| scripts/run_libero.sh | LIBERO 仿真批量评估 |
| scripts/run_serving.sh | 启动真机 WebSocket 推理服务 |
| scripts/draw_openloop_plot.py | 开环推理效果可视化 |
| scripts/merge_sharded_weights.py | 合并 FSDP 分片权重 |