import type { DpoRow, SftRow } from './types.js'; /** A model class we are willing to tune. 7-14B only (the cheap-tier target). */ export interface BaseModelSpec { /** HF/registry id, e.g. "Qwen/Qwen2.5-Coder-7B-Instruct". */ id: string; /** Parameter count in billions — gated to [1, 14]. */ paramsB: number; } export type TrainStage = 'sft' | 'dpo'; export interface LoraConfig { /** Low-rank dimension. */ r: number; /** LoRA alpha scaling. */ alpha: number; /** Dropout on the LoRA path. */ dropout: number; /** Modules to adapt (attention proj by default). */ targetModules: string[]; } export interface TrainConfig { base: BaseModelSpec; stage: TrainStage; lora: LoraConfig; /** Path to the JSONL training set for this stage. */ dataPath: string; /** Output adapter directory / id. */ outputAdapter: string; /** For DPO: the SFT checkpoint to start from (the on-policy reference). */ initFromAdapter?: string; epochs: number; learningRate: number; /** Max sequence length — must fit the 7-14B context window. */ maxSeqLen: number; batchSize: number; } export interface TrainRunOptions { /** Hard gate: must be true to actually train. Default false → dry-run. */ train?: boolean; /** * GPU/endpoint detector. Injected for testability; defaults to a probe that * checks for an env-declared endpoint or `nvidia-smi`. Returns a reason * string when unavailable. */ detectGpu?: () => { available: boolean; detail: string; }; } /** The result of a (dry or real) train invocation. */ export interface TrainRunResult { /** 'plan' for a dry-run, 'trained' for a real run, 'refused' when gated out. */ status: 'plan' | 'trained' | 'refused'; /** The training plan (always emitted, even on refusal — it's the artifact). */ plan: TrainingPlan; /** Why a real run was refused (status === 'refused'). */ reason?: string; } /** A fully-resolved, serializable training plan + the command to run it. */ export interface TrainingPlan { config: TrainConfig; /** The exact CLI command a GPU host runs to execute this plan. */ command: string; /** A one-line human summary. */ summary: string; } export declare const DEFAULT_LORA: LoraConfig; /** Default GPU/endpoint probe. Pure-ish: reads env + tries nvidia-smi presence. */ export declare function defaultDetectGpu(): { available: boolean; detail: string; }; /** Validate a base model is in the tunable 7-14B band (refuse 32B). */ export declare function assertTunableSize(base: BaseModelSpec): void; /** Build a default SFT config for a base model + data path. */ export declare function sftConfig(base: BaseModelSpec, dataPath: string, outputAdapter: string): TrainConfig; /** Build a default on-policy DPO config that starts from the SFT checkpoint. */ export declare function dpoConfig(base: BaseModelSpec, dataPath: string, outputAdapter: string, initFromAdapter: string): TrainConfig; /** Render the exact command a GPU host runs (ruvllm/MicroLoRA CLI form). */ export declare function buildCommand(c: TrainConfig): string; /** Build the full plan (config + command + summary) for a stage. */ export declare function buildPlan(c: TrainConfig): TrainingPlan; /** * Run (or dry-run) a training stage. The hard gate: a real run requires BOTH * an explicit `train:true` AND a detected GPU/endpoint. Otherwise it returns * the plan (dry-run) or refuses (train requested but no GPU). */ export declare function runTraining(c: TrainConfig, opts?: TrainRunOptions): TrainRunResult; /** * Convenience: emit the full two-stage plan (SFT then on-policy DPO) for a * base model and a pair of data paths. The DPO stage starts from the SFT * adapter (the on-policy reference policy). */ export declare function twoStagePlan(base: BaseModelSpec, sftDataPath: string, dpoDataPath: string, adapterPrefix: string): { sft: TrainingPlan; dpo: TrainingPlan; }; /** * Thin runner-adapter: canonical-standard JSONL rows → the record shape * ruvllm/MicroLoRA ingests. Kept at the runner boundary so the EXPORTED files * stay in the portable standard schema (trl/axolotl/unsloth-compatible). This * is a structural pass-through today (ruvllm consumes OpenAI-chat + TRL-pref * directly); the seam exists so a future ingest-format change is local here. */ export declare function adaptSftForRunner(rows: SftRow[]): Array<{ messages: SftRow['messages']; }>; export declare function adaptDpoForRunner(rows: DpoRow[]): Array<{ prompt: DpoRow['prompt']; chosen: DpoRow['chosen']; rejected: DpoRow['rejected']; }>; //# sourceMappingURL=train.d.ts.map