





'''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   =      version.parse(version.parse(torch.__version__).base_version) < version.parse('''1.11''')




def 				_lowerCAmelCase  (			lowerCamelCase_     :					Any						,    lowerCamelCase_     :					tuple						,    lowerCamelCase_     :					Path						,    lowerCamelCase_     :					Dict						,    lowerCamelCase_     :					Dict						,    lowerCamelCase_     :					Optional[Any]						,    lowerCamelCase_     :					Optional[int]						,    lowerCamelCase_     :					Union[str, Any]=False						,    ):
			output_path.parent.mkdir(parents=lowerCamelCase_						,    exist_ok=lowerCamelCase_			)
			# 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(
						    lowerCamelCase_						,    lowerCamelCase_						,    f=output_path.as_posix()						,    input_names=lowerCamelCase_						,    output_names=lowerCamelCase_						,    dynamic_axes=lowerCamelCase_						,    do_constant_folding=lowerCamelCase_						,    use_external_data_format=lowerCamelCase_						,    enable_onnx_checker=lowerCamelCase_						,    opset_version=lowerCamelCase_						,    )
			else:
						export(
						    lowerCamelCase_						,    lowerCamelCase_						,    f=output_path.as_posix()						,    input_names=lowerCamelCase_						,    output_names=lowerCamelCase_						,    dynamic_axes=lowerCamelCase_						,    do_constant_folding=lowerCamelCase_						,    opset_version=lowerCamelCase_						,    )




@torch.no_grad()
def 				_lowerCAmelCase  (			lowerCamelCase_     :					str						,    lowerCamelCase_     :					str						,    lowerCamelCase_     :					int						,    lowerCamelCase_     :					bool = False			):
			__lowercase			  =							torch.floataa if fpaa else torch.floataa
			if fpaa and torch.cuda.is_available():
						__lowercase			  =							'''cuda'''
			elif fpaa and not torch.cuda.is_available():
						raise ValueError('''`float16` model export is only supported on GPUs with CUDA'''			)
			else:
						__lowercase			  =							'''cpu'''
			__lowercase			  =							StableDiffusionPipeline.from_pretrained(lowerCamelCase_						,    torch_dtype=lowerCamelCase_			).to(lowerCamelCase_			)
			__lowercase			  =							Path(lowerCamelCase_			)

			# TEXT ENCODER
			__lowercase			  =							pipeline.text_encoder.config.max_position_embeddings
			__lowercase			  =							pipeline.text_encoder.config.hidden_size
			__lowercase			  =							pipeline.tokenizer(
			    '''A sample prompt'''						,    padding='''max_length'''						,    max_length=pipeline.tokenizer.model_max_length						,    truncation=lowerCamelCase_						,    return_tensors='''pt'''						,    )
			onnx_export(
			    pipeline.text_encoder						,    model_args=(text_input.input_ids.to(device=lowerCamelCase_						,    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=lowerCamelCase_						,    )
			del pipeline.text_encoder

			# UNET
			__lowercase			  =							pipeline.unet.config.in_channels
			__lowercase			  =							pipeline.unet.config.sample_size
			__lowercase			  =							output_path / '''unet''' / '''model.onnx'''
			onnx_export(
			    pipeline.unet						,    model_args=(
			        torch.randn(2						,    lowerCamelCase_						,    lowerCamelCase_						,    lowerCamelCase_			).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
			        torch.randn(2			).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
			        torch.randn(2						,    lowerCamelCase_						,    lowerCamelCase_			).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
			        False,
			    )						,    output_path=lowerCamelCase_						,    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=lowerCamelCase_						,    use_external_data_format=lowerCamelCase_						,    )
			__lowercase			  =							str(unet_path.absolute().as_posix()			)
			__lowercase			  =							os.path.dirname(lowerCamelCase_			)
			__lowercase			  =							onnx.load(lowerCamelCase_			)
			# clean up existing tensor files
			shutil.rmtree(lowerCamelCase_			)
			os.mkdir(lowerCamelCase_			)
			# collate external tensor files into one
			onnx.save_model(
			    lowerCamelCase_						,    lowerCamelCase_						,    save_as_external_data=lowerCamelCase_						,    all_tensors_to_one_file=lowerCamelCase_						,    location='''weights.pb'''						,    convert_attribute=lowerCamelCase_						,    )
			del pipeline.unet

			# VAE ENCODER
			__lowercase			  =							pipeline.vae
			__lowercase			  =							vae_encoder.config.in_channels
			__lowercase			  =							vae_encoder.config.sample_size
			# need to get the raw tensor output (sample) from the encoder
			__lowercase			  =							lambda lowerCamelCase_						,    lowerCamelCase_			: vae_encoder.encode(lowerCamelCase_						,    lowerCamelCase_			)[0].sample()
			onnx_export(
			    lowerCamelCase_						,    model_args=(
			        torch.randn(1						,    lowerCamelCase_						,    lowerCamelCase_						,    lowerCamelCase_			).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
			        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=lowerCamelCase_						,    )

			# VAE DECODER
			__lowercase			  =							pipeline.vae
			__lowercase			  =							vae_decoder.config.latent_channels
			__lowercase			  =							vae_decoder.config.out_channels
			# forward only through the decoder part
			__lowercase			  =							vae_encoder.decode
			onnx_export(
			    lowerCamelCase_						,    model_args=(
			        torch.randn(1						,    lowerCamelCase_						,    lowerCamelCase_						,    lowerCamelCase_			).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
			        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=lowerCamelCase_						,    )
			del pipeline.vae

			# SAFETY CHECKER
			if pipeline.safety_checker is not None:
						__lowercase			  =							pipeline.safety_checker
						__lowercase			  =							safety_checker.config.vision_config.num_channels
						__lowercase			  =							safety_checker.config.vision_config.image_size
						__lowercase			  =							safety_checker.forward_onnx
						onnx_export(
						    pipeline.safety_checker						,    model_args=(
						        torch.randn(
						            1						,    lowerCamelCase_						,    lowerCamelCase_						,    lowerCamelCase_						,    ).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
						        torch.randn(1						,    lowerCamelCase_						,    lowerCamelCase_						,    lowerCamelCase_			).to(device=lowerCamelCase_						,    dtype=lowerCamelCase_			),
						    )						,    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=lowerCamelCase_						,    )
						del pipeline.safety_checker
						__lowercase			  =							OnnxRuntimeModel.from_pretrained(output_path / '''safety_checker'''			)
						__lowercase			  =							pipeline.feature_extractor
			else:
						__lowercase			  =							None
						__lowercase			  =							None

			__lowercase			  =							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=lowerCamelCase_						,    feature_extractor=lowerCamelCase_						,    requires_safety_checker=safety_checker is not None						,    )

			onnx_pipeline.save_pretrained(lowerCamelCase_			)
			print('''ONNX pipeline saved to'''						,    lowerCamelCase_			)

			del pipeline
			del onnx_pipeline
			__lowercase			  =							OnnxStableDiffusionPipeline.from_pretrained(lowerCamelCase_						,    provider='''CPUExecutionProvider'''			)
			print('''ONNX pipeline is loadable'''			)


if __name__ == "__main__":
	_SCREAMING_SNAKE_CASE   =      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=1_4,
	    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   =      parser.parse_args()

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












'''simple docstring'''



from typing import TYPE_CHECKING

# rely on isort to merge the imports
from ...utils import OptionalDependencyNotAvailable, _LazyModule, is_torch_available


_SCREAMING_SNAKE_CASE   =      {'''configuration_focalnet''': ['''FOCALNET_PRETRAINED_CONFIG_ARCHIVE_MAP''', '''FocalNetConfig''']}


try:
	if not is_torch_available():
		raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
	pass
else:
	_SCREAMING_SNAKE_CASE   =      [
	    '''FOCALNET_PRETRAINED_MODEL_ARCHIVE_LIST''',
	    '''FocalNetForImageClassification''',
	    '''FocalNetForMaskedImageModeling''',
	    '''FocalNetBackbone''',
	    '''FocalNetModel''',
	    '''FocalNetPreTrainedModel''',
	]

if TYPE_CHECKING:
	from .configuration_focalnet import FOCALNET_PRETRAINED_CONFIG_ARCHIVE_MAP, FocalNetConfig

	try:
		if not is_torch_available():
			raise OptionalDependencyNotAvailable()
	except OptionalDependencyNotAvailable:
		pass
	else:
		from .modeling_focalnet import (
		    FOCALNET_PRETRAINED_MODEL_ARCHIVE_LIST,
		    FocalNetBackbone,
		    FocalNetForImageClassification,
		    FocalNetForMaskedImageModeling,
		    FocalNetModel,
		    FocalNetPreTrainedModel,
		)

else:
	import sys

	_SCREAMING_SNAKE_CASE   =      _LazyModule(__name__, globals()['''__file__'''], _import_structure, module_spec=__spec__)





