Skip to main content

apr_cli/
model_ops_commands.rs

1
2#[derive(Subcommand, Debug)]
3pub enum ModelOpsCommands {
4    /// Fine-tune model with LoRA/QLoRA (GH-244)
5    #[cfg(feature = "training")]
6    Finetune {
7        /// Input model file
8        #[arg(value_name = "FILE")]
9        file: Option<PathBuf>,
10        /// Fine-tuning method: auto, full, lora, qlora
11        #[arg(long, short = 'm', default_value = "auto")]
12        method: String,
13        /// LoRA rank (default: auto-selected)
14        #[arg(long, short = 'r')]
15        rank: Option<u32>,
16        /// Available VRAM in GB
17        #[arg(long, default_value = "16.0")]
18        vram: f64,
19        /// Plan mode (estimate only)
20        #[arg(long)]
21        plan: bool,
22        /// Training data file (JSONL format)
23        #[arg(long, short = 'd', value_name = "FILE")]
24        data: Option<PathBuf>,
25        /// Output path (adapter dir or merged model)
26        #[arg(short, long)]
27        output: Option<PathBuf>,
28        /// Adapter path for merge mode
29        #[arg(long)]
30        adapter: Option<PathBuf>,
31        /// Merge adapter into base model
32        #[arg(long)]
33        merge: bool,
34        /// Training epochs
35        #[arg(long, default_value = "3")]
36        epochs: u32,
37        /// Learning rate. Default is rank-aware: the classic 2e-4 diverges at
38        /// the high LoRA ranks auto-selected to fill VRAM (e.g. rank 256), so
39        /// when omitted the recommendation is auto-lowered (2e-4 at rank<=32
40        /// down to ~2.5e-5 at rank 256). Pass an explicit value to override.
41        #[arg(long)]
42        learning_rate: Option<f64>,
43        /// Model size for planning (e.g., "7B", "1.5B")
44        #[arg(long, value_name = "SIZE")]
45        model_size: Option<String>,
46        /// Fine-tuning task: classify (sequence classification)
47        #[arg(long)]
48        task: Option<String>,
49        /// Number of classes for classification task
50        #[arg(long, default_value = "5")]
51        num_classes: usize,
52        /// Output format for checkpoints: apr, safetensors, or both (comma-separated)
53        #[arg(long, value_name = "FORMAT", default_value = "apr,safetensors")]
54        checkpoint_format: String,
55        /// Oversample minority classes to match majority (for imbalanced datasets)
56        #[arg(long)]
57        oversample: bool,
58        /// Maximum sequence length for GPU buffer allocation (lower = less VRAM)
59        #[arg(long, value_name = "LEN")]
60        max_seq_len: Option<usize>,
61        /// Quantize frozen weights to NF4 (4-bit) for QLoRA training (~8x VRAM savings)
62        #[arg(long)]
63        quantize_nf4: bool,
64        /// GPU indices for data-parallel training (e.g., "0,1" for dual GPU)
65        #[arg(long, value_name = "INDICES")]
66        gpus: Option<String>,
67        /// GPU backend selection: auto, cuda, wgpu
68        #[arg(long, default_value = "auto")]
69        gpu_backend: String,
70        /// Distributed training role: coordinator or worker
71        #[arg(long, value_name = "ROLE")]
72        role: Option<String>,
73        /// Address to bind (coordinator) or connect to (worker)
74        #[arg(long, value_name = "ADDR")]
75        bind: Option<String>,
76        /// Coordinator address for worker nodes (e.g., "intel:9000")
77        #[arg(long, value_name = "ADDR")]
78        coordinator: Option<String>,
79        /// Expected number of workers (coordinator only)
80        #[arg(long, value_name = "N")]
81        expect_workers: Option<usize>,
82        /// Wait for VRAM availability before training (timeout in seconds, 0 = no wait)
83        #[arg(long, value_name = "SECS", default_value = "0")]
84        wait_gpu: u64,
85        /// Multi-adapter training: data:checkpoint pairs (GPU-SHARE Phase 2)
86        /// Format: --adapters data/corpus-a.jsonl:checkpoints/adapter-a
87        /// Can be specified multiple times for concurrent adapter training.
88        #[arg(long, value_name = "DATA:CHECKPOINT")]
89        adapters: Vec<String>,
90
91        /// Multi-adapter config file: TOML with [[adapter]] entries (GPU-SHARE §2.4)
92        #[arg(long, value_name = "FILE")]
93        adapters_config: Option<PathBuf>,
94
95        /// Enable experimental CUDA MPS for concurrent GPU sharing (GPU-SHARE §1.5).
96        /// WARNING: A GPU fault in any MPS client will crash ALL clients on that GPU.
97        #[arg(long)]
98        experimental_mps: bool,
99
100        /// MPS thread percentage (1-100). Controls SM allocation per process.
101        /// Only effective with --experimental-mps. Default: 50.
102        #[arg(long, value_name = "PCT", default_value = "50")]
103        gpu_share: u32,
104
105        /// PMAT-486: Enable StepProfiler for per-phase wall-clock timing
106        #[arg(long)]
107        profile: bool,
108    },
109    /// Prune model (structured/unstructured pruning) (GH-247)
110    Prune {
111        /// Input model file
112        #[arg(value_name = "FILE")]
113        file: PathBuf,
114        /// Pruning method: magnitude, structured, depth, width, wanda, sparsegpt
115        #[arg(long, short = 'm', default_value = "magnitude")]
116        method: String,
117        /// Target pruning ratio (0-1)
118        #[arg(long, default_value = "0.5")]
119        target_ratio: f32,
120        /// Sparsity level (0-1)
121        #[arg(long, default_value = "0.0")]
122        sparsity: f32,
123        /// Output file path
124        #[arg(short, long)]
125        output: Option<PathBuf>,
126        /// Layers to remove for depth pruning (e.g., "20-24")
127        #[arg(long)]
128        remove_layers: Option<String>,
129        /// Analyze mode (identify pruning opportunities)
130        #[arg(long)]
131        analyze: bool,
132        /// Plan mode (estimate only)
133        #[arg(long)]
134        plan: bool,
135        /// Calibration data file
136        #[arg(long, value_name = "FILE")]
137        calibration: Option<PathBuf>,
138    },
139    /// Knowledge distillation (teacher -> student) (GH-247, ALB-011)
140    Distill {
141        /// Teacher model file (positional, for file-based mode)
142        #[arg(value_name = "TEACHER")]
143        teacher: Option<PathBuf>,
144        /// Student model file
145        #[arg(long, value_name = "FILE")]
146        student: Option<PathBuf>,
147        /// Training data file
148        #[arg(long, short = 'd', value_name = "FILE")]
149        data: Option<PathBuf>,
150        /// Output file path
151        #[arg(short, long)]
152        output: Option<PathBuf>,
153        /// Distillation strategy: standard, progressive, ensemble
154        #[arg(long, default_value = "standard")]
155        strategy: String,
156        /// Temperature for softmax scaling
157        #[arg(long, default_value = "3.0")]
158        temperature: f64,
159        /// Alpha weight for KL vs task loss
160        #[arg(long, default_value = "0.7")]
161        alpha: f64,
162        /// Training epochs
163        #[arg(long, default_value = "3")]
164        epochs: u32,
165        /// Plan mode (estimate only)
166        #[arg(long)]
167        plan: bool,
168        /// YAML config file for two-stage distillation (ALB-011)
169        #[arg(long, value_name = "FILE")]
170        config: Option<PathBuf>,
171        /// Distillation stage: precompute, train (logit KD), or generate (text-based, GH-455)
172        #[arg(long, value_name = "STAGE")]
173        stage: Option<String>,
174        /// SPEC-DISTILL-001 Phase 3-prep (PMAT-697): teacher/student backend
175        /// selector. `fixture` (default) uses the in-memory FixtureTeacher
176        /// + FixtureStudent (CPU-only, useful for plumbing tests + CI).
177        /// `cuda` constructs CudaTrainerTeacher + CudaStudentProvider from
178        /// the on-disk teacher / student checkpoints — required for the
179        /// real F-DISTILL-SMOKE-001 falsifier on GPU hardware.
180        #[arg(long, value_name = "BACKEND", default_value = "fixture")]
181        backend: String,
182        /// SPEC-DISTILL-001 Phase 4 Stage B-2: real-corpus training data.
183        /// Path to a directory containing `.bin` token shards (u32 LE,
184        /// matching the format `apr tokenize encode-corpus` produces).
185        /// When set, the distillation pipeline reads batches from this
186        /// directory via `ShardBatchSource`. When unset (the default),
187        /// the pipeline uses `SyntheticBatchSource` (identity-mapping
188        /// smoke; see PMAT-698m / PMAT-698o).
189        ///
190        /// Phase 4 50K-step dispatch sets this to a tokenized Python
191        /// corpus directory.
192        #[arg(long, value_name = "DIR")]
193        dataset: Option<PathBuf>,
194    },
195}