#!/usr/bin/env python3 """ Main dataset converter that can convert any dataset to HuggingFace format for Robometer model training. This is a generic converter that works with any dataset-specific loader. """ import os os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" # hide INFO/WARN/ERROR; only FATAL remains import multiprocessing as mp import numpy as np from collections.abc import Callable from dataclasses import dataclass, field from functools import partial from multiprocessing import Pool, cpu_count from typing import Any, Optional from pyrallis import wrap from tqdm import tqdm import datasets from datasets import Dataset # from robometer.data.dataset_types import Trajectory # not needed, just type hint from dataset_upload.helpers import ( create_hf_trajectory, create_output_directory, flatten_task_data, load_sentence_transformer_model, ) from huggingface_hub import HfApi # make sure these come after importing torch. otherwise something breaks... try: import absl.logging as absl_logging absl_logging.set_verbosity(absl_logging.ERROR) except Exception: pass try: import tensorflow as tf tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR) except Exception: pass os.environ["TOKENIZERS_PARALLELISM"] = "true" def push_hf_dataset_and_video_files_to_hub(dataset, hub_repo_id, hub_token, dataset_name, output_dir): print(f"Pushing dataset to HuggingFace Hub: {hub_repo_id}") dataset.push_to_hub( hub_repo_id, config_name=dataset_name.lower(), token=hub_token, private=False, commit_message=f"Add {dataset_name} dataset for Robometer training", ) print(f"✅ Successfully pushed dataset to: https://huggingface.co/datasets/{hub_repo_id}") api = HfApi(token=hub_token) api.upload_large_folder( folder_path=output_dir, repo_id=hub_repo_id, repo_type="dataset", num_workers=min(4, cpu_count()), ) print(f"✅ Successfully pushed video files for {dataset_name} to: https://huggingface.co/datasets/{hub_repo_id}") def get_trajectory_subdir_path(trajectory_idx: int, files_per_subdir: int = 1000) -> str: """ Generate subdirectory path for a trajectory to avoid too many files per directory. Args: trajectory_idx: Index of the trajectory files_per_subdir: Maximum files per subdirectory (default: 1000) Returns: str: Subdirectory name like 'batch_0000' """ subdir_index = trajectory_idx // files_per_subdir return f"batch_{subdir_index:04d}" # Global dataset features definition BASE_FEATURES = { "id": datasets.Value("string"), "task": datasets.Value("string"), "lang_vector": datasets.Sequence(datasets.Value("float32")), "data_source": datasets.Value("string"), "frames": None, # Will be set based on use_video parameter "is_robot": datasets.Value("bool"), "quality_label": datasets.Value("string"), # "preference_group_id": datasets.Value("string"), # "preference_rank": datasets.Value("int32"), "partial_success": datasets.Value("float32"), # in [0, 1] } @dataclass class DatasetConfig: """Config for dataset settings""" dataset_path: str = field(default="", metadata={"help": "Path to the dataset"}) dataset_name: str = field(default=None, metadata={"help": "Name of the dataset (defaults to dataset_type)"}) exclude_wrist_cam: bool = field(default=False, metadata={"help": "Exclude wrist camera views (MIT Franka only)"}) @dataclass class OutputConfig: """Config for output settings""" output_dir: str = field(default="robometer_dataset", metadata={"help": "Output directory for the dataset"}) max_trajectories: Optional[int] = field( default=None, metadata={"help": "Maximum number of trajectories to process (None for all)"} ) max_frames: int = field( default=64, metadata={"help": "Maximum number of frames per trajectory (-1 for no downsampling)"} ) use_video: bool = field(default=True, metadata={"help": "Use MP4 videos instead of individual frame images"}) shortest_edge_size: Optional[int] = field(default=240, metadata={"help": "Shortest edge size for video resizing"}) center_crop: bool = field( default=False, metadata={"help": "Center crop the video to the target size. Defaults to False, which means no cropping."}, ) fps: int = field(default=10, metadata={"help": "Frames per second for video creation"}) num_workers: int = field( default=-1, metadata={"help": "Number of parallel workers for processing (-1 for auto, 0 for sequential)"} ) @dataclass class HubConfig: """Config for HuggingFace Hub settings""" push_to_hub: bool = field(default=False, metadata={"help": "Push dataset to HuggingFace Hub"}) hub_repo_id: str = field(default=None, metadata={"help": "HuggingFace Hub repository ID"}) hub_token: str = field( default=None, metadata={"help": "HuggingFace Hub token (or set HF_TOKEN environment variable)"} ) @dataclass class GenerateConfig: """Main configuration for dataset generation""" dataset: DatasetConfig = field(default_factory=DatasetConfig) output: OutputConfig = field(default_factory=OutputConfig) hub: HubConfig = field(default_factory=HubConfig) def process_single_trajectory(args): """ Worker function to process a single trajectory. Args: args: Tuple containing (trajectory_idx, trajectory, lang_vector, hf_creator_fn, output_dir, dataset_name, max_frames, use_video, fps) Returns: Dict: Processed trajectory data or None if failed """ trajectory_idx, trajectory, lang_vector, hf_creator_fn, output_dir, dataset_name, max_frames, use_video, fps = args try: # Create output directory for this trajectory with subdirectory structure subdir_name = get_trajectory_subdir_path(trajectory_idx) full_video_path = os.path.join( output_dir, dataset_name.lower(), subdir_name, f"trajectory_{trajectory_idx:04d}.mp4" ) relative_video_path = os.path.join(dataset_name.lower(), subdir_name, f"trajectory_{trajectory_idx:04d}.mp4") os.makedirs(os.path.dirname(full_video_path), exist_ok=True) # Process trajectory (lang_vector is already computed) processed_trajectory = hf_creator_fn( traj_dict=trajectory, video_path=full_video_path, lang_vector=lang_vector, # Pre-computed language vector max_frames=max_frames, dataset_name=dataset_name, use_video=use_video, fps=fps, ) if processed_trajectory is None: return None # Replace the full path with relative path in the processed trajectory if processed_trajectory and "frames" in processed_trajectory: processed_trajectory["frames"] = relative_video_path return processed_trajectory except Exception as e: print(f"❌ Error processing trajectory {trajectory_idx}: {e}") return None def convert_dataset_to_hf_format( trajectories: list[dict], hf_creator_fn: Callable[[dict, str, str, int, Any, int, str], Any], output_dir: str = "robometer_dataset", dataset_name: str = "", max_trajectories: int | None = None, max_frames: int = -1, use_video: bool = True, fps: int = 10, num_workers: int = -1, push_to_hub: bool = False, hub_repo_id: str | None = None, hub_token: str | None = None, ) -> Dataset: """Convert a list of trajectories to HuggingFace format.""" print(f"Converting {dataset_name} dataset to HuggingFace format...") # Create output directory create_output_directory(output_dir) # Validate input if not trajectories: raise ValueError(f"No trajectories provided for {dataset_name} dataset.") print(f"Processing {len(trajectories)} trajectories") # Limit trajectories if specified if max_trajectories != -1: trajectories = trajectories[:max_trajectories] # Determine number of workers if num_workers == -1: num_workers = min(cpu_count(), len(trajectories)) elif num_workers == 0: num_workers = 1 # Sequential processing print(f"Using {num_workers} worker(s) for parallel processing") # Pre-compute language embeddings to avoid loading sentence transformer in each worker print("Pre-computing language embeddings...") lang_model = load_sentence_transformer_model() lang_vectors = [] unique_tasks = {} # Cache for identical task descriptions for trajectory in tqdm(trajectories, desc="Computing language embeddings"): task_description = trajectory["task"] # Use cache to avoid recomputing identical task descriptions if task_description not in unique_tasks: unique_tasks[task_description] = lang_model.encode(task_description) lang_vectors.append(unique_tasks[task_description]) print(f"Computed embeddings for {len(unique_tasks)} unique task descriptions") # Process trajectories all_entries = [] if num_workers == 1: # Sequential processing (using pre-computed embeddings) for trajectory_idx, (trajectory, lang_vector) in enumerate( tqdm(zip(trajectories, lang_vectors, strict=False), desc="Processing trajectories") ): # Create output directory for this trajectory with subdirectory structure subdir_name = get_trajectory_subdir_path(trajectory_idx) trajectory_dir = os.path.join( output_dir, dataset_name.lower(), subdir_name, f"trajectory_{trajectory_idx:04d}.mp4" ) os.makedirs(os.path.dirname(trajectory_dir), exist_ok=True) processed_trajectory = hf_creator_fn( traj_dict=trajectory, video_path=trajectory_dir, lang_vector=lang_vector, # Pre-computed language vector max_frames=max_frames, dataset_name=dataset_name, use_video=use_video, fps=fps, ) if processed_trajectory is None: continue all_entries.append(processed_trajectory) else: # Parallel processing all_entries = [] # ensure defined if Pool raises before we filter results print(f"Preparing {len(trajectories)} trajectories for parallel processing...") # Prepare arguments for worker processes worker_args = [] for trajectory_idx, (trajectory, lang_vector) in enumerate(zip(trajectories, lang_vectors, strict=False)): args = ( trajectory_idx, trajectory, lang_vector, # Pre-computed language vector hf_creator_fn, output_dir, dataset_name, max_frames, use_video, fps, ) worker_args.append(args) # Use spawn to avoid CUDA context issues from forking after TF import try: mp.set_start_method("spawn", force=True) except RuntimeError: pass # Process trajectories in parallel with Pool(processes=num_workers) as pool: results = list( tqdm( pool.imap_unordered(process_single_trajectory, worker_args), total=len(worker_args), desc="Processing trajectories", ) ) # Filter out failed trajectories (None results) all_entries = [result for result in results if result is not None] if len(all_entries) < len(trajectories): failed_count = len(trajectories) - len(all_entries) print(f"⚠️ {failed_count} trajectories failed to process and were skipped") # Create HuggingFace dataset with proper features print(f"Creating HuggingFace dataset with {len(all_entries)} entries...") # Convert list of entries to dictionary format for from_dict() data_dict = { "id": [entry["id"] for entry in all_entries], "task": [entry["task"] for entry in all_entries], "lang_vector": [entry["lang_vector"] for entry in all_entries], "data_source": [entry["data_source"] for entry in all_entries], "frames": [entry["frames"] for entry in all_entries], "is_robot": [entry["is_robot"] for entry in all_entries], "quality_label": [entry.get("quality_label") for entry in all_entries], "partial_success": [entry.get("partial_success") for entry in all_entries], # "preference_group_id": [entry.get("preference_group_id") for entry in all_entries], # "preference_rank": [entry.get("preference_rank") for entry in all_entries], } # Set frames feature based on video mode features_dict = BASE_FEATURES.copy() if use_video: features_dict["frames"] = datasets.Value("string") # Video file paths as strings else: features_dict["frames"] = datasets.Sequence(datasets.Image()) features = datasets.Features(features_dict) dataset = Dataset.from_dict(data_dict, features=features) print(f"{dataset_name} HuggingFace dataset created successfully!") print(f"Total entries: {len(all_entries)}") # Push to HuggingFace Hub if requested if push_to_hub and hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {hub_repo_id}") try: # Push the dataset to the hub with dataset name as config name dataset.push_to_hub( hub_repo_id, config_name=dataset_name.lower(), # Use dataset name as config name token=hub_token, private=False, commit_message=f"Add {dataset_name} dataset for Robometer training", ) print(f"✅ Successfully pushed dataset to: https://huggingface.co/datasets/{hub_repo_id}") print(f"📁 Dataset available as config: {dataset_name.lower()}") # Also push the video files folder to the hub print("\nPushing video files to HuggingFace Hub...") from huggingface_hub import HfApi api = HfApi(token=hub_token) # Upload the entire output directory (which contains all the video files) api.upload_large_folder( folder_path=output_dir, repo_id=hub_repo_id, repo_type="dataset", # commit_message=f"Add video files for {dataset_name} dataset" ) print(f"✅ Successfully pushed video files to: https://huggingface.co/datasets/{hub_repo_id}") except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push to hub") elif push_to_hub and not hub_repo_id: print("❌ push_to_hub=True but no hub_repo_id provided") else: # Only save locally if not pushing to hub (to avoid redundant Arrow files) dataset_path = os.path.join(output_dir, dataset_name.lower()) dataset.save_to_disk(dataset_path) print(f"Dataset saved locally to: {dataset_path}") return dataset @wrap() def main(cfg: GenerateConfig): """Main function to convert any dataset to HuggingFace format.""" # Get hub token from environment if not provided if cfg.hub.hub_token is None: cfg.hub.hub_token = os.getenv("HF_TOKEN") # Only require HF_USERNAME if pushing to hub if cfg.hub.push_to_hub: username = os.getenv("HF_USERNAME") if not username: raise ValueError( "HF_USERNAME is not set. Please export it to push to the Hub, or set hub.push_to_hub=false." ) if cfg.hub.hub_repo_id: cfg.hub.hub_repo_id = username + "/" + cfg.hub.hub_repo_id # Import the appropriate dataset loader and trajectory creator if "libero" in cfg.dataset.dataset_name: from dataset_upload.dataset_loaders.libero_loader import load_libero_dataset # Load the trajectories using the loader task_data = load_libero_dataset(cfg.dataset.dataset_path) trajectories = flatten_task_data(task_data) elif "agibotworld" in (cfg.dataset.dataset_name or "").lower(): # Stream + convert directly inside the AgiBotWorld loader from dataset_upload.dataset_loaders.agibotworld_loader import ( convert_agibotworld_streaming_to_hf, ) dataset = convert_agibotworld_streaming_to_hf( dataset_name=cfg.dataset.dataset_path, output_dir=cfg.output.output_dir, dataset_label=cfg.dataset.dataset_name or "agibotworld", max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: # Push the arrow table dataset.push_to_hub( cfg.hub.hub_repo_id, config_name=(cfg.dataset.dataset_name or "agibotworld").lower(), token=cfg.hub.hub_token, private=False, commit_message=f"Add {cfg.dataset.dataset_name} dataset for Robometer training", ) print(f"✅ Successfully pushed dataset to: https://huggingface.co/datasets/{cfg.hub.hub_repo_id}") # Push the large video folder(s) print("\nPushing video files to HuggingFace Hub...") from huggingface_hub import HfApi api = HfApi(token=cfg.hub.hub_token) api.upload_large_folder( folder_path=cfg.output.output_dir, repo_id=cfg.hub.hub_repo_id, repo_type="dataset", ) print(f"✅ Successfully pushed video files to: https://huggingface.co/datasets/{cfg.hub.hub_repo_id}") except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push videos and/or metadata to hub") else: dataset_path = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name or "agibotworld").lower()) dataset.save_to_disk(dataset_path) print(f"Dataset saved locally to: {dataset_path}") print("Dataset conversion complete!") return elif "egodex" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.egodex_loader import load_egodex_dataset # Load the trajectories using the loader with max_trajectories limit print(f"Loading EgoDex dataset from: {cfg.dataset.dataset_path}") task_data = load_egodex_dataset( cfg.dataset.dataset_path, cfg.output.max_trajectories, ) trajectories = flatten_task_data(task_data) elif cfg.dataset.dataset_name.lower().startswith("oxe_"): # Treat OXE like AgiBotWorld: create videos and HF entries directly in the loader os.environ.setdefault("CUDA_VISIBLE_DEVICES", "") from dataset_upload.dataset_loaders.oxe_loader import convert_oxe_dataset_to_hf print(f"Converting OXE dataset directly to HF from: {cfg.dataset.dataset_path}") dataset = convert_oxe_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push videos and/or metadata to hub") else: dataset_path = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path) print(f"Dataset saved locally to: {dataset_path}") print("Dataset conversion complete!") return elif "robofail" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.robofail_loader import load_robofail_dataset # Load the trajectories using the loader with max_trajectories limit print(f"Loading RoboFail dataset from: {cfg.dataset.dataset_path}") task_data = load_robofail_dataset( cfg.dataset.dataset_path, cfg.output.max_trajectories, ) trajectories = flatten_task_data(task_data) elif "metaworld" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.mw_collected_loader import load_metaworld_dataset # Load the trajectories using the loader with max_trajectories limit print(f"Loading metaworld dataset from: {cfg.dataset.dataset_path}") task_data = load_metaworld_dataset( cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, ) trajectories = flatten_task_data(task_data) elif "h2r" in cfg.dataset.dataset_name.lower(): # Stream + convert directly inside the H2R loader (OXE-style) from dataset_upload.dataset_loaders.h2r_loader import convert_h2r_dataset_to_hf print(f"Converting H2R dataset directly to HF from: {cfg.dataset.dataset_path}") dataset = convert_h2r_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push videos and/or metadata to hub") else: dataset_path = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path) print(f"Dataset saved locally to: {dataset_path}") print("Dataset conversion complete!") return elif "fino_net" in cfg.dataset.dataset_name.lower() or "fino-net" in cfg.dataset.dataset_name.lower(): # Stream + convert directly inside the FinoNet loader (H2R/OXE-style) from dataset_upload.dataset_loaders.fino_net_loader import convert_fino_net_dataset_to_hf print(f"Converting FinoNet dataset directly to HF from: {cfg.dataset.dataset_path}") dataset = convert_fino_net_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push videos and/or metadata to hub") else: dataset_path = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path) print(f"Dataset saved locally to: {dataset_path}") print("Dataset conversion complete!") return elif "epic" in cfg.dataset.dataset_name.lower(): # Stream + convert directly (H2R/OXE-style) from dataset_upload.dataset_loaders.epic_loader import convert_epic_dataset_to_hf print(f"Converting EPIC-KITCHENS dataset directly to HF from: {cfg.dataset.dataset_path}") dataset = convert_epic_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, shortest_edge_size=cfg.output.shortest_edge_size, center_crop=cfg.output.center_crop, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push videos and/or metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "roboarena" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.roboarena_loader import load_roboarena_dataset # Load the trajectories using the loader with max_trajectories limit print(f"Loading RoboArena dataset from: {cfg.dataset.dataset_path}") task_data = load_roboarena_dataset(cfg.dataset.dataset_path) trajectories = flatten_task_data(task_data) elif "ph2d" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.ph2d_loader import load_ph2d_dataset print(f"Loading Ph2d dataset from: {cfg.dataset.dataset_path}") task_data = load_ph2d_dataset(cfg.dataset.dataset_path) trajectories = flatten_task_data(task_data) elif "galaxea" in cfg.dataset.dataset_name.lower(): # Stream + convert directly (OXE-style, multi-dataset) from dataset_upload.dataset_loaders.galaxea_loader import convert_galaxea_dataset_to_hf rlds_datasets = getattr(cfg.dataset, "rlds_datasets", []) or [] print(f"Converting Galaxea RLDS to HF from: {cfg.dataset.dataset_path} | datasets={rlds_datasets}") dataset = convert_galaxea_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: # remove the galaxea_rfm prefix from the dataset name because otherwise it won't match the video folder name # don't need to do this for OXE or others because I processed it in their loaders but forgot for this. push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "molmoact" in cfg.dataset.dataset_name.lower(): # Stream + convert directly (LeRobot parquet) from dataset_upload.dataset_loaders.molmoact_loader import convert_molmoact_dataset_to_hf print(f"Converting MolmoAct dataset directly to HF from: {cfg.dataset.dataset_path}") dataset = convert_molmoact_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, ) if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "auto_eval" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.autoeval_loader import load_autoeval_dataset print(f"Loading AutoEval dataset from: {cfg.dataset.dataset_path}") task_data = load_autoeval_dataset(cfg.dataset.dataset_path) trajectories = flatten_task_data(task_data) elif "usc_xarm_policy_ranking" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.usc_xarm_policy_ranking_loader import ( load_usc_xarm_policy_ranking_dataset, ) print(f"Loading USC xArm Policy Ranking dataset from: {cfg.dataset.dataset_path}") task_data = load_usc_xarm_policy_ranking_dataset( cfg.dataset.dataset_path, max_trajectories=cfg.output.max_trajectories, ) trajectories = flatten_task_data(task_data) elif "usc_franka_policy_ranking" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.usc_franka_policy_ranking_loader import ( load_usc_franka_policy_ranking_dataset, ) print(f"Loading USC Franka Policy Ranking dataset from: {cfg.dataset.dataset_path}") task_data = load_usc_franka_policy_ranking_dataset( cfg.dataset.dataset_path, max_trajectories=cfg.output.max_trajectories, ) trajectories = flatten_task_data(task_data) elif "utd_so101_policy_ranking" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.utd_so101_loader import ( load_utd_so101_dataset, ) print(f"Loading UTD SO101 robot dataset from: {cfg.dataset.dataset_path}") task_data = load_utd_so101_dataset( cfg.dataset.dataset_path, max_trajectories=cfg.output.max_trajectories, is_robot=True, data_source="utd_so101", ) trajectories = flatten_task_data(task_data) elif "utd_so101_human" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.utd_so101_loader import ( load_utd_so101_dataset, ) print(f"Loading UTD SO101 human dataset from: {cfg.dataset.dataset_path}") task_data = load_utd_so101_dataset( cfg.dataset.dataset_path, max_trajectories=cfg.output.max_trajectories, is_robot=False, data_source="utd_so101_human", ) trajectories = flatten_task_data(task_data) elif "soar" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.soar_loader import convert_soar_dataset_to_hf print(f"Converting SOAR RLDS (local) to HF from: {cfg.dataset.dataset_path} ") dataset = convert_soar_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "mit_franka_p-rank" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.mit_franka_prank_loader import convert_mit_franka_prank_dataset_to_hf print(f"Converting MIT-Franka-Prank dataset to HF from: {cfg.dataset.dataset_path}") dataset = convert_mit_franka_prank_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "rfm_new_mit_franka" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.new_mit_franka_loader import convert_new_mit_franka_dataset_to_hf print(f"Converting New MIT Franka dataset to HF from: {cfg.dataset.dataset_path}") dataset = convert_new_mit_franka_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, exclude_wrist_cam=cfg.dataset.exclude_wrist_cam, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "utd_so101_clean_policy_ranking" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.utd_so101_clean_policy_ranking_loader import ( convert_utd_so101_clean_policy_ranking_to_hf, ) # Determine view from dataset name if "wrist" in cfg.dataset.dataset_name.lower(): view = "wrist" elif "top" in cfg.dataset.dataset_name.lower(): view = "top" else: raise ValueError(f"Dataset name must specify view (wrist or top): {cfg.dataset.dataset_name}") print(f"Converting UTD SO101 Clean Policy Ranking ({view} view) to HF from: {cfg.dataset.dataset_path}") dataset = convert_utd_so101_clean_policy_ranking_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, view=view, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "usc_koch_human_robot_paired" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.usc_koch_human_robot_paired_loader import ( convert_usc_koch_human_robot_paired_to_hf, ) # Determine trajectory type from dataset name if "usc_koch_human_robot_paired_human" in cfg.dataset.dataset_name.lower(): trajectory_type = "human" elif "usc_koch_human_robot_paired_robot" in cfg.dataset.dataset_name.lower(): trajectory_type = "robot" else: raise ValueError( f"Dataset name must specify either 'usc_koch_human_robot_paired_human' or 'usc_koch_human_robot_paired_robot': {cfg.dataset.dataset_name}. " ) print(f"Converting USC Koch Human-Robot Paired ({trajectory_type}) to HF from: {cfg.dataset.dataset_path}") dataset = convert_usc_koch_human_robot_paired_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, trajectory_type=trajectory_type, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: updated_repo_id = cfg.hub.hub_repo_id.replace("usc_koch_human_robot_paired_", "") print(f"\nPushing dataset to HuggingFace Hub: {updated_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, updated_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(output_dir_override, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "usc_koch_p_ranking" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.usc_koch_p_ranking_loader import ( # type: ignore convert_usc_koch_p_ranking_to_hf, ) output_dir_override = os.path.join(os.path.dirname(cfg.output.output_dir), cfg.dataset.dataset_name.lower()) print(f"Converting USC Koch P-Ranking to HF from: {cfg.dataset.dataset_path}") dataset = convert_usc_koch_p_ranking_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=output_dir_override, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: updated_repo_id = cfg.hub.hub_repo_id.replace("usc_koch_p_ranking_rfm", "") print(f"\nPushing dataset to HuggingFace Hub: {updated_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, updated_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, output_dir_override ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push metadata to hub") else: dataset_path_local = os.path.join(output_dir_override, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path_local) print(f"Dataset saved locally to: {dataset_path_local}") print("Dataset conversion complete!") return elif "egocot" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.egocot_loader import load_egocot_dataset # Load the trajectories using the loader print(f"Loading EgoCoT dataset from: {cfg.dataset.dataset_path}") task_data = load_egocot_dataset( cfg.dataset.dataset_path, ) trajectories = flatten_task_data(task_data) elif "humanoid_everyday" in cfg.dataset.dataset_name.lower(): # Stream + convert directly (OXE-style) from dataset_upload.dataset_loaders.humanoid_everyday_loader import convert_humanoid_everyday_dataset_to_hf print(f"Converting Humanoid Everyday dataset directly to HF from: {cfg.dataset.dataset_path}") dataset = convert_humanoid_everyday_dataset_to_hf( dataset_path=cfg.dataset.dataset_path, dataset_name=cfg.dataset.dataset_name, output_dir=cfg.output.output_dir, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, fps=cfg.output.fps, num_workers=cfg.output.num_workers, ) # Handle pushing/saving consistently if cfg.hub.push_to_hub and cfg.hub.hub_repo_id: print(f"\nPushing dataset to HuggingFace Hub: {cfg.hub.hub_repo_id}") try: push_hf_dataset_and_video_files_to_hub( dataset, cfg.hub.hub_repo_id, cfg.hub.hub_token, cfg.dataset.dataset_name, cfg.output.output_dir ) except Exception as e: print(f"❌ Error pushing to hub: {e}") print("Dataset was created locally but failed to push videos and/or metadata to hub") else: dataset_path = os.path.join(cfg.output.output_dir, (cfg.dataset.dataset_name).lower()) dataset.save_to_disk(dataset_path) print(f"Dataset saved locally to: {dataset_path}") print("Dataset conversion complete!") return elif "motif" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.motif_loader import load_motif_dataset print(f"Loading MotIF dataset from: {cfg.dataset.dataset_path}") task_data = load_motif_dataset(cfg.dataset.dataset_path) trajectories = flatten_task_data(task_data) elif "failsafe" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.failsafe_loader import load_failsafe_dataset print(f"Loading FailSafe dataset from: {cfg.dataset.dataset_path}") task_data = load_failsafe_dataset(cfg.dataset.dataset_path) trajectories = flatten_task_data(task_data) elif "racer" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.racer_loader import load_racer_dataset print(f"Loading RACER dataset from: {cfg.dataset.dataset_path}") task_data = load_racer_dataset(cfg.dataset.dataset_path, cfg.dataset.dataset_name) trajectories = flatten_task_data(task_data) elif "hand_paired" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.hand_paired_loader import load_hand_paired_dataset print(f"Loading HAND_paired dataset from: {cfg.dataset.dataset_path}") task_data = load_hand_paired_dataset(cfg.dataset.dataset_path, cfg.dataset.dataset_name) trajectories = flatten_task_data(task_data) elif "roboreward" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.roboreward_loader import load_roboreward_dataset print(f"Loading RoboReward dataset from: {cfg.dataset.dataset_path}") task_data = load_roboreward_dataset(cfg.dataset.dataset_path, cfg.dataset.dataset_name) trajectories = flatten_task_data(task_data) elif "robofac" in cfg.dataset.dataset_name.lower(): from dataset_upload.dataset_loaders.robofac_loader import load_robofac_dataset print(f"Loading RoboFAC dataset from: {cfg.dataset.dataset_path}") task_data = load_robofac_dataset( cfg.dataset.dataset_path, max_trajectories=cfg.output.max_trajectories, ) trajectories = flatten_task_data(task_data) else: raise ValueError(f"Unknown dataset type: {cfg.dataset.dataset_name}") # Convert dataset (non-streaming datasets) convert_dataset_to_hf_format( trajectories=trajectories, hf_creator_fn=partial( create_hf_trajectory, dataset_name=cfg.dataset.dataset_name, use_video=cfg.output.use_video, fps=cfg.output.fps, shortest_edge_size=cfg.output.shortest_edge_size, center_crop=cfg.output.center_crop, hub_repo_id=cfg.hub.hub_repo_id, ), output_dir=cfg.output.output_dir, dataset_name=cfg.dataset.dataset_name, max_trajectories=cfg.output.max_trajectories, max_frames=cfg.output.max_frames, use_video=cfg.output.use_video, fps=cfg.output.fps, num_workers=cfg.output.num_workers, push_to_hub=cfg.hub.push_to_hub, hub_repo_id=cfg.hub.hub_repo_id, hub_token=cfg.hub.hub_token, ) print("Dataset conversion complete!") if __name__ == "__main__": main()