Add checkpoint manifest and compatible benchmark download workflow
Browse filesAdd config.json with checkpoint/statistics paths and integrity metadata; provide a manifest-driven downloader and document full/selected downloads. Preserve existing weights, statistics and evaluation commands. Configuration requests participate in standard Hub download statistics.
- README.md +65 -1
- config.json +61 -0
- download_bridgewam.py +100 -0
README.md
CHANGED
|
@@ -25,6 +25,8 @@ together with the normalization statistics required by each checkpoint.
|
|
| 25 |
|
| 26 |
```text
|
| 27 |
README.md
|
|
|
|
|
|
|
| 28 |
libero/
|
| 29 |
model.pt
|
| 30 |
dataset_stats.json
|
|
@@ -67,11 +69,73 @@ replans after 24 actions.
|
|
| 67 |
|
| 68 |
## Download
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
```bash
|
| 71 |
-
pip install
|
| 72 |
hf download BridgeWAM/bridgewam --local-dir ./checkpoints/bridgewam
|
| 73 |
```
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
## Evaluation
|
| 76 |
|
| 77 |
Install the [BridgeWAM code and dependencies](https://github.com/BridgeWam/BridgeWAM-code)
|
|
|
|
| 25 |
|
| 26 |
```text
|
| 27 |
README.md
|
| 28 |
+
config.json Download manifest and architecture summary
|
| 29 |
+
download_bridgewam.py Optional manifest-driven downloader
|
| 30 |
libero/
|
| 31 |
model.pt
|
| 32 |
dataset_stats.json
|
|
|
|
| 69 |
|
| 70 |
## Download
|
| 71 |
|
| 72 |
+
`config.json` describes the released architecture and maps each benchmark to its
|
| 73 |
+
checkpoint, matching normalization statistics, task configuration, file size and
|
| 74 |
+
SHA-256 checksum. It is a BridgeWAM download manifest, **not** a Transformers
|
| 75 |
+
`AutoConfig` file or a replacement for the codebase's Hydra task YAML.
|
| 76 |
+
The existing `.pt` files, statistics, paths and model-loading API are unchanged.
|
| 77 |
+
|
| 78 |
+
### Download all checkpoints
|
| 79 |
+
|
| 80 |
+
The existing command still works and now also downloads `config.json`:
|
| 81 |
+
|
| 82 |
```bash
|
| 83 |
+
pip install huggingface_hub
|
| 84 |
hf download BridgeWAM/bridgewam --local-dir ./checkpoints/bridgewam
|
| 85 |
```
|
| 86 |
|
| 87 |
+
### Download one benchmark
|
| 88 |
+
|
| 89 |
+
Include `config.json` alongside the weights and their matching statistics:
|
| 90 |
+
|
| 91 |
+
```bash
|
| 92 |
+
# LIBERO (also used for LIBERO-Plus and LIBERO-Pro)
|
| 93 |
+
hf download BridgeWAM/bridgewam config.json libero/model.pt libero/dataset_stats.json \
|
| 94 |
+
--local-dir ./checkpoints/bridgewam
|
| 95 |
+
|
| 96 |
+
# RoboTwin
|
| 97 |
+
hf download BridgeWAM/bridgewam config.json robotwin/model.pt robotwin/dataset_stats.json \
|
| 98 |
+
--local-dir ./checkpoints/bridgewam
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
On older installations (including the codebase's pinned `huggingface_hub==0.29.2`),
|
| 102 |
+
replace `hf download` with `huggingface-cli download`. There is no need to upgrade
|
| 103 |
+
the pinned training environment to use these downloads.
|
| 104 |
+
|
| 105 |
+
### Manifest-driven Python downloader
|
| 106 |
+
|
| 107 |
+
The helper supports `huggingface_hub>=0.29.2` and does not require PyTorch or CUDA.
|
| 108 |
+
Download it once, then select `libero`, `robotwin`, or `all`:
|
| 109 |
+
|
| 110 |
+
```bash
|
| 111 |
+
hf download BridgeWAM/bridgewam download_bridgewam.py --local-dir ./bridgewam-tools
|
| 112 |
+
python ./bridgewam-tools/download_bridgewam.py \
|
| 113 |
+
--benchmark libero --local-dir ./checkpoints/bridgewam
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
The helper reads `config.json`, downloads the selected checkpoint and statistics
|
| 117 |
+
from the same resolved commit, and prints the matching evaluation arguments.
|
| 118 |
+
It checks both file sizes and the statistics checksum; add `--verify` to also
|
| 119 |
+
check the weights' SHA-256 (this reads approximately 10 GB per checkpoint).
|
| 120 |
+
Use `--revision <commit-sha>` to pin a release containing the manifest. Downloads
|
| 121 |
+
use the Hub's normal cache/resume behavior; the helper does not force downloads
|
| 122 |
+
or add separate tracking requests. For offline inference, download first and
|
| 123 |
+
continue using the existing local checkpoint and statistics paths below.
|
| 124 |
+
|
| 125 |
+
### Download statistics
|
| 126 |
+
|
| 127 |
+
Hugging Face counts requests to recognized configuration files such as
|
| 128 |
+
`config.json`. Including this real manifest in the download allows the normal
|
| 129 |
+
Hub download workflow to participate in its standard statistics. This is a
|
| 130 |
+
repository-level request metric, not a count of unique people or completed
|
| 131 |
+
weight downloads; it does not distinguish LIBERO from RoboTwin.
|
| 132 |
+
|
| 133 |
+
Direct downloads of only the old `.pt` URLs remain supported, but do not by
|
| 134 |
+
themselves request the configuration and may remain uncounted. Fully offline
|
| 135 |
+
cache use makes no server request, and earlier uncounted downloads cannot be
|
| 136 |
+
recovered by adding this file. Displayed statistics may take time to update.
|
| 137 |
+
See [Hugging Face's download statistics documentation](https://huggingface.co/docs/hub/models-download-stats).
|
| 138 |
+
|
| 139 |
## Evaluation
|
| 140 |
|
| 141 |
Install the [BridgeWAM code and dependencies](https://github.com/BridgeWam/BridgeWAM-code)
|
config.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema_version": 1,
|
| 3 |
+
"model_name": "BridgeWAM",
|
| 4 |
+
"description": "Download manifest and architecture summary for the released task-specific BridgeWAM checkpoints; use the matching codebase task YAML to instantiate the model.",
|
| 5 |
+
"checkpoint_format": "pytorch_weight_dictionary",
|
| 6 |
+
"architecture": {
|
| 7 |
+
"video_expert_layers": 30,
|
| 8 |
+
"action_expert_layers": 2,
|
| 9 |
+
"action_expert_architecture": "alternating_cross_self",
|
| 10 |
+
"num_lbqs": 32,
|
| 11 |
+
"lbq_start_layer": 0,
|
| 12 |
+
"lbq_readout_layer": -1,
|
| 13 |
+
"conditioning": "lbq_only"
|
| 14 |
+
},
|
| 15 |
+
"inference": {
|
| 16 |
+
"action_horizon": 32,
|
| 17 |
+
"num_inference_steps": 10,
|
| 18 |
+
"generates_future_video": false
|
| 19 |
+
},
|
| 20 |
+
"checkpoints": {
|
| 21 |
+
"libero": {
|
| 22 |
+
"task": "libero_uncond_2cam224_lbqs_only_2layer_alternating_cross_self_fullfinetune_1e-4",
|
| 23 |
+
"action_dim": 7,
|
| 24 |
+
"proprio_dim": 8,
|
| 25 |
+
"cameras": [
|
| 26 |
+
"front",
|
| 27 |
+
"wrist"
|
| 28 |
+
],
|
| 29 |
+
"weights": {
|
| 30 |
+
"path": "libero/model.pt",
|
| 31 |
+
"size_bytes": 10120229217,
|
| 32 |
+
"sha256": "8afbff12d7bca4d978e78b18270a01a5233e56b24f3dded52b355e04cc9a12c3"
|
| 33 |
+
},
|
| 34 |
+
"normalization": {
|
| 35 |
+
"path": "libero/dataset_stats.json",
|
| 36 |
+
"size_bytes": 40940,
|
| 37 |
+
"sha256": "8d4d4a3d376bb91a75353562b0ae8ab217db8107fdcd10d0ed68fdcacf3a923e"
|
| 38 |
+
}
|
| 39 |
+
},
|
| 40 |
+
"robotwin": {
|
| 41 |
+
"task": "robotwin_bridgewam_3cam384_lbq32_2layer_1e-4",
|
| 42 |
+
"action_dim": 14,
|
| 43 |
+
"proprio_dim": 14,
|
| 44 |
+
"cameras": [
|
| 45 |
+
"head",
|
| 46 |
+
"left_wrist",
|
| 47 |
+
"right_wrist"
|
| 48 |
+
],
|
| 49 |
+
"weights": {
|
| 50 |
+
"path": "robotwin/model.pt",
|
| 51 |
+
"size_bytes": 10120307498,
|
| 52 |
+
"sha256": "4decbb9d497b714dfe879e10da10506dc6fa21dbaab4dbeac5fb9d4abc490833"
|
| 53 |
+
},
|
| 54 |
+
"normalization": {
|
| 55 |
+
"path": "robotwin/dataset_stats.json",
|
| 56 |
+
"size_bytes": 88715,
|
| 57 |
+
"sha256": "7a02c46cfc8c5e746c0afbe41fca73f723eda34cbc083f8ca54f76d8f7468095"
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
}
|
download_bridgewam.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Download a matched BridgeWAM checkpoint/statistics pair from its manifest.
|
| 3 |
+
|
| 4 |
+
Requires huggingface_hub>=0.29.2; no PyTorch or CUDA installation is needed.
|
| 5 |
+
Existing model.pt paths and the BridgeWAM model loader remain unchanged.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import argparse
|
| 9 |
+
import hashlib
|
| 10 |
+
import json
|
| 11 |
+
from pathlib import Path, PurePosixPath
|
| 12 |
+
|
| 13 |
+
from huggingface_hub import HfApi, hf_hub_download
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
REPO_ID = "BridgeWAM/bridgewam"
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def validate_manifest(config):
|
| 20 |
+
if config.get("schema_version") != 1 or config.get("model_name") != "BridgeWAM":
|
| 21 |
+
raise ValueError("Unsupported BridgeWAM download manifest")
|
| 22 |
+
variants = config.get("checkpoints", {})
|
| 23 |
+
if set(variants) != {"libero", "robotwin"}:
|
| 24 |
+
raise ValueError("Manifest must provide LIBERO and RoboTwin checkpoints")
|
| 25 |
+
for name, entry in variants.items():
|
| 26 |
+
if not isinstance(entry.get("task"), str) or not entry["task"]:
|
| 27 |
+
raise ValueError("Missing task configuration for " + name)
|
| 28 |
+
for role, filename in (("weights", "model.pt"), ("normalization", "dataset_stats.json")):
|
| 29 |
+
asset = entry[role]
|
| 30 |
+
path = PurePosixPath(asset["path"])
|
| 31 |
+
if str(path) != name + "/" + filename:
|
| 32 |
+
raise ValueError("Unexpected checkpoint/statistics path")
|
| 33 |
+
if not isinstance(asset["size_bytes"], int) or asset["size_bytes"] <= 0:
|
| 34 |
+
raise ValueError("Invalid asset size")
|
| 35 |
+
digest = asset["sha256"]
|
| 36 |
+
if len(digest) != 64 or any(c not in "0123456789abcdef" for c in digest):
|
| 37 |
+
raise ValueError("Invalid asset SHA-256")
|
| 38 |
+
return variants
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def verify_file(path, asset, check_hash):
|
| 42 |
+
if path.stat().st_size != asset["size_bytes"]:
|
| 43 |
+
raise ValueError("Size mismatch: " + str(path))
|
| 44 |
+
if check_hash:
|
| 45 |
+
digest = hashlib.sha256()
|
| 46 |
+
with path.open("rb") as handle:
|
| 47 |
+
for chunk in iter(lambda: handle.read(8 * 1024 * 1024), b""):
|
| 48 |
+
digest.update(chunk)
|
| 49 |
+
if digest.hexdigest() != asset["sha256"]:
|
| 50 |
+
raise ValueError("SHA-256 mismatch: " + str(path))
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def download(benchmark, local_dir, revision="main", verify=False):
|
| 54 |
+
if benchmark not in ("libero", "robotwin", "all"):
|
| 55 |
+
raise ValueError("Choose libero, robotwin or all")
|
| 56 |
+
# Resolve once, then pin the configuration, weights and statistics together.
|
| 57 |
+
commit = HfApi().model_info(REPO_ID, revision=revision).sha
|
| 58 |
+
if not commit:
|
| 59 |
+
raise ValueError("Could not resolve the requested repository revision")
|
| 60 |
+
local_dir = Path(local_dir)
|
| 61 |
+
config_path = hf_hub_download(
|
| 62 |
+
repo_id=REPO_ID, filename="config.json", revision=commit, local_dir=str(local_dir)
|
| 63 |
+
)
|
| 64 |
+
with open(config_path, encoding="utf-8") as handle:
|
| 65 |
+
variants = validate_manifest(json.load(handle))
|
| 66 |
+
selected = ("libero", "robotwin") if benchmark == "all" else (benchmark,)
|
| 67 |
+
results = {}
|
| 68 |
+
for name in selected:
|
| 69 |
+
entry = variants[name]
|
| 70 |
+
files = {}
|
| 71 |
+
for role in ("normalization", "weights"):
|
| 72 |
+
asset = entry[role]
|
| 73 |
+
path = Path(hf_hub_download(
|
| 74 |
+
repo_id=REPO_ID, filename=asset["path"], revision=commit,
|
| 75 |
+
local_dir=str(local_dir)
|
| 76 |
+
))
|
| 77 |
+
# Always validate the small normalization file; weight hashing is optional.
|
| 78 |
+
verify_file(path, asset, check_hash=verify or role == "normalization")
|
| 79 |
+
files[role] = str(path)
|
| 80 |
+
results[name] = {"revision": commit, "task": entry["task"], **files}
|
| 81 |
+
return results
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def main():
|
| 85 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 86 |
+
parser.add_argument("--benchmark", choices=("libero", "robotwin", "all"), required=True)
|
| 87 |
+
parser.add_argument("--local-dir", default="./checkpoints/bridgewam")
|
| 88 |
+
parser.add_argument("--revision", default="main", help="HF branch, tag or commit SHA")
|
| 89 |
+
parser.add_argument("--verify", action="store_true", help="Also SHA-256-check the large weights")
|
| 90 |
+
args = parser.parse_args()
|
| 91 |
+
results = download(args.benchmark, args.local_dir, args.revision, args.verify)
|
| 92 |
+
for name, result in results.items():
|
| 93 |
+
print("\nDownloaded {} at {}".format(name, result["revision"]))
|
| 94 |
+
print("task=" + result["task"])
|
| 95 |
+
print("ckpt=" + result["weights"])
|
| 96 |
+
print("EVALUATION.dataset_stats_path=" + result["normalization"])
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
if __name__ == "__main__":
|
| 100 |
+
main()
|