| """ |
| Configuration for the Music Generation LLM. |
| Tuned for constrained hardware (<=8GB VRAM, <=16GB RAM). |
| """ |
| from dataclasses import dataclass, field |
| from pathlib import Path |
| import torch |
|
|
|
|
| @dataclass |
| class ModelConfig: |
| vocab_size: int = 0 |
| dim: int = 256 |
| n_layers: int = 6 |
| n_heads: int = 8 |
| n_kv_heads: int = 4 |
| max_seq_len: int = 1024 |
| hidden_dim: int = 0 |
| dropout: float = 0.1 |
| rope_theta: float = 10000.0 |
|
|
| def __post_init__(self): |
| if self.hidden_dim == 0: |
| |
| self.hidden_dim = int(2 * (4 * self.dim) / 3) |
| |
| self.hidden_dim = 64 * ((self.hidden_dim + 63) // 64) |
|
|
|
|
| @dataclass |
| class TrainConfig: |
| batch_size: int = 8 |
| grad_accum_steps: int = 4 |
| learning_rate: float = 3e-4 |
| weight_decay: float = 0.1 |
| max_epochs: int = 50 |
| warmup_steps: int = 200 |
| max_grad_norm: float = 1.0 |
| use_amp: bool = True |
| grad_checkpoint: bool = True |
| eval_interval: int = 500 |
| save_interval: int = 1000 |
| log_interval: int = 50 |
| patience: int = 10 |
| min_delta: float = 0.001 |
| num_workers: int = 2 |
| pin_memory: bool = True |
| prefetch_factor: int = 2 |
|
|
|
|
| @dataclass |
| class DataConfig: |
| dataset_name: str = "drengskapur/midi-classical-music" |
| max_seq_len: int = 1024 |
| train_split: float = 0.9 |
| val_split: float = 0.1 |
| tokenizer_params: str = "REMI" |
|
|
|
|
| @dataclass |
| class GenConfig: |
| temperature: float = 0.85 |
| top_k: int = 40 |
| top_p: float = 0.92 |
| max_tokens: int = 1024 |
| repetition_penalty: float = 1.15 |
| seed: int = 42 |
|
|
|
|
| @dataclass |
| class PathConfig: |
| base_dir: Path = field(default_factory=lambda: Path(__file__).resolve().parent.parent) |
| data_dir: Path = field(init=False) |
| checkpoint_dir: Path = field(init=False) |
| output_dir: Path = field(init=False) |
| log_dir: Path = field(init=False) |
| tokenizer_path: Path = field(init=False) |
|
|
| def __post_init__(self): |
| self.data_dir = self.base_dir / "data" |
| self.checkpoint_dir = self.base_dir / "checkpoints" |
| self.output_dir = self.base_dir / "output" |
| self.log_dir = self.base_dir / "runs" |
| self.tokenizer_path = self.data_dir / "tokenizer.json" |
| for d in [self.data_dir, self.checkpoint_dir, self.output_dir, self.log_dir]: |
| d.mkdir(parents=True, exist_ok=True) |
|
|
|
|
| def get_device() -> torch.device: |
| if torch.cuda.is_available(): |
| return torch.device("cuda") |
| return torch.device("cpu") |
|
|