apr_cli/train_commands.rs
1
2/// Training pipeline subcommands (forjar-style plan/apply).
3///
4/// Thin CLI wrappers around entrenar's training plan/apply infrastructure.
5#[derive(Subcommand, Debug)]
6pub enum TrainCommands {
7 /// Generate a training plan without touching the GPU.
8 ///
9 /// Validates data quality, checks model compatibility, builds HPO search space,
10 /// estimates resource usage, and runs pre-flight checks. Outputs a serializable
11 /// plan manifest (text, JSON, or YAML).
12 ///
13 /// Analogous to `forjar plan` — shows what will happen before committing GPU time.
14 Plan {
15 /// Path to training data (JSONL). Only read by `apr finetune --task classify`.
16 #[arg(long, value_name = "FILE")]
17 data: Option<PathBuf>,
18 /// Model size: "0.5B", "9B", "7B", "13B"
19 #[arg(long, default_value = "0.5B")]
20 model_size: String,
21 /// Path to model weights directory
22 #[arg(long, value_name = "DIR")]
23 model_path: Option<PathBuf>,
24 /// Number of output classes
25 #[arg(long, default_value = "5")]
26 num_classes: usize,
27 /// Task type: pretrain (causal LM). Classification fine-tuning is
28 /// `apr finetune --task classify`, not this command.
29 #[arg(long, default_value = "pretrain")]
30 task: String,
31 /// YAML training config (for --task pretrain)
32 #[arg(long, value_name = "FILE")]
33 config: Option<PathBuf>,
34 /// Output directory for checkpoints
35 #[arg(short, long, default_value = "/tmp/training-output")]
36 output: PathBuf,
37 /// HPO strategy: tpe, grid, random, manual
38 #[arg(long, default_value = "tpe")]
39 strategy: String,
40 /// HPO budget (number of trials)
41 #[arg(long, default_value = "20")]
42 budget: usize,
43 /// Scout mode: 1 epoch per trial for fast exploration
44 #[arg(long)]
45 scout: bool,
46 /// Maximum epochs per trial
47 #[arg(long, default_value = "3")]
48 max_epochs: usize,
49 /// Manual learning rate (only used with --strategy manual)
50 #[arg(long)]
51 learning_rate: Option<f32>,
52 /// Manual LoRA rank (only used with --strategy manual)
53 #[arg(long)]
54 lora_rank: Option<usize>,
55 /// Manual batch size (only used with --strategy manual)
56 #[arg(long)]
57 batch_size: Option<usize>,
58 /// Validation data file (JSONL)
59 #[arg(long, value_name = "FILE")]
60 val_data: Option<PathBuf>,
61 /// Test data file (JSONL)
62 #[arg(long, value_name = "FILE")]
63 test_data: Option<PathBuf>,
64 /// Output format: text, json, yaml
65 #[arg(long, default_value = "text")]
66 format: String,
67 },
68
69 /// Execute a training plan (allocate GPU, run trials).
70 ///
71 /// Reads a previously generated plan (YAML/JSON) and executes it:
72 /// - Manual strategy: single training run with specified hyperparameters
73 /// - HPO strategy: multiple trials with automatic hyperparameter tuning
74 ///
75 /// Analogous to `forjar apply` — commits resources and executes the plan.
76 Apply {
77 /// Path to a saved plan file (YAML or JSON from `apr train plan`)
78 #[arg(long, value_name = "FILE")]
79 plan: Option<PathBuf>,
80
81 /// YAML training config (for --task pretrain)
82 #[arg(long, value_name = "FILE")]
83 config: Option<PathBuf>,
84
85 /// Task type: pretrain (causal LM). Classification fine-tuning is
86 /// `apr finetune --task classify`, not this command.
87 #[arg(long, default_value = "pretrain")]
88 task: String,
89
90 // ── Inline plan params (used when no --plan file is given) ─────
91 /// Path to training data (JSONL)
92 #[arg(long, value_name = "FILE")]
93 data: Option<PathBuf>,
94 /// Model size: "0.5B", "9B", "7B", "13B"
95 #[arg(long, default_value = "0.5B")]
96 model_size: String,
97 /// Path to model weights directory
98 #[arg(long, value_name = "DIR")]
99 model_path: Option<PathBuf>,
100 /// Number of output classes
101 #[arg(long, default_value = "5")]
102 num_classes: usize,
103 /// Output directory for checkpoints and leaderboard.
104 ///
105 /// When given it OVERRIDES `training.output_dir` in the YAML config.
106 /// When omitted, the config's `training.output_dir` is used (default
107 /// `./checkpoints`). The directory is created if it does not exist.
108 #[arg(short, long, value_name = "DIR")]
109 output: Option<PathBuf>,
110 /// HPO strategy: tpe, grid, random, manual
111 #[arg(long, default_value = "tpe")]
112 strategy: String,
113 /// HPO budget (number of trials)
114 #[arg(long, default_value = "20")]
115 budget: usize,
116 /// Scout mode: 1 epoch per trial
117 #[arg(long)]
118 scout: bool,
119 /// Maximum epochs per trial
120 #[arg(long, default_value = "3")]
121 max_epochs: usize,
122 /// Manual learning rate (only used with --strategy manual)
123 #[arg(long)]
124 learning_rate: Option<f32>,
125 /// Manual LoRA rank (only used with --strategy manual)
126 #[arg(long)]
127 lora_rank: Option<usize>,
128 /// Manual batch size (only used with --strategy manual)
129 #[arg(long)]
130 batch_size: Option<usize>,
131
132 // ── Distributed training params (tickets #131-#140, aprender #393) ──
133 /// Enable distributed data-parallel training
134 #[arg(long)]
135 distributed: bool,
136 /// Total number of workers (default: auto-detect GPUs)
137 #[arg(long, value_name = "N")]
138 world_size: Option<usize>,
139 /// This worker's global rank (default: 0 = coordinator)
140 #[arg(long, value_name = "N")]
141 rank: Option<usize>,
142 /// Coordinator address for distributed training (default: 0.0.0.0:9000)
143 #[arg(long, value_name = "HOST:PORT")]
144 coordinator_addr: Option<String>,
145
146 // ── Reproducibility params (R-084 C-DETERM-001) ──
147 /// Enable bitwise deterministic training (CUBLAS_WORKSPACE_CONFIG, cuDNN deterministic)
148 #[arg(long)]
149 deterministic: bool,
150 /// Random seed for reproducibility (default: from YAML or 42)
151 #[arg(long, value_name = "N")]
152 seed: Option<u64>,
153
154 // ── Profiling params (PMAT-486) ──
155 /// Enable StepProfiler for per-phase wall-clock timing (KAIZEN-047)
156 #[arg(long)]
157 profile: bool,
158 /// StepProfiler report interval (every N steps, default: 50)
159 #[arg(long, value_name = "N", default_value = "50")]
160 profile_interval: usize,
161 },
162
163 /// Watch a training run with automatic restart on crash and hang detection.
164 ///
165 /// Monitors a running or to-be-started training process:
166 /// - Detects crashes (SIGABRT, SIGSEGV, OOM) and restarts with backoff
167 /// - Detects hangs via heartbeat/training_state.json staleness
168 /// - Captures GPU state and crash diagnostics
169 /// - Auto-enables CUDA_LAUNCH_BLOCKING on async crash pattern
170 ///
171 /// Sovereign Rust replacement for train-guard.sh.
172 Watch {
173 /// YAML training config to run and watch
174 #[arg(long, value_name = "FILE")]
175 config: PathBuf,
176
177 /// Maximum number of restart attempts
178 #[arg(long, default_value = "5")]
179 max_restarts: usize,
180
181 /// Heartbeat staleness threshold in seconds
182 #[arg(long, default_value = "300")]
183 heartbeat_timeout: u64,
184
185 /// Initial backoff delay in seconds
186 #[arg(long, default_value = "30")]
187 backoff_initial: u64,
188
189 /// Maximum backoff delay in seconds
190 #[arg(long, default_value = "600")]
191 backoff_max: u64,
192 },
193
194 /// Generate hyperparameter sweep configs from a base YAML.
195 ///
196 /// Creates N training configs with varied hyperparameters using grid
197 /// or random search. Each config is a complete YAML that can be
198 /// passed to `apr train apply --task pretrain --config <file>`.
199 ///
200 /// Sovereign Rust replacement for hyperparam-sweep.py.
201 Sweep {
202 /// Base YAML training config to sweep from
203 #[arg(long, value_name = "FILE")]
204 config: PathBuf,
205
206 /// Search strategy: grid or random
207 #[arg(long, default_value = "random")]
208 strategy: String,
209
210 /// Number of configs to generate (random) or max combinations (grid)
211 #[arg(long, default_value = "10")]
212 num_configs: usize,
213
214 /// Output directory for generated configs
215 #[arg(long, default_value = "sweeps/")]
216 output_dir: PathBuf,
217
218 /// Seed for random search reproducibility
219 #[arg(long, default_value = "42")]
220 seed: u64,
221 },
222
223 /// Run successive halving HPO on sweep configs (C-HPO-001).
224 ///
225 /// Takes a directory of sweep configs (from `apr train sweep`), runs each
226 /// for `--steps-per-round` steps, kills the worst half by val_ppl, doubles
227 /// steps, and repeats for `--rounds` rounds. Reports the winner with
228 /// μTransfer-scaled LR for the target model width.
229 ///
230 /// References: Hyperband (Li et al. 2018, arXiv:1603.06560),
231 /// μTransfer (Yang et al. 2022, arXiv:2203.03466).
232 Halving {
233 /// Directory containing sweep-*.yaml configs (from `apr train sweep`)
234 #[arg(long, value_name = "DIR")]
235 sweep_dir: PathBuf,
236
237 /// Number of halving rounds (default: 3)
238 #[arg(long, default_value = "3")]
239 rounds: usize,
240
241 /// Training steps in first round (doubles each round)
242 #[arg(long, default_value = "500")]
243 steps_per_round: usize,
244
245 /// Proxy model hidden_size (for μTransfer scaling)
246 #[arg(long, default_value = "512")]
247 source_width: usize,
248
249 /// Target model hidden_size (for μTransfer scaling)
250 #[arg(long, default_value = "1024")]
251 target_width: usize,
252
253 /// Output JSON file for results
254 #[arg(long, default_value = "sweeps/hpo-results.json")]
255 output: PathBuf,
256 },
257
258 /// Archive a checkpoint into a release bundle.
259 ///
260 /// Packages model weights, config, training state, and metadata
261 /// into a self-contained directory with integrity manifest.
262 Archive {
263 /// Path to checkpoint directory
264 #[arg(value_name = "CHECKPOINT_DIR")]
265 checkpoint_dir: PathBuf,
266
267 /// Output archive directory
268 #[arg(short, long, value_name = "DIR")]
269 output: PathBuf,
270
271 /// Release version tag (e.g., "v1.0")
272 #[arg(long = "release-version")]
273 release_version: Option<String>,
274
275 /// Release notes
276 #[arg(long)]
277 notes: Option<String>,
278 },
279
280 /// Submit multi-adapter training jobs to a cluster (GPU-SHARE Phase 3).
281 ///
282 /// Reads a cluster.yaml config, places adapter jobs across nodes using
283 /// the greedy placement algorithm, and generates launch commands.
284 Submit {
285 /// Path to cluster config YAML
286 #[arg(long, value_name = "FILE")]
287 cluster: PathBuf,
288
289 /// Model checkpoint path (.apr)
290 #[arg(long, value_name = "FILE")]
291 model: PathBuf,
292
293 /// Adapter specs: DATA:CHECKPOINT pairs (one per adapter)
294 #[arg(long = "adapter", value_name = "DATA:CHECKPOINT")]
295 adapters: Vec<String>,
296
297 /// LoRA rank
298 #[arg(long, default_value = "16")]
299 rank: u32,
300
301 /// Number of training epochs
302 #[arg(long, default_value = "3")]
303 epochs: u32,
304
305 /// Estimated VRAM budget per adapter (MB)
306 #[arg(long, default_value = "6000")]
307 budget_mb: u64,
308
309 /// Dry run: show placement and commands without executing
310 #[arg(long)]
311 dry_run: bool,
312 },
313
314 /// Show cluster status: nodes, GPUs, adapter capacity (GPU-SHARE Phase 3).
315 ///
316 /// Reads a cluster.yaml config and displays node health, VRAM availability,
317 /// and adapter placement capacity.
318 ClusterStatus {
319 /// Path to cluster config YAML
320 #[arg(long, value_name = "FILE")]
321 cluster: PathBuf,
322 },
323}