Skip to content

Commit 5f826a3

Browse files
authored
Add custom vae (diffusers type) to onnx converter (huggingface#2325)
1 parent f727863 commit 5f826a3

1 file changed

Lines changed: 126 additions & 0 deletions

File tree

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Copyright 2022 The HuggingFace Team. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import argparse
16+
import os
17+
import shutil
18+
from pathlib import Path
19+
20+
import torch
21+
from torch.onnx import export
22+
23+
import onnx
24+
from diffusers import OnnxRuntimeModel, OnnxStableDiffusionPipeline, StableDiffusionPipeline, AutoencoderKL
25+
from packaging import version
26+
27+
28+
is_torch_less_than_1_11 = version.parse(version.parse(torch.__version__).base_version) < version.parse("1.11")
29+
30+
31+
def onnx_export(
32+
model,
33+
model_args: tuple,
34+
output_path: Path,
35+
ordered_input_names,
36+
output_names,
37+
dynamic_axes,
38+
opset,
39+
use_external_data_format=False,
40+
):
41+
output_path.parent.mkdir(parents=True, exist_ok=True)
42+
# PyTorch deprecated the `enable_onnx_checker` and `use_external_data_format` arguments in v1.11,
43+
# so we check the torch version for backwards compatibility
44+
if is_torch_less_than_1_11:
45+
export(
46+
model,
47+
model_args,
48+
f=output_path.as_posix(),
49+
input_names=ordered_input_names,
50+
output_names=output_names,
51+
dynamic_axes=dynamic_axes,
52+
do_constant_folding=True,
53+
use_external_data_format=use_external_data_format,
54+
enable_onnx_checker=True,
55+
opset_version=opset,
56+
)
57+
else:
58+
export(
59+
model,
60+
model_args,
61+
f=output_path.as_posix(),
62+
input_names=ordered_input_names,
63+
output_names=output_names,
64+
dynamic_axes=dynamic_axes,
65+
do_constant_folding=True,
66+
opset_version=opset,
67+
)
68+
69+
70+
@torch.no_grad()
71+
def convert_models(model_path: str, output_path: str, opset: int, fp16: bool = False):
72+
dtype = torch.float16 if fp16 else torch.float32
73+
if fp16 and torch.cuda.is_available():
74+
device = "cuda"
75+
elif fp16 and not torch.cuda.is_available():
76+
raise ValueError("`float16` model export is only supported on GPUs with CUDA")
77+
else:
78+
device = "cpu"
79+
output_path = Path(output_path)
80+
81+
# VAE DECODER
82+
vae_decoder = AutoencoderKL.from_pretrained(model_path + "/vae")
83+
vae_latent_channels = vae_decoder.config.latent_channels
84+
vae_out_channels = vae_decoder.config.out_channels
85+
# forward only through the decoder part
86+
vae_decoder.forward = vae_decoder.decode
87+
onnx_export(
88+
vae_decoder,
89+
model_args=(
90+
torch.randn(1, vae_latent_channels, 25, 25).to(device=device, dtype=dtype),
91+
False,
92+
),
93+
output_path=output_path / "vae_decoder" / "model.onnx",
94+
ordered_input_names=["latent_sample", "return_dict"],
95+
output_names=["sample"],
96+
dynamic_axes={
97+
"latent_sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
98+
},
99+
opset=opset,
100+
)
101+
del vae_decoder
102+
103+
104+
if __name__ == "__main__":
105+
parser = argparse.ArgumentParser()
106+
107+
parser.add_argument(
108+
"--model_path",
109+
type=str,
110+
required=True,
111+
help="Path to the `diffusers` checkpoint to convert (either a local directory or on the Hub).",
112+
)
113+
114+
parser.add_argument("--output_path", type=str, required=True, help="Path to the output model.")
115+
parser.add_argument(
116+
"--opset",
117+
default=14,
118+
type=int,
119+
help="The version of the ONNX operator set to use.",
120+
)
121+
parser.add_argument("--fp16", action="store_true", default=False, help="Export the models in `float16` mode")
122+
123+
args = parser.parse_args()
124+
print(args.output_path)
125+
convert_models(args.model_path, args.output_path, args.opset, args.fp16)
126+
print("SD: Done: ONNX")

0 commit comments

Comments
 (0)