




'''simple docstring'''





import argparse
import os
import shutil
from pathlib import Path

import onnx
import torch
from packaging import version
from torch.onnx import export

from diffusers import OnnxRuntimeModel, OnnxStableDiffusionPipeline, StableDiffusionPipeline


_SCREAMING_SNAKE_CASE							:       int						=			version.parse(version.parse(torch.__version__).base_version) < version.parse("1.11")


def 					UpperCamelCase_(     snake_case							:	Union[str, Any]							,    snake_case							:	tuple							,    snake_case							:	Path							,    snake_case							:	Union[str, Any]							,    snake_case							:	List[str]							,    snake_case							:	Optional[Any]							,    snake_case							:	Optional[Any]							,    snake_case							:	int=False							,    ):

							'''simple docstring'''






							output_path.parent.mkdir(parents=snake_case							,    exist_ok=snake_case					)
							# PyTorch deprecated the `enable_onnx_checker` and `use_external_data_format` arguments in v1.11,
							# so we check the torch version for backwards compatibility
							if is_torch_less_than_1_11:
														export(
														    snake_case							,    snake_case							,    f=output_path.as_posix()							,    input_names=snake_case							,    output_names=snake_case							,    dynamic_axes=snake_case							,    do_constant_folding=snake_case							,    use_external_data_format=snake_case							,    enable_onnx_checker=snake_case							,    opset_version=snake_case							,    )
							else:
														export(
														    snake_case							,    snake_case							,    f=output_path.as_posix()							,    input_names=snake_case							,    output_names=snake_case							,    dynamic_axes=snake_case							,    do_constant_folding=snake_case							,    opset_version=snake_case							,    )


@torch.no_grad()
def 					UpperCamelCase_(     snake_case							:	str							,    snake_case							:	str							,    snake_case							:	int							,    snake_case							:	bool = False					):

							'''simple docstring'''






							snake_case_      =				torch.floataa if fpaa else torch.floataa
							if fpaa and torch.cuda.is_available():
														snake_case_      =				"cuda"
							elif fpaa and not torch.cuda.is_available():
														raise ValueError("`float16` model export is only supported on GPUs with CUDA"					)
							else:
														snake_case_      =				"cpu"
							snake_case_      =				StableDiffusionPipeline.from_pretrained(snake_case							,    torch_dtype=snake_case					).to(snake_case					)
							snake_case_      =				Path(snake_case					)

							# TEXT ENCODER
							snake_case_      =				pipeline.text_encoder.config.max_position_embeddings
							snake_case_      =				pipeline.text_encoder.config.hidden_size
							snake_case_      =				pipeline.tokenizer(
							    "A sample prompt"							,    padding="max_length"							,    max_length=pipeline.tokenizer.model_max_length							,    truncation=snake_case							,    return_tensors="pt"							,    )
							onnx_export(
							    pipeline.text_encoder							,    model_args=(text_input.input_ids.to(device=snake_case							,    dtype=torch.intaa					))							,    output_path=output_path / "text_encoder" / "model.onnx"							,    ordered_input_names=["input_ids"]							,    output_names=["last_hidden_state", "pooler_output"]							,    dynamic_axes={
							        "input_ids": {0: "batch", 1: "sequence"},
							    }							,    opset=snake_case							,    )
							del pipeline.text_encoder

							# UNET
							snake_case_      =				pipeline.unet.config.in_channels
							snake_case_      =				pipeline.unet.config.sample_size
							snake_case_      =				output_path / "unet" / "model.onnx"
							onnx_export(
							    pipeline.unet							,    model_args=(
							        torch.randn(2							,    snake_case							,    snake_case							,    snake_case					).to(device=snake_case							,    dtype=snake_case					),
							        torch.randn(2					).to(device=snake_case							,    dtype=snake_case					),
							        torch.randn(2							,    snake_case							,    snake_case					).to(device=snake_case							,    dtype=snake_case					),
							        False,
							    )							,    output_path=snake_case							,    ordered_input_names=["sample", "timestep", "encoder_hidden_states", "return_dict"]							,    output_names=["out_sample"]							,    dynamic_axes={
							        "sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
							        "timestep": {0: "batch"},
							        "encoder_hidden_states": {0: "batch", 1: "sequence"},
							    }							,    opset=snake_case							,    use_external_data_format=snake_case							,    )
							snake_case_      =				str(unet_path.absolute().as_posix()					)
							snake_case_      =				os.path.dirname(snake_case					)
							snake_case_      =				onnx.load(snake_case					)
							# clean up existing tensor files
							shutil.rmtree(snake_case					)
							os.mkdir(snake_case					)
							# collate external tensor files into one
							onnx.save_model(
							    snake_case							,    snake_case							,    save_as_external_data=snake_case							,    all_tensors_to_one_file=snake_case							,    location="weights.pb"							,    convert_attribute=snake_case							,    )
							del pipeline.unet

							# VAE ENCODER
							snake_case_      =				pipeline.vae
							snake_case_      =				vae_encoder.config.in_channels
							snake_case_      =				vae_encoder.config.sample_size
							# need to get the raw tensor output (sample) from the encoder
							snake_case_      =				lambda snake_case							,    snake_case					: vae_encoder.encode(snake_case							,    snake_case					)[0].sample()
							onnx_export(
							    snake_case							,    model_args=(
							        torch.randn(1							,    snake_case							,    snake_case							,    snake_case					).to(device=snake_case							,    dtype=snake_case					),
							        False,
							    )							,    output_path=output_path / "vae_encoder" / "model.onnx"							,    ordered_input_names=["sample", "return_dict"]							,    output_names=["latent_sample"]							,    dynamic_axes={
							        "sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
							    }							,    opset=snake_case							,    )

							# VAE DECODER
							snake_case_      =				pipeline.vae
							snake_case_      =				vae_decoder.config.latent_channels
							snake_case_      =				vae_decoder.config.out_channels
							# forward only through the decoder part
							snake_case_      =				vae_encoder.decode
							onnx_export(
							    snake_case							,    model_args=(
							        torch.randn(1							,    snake_case							,    snake_case							,    snake_case					).to(device=snake_case							,    dtype=snake_case					),
							        False,
							    )							,    output_path=output_path / "vae_decoder" / "model.onnx"							,    ordered_input_names=["latent_sample", "return_dict"]							,    output_names=["sample"]							,    dynamic_axes={
							        "latent_sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
							    }							,    opset=snake_case							,    )
							del pipeline.vae

							# SAFETY CHECKER
							if pipeline.safety_checker is not None:
														snake_case_      =				pipeline.safety_checker
														snake_case_      =				safety_checker.config.vision_config.num_channels
														snake_case_      =				safety_checker.config.vision_config.image_size
														snake_case_      =				safety_checker.forward_onnx
														onnx_export(
														    pipeline.safety_checker							,    model_args=(
														        torch.randn(
														            1							,    snake_case							,    snake_case							,    snake_case							,    ).to(device=snake_case							,    dtype=snake_case					),
														        torch.randn(1							,    snake_case							,    snake_case							,    snake_case					).to(device=snake_case							,    dtype=snake_case					),
														    )							,    output_path=output_path / "safety_checker" / "model.onnx"							,    ordered_input_names=["clip_input", "images"]							,    output_names=["out_images", "has_nsfw_concepts"]							,    dynamic_axes={
														        "clip_input": {0: "batch", 1: "channels", 2: "height", 3: "width"},
														        "images": {0: "batch", 1: "height", 2: "width", 3: "channels"},
														    }							,    opset=snake_case							,    )
														del pipeline.safety_checker
														snake_case_      =				OnnxRuntimeModel.from_pretrained(output_path / "safety_checker"					)
														snake_case_      =				pipeline.feature_extractor
							else:
														snake_case_      =				None
														snake_case_      =				None

							snake_case_      =				OnnxStableDiffusionPipeline(
							    vae_encoder=OnnxRuntimeModel.from_pretrained(output_path / "vae_encoder"					)							,    vae_decoder=OnnxRuntimeModel.from_pretrained(output_path / "vae_decoder"					)							,    text_encoder=OnnxRuntimeModel.from_pretrained(output_path / "text_encoder"					)							,    tokenizer=pipeline.tokenizer							,    unet=OnnxRuntimeModel.from_pretrained(output_path / "unet"					)							,    scheduler=pipeline.scheduler							,    safety_checker=snake_case							,    feature_extractor=snake_case							,    requires_safety_checker=safety_checker is not None							,    )

							onnx_pipeline.save_pretrained(snake_case					)
							print("ONNX pipeline saved to"							,    snake_case					)

							del pipeline
							del onnx_pipeline
							snake_case_      =				OnnxStableDiffusionPipeline.from_pretrained(snake_case							,    provider="CPUExecutionProvider"					)
							print("ONNX pipeline is loadable"					)


