# import os # from pathlib import Path # from PIL import Image # import onnx # import onnx_graphsurgeon as gs # import torch # from onnx import shape_inference # from packaging import version # from polygraphy.backend.onnx.loader import fold_constants # from torch.onnx import export # from transformers import CLIPVisionModelWithProjection # from transformers import CLIPVisionModelWithProjection, CLIPImageProcessor # is_torch_less_than_1_11 = version.parse(version.parse(torch.__version__).base_version) < version.parse("1.11") # is_torch_2_0_1 = version.parse(version.parse(torch.__version__).base_version) == version.parse("2.0.1") # class Optimizer: # def __init__(self, onnx_graph, verbose=False): # self.graph = gs.import_onnx(onnx_graph) # self.verbose = verbose # def info(self, prefix): # if self.verbose: # print( # f"{prefix} .. {len(self.graph.nodes)} nodes, {len(self.graph.tensors().keys())} tensors, {len(self.graph.inputs)} inputs, {len(self.graph.outputs)} outputs" # ) # def cleanup(self, return_onnx=False): # self.graph.cleanup().toposort() # if return_onnx: # return gs.export_onnx(self.graph) # def select_outputs(self, keep, names=None): # self.graph.outputs = [self.graph.outputs[o] for o in keep] # if names: # for i, name in enumerate(names): # self.graph.outputs[i].name = name # def fold_constants(self, return_onnx=False): # onnx_graph = fold_constants(gs.export_onnx(self.graph), allow_onnxruntime_shape_inference=True) # self.graph = gs.import_onnx(onnx_graph) # if return_onnx: # return onnx_graph # def infer_shapes(self, return_onnx=False): # onnx_graph = gs.export_onnx(self.graph) # if onnx_graph.ByteSize() > 4147483648: # raise TypeError("ERROR: model size exceeds supported 2GB limit") # else: # onnx_graph = shape_inference.infer_shapes(onnx_graph) # self.graph = gs.import_onnx(onnx_graph) # if return_onnx: # return onnx_graph # def optimize(onnx_graph, name, verbose): # opt = Optimizer(onnx_graph, verbose=verbose) # opt.info(name + ": original") # opt.cleanup() # opt.info(name + ": cleanup") # opt.fold_constants() # opt.info(name + ": fold constants") # # opt.infer_shapes() # # opt.info(name + ': shape inference') # onnx_opt_graph = opt.cleanup(return_onnx=True) # opt.info(name + ": finished") # return onnx_opt_graph # class CLIPVisionProj(torch.nn.Module): # def __init__(self, clip_model) -> None: # super().__init__() # self.clip_model = clip_model # def forward(self, image_embedding): # result = self.clip_model(image_embedding,return_dict = False) # return result[0] # def onnx_export( # model, # model_args: tuple, # output_path: Path, # ordered_input_names, # output_names, # dynamic_axes, # opset: int, # use_external_data_format=False, # verbose=False, # Thêm tham số verbose # ): # output_path.parent.mkdir(parents=True, exist_ok=True) # with torch.inference_mode(), torch.autocast("cuda"): # if is_torch_less_than_1_11: # export( # model, # model_args, # f=output_path.as_posix(), # input_names=ordered_input_names, # output_names=output_names, # dynamic_axes=dynamic_axes, # do_constant_folding=True, # use_external_data_format=use_external_data_format, # enable_onnx_checker=True, # opset_version=opset, # verbose=verbose, # Thêm verbose ở đây # ) # else: # export( # model, # model_args, # f=output_path.as_posix(), # input_names=ordered_input_names, # output_names=output_names, # dynamic_axes=dynamic_axes, # do_constant_folding=True, # opset_version=opset, # verbose=verbose, # Thêm verbose ở đây # ) # def convert_models( # image_path:str, # output_path:str, # opset:int=16, # ): # dtype = torch.float32 # device = 'cpu' # image = Image.open(image_path) # image_encoder_processor = CLIPImageProcessor() # image_embedding = image_encoder_processor(image, return_tensors="pt").pixel_values # clip_model= CLIPVisionModelWithProjection.from_pretrained("h94/IP-Adapter", subfolder = 'sdxl_models/image_encoder') # image_encoder = CLIPVisionProj(clip_model).to(device=device) # output_path = Path(output_path) # clip_path = output_path / "clip_vision_proj" / "model.onnx" # clip_optimize = output_path / 'clip_vision_proj' / 'optimize' / 'model.onnx' # #create folder for optimize clip # os.makedirs(output_path / 'optimize', exist_ok= True) # onnx_export(image_encoder, # model_args= (image_embedding).to(dtype = torch.float32, device = device), # output_path =clip_path, # ordered_input_names= ['image_embedding'], # output_names=["image_encoder"], # dynamic_axes={'image_embedding': {0: 'Batch_size', 1: 'channel', 2: 'height', 3:'width'}, # 'image_encoder': {0:'Batch_size', 1: 'sequence_length'} }, # opset=opset, # verbose=True, # use_external_data_format=True, # ) # clip_opt_graph = onnx.load(clip_path) # onnx.save_model( # clip_opt_graph, # clip_optimize, # save_as_external_data=True, # all_tensors_to_one_file=True, # convert_attribute=False, # location="weights.pb", # ) # if __name__ == "__main__": # convert_models(image_path= '/home/SDXL_CNextAnimeCanny_IPAdapter_ONNX/code_inference/image_condition/control_canny_edge/condition_0.jpg', # output_path='/home/new_onnx/image_encoder', # opset=18, # ) import onnx def optimize_onnx_model(clip_path, output_model_path, weight_file="weights.pb"): # Load the ONNX model từ đường dẫn clip_path clip_opt_graph = onnx.load(clip_path) # Save optimized model, với weights được lưu riêng vào weight_file onnx.save_model( clip_opt_graph, output_model_path, save_as_external_data=True, # Lưu dữ liệu tensor lớn ra ngoài all_tensors_to_one_file=True, # Gom tất cả tensor vào một file duy nhất location=weight_file, # Đường dẫn đến file lưu weights ) # Sử dụng hàm clip_path = "/home/new_onnx/image_encoder/clip_vision_proj/model.onnx" # Đường dẫn model đã convert output_model_path = "/home/new_onnx/image_encoder/optimize/model.onnx" # Đường dẫn file model bạn muốn lưu weight_file = "weights.pb" # Tên file chứa weights optimize_onnx_model(clip_path, output_model_path, weight_file)