import argparse from pathlib import Path import torch from safetensors.torch import save_file def convert(path: Path, half: bool = False, no_ema: bool = False): state_dict = torch.load(path, map_location="cpu") if "state_dict" in state_dict: state_dict = state_dict["state_dict"] to_remove = [] for k, v in state_dict.items(): if not isinstance(v, torch.Tensor): to_remove.append(k) if no_ema and "ema" in k: to_remove.append(k) for k in to_remove: del state_dict[k] if half: state_dict = {k: v.half() for k, v in state_dict.items()} output_name = path.stem if no_ema: output_name += "-pruned" if half: output_name += "-fp16" output_path = path.parent / f"{output_name}.safetensors" save_file(state_dict, output_path.as_posix()) def main(path: str, half: bool = False, no_ema: bool = False): path_ = Path(path).resolve() if not path_.exists(): raise ValueError(f"Invalid path: {path}") if path_.is_file(): to_convert = [path_] else: to_convert = list(path_.glob("*.ckpt")) for file in to_convert: if file.with_suffix(".safetensors").exists(): continue print(f"Converting... {file}") convert(file, half, no_ema) def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("path", type=str, help="Path to checkpoint file or directory.") parser.add_argument( "--half", action="store_true", help="Convert to half precision." ) parser.add_argument("--no-ema", action="store_true", help="Ignore EMA weights.") return parser.parse_args() if __name__ == "__main__": args = parse_args() main(args.path, args.half, args.no_ema)