Instructions to use AlexWortega/tinyvla with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use AlexWortega/tinyvla with LeRobot:
- Notebooks
- Google Colab
- Kaggle
tinyvla_b200: B200 streaming training on nvidia/physical-ai (745 samples/s e2e, 7x ViT fast path, hub episode streaming, full instructions)
51ce5b3 verified | #!/usr/bin/env python | |
| """Probe the nvidia/physical-ai collection and emit a streaming specs YAML. | |
| Walks the robotics repos, finds every LeRobot v2.x (sub)dataset that | |
| HubEpisodeStream can consume, assigns embodiment ids BY ROBOT FAMILY (not per | |
| dataset — 127 ids would defeat the embedding) and weights proportional to | |
| sqrt(frames) (plain proportional lets the two biggest GR1 tasks dominate the | |
| mixture; sqrt keeps diversity without starving the big sources). | |
| v3.0 repos (BridgeData2_LeRobot_v3, LIBERO_LeRobot_v3) are NOT emitted — they | |
| need the v3 shard path (build_shards.py); both were already in the C-scaled | |
| pretraining mixture anyway. | |
| Usage: | |
| python make_stream_specs.py --out configs/physical_ai_stream.yaml | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import math | |
| import os | |
| import urllib.request | |
| from concurrent.futures import ThreadPoolExecutor | |
| FAMILIES = [ # ordered: first match wins; ids continue after C-scaled's 0..9 | |
| ("gr1", 10), ("bimanual_panda_gripper", 11), ("bimanual_panda_hand", 12), | |
| ("single_panda_gripper", 13), ("sim_behavior_r1_pro", 14), ("unitree_g1", 15), | |
| ("g1", 15), | |
| ] | |
| ROOTS = [ | |
| ("nvidia/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim", None), # nested | |
| ("nvidia/PhysicalAI-Robotics-GR00T-Teleop-Sim", "LeRobot"), # nested under LeRobot/ | |
| ("nvidia/PhysicalAI-GR00T-Tuned-Tasks", None), # nested | |
| ("nvidia/PhysicalAI-Robotics-GR00T-Teleop-G1", None), # nested | |
| ("nvidia/GR00T-N1.7-AppleToPlate", ""), # root-level v2.1 | |
| ] | |
| def hf_json(url: str, token: str | None): | |
| req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"} if token else {}) | |
| try: | |
| return json.load(urllib.request.urlopen(req, timeout=60)) | |
| except Exception: | |
| return None | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--out", default="configs/physical_ai_stream.yaml") | |
| ap.add_argument("--hz", type=float, default=10.0) | |
| args = ap.parse_args() | |
| token = None | |
| tp = os.path.expanduser("~/.cache/huggingface/token") | |
| if os.path.exists(tp): | |
| token = open(tp).read().strip() | |
| jobs = [] # (repo_id, prefix) | |
| for repo, sub in ROOTS: | |
| if sub == "": # root-level dataset | |
| jobs.append((repo, "")) | |
| continue | |
| base = f"https://huggingface.co/api/datasets/{repo}/tree/main" + (f"/{sub}" if sub else "") | |
| tree = hf_json(base, token) or [] | |
| for e in tree: | |
| if e.get("type") == "directory": | |
| jobs.append((repo, e["path"])) | |
| def probe(job): | |
| repo, pfx = job | |
| p = f"{pfx}/" if pfx else "" | |
| info = hf_json(f"https://huggingface.co/datasets/{repo}/resolve/main/{p}meta/info.json", token) | |
| if not info or "total_frames" not in info: | |
| return None | |
| ver = str(info.get("codebase_version", "")) | |
| if not ver.startswith("v2"): | |
| return None # v3 needs the shard path, v1 untested | |
| return dict( | |
| repo_id=repo, prefix=pfx, frames=info["total_frames"], fps=info["fps"], | |
| state_dim=info["features"]["observation.state"]["shape"][0], | |
| action_dim=info["features"]["action"]["shape"][0], | |
| ncam=sum(1 for v in info["features"].values() if v.get("dtype") == "video"), | |
| ) | |
| with ThreadPoolExecutor(16) as ex: | |
| found = [r for r in ex.map(probe, jobs) if r] | |
| max_state = max(r["state_dim"] for r in found) | |
| max_action = max(r["action_dim"] for r in found) | |
| total = sum(r["frames"] for r in found) | |
| lines = [ | |
| "# Autogenerated by make_stream_specs.py — streaming mixture over the", | |
| "# LeRobot-v2.x part of the nvidia/physical-ai collection.", | |
| f"# {len(found)} datasets, {total:,} source frames.", | |
| f"# max_state_dim needed: {max_state}; max_action_dim needed: {max_action}.", | |
| "datasets:", | |
| ] | |
| for r in sorted(found, key=lambda x: (-x["frames"])): | |
| name = r["prefix"] or r["repo_id"].split("/")[-1] | |
| emb = next((i for k, i in FAMILIES if name.startswith(k) or f"/{k}" in name.lower() or k in name.lower()), 15) | |
| w = math.sqrt(r["frames"]) | |
| lines += [ | |
| f" - repo_id: {r['repo_id']}", | |
| f" prefix: \"{r['prefix']}\"", | |
| f" weight: {w:.1f} # sqrt({r['frames']:,} fr); fps={r['fps']} state={r['state_dim']} act={r['action_dim']} cams={r['ncam']}", | |
| f" embodiment_id: {emb}", | |
| f" hz: {args.hz}", | |
| ] | |
| os.makedirs(os.path.dirname(args.out) or ".", exist_ok=True) | |
| with open(args.out, "w") as f: | |
| f.write("\n".join(lines) + "\n") | |
| print(f"{len(found)} датасетов, {total:,} кадров -> {args.out}") | |
| print(f"max_state_dim={max_state} max_action_dim={max_action}") | |
| if __name__ == "__main__": | |
| main() | |