CoolFace
Modelpublic

diffusers/tools

sourceHugging Facecreativeml-openrail-mupdated 3y agoView on Hugging Face
11likes28downloads
open_pr_version.py171 linesDownload Raw Back to root
1import argparse2import json3import os4import torch5import shutil6from tempfile import TemporaryDirectory7from typing import List, Optional8from diffusers import DiffusionPipeline9 10from huggingface_hub import CommitInfo, CommitOperationAdd, Discussion, HfApi, hf_hub_download11from huggingface_hub.file_download import repo_folder_name12 13 14class AlreadyExists(Exception):15    pass16 17 18def is_index_stable_diffusion_like(config_dict):19    if "_class_name" not in config_dict:20        return False21 22    compatible_classes = [23        "AltDiffusionImg2ImgPipeline",24        "AltDiffusionPipeline",25        "CycleDiffusionPipeline",26        "StableDiffusionImageVariationPipeline",27        "StableDiffusionImg2ImgPipeline",28        "StableDiffusionInpaintPipeline",29        "StableDiffusionInpaintPipelineLegacy",30        "StableDiffusionPipeline",31        "StableDiffusionPipelineSafe",32        "StableDiffusionUpscalePipeline",33        "VersatileDiffusionDualGuidedPipeline",34        "VersatileDiffusionImageVariationPipeline",35        "VersatileDiffusionPipeline",36        "VersatileDiffusionTextToImagePipeline",37        "OnnxStableDiffusionImg2ImgPipeline",38        "OnnxStableDiffusionInpaintPipeline",39        "OnnxStableDiffusionInpaintPipelineLegacy",40        "OnnxStableDiffusionPipeline",41        "StableDiffusionOnnxPipeline",42        "FlaxStableDiffusionPipeline",43    ]44    return config_dict["_class_name"] in compatible_classes45 46 47def convert_single(model_id: str, folder: str) -> List["CommitOperationAdd"]:48    pipe = DiffusionPipeline.from_pretrained(model_id, cache_dir="/home/patrick/cache_to_delete")49 50    try:51        pipe.to(torch_dtype=torch.float16)52        pipe.save_pretrained(folder, variant="fp16")53        pipe.save_pretrained(folder, variant="fp16", safe_serialization=True)54 55        all_files = []56        def find_files_in_dir(directory):57            for root, dirs, files in os.walk(directory):58                for file in files:59                    all_files.append(os.path.join(root, file))60 61        find_files_in_dir(folder)62        files = [f for f in all_files if ".fp16." in f]63 64        operations = [CommitOperationAdd(path_in_repo='/'.join(f.split("/")[-2:]), path_or_fileobj=f) for f in files]65        return operations66    except Exception as e:67        print(e)68        return False69 70def convert_file(71    old_config: str,72    new_config: str,73):74    with open(old_config, "r") as f:75        old_dict = json.load(f)76 77    old_dict["feature_extractor"][-1] = "CLIPImageProcessor"78    # if "clip_sample" not in old_dict:79    #     print("Make scheduler DDIM compatible")80    #     old_dict["clip_sample"] = False81    # else:82    #     print("No matching config")83    #     return False84 85    with open(new_config, 'w') as f:86        json_str = json.dumps(old_dict, indent=2, sort_keys=True) + "\n"87        f.write(json_str)88 89    return "Stable Diffusion"90 91 92def previous_pr(api: "HfApi", model_id: str, pr_title: str) -> Optional["Discussion"]:93    try:94        discussions = api.get_repo_discussions(repo_id=model_id)95    except Exception:96        return None97    for discussion in discussions:98        if discussion.status == "open" and discussion.is_pull_request and discussion.title == pr_title:99            return discussion100 101 102def convert(api: "HfApi", model_id: str, force: bool = False) -> Optional["CommitInfo"]:103    pr_title = "Fix deprecated float16/fp16 variant loading through new `version` API."104 105    with TemporaryDirectory() as d:106        folder = os.path.join(d, repo_folder_name(repo_id=model_id, repo_type="models"))107        os.makedirs(folder)108        new_pr = None109        try:110            operations = None111            pr = previous_pr(api, model_id, pr_title)112            if pr is not None and not force:113                url = f"https://huggingface.co/{model_id}/discussions/{pr.num}"114                new_pr = pr115                raise AlreadyExists(f"Model {model_id} already has an open PR check out {url}")116            else:117                operations = convert_single(model_id, folder)118 119            if operations:120                contributor = model_id.split("/")[0]121                pr_description = (122                        f"Hey {contributor} ๐Ÿ‘‹, \n\n Your model repository seems to contain a [`fp16` branch](https://huggingface.co/{model_id}/tree/fp16) to load the model in float16 precision. "123                        "Loading `fp16` versions from a branch instead of the main branch is deprecated and will eventually be forbidden. "124                        "Instead, we strongly recommend to save `fp16` versions of the model under `.fp16.` version files directly on the 'main' branch as enabled through this PR."125                        f"This PR makes sure that your model repository allows the user to correctly download float16 precision model weights by adding `fp16` model weights in both safetensors and PyTorch bin format:"126                        "\n\n"127                        "```py\n"128                        f"pipe = DiffusionPipeline.from_pretrained({model_id}, torch_dtype=torch.float16, variant='fp16')"129                        "\n```"130                        "\n\n"131                        "For more information please have a look at: https://huggingface.co/docs/diffusers/using-diffusers/loading#checkpoint-variants."132                        "\nWe made sure you that you can safely merge this pull request. \n\n Best, the ๐Ÿงจ Diffusers team."133                )134                new_pr = api.create_commit(135                    repo_id=model_id,136                    operations=operations,137                    commit_message=pr_title,138                    commit_description=pr_description,139                    create_pr=True,140                )141                print(f"Pr created at {new_pr.pr_url}")142            else:143                print(f"No files to convert for {model_id}")144        finally:145            shutil.rmtree(folder)146        return new_pr147 148 149if __name__ == "__main__":150    DESCRIPTION = """151    Simple utility tool to convert automatically some weights on the hub to `safetensors` format.152    It is PyTorch exclusive for now.153    It works by downloading the weights (PT), converting them locally, and uploading them back154    as a PR on the hub.155    """156    parser = argparse.ArgumentParser(description=DESCRIPTION)157    parser.add_argument(158        "model_id",159        type=str,160        help="The name of the model on the hub to convert. E.g. `gpt2` or `facebook/wav2vec2-base-960h`",161    )162    parser.add_argument(163        "--force",164        action="store_true",165        help="Create the PR even if it already exists of if the model was already converted.",166    )167    args = parser.parse_args()168    model_id = args.model_id169    api = HfApi()170    convert(api, model_id, force=args.force)171