Ra / src /sample.py
recoilme's picture
Ra fp16 (step 212000)
b4f5f26 verified
Raw History Blame Contribute Delete
3.17 kB
#!/usr/bin/env python3
"""Сэмпл из transformer/ (или из .pt чекпойнта обучения).
python3 src/sample.py --prompt "A photograph of a red fox in fresh snow." --out fox.png
"""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
import torch
from PIL import Image
ROOT = Path(__file__).resolve().parent.parent
sys.path[:0] = [str(ROOT / "src"), str(ROOT / "vae")]
from model import DEV, UDiT # noqa: E402
from text import EttinText # noqa: E402
from ae.model import AutoEncoder # noqa: E402
from export import load_exported # noqa: E402
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--model", default=str(ROOT / "transformer"), help="папка transformer/ или .pt")
ap.add_argument("--prompt", required=True)
ap.add_argument("--out", default=str(ROOT / "tmp" / "sample.png"))
ap.add_argument("--size", type=int, default=256, help="сторона кадра, кратна 64")
ap.add_argument("--steps", type=int, default=16, help="шагов тела")
ap.add_argument("--tail-steps", type=int, default=8, help="шагов декодера (хвоста)")
ap.add_argument("--cfg", type=float, default=2.5)
ap.add_argument("--seed", type=int, default=0)
ap.add_argument("--n", type=int, default=1, help="сколько картинок подряд от --seed")
ap.add_argument("--text-len", type=int, default=192)
args = ap.parse_args()
ae = AutoEncoder.from_pretrained(str(ROOT / "vae"), device=DEV)
enc = EttinText(str(ROOT / "text_encoder"), DEV, max_len=args.text_len)
m = UDiT(ae, text_dim=enc.dim).to(DEV)
src = Path(args.model)
if src.is_dir():
step = load_exported(m, enc, ae, src, DEV).get("step")
else:
sd = torch.load(src, map_location=DEV, weights_only=False)
own = m.body.state_dict()
m.body.load_state_dict({k: v for k, v in sd["body"].items() if k in own}, strict=False)
enc.mixer.load_state_dict(sd["mixer"])
if sd.get("decoder") is not None:
ae.decoder.load_state_dict(sd["decoder"])
step = sd.get("step")
m.eval()
print(f"[model] {src}, шаг {step}", flush=True)
null_hs, null_mk = enc.slices([""], pad_to_len=args.text_len)
null_t = enc.mix(null_hs.float())
hs, mk = enc.slices([args.prompt], pad_to_len=args.text_len)
txt = enc.mix(hs.float())
out = Path(args.out)
out.parent.mkdir(parents=True, exist_ok=True)
gh = gw = args.size // 8
for i in range(args.n):
y = m.sample(txt, mk, gh, gw, steps=args.steps, tail_steps=args.tail_steps, cfg=args.cfg,
null_text=null_t, null_mask=null_mk,
generator=torch.Generator(DEV).manual_seed(args.seed + i))
im = Image.fromarray(((y[0].clamp(-1, 1) + 1) * 127.5).byte().permute(1, 2, 0).cpu().numpy())
path = out if args.n == 1 else out.with_name(f"{out.stem}_{args.seed + i}{out.suffix}")
im.save(path)
print(f"[ok] {path} {im.size[0]}x{im.size[1]}, seed {args.seed + i}", flush=True)
if __name__ == "__main__":
main()