if __name__ == "__main__":
		_SCREAMING_SNAKE_CASE							:       str						=			argparse.ArgumentParser()

		parser.add_argument(
		    "--model_path",
		    type=str,
		    required=True,
		    help="Path to the `diffusers` checkpoint to convert (either a local directory or on the Hub).",
		)

		parser.add_argument("--output_path", type=str, required=True, help="Path to the output model.")

		parser.add_argument(
		    "--opset",
		    default=14,
		    type=int,
		    help="The version of the ONNX operator set to use.",
		)
		parser.add_argument("--fp16", action="store_true", default=False, help="Export the models in `float16` mode")

		_SCREAMING_SNAKE_CASE							:       Optional[Any]						=			parser.parse_args()

		convert_models(args.model_path, args.output_path, args.opset, args.fpaa)










'''simple docstring'''





from ..utils import DummyObject, requires_backends




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Dict							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    List[Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    str:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Dict							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Dict:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[str]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Optional[Any]							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    str:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Optional[int]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[str]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Optional[Any]							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Union[str, Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[str]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Dict:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				List[str]							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Optional[int]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				int							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    List[str]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Any:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Optional[Any]							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Any:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    int:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Dict							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Optional[int]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    List[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				List[str]							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Dict:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Union[str, Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				int							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Dict:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Union[str, Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    int:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Any							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Tuple:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    str:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				str							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    List[str]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Union[str, Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Union[str, Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




class 			_snake_case		(     metaclass=lowercase_							):
			lowerCAmelCase_					:				Tuple							=   ["flax"]




			def __init__( self    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(self    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    int:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




			@classmethod
			def        lowerCAmelCase__    ( cls    ,							*a__    ,							**a__							)    ->    Optional[Any]:

										'''simple docstring'''




										requires_backends(cls    ,							["flax"]							)




