JohanDL's picture
Solving Sudoku by drawing it: PaTh demo
65635a9 verified
Raw History Blame Contribute Delete
2.89 kB
"""Config, device, model construction and checkpoint helpers shared by the scripts."""
import argparse
import os
import torch
import yaml
from .thinker import Thinker
from .unet import UNet
def parse_args(extra=None):
ap = argparse.ArgumentParser()
ap.add_argument("--config", default="configs/paper.yaml")
ap.add_argument("--mode", choices=["hard", "extreme"], default=None, help="overrides config mode")
ap.add_argument("--set", nargs="*", default=[], help="overrides like thinker.steps=100")
for args, kw in (extra or []):
ap.add_argument(*args, **kw)
args = ap.parse_args()
with open(args.config) as f:
cfg = yaml.safe_load(f)
for kv in args.set:
k, v = kv.split("=", 1)
d = cfg
*path, last = k.split(".")
for p in path:
d = d[p]
d[last] = yaml.safe_load(v)
if args.mode:
cfg["mode"] = args.mode
os.makedirs(cfg["run_dir"], exist_ok=True)
return args, cfg
def device():
if torch.cuda.is_available():
torch.backends.cuda.matmul.allow_tf32 = torch.backends.cudnn.allow_tf32 = True
torch.backends.cudnn.benchmark = True
return torch.device("cuda")
if torch.backends.mps.is_available():
return torch.device("mps")
return torch.device("cpu")
def autocast(dev):
"""bf16 autocast on CUDA (as in TRM); a no-op elsewhere."""
return torch.autocast(dev.type, torch.bfloat16, enabled=dev.type == "cuda")
def compile(fn, dev):
return torch.compile(fn) if dev.type == "cuda" else fn
def build_painter(cfg):
p = cfg["painter"]
return UNet(1, 1, tuple(p["channels"]), p["layers_per_block"])
def build_dm(cfg):
p = cfg["dm"]
return UNet(3, 1, tuple(p["channels"]), p["layers_per_block"])
def build_thinker(cfg, painter):
t = cfg["thinker"]
return Thinker(painter, dim=t["dim"], heads=t["heads"], layers=t["layers"], expansion=t["expansion"],
grid=t["grid"], enc_hidden=tuple(t["enc_hidden"]), H=t["H"], L=t["L"])
def load_eval_models(cfg, kind, mode, dev):
"""EMA weights in eval mode: {'dm': ...} or {'painter': ..., 'thinker': ...} for kind 'dm' / 'path'."""
def ema(model, name):
model.load_state_dict(load(ckpt_path(cfg, name), dev)["ema"])
return model.to(dev).eval()
if kind == "dm":
return {"dm": ema(build_dm(cfg), f"dm_{mode}")}
painter = ema(build_painter(cfg), "painter")
return {"painter": painter, "thinker": ema(build_thinker(cfg, painter), f"thinker_{mode}")}
def n_params(m):
return sum(p.numel() for p in m.parameters())
def ckpt_path(cfg, name):
return os.path.join(cfg["run_dir"], f"{name}.pt")
def save(path, **state):
tmp = path + ".tmp"
torch.save(state, tmp)
os.replace(tmp, path)
def load(path, dev):
return torch.load(path, map_location=dev, weights_only=False)