Download code/hb_groot/hb_launch.py from humanoid-benchmark/groot: direct link, hf CLI and curl.
- Browser
- Download file 3.91 kB
-
https://huggingface.co/humanoid-benchmark/groot/resolve/main/code/hb_groot/hb_launch.py
- Command line
-
hf download hf://humanoid-benchmark/groot/code/hb_groot/hb_launch.py
-
curl -L -o hb_launch.py https://huggingface.co/humanoid-benchmark/groot/resolve/main/code/hb_groot/hb_launch.py
3.91 kB
| """GR00T N1.7 fine-tuning entry with Humanoid Benchmark augmentation v2. | |
| Patches Gr00tN1d7Processor in training mode only: | |
| - images: native random crop / colour jitter / rotation are bypassed (the deterministic eval resize+center-crop is | |
| used), then hb_aug_v2 is applied jointly to all cameras of the sample; | |
| - proprio: the body-joint state groups (HB_BODY_STATE_KEYS) get the v2 bias + noise before normalization. | |
| Then runs the pinned upstream gr00t/experiment/launch_finetune.py unchanged. | |
| """ | |
| import json | |
| import os | |
| import runpy | |
| import sys | |
| from pathlib import Path | |
| import numpy as np | |
| import torch | |
| HERE = Path(__file__).resolve().parent | |
| sys.path.insert(0, str(HERE)) | |
| import hb_offline_fix # noqa: E402,F401 (tokenizer load under HF_HUB_OFFLINE=1, see module docstring) | |
| import hb_aug_v2 as A # noqa: E402 | |
| from gr00t.model.gr00t_n1d7 import processing_gr00t_n1d7 as P # noqa: E402 | |
| Proc = P.Gr00tN1d7Processor | |
| BODY_KEYS = [k for k in os.environ.get("HB_BODY_STATE_KEYS", "left_leg,right_leg,waist,left_arm,right_arm").split(",") if k] | |
| LOG = os.environ.get("HB_AUG_LOG") | |
| _state = {"rng": None, "count": 0} | |
| def _rng(): | |
| if _state["rng"] is None: | |
| _state["rng"] = np.random.default_rng([os.getpid(), int.from_bytes(os.urandom(8), "little")]) | |
| return _state["rng"] | |
| _orig_get, _orig_apply, _orig_call = Proc._get_vlm_inputs, Proc._apply_vlm_processing, Proc.__call__ | |
| def _get_vlm_inputs(self, image_keys, images, masks, image_transform, language): | |
| if getattr(self, "training", False): | |
| self._hb_views = len(image_keys) | |
| try: | |
| return _orig_get(self, image_keys, images, masks, self.eval_image_transform, language) | |
| finally: | |
| self._hb_views = None | |
| return _orig_get(self, image_keys, images, masks, image_transform, language) | |
| def _apply_vlm_processing(self, images, language): | |
| views = getattr(self, "_hb_views", None) | |
| if views and isinstance(images, torch.Tensor): | |
| shape = images.shape | |
| x = images.reshape(-1, views, *shape[1:]).float().div(255.0) | |
| x, p = A.augment(x, _rng()) | |
| images = (x * 255.0 + 0.5).clamp(0, 255).to(torch.uint8).reshape(shape) | |
| _state["count"] += 1 | |
| if LOG and _state["count"] in (1, 50): | |
| with open(f"{LOG}.{os.getpid()}", "a") as f: | |
| f.write(json.dumps({"count": _state["count"], "views": views, "hw": list(shape[-2:]), | |
| "boost": p["boost"], "version": A.VERSION}) + "\n") | |
| return _orig_apply(self, images, language) | |
| def _call(self, messages): | |
| if getattr(self, "training", False) and BODY_KEYS: | |
| states = messages[0]["content"].states | |
| for key in BODY_KEYS: | |
| if key in states: | |
| states[key] = A.perturb_joints(states[key], _rng()) | |
| return _orig_call(self, messages) | |
| Proc._get_vlm_inputs = _get_vlm_inputs | |
| Proc._apply_vlm_processing = _apply_vlm_processing | |
| Proc.__call__ = _call | |
| if os.environ.get("HB_PATCH_ONLY") != "1": | |
| entry = Path(os.environ["GROOT_SRC"]) / "gr00t/experiment/launch_finetune.py" | |
| sys.argv = [str(entry)] + sys.argv[1:] | |
| try: | |
| runpy.run_path(str(entry), run_name="__main__") | |
| finally: # batch probe: report this rank's peak reserved memory (groot_chain.py compares it with MAX_FRAC) | |
| _peak = os.environ.get("HB_PEAK_FILE") | |
| if _peak and torch.cuda.is_available(): | |
| try: | |
| _dev = torch.cuda.current_device() | |
| with open(f"{_peak}-rank{os.environ.get('RANK', '0')}.json", "w") as _f: | |
| json.dump({"rank": int(os.environ.get("RANK", "0")), | |
| "peak_reserved_gb": torch.cuda.max_memory_reserved(_dev) / 1e9, | |
| "total_gb": torch.cuda.get_device_properties(_dev).total_memory / 1e9}, _f) | |
| except Exception: # noqa: BLE001 - never mask the training result | |
| pass | |