// Requires the matching native CUDA training build and a supported Llama GGUF.
// Configure CUBLAS_WORKSPACE_CONFIG=:4096:8 before process startup.
// Supply disjoint question,answer CSVs. All output destinations must be new.
// Checking this program never loads weights, trains or downloads dependencies.
import aner.gen
import aner.llm

let packed = gen.import_nf4("models/base-f16.gguf", double_quant: true,
    max_memory_bytes: 4294967296, device: "cuda:0")
let selected = packed.qlora()
let model = selected.with_training_profile(precision: "float16",
    optimizer: "paged_adamw", nf4_kernel: "fused", page_bytes: 2097152)
// Floating full fine-tuning instead starts from gen.import_model(...,"cuda:0").
// LoRA-FA, rsLoRA and TinyLoRA can use the same explicit training profile.
print(model.training_profile())
print(model.memory_summary())

let training = gen.supervised_csv(model, "training.csv", input: "question",
    target: "answer", role: "training", context: 128)
let validation = gen.supervised_csv(model, "validation.csv", input: "question",
    target: "answer", role: "validation", context: 128)
let tuned = model.fine_tune(training, validation, steps: 2,
    micro_batch: 1, accumulation: 2, rate: 0.0002, seed: 71)
print(tuned.validation_loss())
print(tuned.training_profile())
tuned.checkpoint("checkpoint-accelerated-2")

let restored = gen.load_pretrained_checkpoint("checkpoint-accelerated-2",
    device: "cuda:0", max_memory_bytes: 4294967296)
let continued = restored.resume(training, validation, steps: 1)
// Exports merge the FP32 master state into standard deployment weights.
continued.save_model("accelerated-f32.gguf")
let deployed = llm.load("accelerated-f32.gguf", context: 128, device: "cpu")
print(deployed.generate("Explain the purpose of held-out data.",
    max_tokens: 32, temperature: 0.0, seed: 0).text())
deployed.close()
