Download data/dataset.py from poet70/vla-sft-code-motus: direct link, hf CLI and curl.
- Browser
- Download file 17.2 kB
-
https://huggingface.co/poet70/vla-sft-code-motus/resolve/main/data/dataset.py
- Command line
-
hf download hf://poet70/vla-sft-code-motus/data/dataset.py
-
curl -L -o dataset.py https://huggingface.co/poet70/vla-sft-code-motus/resolve/main/data/dataset.py
17.2 kB
| # Dataset Factory | |
| # Simple factory to create different types of datasets | |
| from typing import Dict, Any, List, Optional | |
| from omegaconf import OmegaConf | |
| import torch | |
| def create_dataset(config: OmegaConf, val: bool = False): | |
| """ | |
| Create dataset based on config. | |
| Args: | |
| config: Configuration object | |
| val: Whether to create validation dataset | |
| Returns: | |
| Dataset instance | |
| """ | |
| dataset_type = config.dataset.get('type', 'robotwin') # Default to robotwin | |
| if dataset_type == 'robotwin': | |
| from .robotwin2.robotwin_agilex_dataset import RobotWinTaskDataset | |
| # Get all parameters from config | |
| params = {} | |
| # Add common parameters | |
| if hasattr(config, 'common'): | |
| params.update({ | |
| 'global_downsample_rate': config.common.global_downsample_rate, | |
| 'video_action_freq_ratio': config.common.video_action_freq_ratio, | |
| 'num_video_frames': config.common.num_video_frames, | |
| 'video_size': (config.common.video_height, config.common.video_width), | |
| 'state_dim': config.common.state_dim, | |
| 'action_dim': config.common.action_dim, | |
| }) | |
| # Add dataset-specific parameters | |
| if hasattr(config.dataset, 'dataset_dir'): | |
| params['dataset_dir'] = config.dataset.dataset_dir | |
| if hasattr(config.dataset, 'data_mode'): | |
| params['data_mode'] = config.dataset.data_mode | |
| if hasattr(config.dataset, 'task_mode'): | |
| params['task_mode'] = config.dataset.task_mode | |
| if hasattr(config.dataset, 'task_name'): | |
| params['task_name'] = config.dataset.task_name | |
| if hasattr(config.dataset, 'max_episodes'): | |
| params['max_episodes'] = config.dataset.max_episodes | |
| if hasattr(config.dataset, 'image_aug'): | |
| params['image_aug'] = config.dataset.image_aug and not val # No aug for validation | |
| if hasattr(config.dataset, 'randomized_limit_per_task'): | |
| params['randomized_limit_per_task'] = config.dataset.randomized_limit_per_task | |
| # Add VLM checkpoint path | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| # Add any additional parameters from dataset.params | |
| if hasattr(config.dataset, 'params'): | |
| additional_params = OmegaConf.to_object(config.dataset.params) | |
| params.update(additional_params) | |
| # Set validation flag | |
| params['val'] = val | |
| return RobotWinTaskDataset(**params) | |
| elif dataset_type == 'ac_one': | |
| from .ac_one.ac_one_dataset import ACOneDataset | |
| # Get all parameters from config | |
| params = {} | |
| # Add common parameters | |
| if hasattr(config, 'common'): | |
| params.update({ | |
| 'global_downsample_rate': config.common.global_downsample_rate, | |
| 'video_action_freq_ratio': config.common.video_action_freq_ratio, | |
| 'num_video_frames': config.common.num_video_frames, | |
| 'video_size': (config.common.video_height, config.common.video_width), | |
| }) | |
| # Add dataset-specific parameters | |
| if hasattr(config.dataset, 'dataset_dir'): | |
| params['dataset_dir'] = config.dataset.dataset_dir | |
| if hasattr(config.dataset, 'task_mode'): | |
| params['task_mode'] = config.dataset.task_mode | |
| if hasattr(config.dataset, 'task_name'): | |
| params['task_name'] = config.dataset.task_name | |
| if hasattr(config.dataset, 'max_episodes'): | |
| params['max_episodes'] = config.dataset.max_episodes | |
| if hasattr(config.dataset, 'val_episodes'): | |
| params['val_episodes'] = config.dataset.val_episodes | |
| if hasattr(config.dataset, 'image_aug'): | |
| params['image_aug'] = config.dataset.image_aug and not val # No aug for validation | |
| # Add VLM checkpoint path | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| # Add any additional parameters from dataset.params | |
| if hasattr(config.dataset, 'params'): | |
| additional_params = OmegaConf.to_object(config.dataset.params) | |
| params.update(additional_params) | |
| # Set validation flag | |
| params['val'] = val | |
| return ACOneDataset(**params) | |
| elif dataset_type == 'latent_action': | |
| from .latent_action.latent_action_dataset import LatentActionDataset | |
| params = {} | |
| # Common parameters | |
| if hasattr(config, 'common'): | |
| params.update({ | |
| 'global_downsample_rate': config.common.global_downsample_rate, | |
| 'num_video_frames': config.common.num_video_frames, | |
| 'video_size': (config.common.video_height, config.common.video_width), | |
| }) | |
| if hasattr(config.dataset, 'dataset_dir'): | |
| dataset_dir = list(config.dataset.dataset_dir) | |
| params['dataset_dir'] = [str(p) for p in dataset_dir] | |
| if hasattr(config.dataset, 'max_episodes'): | |
| params['max_episodes'] = config.dataset.max_episodes | |
| if hasattr(config.dataset, 'image_aug'): | |
| params['image_aug'] = config.dataset.image_aug and not val | |
| # Optional VLM checkpoint path | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| # Optional additional params | |
| if hasattr(config.dataset, 'params'): | |
| additional_params = OmegaConf.to_object(config.dataset.params) | |
| params.update(additional_params) | |
| params['val'] = val | |
| return LatentActionDataset(**params) | |
| elif dataset_type == 'aloha_agilex_2': | |
| from .aloha_agilex_2.aloha_agilex2_dataset import AlohaAgilex2Dataset | |
| # Get all parameters from config | |
| params = {} | |
| # Add common parameters | |
| if hasattr(config, 'common'): | |
| params.update({ | |
| 'global_downsample_rate': config.common.global_downsample_rate, | |
| 'video_action_freq_ratio': config.common.video_action_freq_ratio, | |
| 'num_video_frames': config.common.num_video_frames, | |
| 'video_size': (config.common.video_height, config.common.video_width), | |
| }) | |
| # Add dataset-specific parameters | |
| if hasattr(config.dataset, 'dataset_dir'): | |
| params['dataset_dir'] = config.dataset.dataset_dir | |
| if hasattr(config.dataset, 'task_mode'): | |
| params['task_mode'] = config.dataset.task_mode | |
| if hasattr(config.dataset, 'task_name'): | |
| params['task_name'] = config.dataset.task_name | |
| if hasattr(config.dataset, 'max_episodes'): | |
| params['max_episodes'] = config.dataset.max_episodes | |
| if hasattr(config.dataset, 'val_episodes'): | |
| params['val_episodes'] = config.dataset.val_episodes | |
| if hasattr(config.dataset, 'image_aug'): | |
| params['image_aug'] = config.dataset.image_aug and not val # No aug for validation | |
| # Add VLM checkpoint path | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| # Add any additional parameters from dataset.params | |
| if hasattr(config.dataset, 'params'): | |
| additional_params = OmegaConf.to_object(config.dataset.params) | |
| params.update(additional_params) | |
| # Set validation flag | |
| params['val'] = val | |
| return AlohaAgilex2Dataset(**params) | |
| elif dataset_type == "manifeel_zarr": | |
| from .manifeel.manifeel_zarr_dataset import ManiFeelZarrDataset | |
| params = {} | |
| if hasattr(config, "common"): | |
| params.update({ | |
| "global_downsample_rate": config.common.global_downsample_rate, | |
| "video_action_freq_ratio": config.common.video_action_freq_ratio, | |
| "num_video_frames": config.common.num_video_frames, | |
| "video_size": (config.common.video_height, config.common.video_width), | |
| }) | |
| if hasattr(config.dataset, "dataset_dir"): | |
| params["dataset_dir"] = config.dataset.dataset_dir | |
| if hasattr(config.dataset, "max_episodes"): | |
| params["max_episodes"] = config.dataset.max_episodes | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| params["val"] = val | |
| return ManiFeelZarrDataset(**params) | |
| elif dataset_type == 'libero': | |
| from .libero_dataset import LiberoDataset | |
| params = {} | |
| if hasattr(config, 'common'): | |
| params.update({ | |
| 'global_downsample_rate': config.common.global_downsample_rate, | |
| 'video_action_freq_ratio': config.common.video_action_freq_ratio, | |
| 'num_video_frames': config.common.num_video_frames, | |
| 'video_size': (config.common.video_height, config.common.video_width), | |
| 'state_dim': config.common.state_dim, | |
| 'action_dim': config.common.action_dim, | |
| }) | |
| if hasattr(config.dataset, 'dataset_dir'): | |
| params['dataset_dir'] = config.dataset.dataset_dir | |
| elif hasattr(config.dataset, 'params') and hasattr(config.dataset.params, 'root'): | |
| params['dataset_dir'] = config.dataset.params.root | |
| if hasattr(config.dataset, 'max_episodes'): | |
| params['max_episodes'] = config.dataset.max_episodes | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| return LiberoDataset(**params) | |
| elif dataset_type == 'lerobot': | |
| from .lerobot.lerobot_dataset import LeRobotMotusDataset | |
| # Get all parameters from config | |
| params = {} | |
| # Add common parameters | |
| if hasattr(config, 'common'): | |
| params.update({ | |
| 'global_downsample_rate': config.common.global_downsample_rate, | |
| 'video_action_freq_ratio': config.common.video_action_freq_ratio, | |
| 'num_video_frames': config.common.num_video_frames, | |
| 'video_size': (config.common.video_height, config.common.video_width), | |
| }) | |
| # Add dataset-specific parameters | |
| if hasattr(config.dataset, 'dataset_dir'): | |
| params['dataset_dir'] = config.dataset.dataset_dir | |
| if hasattr(config.dataset, 'task_mode'): | |
| params['task_mode'] = config.dataset.task_mode | |
| if hasattr(config.dataset, 'task_name'): | |
| params['task_name'] = config.dataset.task_name | |
| if hasattr(config.dataset, 'max_episodes'): | |
| params['max_episodes'] = config.dataset.max_episodes | |
| if hasattr(config.dataset, 'image_aug'): | |
| params['image_aug'] = config.dataset.image_aug and not val | |
| # Add VLM checkpoint path | |
| if hasattr(config.model, 'vlm') and hasattr(config.model.vlm, 'checkpoint_path'): | |
| params['vlm_checkpoint_path'] = config.model.vlm.checkpoint_path | |
| # Add any additional parameters from dataset.params | |
| if hasattr(config.dataset, 'params'): | |
| additional_params = OmegaConf.to_object(config.dataset.params) | |
| params.update(additional_params) | |
| # Set validation flag | |
| params['val'] = val | |
| return LeRobotMotusDataset(**params) | |
| # Example: Add more dataset types here | |
| # elif dataset_type == 'bridge': | |
| # from .bridge_dataset import BridgeDataset | |
| # return BridgeDataset(**params) | |
| else: | |
| raise ValueError(f"Unknown dataset type: {dataset_type}. Available types: robotwin, aloha_agilex_1, ac_one, aloha_agilex_2, table30") | |
| def _process_vlm_inputs_batch(vlm_inputs: List[Dict[str, Any]]) -> Dict[str, torch.Tensor]: | |
| """Process and batch VLM inputs with padding.""" | |
| # Extract components | |
| input_ids_list = [vlm_input['input_ids'] for vlm_input in vlm_inputs] | |
| pixel_values_list = [vlm_input.get('pixel_values') for vlm_input in vlm_inputs] | |
| image_grid_thw_list = [vlm_input.get('image_grid_thw') for vlm_input in vlm_inputs] | |
| attention_mask_list = [vlm_input.get('attention_mask') for vlm_input in vlm_inputs] | |
| # Pad input_ids to same length (simplified like model implementation) | |
| max_seq_len = max(ids.shape[1] for ids in input_ids_list) | |
| padded_input_ids = [] | |
| padded_attention_masks = [] | |
| for ids, mask in zip(input_ids_list, attention_mask_list): | |
| if ids.shape[1] < max_seq_len: | |
| padding_size = max_seq_len - ids.shape[1] | |
| # Pad input_ids | |
| padding = torch.zeros(ids.shape[0], padding_size, dtype=ids.dtype, device=ids.device) | |
| padded_ids = torch.cat([ids, padding], dim=1) | |
| # Pad attention_mask | |
| if mask is not None: | |
| mask_padding = torch.zeros(mask.shape[0], padding_size, dtype=mask.dtype, device=mask.device) | |
| padded_mask = torch.cat([mask, mask_padding], dim=1) | |
| else: | |
| padded_mask = None | |
| else: | |
| padded_ids = ids | |
| padded_mask = mask | |
| padded_input_ids.append(padded_ids) | |
| padded_attention_masks.append(padded_mask) | |
| # Batch everything | |
| return { | |
| 'input_ids': torch.cat(padded_input_ids, dim=0), | |
| 'pixel_values': torch.cat([pv for pv in pixel_values_list if pv is not None], dim=0) if pixel_values_list and any(pv is not None for pv in pixel_values_list) else None, | |
| 'image_grid_thw': torch.cat([igt for igt in image_grid_thw_list if igt is not None], dim=0) if image_grid_thw_list and any(igt is not None for igt in image_grid_thw_list) else None, | |
| 'attention_mask': torch.cat([mask for mask in padded_attention_masks if mask is not None], dim=0) if any(mask is not None for mask in padded_attention_masks) else None, | |
| } | |
| def _process_language_embeddings_batch(language_embeddings: List[torch.Tensor], text_len: int = 512) -> torch.Tensor: | |
| """Process and batch language embeddings with padding.""" | |
| padded_embeddings = [] | |
| for emb in language_embeddings: | |
| if emb.shape[0] <= text_len: | |
| padded = torch.cat([emb, emb.new_zeros(text_len - emb.shape[0], emb.shape[1])]) | |
| else: | |
| padded = emb[:text_len] | |
| padded_embeddings.append(padded) | |
| # Stack to [B, seq_len, dim] | |
| return torch.stack(padded_embeddings, dim=0) | |
| def collate_fn(batch: List[Optional[Dict[str, Any]]]) -> Optional[Dict[str, Any]]: | |
| """ | |
| Universal collate function for all datasets. | |
| Args: | |
| batch: List of sample dictionaries (may contain None) | |
| Returns: | |
| Batched dictionary or None if all samples are None | |
| """ | |
| # Filter out None samples | |
| batch = [sample for sample in batch if sample is not None] | |
| if len(batch) == 0: | |
| return None | |
| # Stack tensors(支持无 initial_state 的样本) | |
| first_frames = torch.stack([sample['first_frame'] for sample in batch]) | |
| video_frames = torch.stack([sample['video_frames'] for sample in batch]) | |
| action_sequences = torch.stack([sample['action_sequence'] for sample in batch]) | |
| has_initial_state = all(('initial_state' in sample and sample['initial_state'] is not None) for sample in batch) | |
| initial_states = torch.stack([sample['initial_state'] for sample in batch]) if has_initial_state else None | |
| # Process VLM inputs with padding in collate_fn | |
| vlm_inputs = [sample.get('vlm_inputs') for sample in batch] | |
| processed_vlm_inputs = None | |
| if vlm_inputs and all(vlm_input is not None for vlm_input in vlm_inputs): | |
| processed_vlm_inputs = _process_vlm_inputs_batch(vlm_inputs) | |
| # Process language embeddings with padding in collate_fn | |
| language_embeddings = [sample.get('language_embedding') for sample in batch if 'language_embedding' in sample] | |
| processed_language_embeddings = None | |
| if language_embeddings and any(emb is not None for emb in language_embeddings): | |
| processed_language_embeddings = _process_language_embeddings_batch(language_embeddings) | |
| result = { | |
| 'first_frame': first_frames, # [B, C, H, W] | |
| 'video_frames': video_frames, # [B, F, C, H, W] | |
| 'action_sequence': action_sequences, # [B, F, D] | |
| 'vlm_inputs': processed_vlm_inputs, | |
| 'language_embedding': processed_language_embeddings, | |
| } | |
| if initial_states is not None: | |
| result['initial_state'] = initial_states | |
| return result# This line is no-op - we'll use sed instead | |