| import yaml |
| import os |
|
|
|
|
| class SamplingConfig: |
| """Sampling configuration for generation.""" |
| def __init__(self, **kwargs): |
| for k, v in kwargs.items(): |
| setattr(self, k, v) |
|
|
| def __repr__(self): |
| fields = {k: v for k, v in vars(self).items() if not k.startswith("_")} |
| for k in self.__class__.__annotations__: |
| if k not in fields: |
| fields[k] = getattr(self, k, None) |
| items = ", ".join(f"{k}={v!r}" for k, v in fields.items()) |
| return f"SamplingConfig({items})" |
|
|
| sampling_method: str = "ode" |
| num_sampling_steps: list = [50] |
| cfgs: list = [1] |
| self_cond_cfg_scales: list = [1.0] |
| time_schedule: str = "logit_normal" |
| sde_gamma: float = 0.0 |
|
|
|
|
| |
| |
| |
| class Config: |
| |
| data_path: str = None |
| eval_data_path: str = None |
| max_length: int = 128 |
| max_input_length: int = None |
| pad_token: str = "pad" |
|
|
| |
| tokenizer_name: str = None |
|
|
| |
| encoder_model_name: str = "t5-small" |
| encoder_checkpoint: str = None |
| latent_mean: float = 0.0 |
| latent_std: float = 1.0 |
|
|
| |
| model: str = "ELF-B" |
| bottleneck_dim: int = 128 |
| num_time_tokens: int = 4 |
| num_self_cond_cfg_tokens: int = 4 |
| num_model_mode_tokens: int = 4 |
| attn_dropout: float = 0.0 |
| proj_dropout: float = 0.0 |
|
|
| |
| denoiser_p_mean: float = 0.8 |
| denoiser_p_std: float = 0.8 |
| denoiser_noise_scale: float = 1.0 |
| t_eps: float = 5e-2 |
| time_schedule: str = "logit_normal" |
|
|
| |
| decoder_prob: float = 0.5 |
| decoder_noise_scale: float = 1.0 |
| decoder_p_mean: float = 0.8 |
| decoder_p_std: float = 0.8 |
|
|
| |
| label_drop_prob: float = 0.0 |
| self_cond_prob: float = 0.5 |
| self_cond_cfg_min: float = 0.5 |
| self_cond_cfg_max: float = 5.0 |
|
|
| |
| epochs: int = 200 |
| warmup_epochs: float = None |
| warmup_steps: int = 5000 |
| batch_size: int = None |
| global_batch_size: int = 512 |
| lr: float = None |
| blr: float = 5e-5 |
| min_lr: float = 0.0 |
| lr_schedule: str = "constant" |
| weight_decay: float = 0.0 |
| optimizer: str = "muon" |
| adam_b1: float = 0.9 |
| adam_b2: float = 0.95 |
| grad_accum_steps: int = 1 |
|
|
| |
| ema_decay1: float = 0.9999 |
|
|
| |
| sampling_configs_path: str = None |
| |
| sampling_configs: list = [SamplingConfig()] |
| num_samples: int = 100 |
|
|
| |
| online_eval: bool = True |
| eval_ppl_model: str = "gpt2-large" |
| eval_ppl_batch_size: int = 64 |
| eval_ppl_max_length: int = 1024 |
|
|
| |
| log_freq: int = 100 |
| eval_freq: int = 10 |
| save_freq: float = 100 |
|
|
| |
| output_dir: str = "./output_dir" |
| hf_repo_id: str = None |
| resume: str = None |
|
|
| |
| use_wandb: bool = False |
| wandb_project: str = "ELF" |
| wandb_entity: str = None |
| wandb_run_name: str = None |
| wandb_tag: str = None |
| wandb_resume: str = "allow" |
|
|
| |
| seed: int = 0 |
| num_workers: int = 0 |
|
|
|
|
| def load_config_from_yaml(path: str) -> Config: |
| """Load a YAML config and override defaults in Config.""" |
| config = Config() |
| if not path or not os.path.isfile(path): |
| return config |
|
|
| with open(path, "r") as f: |
| cfg_dict = yaml.safe_load(f) or {} |
|
|
| for key, value in cfg_dict.items(): |
| if key == "sampling_configs": |
| continue |
| if hasattr(config, key): |
| setattr(config, key, value) |
|
|
| if config.sampling_configs_path: |
| config.sampling_configs = load_sampling_configs(config.sampling_configs_path) |
|
|
| return config |
|
|
|
|
| def apply_config_overrides(config: Config, overrides: list) -> Config: |
| """Apply command-line config overrides to a Config object. |
| |
| Args: |
| config: Config object to modify |
| overrides: List of strings in format "field_name=value" |
| |
| Returns: |
| Modified config object |
| """ |
| if not overrides: |
| return config |
| |
| for override in overrides: |
| if "=" not in override: |
| raise ValueError(f"Invalid override format: '{override}'. Expected 'field_name=value'") |
| |
| field_name, value_str = override.split("=", 1) |
| field_name = field_name.strip() |
| value_str = value_str.strip() |
| |
| if not hasattr(config, field_name): |
| raise ValueError(f"Config has no field named '{field_name}'") |
| |
| original_value = getattr(config, field_name) |
| original_type = type(original_value) |
|
|
| |
| if value_str.lower() == "none": |
| setattr(config, field_name, None) |
| continue |
|
|
| if original_value is None: |
| |
| annotated_type = config.__annotations__.get(field_name) |
| if annotated_type == int: |
| converted_value = int(value_str) |
| elif annotated_type == float: |
| converted_value = float(value_str) |
| elif annotated_type == bool: |
| converted_value = value_str.lower() in ("true", "1", "yes") |
| else: |
| converted_value = value_str |
| elif original_type == bool: |
| converted_value = value_str.lower() in ("true", "1", "yes") |
| elif original_type == int: |
| converted_value = int(value_str) |
| elif original_type == float: |
| converted_value = float(value_str) |
| elif original_type == str: |
| converted_value = value_str |
| else: |
| converted_value = value_str |
| |
| setattr(config, field_name, converted_value) |
|
|
| return config |
|
|
|
|
| def load_sampling_configs(sampling_configs_path: str): |
| """Return sampling configs, loading from sampling_configs_path if set.""" |
| with open(sampling_configs_path, "r") as f: |
| entries = yaml.safe_load(f) |
| return [SamplingConfig(**entry) for entry in entries] |
|
|