#!/usr/bin/env bash
# README recipe: LoRA fine-tuning of Qwen2.5-0.5B-Instruct on alpaca-cleaned, one epoch.
# Metrics are read from the DiskLogger file the recipe writes during this run.
set -o pipefail
ROW=/var/tmp/kv-repro/014-meta-pytorch-torchtune
M=$ROW/data/Qwen2.5-0.5B-Instruct
OUT=$ROW/data/run
echo "KVERITAS_INPUT src=seed:42"
echo "KVERITAS_PHASE name=finetune"
tune run lora_finetune_single_device --config qwen2_5/0.5B_lora_single_device \
  tokenizer.path=$M/vocab.json tokenizer.merges_file=$M/merges.txt checkpointer.checkpoint_dir=$M \
  output_dir=$OUT seed=42 || exit 1
python - "$OUT" <<'PY'
import glob, os, re, sys
log = max(glob.glob(os.path.join(sys.argv[1], "logs", "log_*.txt")), key=os.path.getmtime)
rows = []
for line in open(log):
    m = re.match(r"Step (\d+) \| (.*)", line)
    if m:
        rows.append((int(m.group(1)), {k: float(v) for k, v in re.findall(r"(\w+):([0-9.eE+-]+)", m.group(2))}))
for step, r in rows:
    if step == 1 or step % 25 == 0 or step == rows[-1][0]:
        print(f"KVERITAS_METRIC name=train_loss value={r['loss']:.6g} step={step}")
tail = [r["loss"] for _, r in rows[-100:]]
tps = [r["tokens_per_second_per_gpu"] for _, r in rows[1:]]
print(f"KVERITAS_METRIC name=steps value={rows[-1][0]}")
print(f"KVERITAS_METRIC name=peak_memory_reserved_gb value={max(r['peak_memory_reserved'] for _, r in rows):.6g}")
print(f"KVERITAS_METRIC name=mean_tokens_per_second value={sum(tps)/len(tps):.6g}")
print(f"KVERITAS_CLAIM metric=first_step_loss value={rows[0][1]['loss']:.6g}")
print(f"KVERITAS_CLAIM metric=final_loss_mean_last100 value={sum(tail)/len(tail):.6g}")
PY
