File size: 3,285 Bytes
d70361b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""
Day 6 (Uday): export the best fine-tuned AdaptFormer checkpoint to
``models/adaptformer_delhi/``.

Copies a HuggingFace ``save_pretrained`` directory (from finetune runs) and
optionally writes ``best.pt`` (state_dict) for the plan deliverable name.

Usage:
    python scripts/export_adaptformer_delhi.py
    python scripts/export_adaptformer_delhi.py --src runs/day5_full/20260716_142643/best
"""
from __future__ import annotations

import argparse
import json
import shutil
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
DEFAULT_CANDIDATES = [
    ROOT / "runs" / "finetune_v3",
    ROOT / "runs" / "finetune_v2",
    ROOT / "runs" / "finetune_fix",
    ROOT / "runs" / "day5_full",
    ROOT / "runs" / "finetune_adaptformer",
]


def _find_latest_best() -> Path | None:
    found: list[Path] = []
    for cand in DEFAULT_CANDIDATES:
        if cand.name == "best" and cand.is_dir():
            found.append(cand)
            continue
        if cand.is_dir():
            found.extend([p for p in cand.glob("*/best") if p.is_dir()])
    if not found:
        return None
    return sorted(found, key=lambda p: p.stat().st_mtime, reverse=True)[0]


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--src", default="", help="path to HF best/ directory")
    parser.add_argument("--out", default="models/adaptformer_delhi")
    args = parser.parse_args()

    src = Path(args.src).resolve() if args.src else _find_latest_best()
    if src is None or not src.is_dir():
        raise SystemExit(
            "No fine-tune checkpoint found. Run Day 5 training first or pass --src."
        )

    out_root = ROOT / args.out
    best_dir = out_root / "best"
    best_dir.mkdir(parents=True, exist_ok=True)

    # Copy HF artifacts
    for name in ("config.json", "model.safetensors", "pytorch_model.bin",
                 "preprocessor_config.json", "tokenizer_config.json",
                 "special_tokens_map.json"):
        f = src / name
        if f.is_file():
            shutil.copy2(f, best_dir / name)
    # Copy any remaining files (custom code modules if present)
    for f in src.iterdir():
        if f.is_file() and not (best_dir / f.name).exists():
            shutil.copy2(f, best_dir / f.name)

    meta = {
        "source": str(src),
        "exported_to": "models/adaptformer_delhi/best",
        "load_via": "ADAPTFORMER_WEIGHTS=models/adaptformer_delhi/best",
    }

    # Optional best.pt state_dict for plan naming
    try:
        import torch
        from transformers import AutoModel
        model = AutoModel.from_pretrained(best_dir, trust_remote_code=True)
        pt_path = out_root / "best.pt"
        torch.save(model.state_dict(), pt_path)
        meta["best_pt"] = str(pt_path.relative_to(ROOT))
        print(f"Wrote {pt_path}")
    except Exception as exc:
        meta["best_pt_error"] = str(exc)
        print(f"Warning: could not write best.pt ({exc}); HF dir still exported.")

    (out_root / "export_meta.json").write_text(json.dumps(meta, indent=2), encoding="utf-8")
    print(f"Exported AdaptFormer Delhi weights -> {best_dir}")
    print("Set ADAPTFORMER_WEIGHTS=models/adaptformer_delhi/best to use in the app.")


if __name__ == "__main__":
    main()