diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 3a241177f2f2488fcbabec586b5585ca46da9a25..0000000000000000000000000000000000000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.jpg filter=lfs diff=lfs merge=lfs -text -*.png filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore deleted file mode 100644 index cc88cfb950a2177046fc303991cfef291c19f958..0000000000000000000000000000000000000000 --- a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -env -env_old -*.bak -*.pyc -__pycache__ -results -# excluding user settings for the GUI frontend -configs/settings.yaml diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ab84360cb0e940f6e4af2c0731e51cac0f66d19a..0000000000000000000000000000000000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Rupesh Sreeraman - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/THIRD-PARTY-LICENSES b/THIRD-PARTY-LICENSES deleted file mode 100644 index 9fb29b1d3d52582f6047a41d8f5622de43d24868..0000000000000000000000000000000000000000 --- a/THIRD-PARTY-LICENSES +++ /dev/null @@ -1,143 +0,0 @@ -stablediffusion.cpp - MIT - -OpenVINO stablediffusion engine - Apache 2 - -SD Turbo - STABILITY AI NON-COMMERCIAL RESEARCH COMMUNITY LICENSE AGREEMENT - -MIT License - -Copyright (c) 2023 leejet - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -ERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. - -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. - -Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. - -Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. - -Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - -(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and - -(b) You must cause any modified files to carry prominent notices stating that You changed the files; and - -(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - -(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. - -You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - -Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. - -Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. - -Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - -Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - -Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -STABILITY AI NON-COMMERCIAL RESEARCH COMMUNITY LICENSE AGREEMENT -Dated: November 28, 2023 - -By using or distributing any portion or element of the Models, Software, Software Products or Derivative Works, you agree to be bound by this Agreement. - -"Agreement" means this Stable Non-Commercial Research Community License Agreement. - -“AUP” means the Stability AI Acceptable Use Policy available at , as may be updated from time to time. - -"Derivative Work(s)” means (a) any derivative work of the Software Products as recognized by U.S. copyright laws and (b) any modifications to a Model, and any other model created which is based on or derived from the Model or the Model’s output. For clarity, Derivative Works do not include the output of any Model. - -“Documentation” means any specifications, manuals, documentation, and other written information provided by Stability AI related to the Software. - -"Licensee" or "you" means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity's behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering in this Agreement on their behalf. - -“Model(s)" means, collectively, Stability AI’s proprietary models and algorithms, including machine-learning models, trained model weights and other elements of the foregoing, made available under this Agreement. - -“Non-Commercial Uses” means exercising any of the rights granted herein for the purpose of research or non-commercial purposes. Non-Commercial Uses does not include any production use of the Software Products or any Derivative Works. - -"Stability AI" or "we" means Stability AI Ltd. and its affiliates. - -"Software" means Stability AI’s proprietary software made available under this Agreement. - -“Software Products” means the Models, Software and Documentation, individually or in any combination. - -1. License Rights and Redistribution. - -a. Subject to your compliance with this Agreement, the AUP (which is hereby incorporated herein by reference), and the Documentation, Stability AI grants you a non-exclusive, worldwide, non-transferable, non-sublicensable, revocable, royalty free and limited license under Stability AI’s intellectual property or other rights owned or controlled by Stability AI embodied in the Software Products to use, reproduce, distribute, and create Derivative Works of, the Software Products, in each case for Non-Commercial Uses only. - -b. You may not use the Software Products or Derivative Works to enable third parties to use the Software Products or Derivative Works as part of your hosted service or via your APIs, whether you are adding substantial additional functionality thereto or not. Merely distributing the Software Products or Derivative Works for download online without offering any related service (ex. by distributing the Models on HuggingFace) is not a violation of this subsection. If you wish to use the Software Products or any Derivative Works for commercial or production use or you wish to make the Software Products or any Derivative Works available to third parties via your hosted service or your APIs, contact Stability AI at . - -c. If you distribute or make the Software Products, or any Derivative Works thereof, available to a third party, the Software Products, Derivative Works, or any portion thereof, respectively, will remain subject to this Agreement and you must (i) provide a copy of this Agreement to such third party, and (ii) retain the following attribution notice within a "Notice" text file distributed as a part of such copies: "This Stability AI Model is licensed under the Stability AI Non-Commercial Research Community License, Copyright (c) Stability AI Ltd. All Rights Reserved.” If you create a Derivative Work of a Software Product, you may add your own attribution notices to the Notice file included with the Software Product, provided that you clearly indicate which attributions apply to the Software Product and you must state in the NOTICE file that you changed the Software Product and how it was modified. - -2. Disclaimer of Warranty. UNLESS REQUIRED BY APPLICABLE LAW, THE SOFTWARE PRODUCTS AND ANY OUTPUT AND RESULTS THERE FROM ARE PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE SOFTWARE PRODUCTS, DERIVATIVE WORKS OR ANY OUTPUT OR RESULTS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE SOFTWARE PRODUCTS, DERIVATIVE WORKS AND ANY OUTPUT AND RESULTS. - -3. Limitation of Liability. IN NO EVENT WILL STABILITY AI OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF STABILITY AI OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING. - -4. Intellectual Property. - -a. No trademark licenses are granted under this Agreement, and in connection with the Software Products or Derivative Works, neither Stability AI nor Licensee may use any name or mark owned by or associated with the other or any of its affiliates, except as required for reasonable and customary use in describing and redistributing the Software Products or Derivative Works. - -b. Subject to Stability AI’s ownership of the Software Products and Derivative Works made by or for Stability AI, with respect to any Derivative Works that are made by you, as between you and Stability AI, you are and will be the owner of such Derivative Works - -c. If you institute litigation or other proceedings against Stability AI (including a cross-claim or counterclaim in a lawsuit) alleging that the Software Products, Derivative Works or associated outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by you, then any licenses granted to you under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Stability AI from and against any claim by any third party arising out of or related to your use or distribution of the Software Products or Derivative Works in violation of this Agreement. - -5. Term and Termination. The term of this Agreement will commence upon your acceptance of this Agreement or access to the Software Products and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Stability AI may terminate this Agreement if you are in breach of any term or condition of this Agreement. Upon termination of this Agreement, you shall delete and cease use of any Software Products or Derivative Works. Sections 2-4 shall survive the termination of this Agreement. diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app.py b/app.py deleted file mode 100644 index aece2dd635bbdef74dd7707c93efcec55dcc5d15..0000000000000000000000000000000000000000 --- a/app.py +++ /dev/null @@ -1,4 +0,0 @@ -from frontend.webui.hf_demo import start_demo_text_to_image - -print("Starting HF demo text to image") -start_demo_text_to_image(False) diff --git a/app_settings.py b/app_settings.py deleted file mode 100644 index 14aa6f5964f42249878c15e67c0fec31b20979ad..0000000000000000000000000000000000000000 --- a/app_settings.py +++ /dev/null @@ -1,81 +0,0 @@ -import yaml -from os import path, makedirs -from models.settings import Settings -from paths import FastStableDiffusionPaths -from utils import get_models_from_text_file -from constants import ( - OPENVINO_LCM_MODELS_FILE, - LCM_LORA_MODELS_FILE, - SD_MODELS_FILE, - LCM_MODELS_FILE, -) -from copy import deepcopy - - -class AppSettings: - def __init__(self): - self.config_path = FastStableDiffusionPaths().get_app_settings_path() - self._stable_diffsuion_models = ["Lykon/dreamshaper-8"] - self._lcm_lora_models = ["latent-consistency/lcm-lora-sdv1-5"] - self._openvino_lcm_models = ["rupeshs/sd-turbo-openvino"] - self._lcm_models = ["stabilityai/sd-turbo"] - - @property - def settings(self): - return self._config - - @property - def stable_diffsuion_models(self): - return self._stable_diffsuion_models - - @property - def openvino_lcm_models(self): - return self._openvino_lcm_models - - @property - def lcm_models(self): - return self._lcm_models - - @property - def lcm_lora_models(self): - return self._lcm_lora_models - - def load(self, skip_file=False): - if skip_file: - print("Skipping config file") - settings_dict = self._load_default() - self._config = Settings.parse_obj(settings_dict) - else: - if not path.exists(self.config_path): - base_dir = path.dirname(self.config_path) - if not path.exists(base_dir): - makedirs(base_dir) - try: - print("Settings not found creating default settings") - with open(self.config_path, "w") as file: - yaml.dump( - self._load_default(), - file, - ) - except Exception as ex: - print(f"Error in creating settings : {ex}") - exit() - try: - with open(self.config_path) as file: - settings_dict = yaml.safe_load(file) - self._config = Settings.parse_obj(settings_dict) - except Exception as ex: - print(f"Error in loading settings : {ex}") - - def save(self): - try: - with open(self.config_path, "w") as file: - tmp_cfg = deepcopy(self._config) - tmp_cfg.lcm_diffusion_setting.init_image = None - yaml.dump(tmp_cfg.dict(), file) - except Exception as ex: - print(f"Error in saving settings : {ex}") - - def _load_default(self) -> dict: - defult_config = Settings() - return defult_config.dict() diff --git a/backend/__init__.py b/backend/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/backend/__pycache__/__init__.cpython-311.pyc b/backend/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 6f26b7951cf3336b541fec0fc40686964b1aee28..0000000000000000000000000000000000000000 Binary files a/backend/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/backend/__pycache__/device.cpython-311.pyc b/backend/__pycache__/device.cpython-311.pyc deleted file mode 100644 index a9b4bf671a195983cfb6d2c050290a90a9feccd5..0000000000000000000000000000000000000000 Binary files a/backend/__pycache__/device.cpython-311.pyc and /dev/null differ diff --git a/backend/__pycache__/image_saver.cpython-311.pyc b/backend/__pycache__/image_saver.cpython-311.pyc deleted file mode 100644 index 083b5d922de69826a3f96055a7530e3d224bf0e8..0000000000000000000000000000000000000000 Binary files a/backend/__pycache__/image_saver.cpython-311.pyc and /dev/null differ diff --git a/backend/__pycache__/lcm_models.cpython-311.pyc b/backend/__pycache__/lcm_models.cpython-311.pyc deleted file mode 100644 index 1f5af3cedc5bcca3cda521aaf8314a8cfcd6c479..0000000000000000000000000000000000000000 Binary files a/backend/__pycache__/lcm_models.cpython-311.pyc and /dev/null differ diff --git a/backend/__pycache__/lcm_text_to_image.cpython-311.pyc b/backend/__pycache__/lcm_text_to_image.cpython-311.pyc deleted file mode 100644 index 85a17dd3f56c9a5a60e557505c704dad986389db..0000000000000000000000000000000000000000 Binary files a/backend/__pycache__/lcm_text_to_image.cpython-311.pyc and /dev/null differ diff --git a/backend/device.py b/backend/device.py deleted file mode 100644 index d3a0aeb72cd292c107e5cd138c22bbdba38f83bc..0000000000000000000000000000000000000000 --- a/backend/device.py +++ /dev/null @@ -1,23 +0,0 @@ -import platform -from constants import DEVICE -import torch -import openvino as ov - -core = ov.Core() - - -def is_openvino_device() -> bool: - if DEVICE.lower() == "cpu" or DEVICE.lower()[0] == "g": - return True - else: - return False - - -def get_device_name() -> str: - if DEVICE == "cuda" or DEVICE == "mps": - default_gpu_index = torch.cuda.current_device() - return torch.cuda.get_device_name(default_gpu_index) - elif platform.system().lower() == "darwin": - return platform.processor() - elif is_openvino_device(): - return core.get_property(DEVICE.upper(), "FULL_DEVICE_NAME") diff --git a/backend/image_saver.py b/backend/image_saver.py deleted file mode 100644 index 9dcfc204491a2058d19fb1dd17c0881cafcee78d..0000000000000000000000000000000000000000 --- a/backend/image_saver.py +++ /dev/null @@ -1,40 +0,0 @@ -from os import path, mkdir -from typing import Any -from uuid import uuid4 -from backend.models.lcmdiffusion_setting import LCMDiffusionSetting -import json - - -class ImageSaver: - @staticmethod - def save_images( - output_path: str, - images: Any, - folder_name: str = "", - format: str = ".png", - lcm_diffusion_setting: LCMDiffusionSetting = None, - ) -> None: - gen_id = uuid4() - - for index, image in enumerate(images): - if not path.exists(output_path): - mkdir(output_path) - - if folder_name: - out_path = path.join( - output_path, - folder_name, - ) - else: - out_path = output_path - - if not path.exists(out_path): - mkdir(out_path) - image.save(path.join(out_path, f"{gen_id}-{index+1}{format}")) - if lcm_diffusion_setting: - with open(path.join(out_path, f"{gen_id}.json"), "w") as json_file: - json.dump( - lcm_diffusion_setting.model_dump(exclude="init_image"), - json_file, - indent=4, - ) diff --git a/backend/lcm_models.py b/backend/lcm_models.py deleted file mode 100644 index baf7877aa1aea870d558eba835bc6d03a778d736..0000000000000000000000000000000000000000 --- a/backend/lcm_models.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import List -from constants import LCM_DEFAULT_MODEL - - -def get_available_models() -> List: - models = [ - LCM_DEFAULT_MODEL, - "latent-consistency/lcm-sdxl", - "latent-consistency/lcm-ssd-1b", - ] - return models diff --git a/backend/lcm_text_to_image.py b/backend/lcm_text_to_image.py deleted file mode 100644 index b968e4d437df55fa23c7bca90d820e64ab82e44c..0000000000000000000000000000000000000000 --- a/backend/lcm_text_to_image.py +++ /dev/null @@ -1,355 +0,0 @@ -from typing import Any -from diffusers import LCMScheduler -import torch -from backend.models.lcmdiffusion_setting import LCMDiffusionSetting -import numpy as np -from constants import DEVICE -from backend.models.lcmdiffusion_setting import LCMLora -from backend.device import is_openvino_device -from backend.openvino.pipelines import ( - get_ov_text_to_image_pipeline, - ov_load_taesd, - get_ov_image_to_image_pipeline, -) -from backend.pipelines.lcm import ( - get_lcm_model_pipeline, - load_taesd, - get_image_to_image_pipeline, -) -from backend.pipelines.lcm_lora import get_lcm_lora_pipeline -from backend.models.lcmdiffusion_setting import DiffusionTask -from image_ops import resize_pil_image -from math import ceil - - -class LCMTextToImage: - def __init__( - self, - device: str = "cpu", - ) -> None: - self.pipeline = None - self.use_openvino = False - self.device = "" - self.previous_model_id = None - self.previous_use_tae_sd = False - self.previous_use_lcm_lora = False - self.previous_ov_model_id = "" - self.previous_safety_checker = False - self.previous_use_openvino = False - self.img_to_img_pipeline = None - self.is_openvino_init = False - self.task_type = DiffusionTask.text_to_image - self.torch_data_type = ( - torch.float32 if is_openvino_device() or DEVICE == "mps" else torch.float16 - ) - print(f"Torch datatype : {self.torch_data_type}") - - def _pipeline_to_device(self): - print(f"Pipeline device : {DEVICE}") - print(f"Pipeline dtype : {self.torch_data_type}") - self.pipeline.to( - torch_device=DEVICE, - torch_dtype=self.torch_data_type, - ) - - def _add_freeu(self): - pipeline_class = self.pipeline.__class__.__name__ - if isinstance(self.pipeline.scheduler, LCMScheduler): - if pipeline_class == "StableDiffusionPipeline": - print("Add FreeU - SD") - self.pipeline.enable_freeu( - s1=0.9, - s2=0.2, - b1=1.2, - b2=1.4, - ) - elif pipeline_class == "StableDiffusionXLPipeline": - print("Add FreeU - SDXL") - self.pipeline.enable_freeu( - s1=0.6, - s2=0.4, - b1=1.1, - b2=1.2, - ) - - def _update_lcm_scheduler_params(self): - if isinstance(self.pipeline.scheduler, LCMScheduler): - self.pipeline.scheduler = LCMScheduler.from_config( - self.pipeline.scheduler.config, - beta_start=0.001, - beta_end=0.01, - ) - - def init( - self, - device: str = "cpu", - lcm_diffusion_setting: LCMDiffusionSetting = LCMDiffusionSetting(), - ) -> None: - self.device = device - self.use_openvino = lcm_diffusion_setting.use_openvino - model_id = lcm_diffusion_setting.lcm_model_id - use_local_model = lcm_diffusion_setting.use_offline_model - use_tiny_auto_encoder = lcm_diffusion_setting.use_tiny_auto_encoder - use_lora = lcm_diffusion_setting.use_lcm_lora - lcm_lora: LCMLora = lcm_diffusion_setting.lcm_lora - ov_model_id = lcm_diffusion_setting.openvino_lcm_model_id - - if lcm_diffusion_setting.diffusion_task == DiffusionTask.image_to_image.value: - lcm_diffusion_setting.init_image = resize_pil_image( - lcm_diffusion_setting.init_image, - lcm_diffusion_setting.image_width, - lcm_diffusion_setting.image_height, - ) - - if ( - self.pipeline is None - or self.previous_model_id != model_id - or self.previous_use_tae_sd != use_tiny_auto_encoder - or self.previous_lcm_lora_base_id != lcm_lora.base_model_id - or self.previous_lcm_lora_id != lcm_lora.lcm_lora_id - or self.previous_use_lcm_lora != use_lora - or self.previous_ov_model_id != ov_model_id - or self.previous_safety_checker != lcm_diffusion_setting.use_safety_checker - or self.previous_use_openvino != lcm_diffusion_setting.use_openvino - or self.previous_task_type != lcm_diffusion_setting.diffusion_task - ): - if self.use_openvino and is_openvino_device(): - if self.pipeline: - del self.pipeline - self.pipeline = None - self.is_openvino_init = True - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.text_to_image.value - ): - print(f"***** Init Text to image (OpenVINO) - {ov_model_id} *****") - self.pipeline = get_ov_text_to_image_pipeline( - ov_model_id, - use_local_model, - ) - elif ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - ): - print(f"***** Image to image (OpenVINO) - {ov_model_id} *****") - self.pipeline = get_ov_image_to_image_pipeline( - ov_model_id, - use_local_model, - ) - else: - if self.pipeline: - del self.pipeline - self.pipeline = None - if self.img_to_img_pipeline: - del self.img_to_img_pipeline - self.img_to_img_pipeline = None - - if use_lora: - print( - f"***** Init LCM-LoRA pipeline - {lcm_lora.base_model_id} *****" - ) - self.pipeline = get_lcm_lora_pipeline( - lcm_lora.base_model_id, - lcm_lora.lcm_lora_id, - use_local_model, - torch_data_type=self.torch_data_type, - ) - else: - print(f"***** Init LCM Model pipeline - {model_id} *****") - self.pipeline = get_lcm_model_pipeline( - model_id, - use_local_model, - ) - - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - ): - self.img_to_img_pipeline = get_image_to_image_pipeline( - self.pipeline - ) - self._pipeline_to_device() - - if use_tiny_auto_encoder: - if self.use_openvino and is_openvino_device(): - print("Using Tiny Auto Encoder (OpenVINO)") - ov_load_taesd( - self.pipeline, - use_local_model, - ) - else: - print("Using Tiny Auto Encoder") - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.text_to_image.value - ): - load_taesd( - self.pipeline, - use_local_model, - self.torch_data_type, - ) - elif ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - ): - load_taesd( - self.img_to_img_pipeline, - use_local_model, - self.torch_data_type, - ) - - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - and lcm_diffusion_setting.use_openvino - ): - self.pipeline.scheduler = LCMScheduler.from_config( - self.pipeline.scheduler.config, - ) - else: - self._update_lcm_scheduler_params() - - if use_lora: - self._add_freeu() - - self.previous_model_id = model_id - self.previous_ov_model_id = ov_model_id - self.previous_use_tae_sd = use_tiny_auto_encoder - self.previous_lcm_lora_base_id = lcm_lora.base_model_id - self.previous_lcm_lora_id = lcm_lora.lcm_lora_id - self.previous_use_lcm_lora = use_lora - self.previous_safety_checker = lcm_diffusion_setting.use_safety_checker - self.previous_use_openvino = lcm_diffusion_setting.use_openvino - self.previous_task_type = lcm_diffusion_setting.diffusion_task - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.text_to_image.value - ): - print(f"Pipeline : {self.pipeline}") - elif ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - ): - if self.use_openvino and is_openvino_device(): - print(f"Pipeline : {self.pipeline}") - else: - print(f"Pipeline : {self.img_to_img_pipeline}") - - def generate( - self, - lcm_diffusion_setting: LCMDiffusionSetting, - reshape: bool = False, - ) -> Any: - guidance_scale = lcm_diffusion_setting.guidance_scale - img_to_img_inference_steps = lcm_diffusion_setting.inference_steps - check_step_value = int( - lcm_diffusion_setting.inference_steps * lcm_diffusion_setting.strength - ) - if ( - lcm_diffusion_setting.diffusion_task == DiffusionTask.image_to_image.value - and check_step_value < 1 - ): - img_to_img_inference_steps = ceil(1 / lcm_diffusion_setting.strength) - print( - f"Strength: {lcm_diffusion_setting.strength},{img_to_img_inference_steps}" - ) - - if lcm_diffusion_setting.use_seed: - cur_seed = lcm_diffusion_setting.seed - if self.use_openvino: - np.random.seed(cur_seed) - else: - torch.manual_seed(cur_seed) - - is_openvino_pipe = lcm_diffusion_setting.use_openvino and is_openvino_device() - if is_openvino_pipe: - print("Using OpenVINO") - if reshape and not self.is_openvino_init: - print("Reshape and compile") - self.pipeline.reshape( - batch_size=-1, - height=lcm_diffusion_setting.image_height, - width=lcm_diffusion_setting.image_width, - num_images_per_prompt=lcm_diffusion_setting.number_of_images, - ) - self.pipeline.compile() - - if self.is_openvino_init: - self.is_openvino_init = False - - if not lcm_diffusion_setting.use_safety_checker: - self.pipeline.safety_checker = None - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - and not is_openvino_pipe - ): - self.img_to_img_pipeline.safety_checker = None - - if ( - not lcm_diffusion_setting.use_lcm_lora - and not lcm_diffusion_setting.use_openvino - and lcm_diffusion_setting.guidance_scale != 1.0 - ): - print("Not using LCM-LoRA so setting guidance_scale 1.0") - guidance_scale = 1.0 - - if lcm_diffusion_setting.use_openvino: - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.text_to_image.value - ): - result_images = self.pipeline( - prompt=lcm_diffusion_setting.prompt, - negative_prompt=lcm_diffusion_setting.negative_prompt, - num_inference_steps=lcm_diffusion_setting.inference_steps, - guidance_scale=guidance_scale, - width=lcm_diffusion_setting.image_width, - height=lcm_diffusion_setting.image_height, - num_images_per_prompt=lcm_diffusion_setting.number_of_images, - ).images - elif ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - ): - result_images = self.pipeline( - image=lcm_diffusion_setting.init_image, - strength=lcm_diffusion_setting.strength, - prompt=lcm_diffusion_setting.prompt, - negative_prompt=lcm_diffusion_setting.negative_prompt, - num_inference_steps=img_to_img_inference_steps * 3, - guidance_scale=guidance_scale, - num_images_per_prompt=lcm_diffusion_setting.number_of_images, - ).images - - else: - if ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.text_to_image.value - ): - result_images = self.pipeline( - prompt=lcm_diffusion_setting.prompt, - negative_prompt=lcm_diffusion_setting.negative_prompt, - num_inference_steps=lcm_diffusion_setting.inference_steps, - guidance_scale=guidance_scale, - width=lcm_diffusion_setting.image_width, - height=lcm_diffusion_setting.image_height, - num_images_per_prompt=lcm_diffusion_setting.number_of_images, - ).images - elif ( - lcm_diffusion_setting.diffusion_task - == DiffusionTask.image_to_image.value - ): - result_images = self.img_to_img_pipeline( - image=lcm_diffusion_setting.init_image, - strength=lcm_diffusion_setting.strength, - prompt=lcm_diffusion_setting.prompt, - negative_prompt=lcm_diffusion_setting.negative_prompt, - num_inference_steps=img_to_img_inference_steps, - guidance_scale=guidance_scale, - width=lcm_diffusion_setting.image_width, - height=lcm_diffusion_setting.image_height, - num_images_per_prompt=lcm_diffusion_setting.number_of_images, - ).images - - return result_images diff --git a/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc b/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc deleted file mode 100644 index e194a1b5d710a6bb72af40bf31a7f7dd30f0b25c..0000000000000000000000000000000000000000 Binary files a/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_ov_pipeline.cpython-311.pyc and /dev/null differ diff --git a/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc b/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc deleted file mode 100644 index cc26cf76d94666dc5d5620cad1837599bfe8e3cc..0000000000000000000000000000000000000000 Binary files a/backend/lcmdiffusion/pipelines/openvino/__pycache__/lcm_scheduler.cpython-311.pyc and /dev/null differ diff --git a/backend/lcmdiffusion/pipelines/openvino/lcm_ov_pipeline.py b/backend/lcmdiffusion/pipelines/openvino/lcm_ov_pipeline.py deleted file mode 100644 index 9a126cf097014e84d136b9fefa1851df5f2d1be7..0000000000000000000000000000000000000000 --- a/backend/lcmdiffusion/pipelines/openvino/lcm_ov_pipeline.py +++ /dev/null @@ -1,447 +0,0 @@ -# https://huggingface.co/deinferno/LCM_Dreamshaper_v7-openvino - -import inspect - -from pathlib import Path -from tempfile import TemporaryDirectory -from typing import List, Optional, Tuple, Union, Dict, Any, Callable, OrderedDict - -import numpy as np -import openvino -import torch - -from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput -from optimum.intel.openvino.modeling_diffusion import ( - OVStableDiffusionPipeline, - OVModelUnet, - OVModelVaeDecoder, - OVModelTextEncoder, - OVModelVaeEncoder, - VaeImageProcessor, -) -from optimum.utils import ( - DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER, - DIFFUSION_MODEL_TEXT_ENCODER_SUBFOLDER, - DIFFUSION_MODEL_UNET_SUBFOLDER, - DIFFUSION_MODEL_VAE_DECODER_SUBFOLDER, - DIFFUSION_MODEL_VAE_ENCODER_SUBFOLDER, -) - - -from diffusers import logging - -logger = logging.get_logger(__name__) # pylint: disable=invalid-name - - -class LCMOVModelUnet(OVModelUnet): - def __call__( - self, - sample: np.ndarray, - timestep: np.ndarray, - encoder_hidden_states: np.ndarray, - timestep_cond: Optional[np.ndarray] = None, - text_embeds: Optional[np.ndarray] = None, - time_ids: Optional[np.ndarray] = None, - ): - self._compile() - - inputs = { - "sample": sample, - "timestep": timestep, - "encoder_hidden_states": encoder_hidden_states, - } - - if timestep_cond is not None: - inputs["timestep_cond"] = timestep_cond - if text_embeds is not None: - inputs["text_embeds"] = text_embeds - if time_ids is not None: - inputs["time_ids"] = time_ids - - outputs = self.request(inputs, shared_memory=True) - return list(outputs.values()) - - -class OVLatentConsistencyModelPipeline(OVStableDiffusionPipeline): - def __init__( - self, - vae_decoder: openvino.runtime.Model, - text_encoder: openvino.runtime.Model, - unet: openvino.runtime.Model, - config: Dict[str, Any], - tokenizer: "CLIPTokenizer", - scheduler: Union["DDIMScheduler", "PNDMScheduler", "LMSDiscreteScheduler"], - feature_extractor: Optional["CLIPFeatureExtractor"] = None, - vae_encoder: Optional[openvino.runtime.Model] = None, - text_encoder_2: Optional[openvino.runtime.Model] = None, - tokenizer_2: Optional["CLIPTokenizer"] = None, - device: str = "CPU", - dynamic_shapes: bool = True, - compile: bool = True, - ov_config: Optional[Dict[str, str]] = None, - model_save_dir: Optional[Union[str, Path, TemporaryDirectory]] = None, - **kwargs, - ): - self._internal_dict = config - self._device = device.upper() - self.is_dynamic = dynamic_shapes - self.ov_config = ov_config if ov_config is not None else {} - self._model_save_dir = ( - Path(model_save_dir.name) - if isinstance(model_save_dir, TemporaryDirectory) - else model_save_dir - ) - self.vae_decoder = OVModelVaeDecoder(vae_decoder, self) - self.unet = LCMOVModelUnet(unet, self) - self.text_encoder = ( - OVModelTextEncoder(text_encoder, self) if text_encoder is not None else None - ) - self.text_encoder_2 = ( - OVModelTextEncoder( - text_encoder_2, - self, - model_name=DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER, - ) - if text_encoder_2 is not None - else None - ) - self.vae_encoder = ( - OVModelVaeEncoder(vae_encoder, self) if vae_encoder is not None else None - ) - - if "block_out_channels" in self.vae_decoder.config: - self.vae_scale_factor = 2 ** ( - len(self.vae_decoder.config["block_out_channels"]) - 1 - ) - else: - self.vae_scale_factor = 8 - - self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor) - - self.tokenizer = tokenizer - self.tokenizer_2 = tokenizer_2 - self.scheduler = scheduler - self.feature_extractor = feature_extractor - self.safety_checker = None - self.preprocessors = [] - - if self.is_dynamic: - self.reshape(batch_size=-1, height=-1, width=-1, num_images_per_prompt=-1) - - if compile: - self.compile() - - sub_models = { - DIFFUSION_MODEL_TEXT_ENCODER_SUBFOLDER: self.text_encoder, - DIFFUSION_MODEL_UNET_SUBFOLDER: self.unet, - DIFFUSION_MODEL_VAE_DECODER_SUBFOLDER: self.vae_decoder, - DIFFUSION_MODEL_VAE_ENCODER_SUBFOLDER: self.vae_encoder, - DIFFUSION_MODEL_TEXT_ENCODER_2_SUBFOLDER: self.text_encoder_2, - } - for name in sub_models.keys(): - self._internal_dict[name] = ( - ("optimum", sub_models[name].__class__.__name__) - if sub_models[name] is not None - else (None, None) - ) - - self._internal_dict.pop("vae", None) - - def _reshape_unet( - self, - model: openvino.runtime.Model, - batch_size: int = -1, - height: int = -1, - width: int = -1, - num_images_per_prompt: int = -1, - tokenizer_max_length: int = -1, - ): - if batch_size == -1 or num_images_per_prompt == -1: - batch_size = -1 - else: - batch_size = batch_size * num_images_per_prompt - - height = height // self.vae_scale_factor if height > 0 else height - width = width // self.vae_scale_factor if width > 0 else width - shapes = {} - for inputs in model.inputs: - shapes[inputs] = inputs.get_partial_shape() - if inputs.get_any_name() == "timestep": - shapes[inputs][0] = 1 - elif inputs.get_any_name() == "sample": - in_channels = self.unet.config.get("in_channels", None) - if in_channels is None: - in_channels = shapes[inputs][1] - if in_channels.is_dynamic: - logger.warning( - "Could not identify `in_channels` from the unet configuration, to statically reshape the unet please provide a configuration." - ) - self.is_dynamic = True - - shapes[inputs] = [batch_size, in_channels, height, width] - elif inputs.get_any_name() == "timestep_cond": - shapes[inputs] = [batch_size, inputs.get_partial_shape()[1]] - elif inputs.get_any_name() == "text_embeds": - shapes[inputs] = [ - batch_size, - self.text_encoder_2.config["projection_dim"], - ] - elif inputs.get_any_name() == "time_ids": - shapes[inputs] = [batch_size, inputs.get_partial_shape()[1]] - else: - shapes[inputs][0] = batch_size - shapes[inputs][1] = tokenizer_max_length - model.reshape(shapes) - return model - - def get_guidance_scale_embedding(self, w, embedding_dim=512, dtype=np.float32): - """ - see https://github.com/google-research/vdm/blob/dc27b98a554f65cdc654b800da5aa1846545d41b/model_vdm.py#L298 - Args: - timesteps: np.array: generate embedding vectors at these timesteps - embedding_dim: int: dimension of the embeddings to generate - dtype: data type of the generated embeddings - - Returns: - embedding vectors with shape `(len(timesteps), embedding_dim)` - """ - assert len(w.shape) == 1 - w = w * 1000.0 - - half_dim = embedding_dim // 2 - emb = np.log(np.array(10000.0)) / (half_dim - 1) - emb = np.exp(np.arange(half_dim, dtype=dtype) * -emb) - emb = w.astype(dtype)[:, None] * emb[None, :] - emb = np.concatenate([np.sin(emb), np.cos(emb)], axis=1) - if embedding_dim % 2 == 1: # zero pad - emb = np.pad(emb, (0, 1)) - assert emb.shape == (w.shape[0], embedding_dim) - return emb - - # Adapted from https://github.com/huggingface/optimum/blob/15b8d1eed4d83c5004d3b60f6b6f13744b358f01/optimum/pipelines/diffusers/pipeline_stable_diffusion.py#L201 - def __call__( - self, - prompt: Optional[Union[str, List[str]]] = None, - height: Optional[int] = None, - width: Optional[int] = None, - num_inference_steps: int = 4, - original_inference_steps: int = None, - guidance_scale: float = 7.5, - num_images_per_prompt: int = 1, - eta: float = 0.0, - generator: Optional[np.random.RandomState] = None, - latents: Optional[np.ndarray] = None, - prompt_embeds: Optional[np.ndarray] = None, - output_type: str = "pil", - return_dict: bool = True, - callback: Optional[Callable[[int, int, np.ndarray], None]] = None, - callback_steps: int = 1, - guidance_rescale: float = 0.0, - ): - r""" - Function invoked when calling the pipeline for generation. - - Args: - prompt (`Optional[Union[str, List[str]]]`, defaults to None): - The prompt or prompts to guide the image generation. If not defined, one has to pass `prompt_embeds`. - instead. - height (`Optional[int]`, defaults to None): - The height in pixels of the generated image. - width (`Optional[int]`, defaults to None): - The width in pixels of the generated image. - num_inference_steps (`int`, defaults to 4): - The number of denoising steps. More denoising steps usually lead to a higher quality image at the - expense of slower inference. - original_inference_steps (`int`, *optional*): - The original number of inference steps use to generate a linearly-spaced timestep schedule, from which - we will draw `num_inference_steps` evenly spaced timesteps from as our final timestep schedule, - following the Skipping-Step method in the paper (see Section 4.3). If not set this will default to the - scheduler's `original_inference_steps` attribute. - guidance_scale (`float`, defaults to 7.5): - Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598). - `guidance_scale` is defined as `w` of equation 2. of [Imagen - Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale > - 1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`, - usually at the expense of lower image quality. - num_images_per_prompt (`int`, defaults to 1): - The number of images to generate per prompt. - eta (`float`, defaults to 0.0): - Corresponds to parameter eta (η) in the DDIM paper: https://arxiv.org/abs/2010.02502. Only applies to - [`schedulers.DDIMScheduler`], will be ignored for others. - generator (`Optional[np.random.RandomState]`, defaults to `None`):: - A np.random.RandomState to make generation deterministic. - latents (`Optional[np.ndarray]`, defaults to `None`): - Pre-generated noisy latents, sampled from a Gaussian distribution, to be used as inputs for image - generation. Can be used to tweak the same generation with different prompts. If not provided, a latents - tensor will ge generated by sampling using the supplied random `generator`. - prompt_embeds (`Optional[np.ndarray]`, defaults to `None`): - Pre-generated text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt weighting. If not - provided, text embeddings will be generated from `prompt` input argument. - output_type (`str`, defaults to `"pil"`): - The output format of the generate image. Choose between - [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`. - return_dict (`bool`, defaults to `True`): - Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a - plain tuple. - callback (Optional[Callable], defaults to `None`): - A function that will be called every `callback_steps` steps during inference. The function will be - called with the following arguments: `callback(step: int, timestep: int, latents: torch.FloatTensor)`. - callback_steps (`int`, defaults to 1): - The frequency at which the `callback` function will be called. If not specified, the callback will be - called at every step. - guidance_rescale (`float`, defaults to 0.0): - Guidance rescale factor proposed by [Common Diffusion Noise Schedules and Sample Steps are - Flawed](https://arxiv.org/pdf/2305.08891.pdf) `guidance_scale` is defined as `φ` in equation 16. of - [Common Diffusion Noise Schedules and Sample Steps are Flawed](https://arxiv.org/pdf/2305.08891.pdf). - Guidance rescale factor should fix overexposure when using zero terminal SNR. - - Returns: - [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`: - [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple. - When returning a tuple, the first element is a list with the generated images, and the second element is a - list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work" - (nsfw) content, according to the `safety_checker`. - """ - height = ( - height or self.unet.config.get("sample_size", 64) * self.vae_scale_factor - ) - width = width or self.unet.config.get("sample_size", 64) * self.vae_scale_factor - - # check inputs. Raise error if not correct - self.check_inputs( - prompt, height, width, callback_steps, None, prompt_embeds, None - ) - - # define call parameters - if isinstance(prompt, str): - batch_size = 1 - elif isinstance(prompt, list): - batch_size = len(prompt) - else: - batch_size = prompt_embeds.shape[0] - - if generator is None: - generator = np.random - - # Create torch.Generator instance with same state as np.random.RandomState - torch_generator = torch.Generator().manual_seed( - int(generator.get_state()[1][0]) - ) - - # do_classifier_free_guidance = guidance_scale > 1.0 - - # NOTE: when a LCM is distilled from an LDM via latent consistency distillation (Algorithm 1) with guided - # distillation, the forward pass of the LCM learns to approximate sampling from the LDM using CFG with the - # unconditional prompt "" (the empty string). Due to this, LCMs currently do not support negative prompts. - prompt_embeds = self._encode_prompt( - prompt, - num_images_per_prompt, - False, - negative_prompt=None, - prompt_embeds=prompt_embeds, - negative_prompt_embeds=None, - ) - - # set timesteps - self.scheduler.set_timesteps( - num_inference_steps, - "cpu", - original_inference_steps=original_inference_steps, - ) - timesteps = self.scheduler.timesteps - - latents = self.prepare_latents( - batch_size * num_images_per_prompt, - self.unet.config.get("in_channels", 4), - height, - width, - prompt_embeds.dtype, - generator, - latents, - ) - - # Get Guidance Scale Embedding - w = np.tile(guidance_scale - 1, batch_size * num_images_per_prompt) - w_embedding = self.get_guidance_scale_embedding( - w, embedding_dim=self.unet.config.get("time_cond_proj_dim", 256) - ) - - # Adapted from diffusers to extend it for other runtimes than ORT - timestep_dtype = self.unet.input_dtype.get("timestep", np.float32) - - # prepare extra kwargs for the scheduler step, since not all schedulers have the same signature - # eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers. - # eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502 - # and should be between [0, 1] - accepts_eta = "eta" in set( - inspect.signature(self.scheduler.step).parameters.keys() - ) - extra_step_kwargs = {} - if accepts_eta: - extra_step_kwargs["eta"] = eta - - accepts_generator = "generator" in set( - inspect.signature(self.scheduler.step).parameters.keys() - ) - if accepts_generator: - extra_step_kwargs["generator"] = torch_generator - - num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order - for i, t in enumerate(self.progress_bar(timesteps)): - # predict the noise residual - timestep = np.array([t], dtype=timestep_dtype) - - noise_pred = self.unet( - sample=latents, - timestep=timestep, - timestep_cond=w_embedding, - encoder_hidden_states=prompt_embeds, - )[0] - - # compute the previous noisy sample x_t -> x_t-1 - latents, denoised = self.scheduler.step( - torch.from_numpy(noise_pred), - t, - torch.from_numpy(latents), - **extra_step_kwargs, - return_dict=False, - ) - - latents, denoised = latents.numpy(), denoised.numpy() - - # call the callback, if provided - if i == len(timesteps) - 1 or ( - (i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0 - ): - if callback is not None and i % callback_steps == 0: - callback(i, t, latents) - - if output_type == "latent": - image = latents - has_nsfw_concept = None - else: - denoised /= self.vae_decoder.config.get("scaling_factor", 0.18215) - # it seems likes there is a strange result for using half-precision vae decoder if batchsize>1 - image = np.concatenate( - [ - self.vae_decoder(latent_sample=denoised[i : i + 1])[0] - for i in range(latents.shape[0]) - ] - ) - image, has_nsfw_concept = self.run_safety_checker(image) - - if has_nsfw_concept is None: - do_denormalize = [True] * image.shape[0] - else: - do_denormalize = [not has_nsfw for has_nsfw in has_nsfw_concept] - - image = self.image_processor.postprocess( - image, output_type=output_type, do_denormalize=do_denormalize - ) - - if not return_dict: - return (image, has_nsfw_concept) - - return StableDiffusionPipelineOutput( - images=image, nsfw_content_detected=has_nsfw_concept - ) diff --git a/backend/lcmdiffusion/pipelines/openvino/lcm_scheduler.py b/backend/lcmdiffusion/pipelines/openvino/lcm_scheduler.py deleted file mode 100644 index 5e139588bca57daeda5d282fe125aa691bd10003..0000000000000000000000000000000000000000 --- a/backend/lcmdiffusion/pipelines/openvino/lcm_scheduler.py +++ /dev/null @@ -1,576 +0,0 @@ -# Copyright 2023 Stanford University Team and The HuggingFace Team. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# DISCLAIMER: This code is strongly influenced by https://github.com/pesser/pytorch_diffusion -# and https://github.com/hojonathanho/diffusion - -import math -from dataclasses import dataclass -from typing import List, Optional, Tuple, Union - -import numpy as np -import torch - -from diffusers.configuration_utils import ConfigMixin, register_to_config -from diffusers.utils import BaseOutput, logging -from diffusers.utils.torch_utils import randn_tensor -from diffusers.schedulers.scheduling_utils import SchedulerMixin - - -logger = logging.get_logger(__name__) # pylint: disable=invalid-name - - -@dataclass -class LCMSchedulerOutput(BaseOutput): - """ - Output class for the scheduler's `step` function output. - - Args: - prev_sample (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)` for images): - Computed sample `(x_{t-1})` of previous timestep. `prev_sample` should be used as next model input in the - denoising loop. - pred_original_sample (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)` for images): - The predicted denoised sample `(x_{0})` based on the model output from the current timestep. - `pred_original_sample` can be used to preview progress or for guidance. - """ - - prev_sample: torch.FloatTensor - denoised: Optional[torch.FloatTensor] = None - - -# Copied from diffusers.schedulers.scheduling_ddpm.betas_for_alpha_bar -def betas_for_alpha_bar( - num_diffusion_timesteps, - max_beta=0.999, - alpha_transform_type="cosine", -): - """ - Create a beta schedule that discretizes the given alpha_t_bar function, which defines the cumulative product of - (1-beta) over time from t = [0,1]. - - Contains a function alpha_bar that takes an argument t and transforms it to the cumulative product of (1-beta) up - to that part of the diffusion process. - - - Args: - num_diffusion_timesteps (`int`): the number of betas to produce. - max_beta (`float`): the maximum beta to use; use values lower than 1 to - prevent singularities. - alpha_transform_type (`str`, *optional*, default to `cosine`): the type of noise schedule for alpha_bar. - Choose from `cosine` or `exp` - - Returns: - betas (`np.ndarray`): the betas used by the scheduler to step the model outputs - """ - if alpha_transform_type == "cosine": - - def alpha_bar_fn(t): - return math.cos((t + 0.008) / 1.008 * math.pi / 2) ** 2 - - elif alpha_transform_type == "exp": - - def alpha_bar_fn(t): - return math.exp(t * -12.0) - - else: - raise ValueError(f"Unsupported alpha_tranform_type: {alpha_transform_type}") - - betas = [] - for i in range(num_diffusion_timesteps): - t1 = i / num_diffusion_timesteps - t2 = (i + 1) / num_diffusion_timesteps - betas.append(min(1 - alpha_bar_fn(t2) / alpha_bar_fn(t1), max_beta)) - return torch.tensor(betas, dtype=torch.float32) - - -# Copied from diffusers.schedulers.scheduling_ddim.rescale_zero_terminal_snr -def rescale_zero_terminal_snr(betas: torch.FloatTensor) -> torch.FloatTensor: - """ - Rescales betas to have zero terminal SNR Based on https://arxiv.org/pdf/2305.08891.pdf (Algorithm 1) - - - Args: - betas (`torch.FloatTensor`): - the betas that the scheduler is being initialized with. - - Returns: - `torch.FloatTensor`: rescaled betas with zero terminal SNR - """ - # Convert betas to alphas_bar_sqrt - alphas = 1.0 - betas - alphas_cumprod = torch.cumprod(alphas, dim=0) - alphas_bar_sqrt = alphas_cumprod.sqrt() - - # Store old values. - alphas_bar_sqrt_0 = alphas_bar_sqrt[0].clone() - alphas_bar_sqrt_T = alphas_bar_sqrt[-1].clone() - - # Shift so the last timestep is zero. - alphas_bar_sqrt -= alphas_bar_sqrt_T - - # Scale so the first timestep is back to the old value. - alphas_bar_sqrt *= alphas_bar_sqrt_0 / (alphas_bar_sqrt_0 - alphas_bar_sqrt_T) - - # Convert alphas_bar_sqrt to betas - alphas_bar = alphas_bar_sqrt**2 # Revert sqrt - alphas = alphas_bar[1:] / alphas_bar[:-1] # Revert cumprod - alphas = torch.cat([alphas_bar[0:1], alphas]) - betas = 1 - alphas - - return betas - - -class LCMScheduler(SchedulerMixin, ConfigMixin): - """ - `LCMScheduler` extends the denoising procedure introduced in denoising diffusion probabilistic models (DDPMs) with - non-Markovian guidance. - - This model inherits from [`SchedulerMixin`] and [`ConfigMixin`]. [`~ConfigMixin`] takes care of storing all config - attributes that are passed in the scheduler's `__init__` function, such as `num_train_timesteps`. They can be - accessed via `scheduler.config.num_train_timesteps`. [`SchedulerMixin`] provides general loading and saving - functionality via the [`SchedulerMixin.save_pretrained`] and [`~SchedulerMixin.from_pretrained`] functions. - - Args: - num_train_timesteps (`int`, defaults to 1000): - The number of diffusion steps to train the model. - beta_start (`float`, defaults to 0.0001): - The starting `beta` value of inference. - beta_end (`float`, defaults to 0.02): - The final `beta` value. - beta_schedule (`str`, defaults to `"linear"`): - The beta schedule, a mapping from a beta range to a sequence of betas for stepping the model. Choose from - `linear`, `scaled_linear`, or `squaredcos_cap_v2`. - trained_betas (`np.ndarray`, *optional*): - Pass an array of betas directly to the constructor to bypass `beta_start` and `beta_end`. - original_inference_steps (`int`, *optional*, defaults to 50): - The default number of inference steps used to generate a linearly-spaced timestep schedule, from which we - will ultimately take `num_inference_steps` evenly spaced timesteps to form the final timestep schedule. - clip_sample (`bool`, defaults to `True`): - Clip the predicted sample for numerical stability. - clip_sample_range (`float`, defaults to 1.0): - The maximum magnitude for sample clipping. Valid only when `clip_sample=True`. - set_alpha_to_one (`bool`, defaults to `True`): - Each diffusion step uses the alphas product value at that step and at the previous one. For the final step - there is no previous alpha. When this option is `True` the previous alpha product is fixed to `1`, - otherwise it uses the alpha value at step 0. - steps_offset (`int`, defaults to 0): - An offset added to the inference steps. You can use a combination of `offset=1` and - `set_alpha_to_one=False` to make the last step use step 0 for the previous alpha product like in Stable - Diffusion. - prediction_type (`str`, defaults to `epsilon`, *optional*): - Prediction type of the scheduler function; can be `epsilon` (predicts the noise of the diffusion process), - `sample` (directly predicts the noisy sample`) or `v_prediction` (see section 2.4 of [Imagen - Video](https://imagen.research.google/video/paper.pdf) paper). - thresholding (`bool`, defaults to `False`): - Whether to use the "dynamic thresholding" method. This is unsuitable for latent-space diffusion models such - as Stable Diffusion. - dynamic_thresholding_ratio (`float`, defaults to 0.995): - The ratio for the dynamic thresholding method. Valid only when `thresholding=True`. - sample_max_value (`float`, defaults to 1.0): - The threshold value for dynamic thresholding. Valid only when `thresholding=True`. - timestep_spacing (`str`, defaults to `"leading"`): - The way the timesteps should be scaled. Refer to Table 2 of the [Common Diffusion Noise Schedules and - Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) for more information. - rescale_betas_zero_snr (`bool`, defaults to `False`): - Whether to rescale the betas to have zero terminal SNR. This enables the model to generate very bright and - dark samples instead of limiting it to samples with medium brightness. Loosely related to - [`--offset_noise`](https://github.com/huggingface/diffusers/blob/74fd735eb073eb1d774b1ab4154a0876eb82f055/examples/dreambooth/train_dreambooth.py#L506). - """ - - order = 1 - - @register_to_config - def __init__( - self, - num_train_timesteps: int = 1000, - beta_start: float = 0.00085, - beta_end: float = 0.012, - beta_schedule: str = "scaled_linear", - trained_betas: Optional[Union[np.ndarray, List[float]]] = None, - original_inference_steps: int = 50, - clip_sample: bool = False, - clip_sample_range: float = 1.0, - set_alpha_to_one: bool = True, - steps_offset: int = 0, - prediction_type: str = "epsilon", - thresholding: bool = False, - dynamic_thresholding_ratio: float = 0.995, - sample_max_value: float = 1.0, - timestep_spacing: str = "leading", - rescale_betas_zero_snr: bool = False, - ): - if trained_betas is not None: - self.betas = torch.tensor(trained_betas, dtype=torch.float32) - elif beta_schedule == "linear": - self.betas = torch.linspace( - beta_start, beta_end, num_train_timesteps, dtype=torch.float32 - ) - elif beta_schedule == "scaled_linear": - # this schedule is very specific to the latent diffusion model. - self.betas = ( - torch.linspace( - beta_start**0.5, - beta_end**0.5, - num_train_timesteps, - dtype=torch.float32, - ) - ** 2 - ) - elif beta_schedule == "squaredcos_cap_v2": - # Glide cosine schedule - self.betas = betas_for_alpha_bar(num_train_timesteps) - else: - raise NotImplementedError( - f"{beta_schedule} does is not implemented for {self.__class__}" - ) - - # Rescale for zero SNR - if rescale_betas_zero_snr: - self.betas = rescale_zero_terminal_snr(self.betas) - - self.alphas = 1.0 - self.betas - self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) - - # At every step in ddim, we are looking into the previous alphas_cumprod - # For the final step, there is no previous alphas_cumprod because we are already at 0 - # `set_alpha_to_one` decides whether we set this parameter simply to one or - # whether we use the final alpha of the "non-previous" one. - self.final_alpha_cumprod = ( - torch.tensor(1.0) if set_alpha_to_one else self.alphas_cumprod[0] - ) - - # standard deviation of the initial noise distribution - self.init_noise_sigma = 1.0 - - # setable values - self.num_inference_steps = None - self.timesteps = torch.from_numpy( - np.arange(0, num_train_timesteps)[::-1].copy().astype(np.int64) - ) - - self._step_index = None - - # Copied from diffusers.schedulers.scheduling_euler_discrete.EulerDiscreteScheduler._init_step_index - def _init_step_index(self, timestep): - if isinstance(timestep, torch.Tensor): - timestep = timestep.to(self.timesteps.device) - - index_candidates = (self.timesteps == timestep).nonzero() - - # The sigma index that is taken for the **very** first `step` - # is always the second index (or the last index if there is only 1) - # This way we can ensure we don't accidentally skip a sigma in - # case we start in the middle of the denoising schedule (e.g. for image-to-image) - if len(index_candidates) > 1: - step_index = index_candidates[1] - else: - step_index = index_candidates[0] - - self._step_index = step_index.item() - - @property - def step_index(self): - return self._step_index - - def scale_model_input( - self, sample: torch.FloatTensor, timestep: Optional[int] = None - ) -> torch.FloatTensor: - """ - Ensures interchangeability with schedulers that need to scale the denoising model input depending on the - current timestep. - - Args: - sample (`torch.FloatTensor`): - The input sample. - timestep (`int`, *optional*): - The current timestep in the diffusion chain. - Returns: - `torch.FloatTensor`: - A scaled input sample. - """ - return sample - - # Copied from diffusers.schedulers.scheduling_ddpm.DDPMScheduler._threshold_sample - def _threshold_sample(self, sample: torch.FloatTensor) -> torch.FloatTensor: - """ - "Dynamic thresholding: At each sampling step we set s to a certain percentile absolute pixel value in xt0 (the - prediction of x_0 at timestep t), and if s > 1, then we threshold xt0 to the range [-s, s] and then divide by - s. Dynamic thresholding pushes saturated pixels (those near -1 and 1) inwards, thereby actively preventing - pixels from saturation at each step. We find that dynamic thresholding results in significantly better - photorealism as well as better image-text alignment, especially when using very large guidance weights." - - https://arxiv.org/abs/2205.11487 - """ - dtype = sample.dtype - batch_size, channels, *remaining_dims = sample.shape - - if dtype not in (torch.float32, torch.float64): - sample = ( - sample.float() - ) # upcast for quantile calculation, and clamp not implemented for cpu half - - # Flatten sample for doing quantile calculation along each image - sample = sample.reshape(batch_size, channels * np.prod(remaining_dims)) - - abs_sample = sample.abs() # "a certain percentile absolute pixel value" - - s = torch.quantile(abs_sample, self.config.dynamic_thresholding_ratio, dim=1) - s = torch.clamp( - s, min=1, max=self.config.sample_max_value - ) # When clamped to min=1, equivalent to standard clipping to [-1, 1] - s = s.unsqueeze(1) # (batch_size, 1) because clamp will broadcast along dim=0 - sample = ( - torch.clamp(sample, -s, s) / s - ) # "we threshold xt0 to the range [-s, s] and then divide by s" - - sample = sample.reshape(batch_size, channels, *remaining_dims) - sample = sample.to(dtype) - - return sample - - def set_timesteps( - self, - num_inference_steps: int, - device: Union[str, torch.device] = None, - original_inference_steps: Optional[int] = None, - ): - """ - Sets the discrete timesteps used for the diffusion chain (to be run before inference). - - Args: - num_inference_steps (`int`): - The number of diffusion steps used when generating samples with a pre-trained model. - device (`str` or `torch.device`, *optional*): - The device to which the timesteps should be moved to. If `None`, the timesteps are not moved. - original_inference_steps (`int`, *optional*): - The original number of inference steps, which will be used to generate a linearly-spaced timestep - schedule (which is different from the standard `diffusers` implementation). We will then take - `num_inference_steps` timesteps from this schedule, evenly spaced in terms of indices, and use that as - our final timestep schedule. If not set, this will default to the `original_inference_steps` attribute. - """ - - if num_inference_steps > self.config.num_train_timesteps: - raise ValueError( - f"`num_inference_steps`: {num_inference_steps} cannot be larger than `self.config.train_timesteps`:" - f" {self.config.num_train_timesteps} as the unet model trained with this scheduler can only handle" - f" maximal {self.config.num_train_timesteps} timesteps." - ) - - self.num_inference_steps = num_inference_steps - original_steps = ( - original_inference_steps - if original_inference_steps is not None - else self.original_inference_steps - ) - - if original_steps > self.config.num_train_timesteps: - raise ValueError( - f"`original_steps`: {original_steps} cannot be larger than `self.config.train_timesteps`:" - f" {self.config.num_train_timesteps} as the unet model trained with this scheduler can only handle" - f" maximal {self.config.num_train_timesteps} timesteps." - ) - - if num_inference_steps > original_steps: - raise ValueError( - f"`num_inference_steps`: {num_inference_steps} cannot be larger than `original_inference_steps`:" - f" {original_steps} because the final timestep schedule will be a subset of the" - f" `original_inference_steps`-sized initial timestep schedule." - ) - - # LCM Timesteps Setting - # Currently, only linear spacing is supported. - c = self.config.num_train_timesteps // original_steps - # LCM Training Steps Schedule - lcm_origin_timesteps = np.asarray(list(range(1, original_steps + 1))) * c - 1 - skipping_step = len(lcm_origin_timesteps) // num_inference_steps - # LCM Inference Steps Schedule - timesteps = lcm_origin_timesteps[::-skipping_step][:num_inference_steps] - - self.timesteps = torch.from_numpy(timesteps.copy()).to( - device=device, dtype=torch.long - ) - - self._step_index = None - - def get_scalings_for_boundary_condition_discrete(self, t): - self.sigma_data = 0.5 # Default: 0.5 - - # By dividing 0.1: This is almost a delta function at t=0. - c_skip = self.sigma_data**2 / ((t / 0.1) ** 2 + self.sigma_data**2) - c_out = (t / 0.1) / ((t / 0.1) ** 2 + self.sigma_data**2) ** 0.5 - return c_skip, c_out - - def step( - self, - model_output: torch.FloatTensor, - timestep: int, - sample: torch.FloatTensor, - generator: Optional[torch.Generator] = None, - return_dict: bool = True, - ) -> Union[LCMSchedulerOutput, Tuple]: - """ - Predict the sample from the previous timestep by reversing the SDE. This function propagates the diffusion - process from the learned model outputs (most often the predicted noise). - - Args: - model_output (`torch.FloatTensor`): - The direct output from learned diffusion model. - timestep (`float`): - The current discrete timestep in the diffusion chain. - sample (`torch.FloatTensor`): - A current instance of a sample created by the diffusion process. - generator (`torch.Generator`, *optional*): - A random number generator. - return_dict (`bool`, *optional*, defaults to `True`): - Whether or not to return a [`~schedulers.scheduling_lcm.LCMSchedulerOutput`] or `tuple`. - Returns: - [`~schedulers.scheduling_utils.LCMSchedulerOutput`] or `tuple`: - If return_dict is `True`, [`~schedulers.scheduling_lcm.LCMSchedulerOutput`] is returned, otherwise a - tuple is returned where the first element is the sample tensor. - """ - if self.num_inference_steps is None: - raise ValueError( - "Number of inference steps is 'None', you need to run 'set_timesteps' after creating the scheduler" - ) - - if self.step_index is None: - self._init_step_index(timestep) - - # 1. get previous step value - prev_step_index = self.step_index + 1 - if prev_step_index < len(self.timesteps): - prev_timestep = self.timesteps[prev_step_index] - else: - prev_timestep = timestep - - # 2. compute alphas, betas - alpha_prod_t = self.alphas_cumprod[timestep] - alpha_prod_t_prev = ( - self.alphas_cumprod[prev_timestep] - if prev_timestep >= 0 - else self.final_alpha_cumprod - ) - - beta_prod_t = 1 - alpha_prod_t - beta_prod_t_prev = 1 - alpha_prod_t_prev - - # 3. Get scalings for boundary conditions - c_skip, c_out = self.get_scalings_for_boundary_condition_discrete(timestep) - - # 4. Compute the predicted original sample x_0 based on the model parameterization - if self.config.prediction_type == "epsilon": # noise-prediction - predicted_original_sample = ( - sample - beta_prod_t.sqrt() * model_output - ) / alpha_prod_t.sqrt() - elif self.config.prediction_type == "sample": # x-prediction - predicted_original_sample = model_output - elif self.config.prediction_type == "v_prediction": # v-prediction - predicted_original_sample = ( - alpha_prod_t.sqrt() * sample - beta_prod_t.sqrt() * model_output - ) - else: - raise ValueError( - f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample` or" - " `v_prediction` for `LCMScheduler`." - ) - - # 5. Clip or threshold "predicted x_0" - if self.config.thresholding: - predicted_original_sample = self._threshold_sample( - predicted_original_sample - ) - elif self.config.clip_sample: - predicted_original_sample = predicted_original_sample.clamp( - -self.config.clip_sample_range, self.config.clip_sample_range - ) - - # 6. Denoise model output using boundary conditions - denoised = c_out * predicted_original_sample + c_skip * sample - - # 7. Sample and inject noise z ~ N(0, I) for MultiStep Inference - # Noise is not used for one-step sampling. - if len(self.timesteps) > 1: - noise = randn_tensor( - model_output.shape, generator=generator, device=model_output.device - ) - prev_sample = ( - alpha_prod_t_prev.sqrt() * denoised + beta_prod_t_prev.sqrt() * noise - ) - else: - prev_sample = denoised - - # upon completion increase step index by one - self._step_index += 1 - - if not return_dict: - return (prev_sample, denoised) - - return LCMSchedulerOutput(prev_sample=prev_sample, denoised=denoised) - - # Copied from diffusers.schedulers.scheduling_ddpm.DDPMScheduler.add_noise - def add_noise( - self, - original_samples: torch.FloatTensor, - noise: torch.FloatTensor, - timesteps: torch.IntTensor, - ) -> torch.FloatTensor: - # Make sure alphas_cumprod and timestep have same device and dtype as original_samples - alphas_cumprod = self.alphas_cumprod.to( - device=original_samples.device, dtype=original_samples.dtype - ) - timesteps = timesteps.to(original_samples.device) - - sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5 - sqrt_alpha_prod = sqrt_alpha_prod.flatten() - while len(sqrt_alpha_prod.shape) < len(original_samples.shape): - sqrt_alpha_prod = sqrt_alpha_prod.unsqueeze(-1) - - sqrt_one_minus_alpha_prod = (1 - alphas_cumprod[timesteps]) ** 0.5 - sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.flatten() - while len(sqrt_one_minus_alpha_prod.shape) < len(original_samples.shape): - sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.unsqueeze(-1) - - noisy_samples = ( - sqrt_alpha_prod * original_samples + sqrt_one_minus_alpha_prod * noise - ) - return noisy_samples - - # Copied from diffusers.schedulers.scheduling_ddpm.DDPMScheduler.get_velocity - def get_velocity( - self, - sample: torch.FloatTensor, - noise: torch.FloatTensor, - timesteps: torch.IntTensor, - ) -> torch.FloatTensor: - # Make sure alphas_cumprod and timestep have same device and dtype as sample - alphas_cumprod = self.alphas_cumprod.to( - device=sample.device, dtype=sample.dtype - ) - timesteps = timesteps.to(sample.device) - - sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5 - sqrt_alpha_prod = sqrt_alpha_prod.flatten() - while len(sqrt_alpha_prod.shape) < len(sample.shape): - sqrt_alpha_prod = sqrt_alpha_prod.unsqueeze(-1) - - sqrt_one_minus_alpha_prod = (1 - alphas_cumprod[timesteps]) ** 0.5 - sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.flatten() - while len(sqrt_one_minus_alpha_prod.shape) < len(sample.shape): - sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.unsqueeze(-1) - - velocity = sqrt_alpha_prod * noise - sqrt_one_minus_alpha_prod * sample - return velocity - - def __len__(self): - return self.config.num_train_timesteps diff --git a/backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc b/backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc deleted file mode 100644 index 1ac7caecfac9069235e06b6059fe70769fc47457..0000000000000000000000000000000000000000 Binary files a/backend/models/__pycache__/lcmdiffusion_setting.cpython-311.pyc and /dev/null differ diff --git a/backend/models/lcmdiffusion_setting.py b/backend/models/lcmdiffusion_setting.py deleted file mode 100644 index c11a7902d7159d15529bdc75e1e6b639d7fd6462..0000000000000000000000000000000000000000 --- a/backend/models/lcmdiffusion_setting.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Optional, Any -from enum import Enum -from pydantic import BaseModel -from constants import LCM_DEFAULT_MODEL, LCM_DEFAULT_MODEL_OPENVINO - - -class LCMLora(BaseModel): - base_model_id: str = "Lykon/dreamshaper-8" - lcm_lora_id: str = "latent-consistency/lcm-lora-sdv1-5" - - -class DiffusionTask(str, Enum): - """Diffusion task types""" - - text_to_image = "text_to_image" - image_to_image = "image_to_image" - - -class LCMDiffusionSetting(BaseModel): - lcm_model_id: str = LCM_DEFAULT_MODEL - openvino_lcm_model_id: str = LCM_DEFAULT_MODEL_OPENVINO - use_offline_model: bool = False - use_lcm_lora: bool = False - lcm_lora: Optional[LCMLora] = LCMLora() - use_tiny_auto_encoder: bool = False - use_openvino: bool = False - prompt: str = "" - negative_prompt: str = "" - init_image: Any = None - strength: Optional[float] = 0.6 - image_height: Optional[int] = 512 - image_width: Optional[int] = 512 - inference_steps: Optional[int] = 1 - guidance_scale: Optional[float] = 1 - number_of_images: Optional[int] = 1 - seed: Optional[int] = 123123 - use_seed: bool = False - use_safety_checker: bool = False - diffusion_task: str = DiffusionTask.text_to_image.value diff --git a/backend/openvino/custom_ov_model_vae_decoder.py b/backend/openvino/custom_ov_model_vae_decoder.py deleted file mode 100644 index ef83fb079f9956c80043cab04a65e114f7e56c66..0000000000000000000000000000000000000000 --- a/backend/openvino/custom_ov_model_vae_decoder.py +++ /dev/null @@ -1,21 +0,0 @@ -from backend.device import is_openvino_device - -if is_openvino_device(): - from optimum.intel.openvino.modeling_diffusion import OVModelVaeDecoder - - -class CustomOVModelVaeDecoder(OVModelVaeDecoder): - def __init__( - self, - model, - parent_model, - ov_config=None, - model_dir=None, - ): - super(OVModelVaeDecoder, self).__init__( - model, - parent_model, - ov_config, - "vae_decoder", - model_dir, - ) diff --git a/backend/openvino/pipelines.py b/backend/openvino/pipelines.py deleted file mode 100644 index 62d936dd7426bbe1dd7f43376bbfa61089cf0a8a..0000000000000000000000000000000000000000 --- a/backend/openvino/pipelines.py +++ /dev/null @@ -1,75 +0,0 @@ -from constants import DEVICE, LCM_DEFAULT_MODEL_OPENVINO -from backend.tiny_decoder import get_tiny_decoder_vae_model -from typing import Any -from backend.device import is_openvino_device -from paths import get_base_folder_name - -if is_openvino_device(): - from huggingface_hub import snapshot_download - from optimum.intel.openvino.modeling_diffusion import OVBaseModel - - from optimum.intel.openvino.modeling_diffusion import ( - OVStableDiffusionPipeline, - OVStableDiffusionImg2ImgPipeline, - OVStableDiffusionXLPipeline, - OVStableDiffusionXLImg2ImgPipeline, - ) - from backend.openvino.custom_ov_model_vae_decoder import CustomOVModelVaeDecoder - - -def ov_load_taesd( - pipeline: Any, - use_local_model: bool = False, -): - taesd_dir = snapshot_download( - repo_id=get_tiny_decoder_vae_model(pipeline.__class__.__name__), - local_files_only=use_local_model, - ) - pipeline.vae_decoder = CustomOVModelVaeDecoder( - model=OVBaseModel.load_model(f"{taesd_dir}/vae_decoder/openvino_model.xml"), - parent_model=pipeline, - model_dir=taesd_dir, - ) - - -def get_ov_text_to_image_pipeline( - model_id: str = LCM_DEFAULT_MODEL_OPENVINO, - use_local_model: bool = False, -) -> Any: - if "xl" in get_base_folder_name(model_id).lower(): - pipeline = OVStableDiffusionXLPipeline.from_pretrained( - model_id, - local_files_only=use_local_model, - ov_config={"CACHE_DIR": ""}, - device=DEVICE.upper(), - ) - else: - pipeline = OVStableDiffusionPipeline.from_pretrained( - model_id, - local_files_only=use_local_model, - ov_config={"CACHE_DIR": ""}, - device=DEVICE.upper(), - ) - - return pipeline - - -def get_ov_image_to_image_pipeline( - model_id: str = LCM_DEFAULT_MODEL_OPENVINO, - use_local_model: bool = False, -) -> Any: - if "xl" in get_base_folder_name(model_id).lower(): - pipeline = OVStableDiffusionXLImg2ImgPipeline.from_pretrained( - model_id, - local_files_only=use_local_model, - ov_config={"CACHE_DIR": ""}, - device=DEVICE.upper(), - ) - else: - pipeline = OVStableDiffusionImg2ImgPipeline.from_pretrained( - model_id, - local_files_only=use_local_model, - ov_config={"CACHE_DIR": ""}, - device=DEVICE.upper(), - ) - return pipeline diff --git a/backend/pipelines/lcm.py b/backend/pipelines/lcm.py deleted file mode 100644 index 18fea2ae5033700b95fbc2530045fcfc58193bcb..0000000000000000000000000000000000000000 --- a/backend/pipelines/lcm.py +++ /dev/null @@ -1,90 +0,0 @@ -from constants import LCM_DEFAULT_MODEL -from diffusers import ( - DiffusionPipeline, - AutoencoderTiny, - UNet2DConditionModel, - LCMScheduler, -) -import torch -from backend.tiny_decoder import get_tiny_decoder_vae_model -from typing import Any -from diffusers import ( - LCMScheduler, - StableDiffusionImg2ImgPipeline, - StableDiffusionXLImg2ImgPipeline, -) - - -def _get_lcm_pipeline_from_base_model( - lcm_model_id: str, - base_model_id: str, - use_local_model: bool, -): - pipeline = None - unet = UNet2DConditionModel.from_pretrained( - lcm_model_id, - torch_dtype=torch.float32, - local_files_only=use_local_model, - ) - pipeline = DiffusionPipeline.from_pretrained( - base_model_id, - unet=unet, - torch_dtype=torch.float32, - local_files_only=use_local_model, - ) - pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config) - return pipeline - - -def load_taesd( - pipeline: Any, - use_local_model: bool = False, - torch_data_type: torch.dtype = torch.float32, -): - vae_model = get_tiny_decoder_vae_model(pipeline.__class__.__name__) - pipeline.vae = AutoencoderTiny.from_pretrained( - vae_model, - torch_dtype=torch_data_type, - local_files_only=use_local_model, - ) - - -def get_lcm_model_pipeline( - model_id: str = LCM_DEFAULT_MODEL, - use_local_model: bool = False, -): - pipeline = None - if model_id == "latent-consistency/lcm-sdxl": - pipeline = _get_lcm_pipeline_from_base_model( - model_id, - "stabilityai/stable-diffusion-xl-base-1.0", - use_local_model, - ) - - elif model_id == "latent-consistency/lcm-ssd-1b": - pipeline = _get_lcm_pipeline_from_base_model( - model_id, - "segmind/SSD-1B", - use_local_model, - ) - else: - pipeline = DiffusionPipeline.from_pretrained( - model_id, - local_files_only=use_local_model, - ) - - return pipeline - - -def get_image_to_image_pipeline(pipeline: Any) -> Any: - components = pipeline.components - pipeline_class = pipeline.__class__.__name__ - if ( - pipeline_class == "LatentConsistencyModelPipeline" - or pipeline_class == "StableDiffusionPipeline" - ): - return StableDiffusionImg2ImgPipeline(**components) - elif pipeline_class == "StableDiffusionXLPipeline": - return StableDiffusionXLImg2ImgPipeline(**components) - else: - raise Exception(f"Unknown pipeline {pipeline_class}") diff --git a/backend/pipelines/lcm_lora.py b/backend/pipelines/lcm_lora.py deleted file mode 100644 index 96f8cb716ab0ea3438c8e80062a7e9ca70ddcc43..0000000000000000000000000000000000000000 --- a/backend/pipelines/lcm_lora.py +++ /dev/null @@ -1,25 +0,0 @@ -from diffusers import DiffusionPipeline, LCMScheduler -import torch - - -def get_lcm_lora_pipeline( - base_model_id: str, - lcm_lora_id: str, - use_local_model: bool, - torch_data_type: torch.dtype, -): - pipeline = DiffusionPipeline.from_pretrained( - base_model_id, - torch_dtype=torch_data_type, - local_files_only=use_local_model, - ) - pipeline.load_lora_weights( - lcm_lora_id, - local_files_only=use_local_model, - ) - if "lcm" in lcm_lora_id.lower(): - print("LCM LoRA model detected so using recommended LCMScheduler") - pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config) - pipeline.fuse_lora() - pipeline.unet.to(memory_format=torch.channels_last) - return pipeline diff --git a/backend/safety_check.py b/backend/safety_check.py deleted file mode 100644 index 46d971f39348fe3974568d522dbf9e663cc874f1..0000000000000000000000000000000000000000 --- a/backend/safety_check.py +++ /dev/null @@ -1,17 +0,0 @@ -from transformers import pipeline - - -def is_safe_image( - classifier, - image, -): - pred = classifier(image) - nsfw_score = 0 - normal_score = 0 - for label in pred: - if label["label"] == "nsfw": - nsfw_score = label["score"] - elif label["label"] == "normal": - normal_score = label["score"] - print(f"nsfw_score: {nsfw_score}, normal_score: {normal_score}") - return normal_score > nsfw_score diff --git a/backend/tiny_decoder.py b/backend/tiny_decoder.py deleted file mode 100644 index 40f4619fa722fde78dbda0ebf3a0d4317ef6232d..0000000000000000000000000000000000000000 --- a/backend/tiny_decoder.py +++ /dev/null @@ -1,30 +0,0 @@ -from constants import ( - TAESD_MODEL, - TAESDXL_MODEL, - TAESD_MODEL_OPENVINO, - TAESDXL_MODEL_OPENVINO, -) - - -def get_tiny_decoder_vae_model(pipeline_class) -> str: - print(f"Pipeline class : {pipeline_class}") - if ( - pipeline_class == "LatentConsistencyModelPipeline" - or pipeline_class == "StableDiffusionPipeline" - or pipeline_class == "StableDiffusionImg2ImgPipeline" - ): - return TAESD_MODEL - elif ( - pipeline_class == "StableDiffusionXLPipeline" - or pipeline_class == "StableDiffusionXLImg2ImgPipeline" - ): - return TAESDXL_MODEL - elif ( - pipeline_class == "OVStableDiffusionPipeline" - or pipeline_class == "OVStableDiffusionImg2ImgPipeline" - ): - return TAESD_MODEL_OPENVINO - elif pipeline_class == "OVStableDiffusionXLPipeline": - return TAESDXL_MODEL_OPENVINO - else: - raise Exception("No valid pipeline class found!") diff --git a/benchmark-openvino.bat b/benchmark-openvino.bat deleted file mode 100644 index c42dd4b3dfda63bca515f23a788ee5f417dbb2e4..0000000000000000000000000000000000000000 --- a/benchmark-openvino.bat +++ /dev/null @@ -1,23 +0,0 @@ -@echo off -setlocal - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% src/app.py -b --use_openvino --openvino_lcm_model_id "rupeshs/sd-turbo-openvino" \ No newline at end of file diff --git a/benchmark.bat b/benchmark.bat deleted file mode 100644 index 97e8d9da773696f2ce57e69572fa9973977b3f7e..0000000000000000000000000000000000000000 --- a/benchmark.bat +++ /dev/null @@ -1,23 +0,0 @@ -@echo off -setlocal - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% src/app.py -b \ No newline at end of file diff --git a/configs/lcm-lora-models.txt b/configs/lcm-lora-models.txt deleted file mode 100644 index f252571ecfc0936d6374e83c3cdfd2f87508ff69..0000000000000000000000000000000000000000 --- a/configs/lcm-lora-models.txt +++ /dev/null @@ -1,4 +0,0 @@ -latent-consistency/lcm-lora-sdv1-5 -latent-consistency/lcm-lora-sdxl -latent-consistency/lcm-lora-ssd-1b -rupeshs/hypersd-sd1-5-1-step-lora \ No newline at end of file diff --git a/configs/lcm-models.txt b/configs/lcm-models.txt deleted file mode 100644 index 9721ed6f43a6ccc00d3cd456d44f6632674e359c..0000000000000000000000000000000000000000 --- a/configs/lcm-models.txt +++ /dev/null @@ -1,8 +0,0 @@ -stabilityai/sd-turbo -rupeshs/sdxs-512-0.9-orig-vae -rupeshs/hyper-sd-sdxl-1-step -rupeshs/SDXL-Lightning-2steps -stabilityai/sdxl-turbo -SimianLuo/LCM_Dreamshaper_v7 -latent-consistency/lcm-sdxl -latent-consistency/lcm-ssd-1b \ No newline at end of file diff --git a/configs/openvino-lcm-models.txt b/configs/openvino-lcm-models.txt deleted file mode 100644 index 656096d1bbabe6472a65869773b14a6c5bb9ec62..0000000000000000000000000000000000000000 --- a/configs/openvino-lcm-models.txt +++ /dev/null @@ -1,9 +0,0 @@ -rupeshs/sd-turbo-openvino -rupeshs/sdxs-512-0.9-openvino -rupeshs/hyper-sd-sdxl-1-step-openvino-int8 -rupeshs/SDXL-Lightning-2steps-openvino-int8 -rupeshs/sdxl-turbo-openvino-int8 -rupeshs/LCM-dreamshaper-v7-openvino -Disty0/LCM_SoteMix -rupeshs/FLUX.1-schnell-openvino-int4 -rupeshs/sd15-lcm-square-openvino-int8 \ No newline at end of file diff --git a/configs/stable-diffusion-models.txt b/configs/stable-diffusion-models.txt deleted file mode 100644 index d5d21c9c5e64bb55c642243d27c230f04c6aab58..0000000000000000000000000000000000000000 --- a/configs/stable-diffusion-models.txt +++ /dev/null @@ -1,7 +0,0 @@ -Lykon/dreamshaper-8 -Fictiverse/Stable_Diffusion_PaperCut_Model -stabilityai/stable-diffusion-xl-base-1.0 -runwayml/stable-diffusion-v1-5 -segmind/SSD-1B -stablediffusionapi/anything-v5 -prompthero/openjourney-v4 \ No newline at end of file diff --git a/constants.py b/constants.py deleted file mode 100644 index 9e49573c7ebbab4b1d20659559c5a67057381a81..0000000000000000000000000000000000000000 --- a/constants.py +++ /dev/null @@ -1,25 +0,0 @@ -from os import environ, cpu_count - -cpu_cores = cpu_count() -cpus = cpu_cores // 2 if cpu_cores else 0 -APP_VERSION = "v1.0.0 beta 200" -LCM_DEFAULT_MODEL = "stabilityai/sd-turbo" -LCM_DEFAULT_MODEL_OPENVINO = "rupeshs/sd-turbo-openvino" -APP_NAME = "FastSD CPU" -APP_SETTINGS_FILE = "settings.yaml" -RESULTS_DIRECTORY = "results" -CONFIG_DIRECTORY = "configs" -DEVICE = environ.get("DEVICE", "cpu") -SD_MODELS_FILE = "stable-diffusion-models.txt" -LCM_LORA_MODELS_FILE = "lcm-lora-models.txt" -OPENVINO_LCM_MODELS_FILE = "openvino-lcm-models.txt" -TAESD_MODEL = "madebyollin/taesd" -TAESDXL_MODEL = "madebyollin/taesdxl" -TAESD_MODEL_OPENVINO = "rupeshs/taesd-ov" -LCM_MODELS_FILE = "lcm-models.txt" -TAESDXL_MODEL_OPENVINO = "rupeshs/taesdxl-openvino" -LORA_DIRECTORY = "lora_models" -CONTROLNET_DIRECTORY = "controlnet_models" -MODELS_DIRECTORY = "models" -GGUF_THREADS = environ.get("GGUF_THREADS", cpus) -TAEF1_MODEL_OPENVINO = "rupeshs/taef1-openvino" diff --git a/context.py b/context.py deleted file mode 100644 index 9fa3f695b31d071acaa886dd928e9f8931cee1d3..0000000000000000000000000000000000000000 --- a/context.py +++ /dev/null @@ -1,47 +0,0 @@ -from typing import Any -from app_settings import Settings -from models.interface_types import InterfaceType -from backend.lcm_text_to_image import LCMTextToImage -from time import perf_counter -from backend.image_saver import ImageSaver -from pprint import pprint - - -class Context: - def __init__( - self, - interface_type: InterfaceType, - device="cpu", - ): - self.interface_type = interface_type - self.lcm_text_to_image = LCMTextToImage(device) - - def generate_text_to_image( - self, - settings: Settings, - reshape: bool = False, - device: str = "cpu", - ) -> Any: - tick = perf_counter() - from state import get_settings - - get_settings().save() - pprint(settings.lcm_diffusion_setting.model_dump()) - if not settings.lcm_diffusion_setting.lcm_lora: - return None - self.lcm_text_to_image.init( - device, - settings.lcm_diffusion_setting, - ) - images = self.lcm_text_to_image.generate( - settings.lcm_diffusion_setting, - reshape, - ) - elapsed = perf_counter() - tick - # ImageSaver.save_images( - # settings.results_path, - # images=images, - # lcm_diffusion_setting=settings.lcm_diffusion_setting, - # ) - print(f"Latency : {elapsed:.2f} seconds") - return images diff --git a/controlnet_models/Readme.txt b/controlnet_models/Readme.txt deleted file mode 100644 index fdf39a3d9ae7982663447fff8c0b38edcd91353c..0000000000000000000000000000000000000000 --- a/controlnet_models/Readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Place your ControlNet models in this folder. -You can download controlnet model (.safetensors) from https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/tree/main -E.g: https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/blob/main/control_v11p_sd15_canny_fp16.safetensors \ No newline at end of file diff --git a/docs/images/2steps-inference.jpg b/docs/images/2steps-inference.jpg deleted file mode 100644 index 31539c68c6a2301a8688cc28e52612107f777d0e..0000000000000000000000000000000000000000 --- a/docs/images/2steps-inference.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd0a36195619b4d29a92a1a7c0ee446b7a37caef1097bbaf23e38a0043884426 -size 73231 diff --git a/docs/images/ARCGPU.png b/docs/images/ARCGPU.png deleted file mode 100644 index 59986e55669aa37429e06ece0b64586d6fcb62f9..0000000000000000000000000000000000000000 --- a/docs/images/ARCGPU.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9497008babdfd2cc2b5c2c1e58b435e94cbe69406e2ce7e18ea70cc638f7776e -size 51340 diff --git a/docs/images/fastcpu-cli.png b/docs/images/fastcpu-cli.png deleted file mode 100644 index f559783d1344eaadaf36be0627d459d2a0ebe79b..0000000000000000000000000000000000000000 --- a/docs/images/fastcpu-cli.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4a9d22055f37ef91b2b097871c5a632eaf2bb7431bbac2405ff487bfcc4a8499 -size 56613 diff --git a/docs/images/fastcpu-webui.png b/docs/images/fastcpu-webui.png deleted file mode 100644 index 8fbaae6d761978fab13c45d535235fed3878ce2a..0000000000000000000000000000000000000000 --- a/docs/images/fastcpu-webui.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d26b4e4bc41d515a730b757a6a984724aa59497235bf771b25e5a7d9c2d5680f -size 263249 diff --git a/docs/images/fastsdcpu-android-termux-pixel7.png b/docs/images/fastsdcpu-android-termux-pixel7.png deleted file mode 100644 index da4845a340ec3331f7e552558ece96c1968ac68a..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu-android-termux-pixel7.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e18187cb43b8e905971fd607e6640a66c2877d4dc135647425f3cb66d7f22ae -size 298843 diff --git a/docs/images/fastsdcpu-api.png b/docs/images/fastsdcpu-api.png deleted file mode 100644 index 8a40c386f1f61bb40bef89526ca395cd9c851bff..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu-api.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ed9600154d423cff4e3baaaf6da31f070cb401cf6a1b497e1987a6c5731907d -size 50697 diff --git a/docs/images/fastsdcpu-gui.jpg b/docs/images/fastsdcpu-gui.jpg deleted file mode 100644 index 698517415079debc82a55c4180f2472a3ed74679..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu-gui.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:03c1fe3b5ea4dfcc25654c4fc76fc392a59bdf668b1c45e5e6fc14edcf2fac5c -size 207258 diff --git a/docs/images/fastsdcpu-mac-gui.jpg b/docs/images/fastsdcpu-mac-gui.jpg deleted file mode 100644 index 3cb1c36ccaf33fbaa489c9c3e99dd471ac918c91..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu-mac-gui.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd6fedc02f2922b7817f6b078c72feae48a8227b69035926bbd15ebbbb2426bb -size 93250 diff --git a/docs/images/fastsdcpu-screenshot.png b/docs/images/fastsdcpu-screenshot.png deleted file mode 100644 index 4cfe1931059b4bf6c6218521883e218fd9a698c6..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu-screenshot.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3729a8a87629800c63ca98ed36c1a48c7c0bc64c02a144e396aca05e7c529ee6 -size 293249 diff --git a/docs/images/fastsdcpu-webui.png b/docs/images/fastsdcpu-webui.png deleted file mode 100644 index d5528d7a934cfcfbbf67c4598bd7506eadeae0d4..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu-webui.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b1378a52fab340ad566e69074f93af40a82f92afb29d8a3b27cbe218b5ee4bff -size 380162 diff --git a/docs/images/fastsdcpu_claude.jpg b/docs/images/fastsdcpu_claude.jpg deleted file mode 100644 index 3782d6141807787e40f43e08a52da586ad8bd546..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu_claude.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f1509224a6c0fbf39362b1332f99b5d65ebe52cd9927474dae44d25321bf8a0 -size 145020 diff --git a/docs/images/fastsdcpu_flux_on_cpu.png b/docs/images/fastsdcpu_flux_on_cpu.png deleted file mode 100644 index 53dc5ff72f7c442284133cb66e68a7bf665e4586..0000000000000000000000000000000000000000 --- a/docs/images/fastsdcpu_flux_on_cpu.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5e42851d654dc88a75e479cb6dcf25bc1e7a7463f7c2eb2a98ec77e2b3c74e06 -size 383111 diff --git a/docs/images/openwebui-fastsd.jpg b/docs/images/openwebui-fastsd.jpg deleted file mode 100644 index 4ee5c11fce0238b6c68f9fe2f3b481909feb312b..0000000000000000000000000000000000000000 --- a/docs/images/openwebui-fastsd.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d68627a2dc9e66971d6332563c3e1cdc552ca4a96360e69c1ceee5a067568889 -size 128433 diff --git a/docs/images/openwebui-settings.png b/docs/images/openwebui-settings.png deleted file mode 100644 index 5a2ca47b1bf9ecb9392b4b5386c5894835a35f9b..0000000000000000000000000000000000000000 --- a/docs/images/openwebui-settings.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b156920e2c0cfed9e6540ddbbdbbf7f8635efb7d7bd971b354e313431e85700 -size 43100 diff --git a/frontend/__pycache__/utils.cpython-311.pyc b/frontend/__pycache__/utils.cpython-311.pyc deleted file mode 100644 index 7e85f4b64b6359c02ab691b2ff7f85661ee4f3d8..0000000000000000000000000000000000000000 Binary files a/frontend/__pycache__/utils.cpython-311.pyc and /dev/null differ diff --git a/frontend/gui/__pycache__/app_window.cpython-311.pyc b/frontend/gui/__pycache__/app_window.cpython-311.pyc deleted file mode 100644 index 8fc32ea533bdbe62084218d892783139d296d509..0000000000000000000000000000000000000000 Binary files a/frontend/gui/__pycache__/app_window.cpython-311.pyc and /dev/null differ diff --git a/frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc b/frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc deleted file mode 100644 index ef460d421d4c71e1134babc77111ec34cca6ffb3..0000000000000000000000000000000000000000 Binary files a/frontend/gui/__pycache__/image_generator_worker.cpython-311.pyc and /dev/null differ diff --git a/frontend/gui/__pycache__/ui.cpython-311.pyc b/frontend/gui/__pycache__/ui.cpython-311.pyc deleted file mode 100644 index bed5535ac7b2ccca3e5b6495185c0312ab14ebcb..0000000000000000000000000000000000000000 Binary files a/frontend/gui/__pycache__/ui.cpython-311.pyc and /dev/null differ diff --git a/frontend/gui/app_window.py b/frontend/gui/app_window.py deleted file mode 100644 index bbdd6ce3f7b9d76227bba5b8c9bfee4344a707f2..0000000000000000000000000000000000000000 --- a/frontend/gui/app_window.py +++ /dev/null @@ -1,604 +0,0 @@ -from PyQt5.QtWidgets import ( - QWidget, - QPushButton, - QHBoxLayout, - QVBoxLayout, - QLabel, - QLineEdit, - QMainWindow, - QSlider, - QTabWidget, - QSpacerItem, - QSizePolicy, - QComboBox, - QCheckBox, - QTextEdit, - QToolButton, - QFileDialog, -) -from PyQt5 import QtWidgets, QtCore -from PyQt5.QtGui import QPixmap, QDesktopServices -from PyQt5.QtCore import QSize, QThreadPool, Qt, QUrl - -from PIL.ImageQt import ImageQt -from constants import ( - LCM_DEFAULT_MODEL, - LCM_DEFAULT_MODEL_OPENVINO, - APP_NAME, - APP_VERSION, -) -from frontend.gui.image_generator_worker import ImageGeneratorWorker -from app_settings import AppSettings -from paths import FastStableDiffusionPaths -from frontend.utils import is_reshape_required -from context import Context -from models.interface_types import InterfaceType -from constants import DEVICE -from frontend.utils import enable_openvino_controls, get_valid_model_id -from backend.models.lcmdiffusion_setting import DiffusionTask - -# DPI scale fix -QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) -QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) - - -class MainWindow(QMainWindow): - def __init__(self, config: AppSettings): - super().__init__() - self.config = config - self.setWindowTitle(APP_NAME) - self.setFixedSize(QSize(600, 670)) - self.init_ui() - self.pipeline = None - self.threadpool = QThreadPool() - self.device = "cpu" - self.previous_width = 0 - self.previous_height = 0 - self.previous_model = "" - self.previous_num_of_images = 0 - self.context = Context(InterfaceType.GUI) - self.init_ui_values() - self.gen_images = [] - self.image_index = 0 - print(f"Output path : { self.config.settings.results_path}") - - def init_ui_values(self): - self.lcm_model.setEnabled( - not self.config.settings.lcm_diffusion_setting.use_openvino - ) - self.guidance.setValue( - int(self.config.settings.lcm_diffusion_setting.guidance_scale * 10) - ) - self.seed_value.setEnabled(self.config.settings.lcm_diffusion_setting.use_seed) - self.safety_checker.setChecked( - self.config.settings.lcm_diffusion_setting.use_safety_checker - ) - self.use_openvino_check.setChecked( - self.config.settings.lcm_diffusion_setting.use_openvino - ) - self.width.setCurrentText( - str(self.config.settings.lcm_diffusion_setting.image_width) - ) - self.height.setCurrentText( - str(self.config.settings.lcm_diffusion_setting.image_height) - ) - self.inference_steps.setValue( - int(self.config.settings.lcm_diffusion_setting.inference_steps) - ) - self.seed_check.setChecked(self.config.settings.lcm_diffusion_setting.use_seed) - self.seed_value.setText(str(self.config.settings.lcm_diffusion_setting.seed)) - self.use_local_model_folder.setChecked( - self.config.settings.lcm_diffusion_setting.use_offline_model - ) - self.results_path.setText(self.config.settings.results_path) - self.num_images.setValue( - self.config.settings.lcm_diffusion_setting.number_of_images - ) - self.use_tae_sd.setChecked( - self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder - ) - self.use_lcm_lora.setChecked( - self.config.settings.lcm_diffusion_setting.use_lcm_lora - ) - self.lcm_model.setCurrentText( - get_valid_model_id( - self.config.lcm_models, - self.config.settings.lcm_diffusion_setting.lcm_model_id, - LCM_DEFAULT_MODEL, - ) - ) - self.base_model_id.setCurrentText( - get_valid_model_id( - self.config.stable_diffsuion_models, - self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id, - ) - ) - self.lcm_lora_id.setCurrentText( - get_valid_model_id( - self.config.lcm_lora_models, - self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id, - ) - ) - self.openvino_lcm_model_id.setCurrentText( - get_valid_model_id( - self.config.openvino_lcm_models, - self.config.settings.lcm_diffusion_setting.openvino_lcm_model_id, - LCM_DEFAULT_MODEL_OPENVINO, - ) - ) - self.neg_prompt.setEnabled( - self.config.settings.lcm_diffusion_setting.use_lcm_lora - or self.config.settings.lcm_diffusion_setting.use_openvino - ) - self.openvino_lcm_model_id.setEnabled( - self.config.settings.lcm_diffusion_setting.use_openvino - ) - - def init_ui(self): - self.create_main_tab() - self.create_settings_tab() - self.create_about_tab() - self.show() - - def create_main_tab(self): - self.img = QLabel("<>") - self.img.setAlignment(Qt.AlignCenter) - self.img.setFixedSize(QSize(512, 512)) - self.vspacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - - self.prompt = QTextEdit() - self.prompt.setPlaceholderText("A fantasy landscape") - self.prompt.setAcceptRichText(False) - self.neg_prompt = QTextEdit() - self.neg_prompt.setPlaceholderText("") - self.neg_prompt.setAcceptRichText(False) - self.neg_prompt_label = QLabel("Negative prompt (Set guidance scale > 1.0):") - self.generate = QPushButton("Generate") - self.generate.clicked.connect(self.text_to_image) - self.prompt.setFixedHeight(40) - self.neg_prompt.setFixedHeight(35) - self.browse_results = QPushButton("...") - self.browse_results.setFixedWidth(30) - self.browse_results.clicked.connect(self.on_open_results_folder) - self.browse_results.setToolTip("Open output folder") - - hlayout = QHBoxLayout() - hlayout.addWidget(self.neg_prompt) - hlayout.addWidget(self.generate) - hlayout.addWidget(self.browse_results) - - self.previous_img_btn = QToolButton() - self.previous_img_btn.setText("<") - self.previous_img_btn.clicked.connect(self.on_show_previous_image) - self.next_img_btn = QToolButton() - self.next_img_btn.setText(">") - self.next_img_btn.clicked.connect(self.on_show_next_image) - hlayout_nav = QHBoxLayout() - hlayout_nav.addWidget(self.previous_img_btn) - hlayout_nav.addWidget(self.img) - hlayout_nav.addWidget(self.next_img_btn) - - vlayout = QVBoxLayout() - vlayout.addLayout(hlayout_nav) - vlayout.addItem(self.vspacer) - vlayout.addWidget(self.prompt) - vlayout.addWidget(self.neg_prompt_label) - vlayout.addLayout(hlayout) - - self.tab_widget = QTabWidget(self) - self.tab_main = QWidget() - self.tab_settings = QWidget() - self.tab_about = QWidget() - self.tab_main.setLayout(vlayout) - - self.tab_widget.addTab(self.tab_main, "Text to Image") - self.tab_widget.addTab(self.tab_settings, "Settings") - self.tab_widget.addTab(self.tab_about, "About") - - self.setCentralWidget(self.tab_widget) - self.use_seed = False - - def create_settings_tab(self): - self.lcm_model_label = QLabel("Latent Consistency Model:") - # self.lcm_model = QLineEdit(LCM_DEFAULT_MODEL) - self.lcm_model = QComboBox(self) - self.lcm_model.addItems(self.config.lcm_models) - self.lcm_model.currentIndexChanged.connect(self.on_lcm_model_changed) - - self.use_lcm_lora = QCheckBox("Use LCM LoRA") - self.use_lcm_lora.setChecked(False) - self.use_lcm_lora.stateChanged.connect(self.use_lcm_lora_changed) - - self.lora_base_model_id_label = QLabel("Lora base model ID :") - self.base_model_id = QComboBox(self) - self.base_model_id.addItems(self.config.stable_diffsuion_models) - self.base_model_id.currentIndexChanged.connect(self.on_base_model_id_changed) - - self.lcm_lora_model_id_label = QLabel("LCM LoRA model ID :") - self.lcm_lora_id = QComboBox(self) - self.lcm_lora_id.addItems(self.config.lcm_lora_models) - self.lcm_lora_id.currentIndexChanged.connect(self.on_lcm_lora_id_changed) - - self.inference_steps_value = QLabel("Number of inference steps: 4") - self.inference_steps = QSlider(orientation=Qt.Orientation.Horizontal) - self.inference_steps.setMaximum(25) - self.inference_steps.setMinimum(1) - self.inference_steps.setValue(4) - self.inference_steps.valueChanged.connect(self.update_steps_label) - - self.num_images_value = QLabel("Number of images: 1") - self.num_images = QSlider(orientation=Qt.Orientation.Horizontal) - self.num_images.setMaximum(100) - self.num_images.setMinimum(1) - self.num_images.setValue(1) - self.num_images.valueChanged.connect(self.update_num_images_label) - - self.guidance_value = QLabel("Guidance scale: 1") - self.guidance = QSlider(orientation=Qt.Orientation.Horizontal) - self.guidance.setMaximum(20) - self.guidance.setMinimum(10) - self.guidance.setValue(10) - self.guidance.valueChanged.connect(self.update_guidance_label) - - self.width_value = QLabel("Width :") - self.width = QComboBox(self) - self.width.addItem("256") - self.width.addItem("512") - self.width.addItem("768") - self.width.addItem("1024") - self.width.setCurrentText("512") - self.width.currentIndexChanged.connect(self.on_width_changed) - - self.height_value = QLabel("Height :") - self.height = QComboBox(self) - self.height.addItem("256") - self.height.addItem("512") - self.height.addItem("768") - self.height.addItem("1024") - self.height.setCurrentText("512") - self.height.currentIndexChanged.connect(self.on_height_changed) - - self.seed_check = QCheckBox("Use seed") - self.seed_value = QLineEdit() - self.seed_value.setInputMask("9999999999") - self.seed_value.setText("123123") - self.seed_check.stateChanged.connect(self.seed_changed) - - self.safety_checker = QCheckBox("Use safety checker") - self.safety_checker.setChecked(True) - self.safety_checker.stateChanged.connect(self.use_safety_checker_changed) - - self.use_openvino_check = QCheckBox("Use OpenVINO") - self.use_openvino_check.setChecked(False) - self.openvino_model_label = QLabel("OpenVINO LCM model:") - self.use_local_model_folder = QCheckBox( - "Use locally cached model or downloaded model folder(offline)" - ) - self.openvino_lcm_model_id = QComboBox(self) - self.openvino_lcm_model_id.addItems(self.config.openvino_lcm_models) - self.openvino_lcm_model_id.currentIndexChanged.connect( - self.on_openvino_lcm_model_id_changed - ) - - self.use_openvino_check.setEnabled(enable_openvino_controls()) - self.use_local_model_folder.setChecked(False) - self.use_local_model_folder.stateChanged.connect(self.use_offline_model_changed) - self.use_openvino_check.stateChanged.connect(self.use_openvino_changed) - - self.use_tae_sd = QCheckBox( - "Use Tiny Auto Encoder - TAESD (Fast, moderate quality)" - ) - self.use_tae_sd.setChecked(False) - self.use_tae_sd.stateChanged.connect(self.use_tae_sd_changed) - - hlayout = QHBoxLayout() - hlayout.addWidget(self.seed_check) - hlayout.addWidget(self.seed_value) - hspacer = QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) - slider_hspacer = QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) - - self.results_path_label = QLabel("Output path:") - self.results_path = QLineEdit() - self.results_path.textChanged.connect(self.on_path_changed) - self.browse_folder_btn = QToolButton() - self.browse_folder_btn.setText("...") - self.browse_folder_btn.clicked.connect(self.on_browse_folder) - - self.reset = QPushButton("Reset All") - self.reset.clicked.connect(self.reset_all_settings) - - vlayout = QVBoxLayout() - vspacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) - vlayout.addItem(hspacer) - vlayout.setSpacing(3) - vlayout.addWidget(self.lcm_model_label) - vlayout.addWidget(self.lcm_model) - vlayout.addWidget(self.use_local_model_folder) - vlayout.addWidget(self.use_lcm_lora) - vlayout.addWidget(self.lora_base_model_id_label) - vlayout.addWidget(self.base_model_id) - vlayout.addWidget(self.lcm_lora_model_id_label) - vlayout.addWidget(self.lcm_lora_id) - vlayout.addWidget(self.use_openvino_check) - vlayout.addWidget(self.openvino_model_label) - vlayout.addWidget(self.openvino_lcm_model_id) - vlayout.addWidget(self.use_tae_sd) - vlayout.addItem(slider_hspacer) - vlayout.addWidget(self.inference_steps_value) - vlayout.addWidget(self.inference_steps) - vlayout.addWidget(self.num_images_value) - vlayout.addWidget(self.num_images) - vlayout.addWidget(self.width_value) - vlayout.addWidget(self.width) - vlayout.addWidget(self.height_value) - vlayout.addWidget(self.height) - vlayout.addWidget(self.guidance_value) - vlayout.addWidget(self.guidance) - vlayout.addLayout(hlayout) - vlayout.addWidget(self.safety_checker) - - vlayout.addWidget(self.results_path_label) - hlayout_path = QHBoxLayout() - hlayout_path.addWidget(self.results_path) - hlayout_path.addWidget(self.browse_folder_btn) - vlayout.addLayout(hlayout_path) - self.tab_settings.setLayout(vlayout) - hlayout_reset = QHBoxLayout() - hspacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) - hlayout_reset.addItem(hspacer) - hlayout_reset.addWidget(self.reset) - vlayout.addLayout(hlayout_reset) - vlayout.addItem(vspacer) - - def create_about_tab(self): - self.label = QLabel() - self.label.setAlignment(Qt.AlignCenter) - self.label.setText( - f"""

FastSD CPU {APP_VERSION}

-

(c)2023 - Rupesh Sreeraman

-

Faster stable diffusion on CPU

-

Based on Latent Consistency Models

-

GitHub : https://github.com/rupeshs/fastsdcpu/

""" - ) - - vlayout = QVBoxLayout() - vlayout.addWidget(self.label) - self.tab_about.setLayout(vlayout) - - def show_image(self, pixmap): - image_width = self.config.settings.lcm_diffusion_setting.image_width - image_height = self.config.settings.lcm_diffusion_setting.image_height - if image_width > 512 or image_height > 512: - new_width = 512 if image_width > 512 else image_width - new_height = 512 if image_height > 512 else image_height - self.img.setPixmap( - pixmap.scaled( - new_width, - new_height, - Qt.KeepAspectRatio, - ) - ) - else: - self.img.setPixmap(pixmap) - - def on_show_next_image(self): - if self.image_index != len(self.gen_images) - 1 and len(self.gen_images) > 0: - self.previous_img_btn.setEnabled(True) - self.image_index += 1 - self.show_image(self.gen_images[self.image_index]) - if self.image_index == len(self.gen_images) - 1: - self.next_img_btn.setEnabled(False) - - def on_open_results_folder(self): - QDesktopServices.openUrl(QUrl.fromLocalFile(self.config.settings.results_path)) - - def on_show_previous_image(self): - if self.image_index != 0: - self.next_img_btn.setEnabled(True) - self.image_index -= 1 - self.show_image(self.gen_images[self.image_index]) - if self.image_index == 0: - self.previous_img_btn.setEnabled(False) - - def on_path_changed(self, text): - self.config.settings.results_path = text - - def on_browse_folder(self): - options = QFileDialog.Options() - options |= QFileDialog.ShowDirsOnly - - folder_path = QFileDialog.getExistingDirectory( - self, "Select a Folder", "", options=options - ) - - if folder_path: - self.config.settings.results_path = folder_path - self.results_path.setText(folder_path) - - def on_width_changed(self, index): - width_txt = self.width.itemText(index) - self.config.settings.lcm_diffusion_setting.image_width = int(width_txt) - - def on_height_changed(self, index): - height_txt = self.height.itemText(index) - self.config.settings.lcm_diffusion_setting.image_height = int(height_txt) - - def on_lcm_model_changed(self, index): - model_id = self.lcm_model.itemText(index) - self.config.settings.lcm_diffusion_setting.lcm_model_id = model_id - - def on_base_model_id_changed(self, index): - model_id = self.base_model_id.itemText(index) - self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id = model_id - - def on_lcm_lora_id_changed(self, index): - model_id = self.lcm_lora_id.itemText(index) - self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = model_id - - def on_openvino_lcm_model_id_changed(self, index): - model_id = self.openvino_lcm_model_id.itemText(index) - self.config.settings.lcm_diffusion_setting.openvino_lcm_model_id = model_id - - def use_openvino_changed(self, state): - if state == 2: - self.lcm_model.setEnabled(False) - self.use_lcm_lora.setEnabled(False) - self.lcm_lora_id.setEnabled(False) - self.base_model_id.setEnabled(False) - self.neg_prompt.setEnabled(True) - self.openvino_lcm_model_id.setEnabled(True) - self.config.settings.lcm_diffusion_setting.use_openvino = True - else: - self.lcm_model.setEnabled(True) - self.use_lcm_lora.setEnabled(True) - self.lcm_lora_id.setEnabled(True) - self.base_model_id.setEnabled(True) - self.neg_prompt.setEnabled(False) - self.openvino_lcm_model_id.setEnabled(False) - self.config.settings.lcm_diffusion_setting.use_openvino = False - - def use_tae_sd_changed(self, state): - if state == 2: - self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder = True - else: - self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder = False - - def use_offline_model_changed(self, state): - if state == 2: - self.config.settings.lcm_diffusion_setting.use_offline_model = True - else: - self.config.settings.lcm_diffusion_setting.use_offline_model = False - - def use_lcm_lora_changed(self, state): - if state == 2: - self.lcm_model.setEnabled(False) - self.lcm_lora_id.setEnabled(True) - self.base_model_id.setEnabled(True) - self.neg_prompt.setEnabled(True) - self.config.settings.lcm_diffusion_setting.use_lcm_lora = True - else: - self.lcm_model.setEnabled(True) - self.lcm_lora_id.setEnabled(False) - self.base_model_id.setEnabled(False) - self.neg_prompt.setEnabled(False) - self.config.settings.lcm_diffusion_setting.use_lcm_lora = False - - def use_safety_checker_changed(self, state): - if state == 2: - self.config.settings.lcm_diffusion_setting.use_safety_checker = True - else: - self.config.settings.lcm_diffusion_setting.use_safety_checker = False - - def update_steps_label(self, value): - self.inference_steps_value.setText(f"Number of inference steps: {value}") - self.config.settings.lcm_diffusion_setting.inference_steps = value - - def update_num_images_label(self, value): - self.num_images_value.setText(f"Number of images: {value}") - self.config.settings.lcm_diffusion_setting.number_of_images = value - - def update_guidance_label(self, value): - val = round(int(value) / 10, 1) - self.guidance_value.setText(f"Guidance scale: {val}") - self.config.settings.lcm_diffusion_setting.guidance_scale = val - - def seed_changed(self, state): - if state == 2: - self.seed_value.setEnabled(True) - self.config.settings.lcm_diffusion_setting.use_seed = True - else: - self.seed_value.setEnabled(False) - self.config.settings.lcm_diffusion_setting.use_seed = False - - def get_seed_value(self) -> int: - use_seed = self.config.settings.lcm_diffusion_setting.use_seed - seed_value = int(self.seed_value.text()) if use_seed else -1 - return seed_value - - def generate_image(self): - self.config.settings.lcm_diffusion_setting.seed = self.get_seed_value() - self.config.settings.lcm_diffusion_setting.prompt = self.prompt.toPlainText() - self.config.settings.lcm_diffusion_setting.negative_prompt = ( - self.neg_prompt.toPlainText() - ) - self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = ( - self.lcm_lora_id.currentText() - ) - self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id = ( - self.base_model_id.currentText() - ) - - if self.config.settings.lcm_diffusion_setting.use_openvino: - model_id = self.openvino_lcm_model_id.currentText() - else: - model_id = self.lcm_model.currentText() - - self.config.settings.lcm_diffusion_setting.lcm_model_id = model_id - - reshape_required = False - if self.config.settings.lcm_diffusion_setting.use_openvino: - # Detect dimension change - reshape_required = is_reshape_required( - self.previous_width, - self.config.settings.lcm_diffusion_setting.image_width, - self.previous_height, - self.config.settings.lcm_diffusion_setting.image_height, - self.previous_model, - model_id, - self.previous_num_of_images, - self.config.settings.lcm_diffusion_setting.number_of_images, - ) - self.config.settings.lcm_diffusion_setting.diffusion_task = ( - DiffusionTask.text_to_image.value - ) - images = self.context.generate_text_to_image( - self.config.settings, - reshape_required, - DEVICE, - ) - self.image_index = 0 - self.gen_images = [] - for img in images: - im = ImageQt(img).copy() - pixmap = QPixmap.fromImage(im) - self.gen_images.append(pixmap) - - if len(self.gen_images) > 1: - self.next_img_btn.setEnabled(True) - self.previous_img_btn.setEnabled(False) - else: - self.next_img_btn.setEnabled(False) - self.previous_img_btn.setEnabled(False) - - self.show_image(self.gen_images[0]) - - self.previous_width = self.config.settings.lcm_diffusion_setting.image_width - self.previous_height = self.config.settings.lcm_diffusion_setting.image_height - self.previous_model = model_id - self.previous_num_of_images = ( - self.config.settings.lcm_diffusion_setting.number_of_images - ) - - def text_to_image(self): - self.img.setText("Please wait...") - worker = ImageGeneratorWorker(self.generate_image) - self.threadpool.start(worker) - - def closeEvent(self, event): - self.config.settings.lcm_diffusion_setting.seed = self.get_seed_value() - print(self.config.settings.lcm_diffusion_setting) - print("Saving settings") - self.config.save() - - def reset_all_settings(self): - self.use_local_model_folder.setChecked(False) - self.width.setCurrentText("512") - self.height.setCurrentText("512") - self.inference_steps.setValue(4) - self.guidance.setValue(10) - self.use_openvino_check.setChecked(False) - self.seed_check.setChecked(False) - self.safety_checker.setChecked(False) - self.results_path.setText(FastStableDiffusionPaths().get_results_path()) - self.use_tae_sd.setChecked(False) - self.use_lcm_lora.setChecked(False) diff --git a/frontend/gui/image_generator_worker.py b/frontend/gui/image_generator_worker.py deleted file mode 100644 index 3a948365085ece82337309ac91d278e77fa03e40..0000000000000000000000000000000000000000 --- a/frontend/gui/image_generator_worker.py +++ /dev/null @@ -1,37 +0,0 @@ -from PyQt5.QtCore import ( - pyqtSlot, - QRunnable, - pyqtSignal, - pyqtSlot, -) -from PyQt5.QtCore import QObject -import traceback -import sys - - -class WorkerSignals(QObject): - finished = pyqtSignal() - error = pyqtSignal(tuple) - result = pyqtSignal(object) - - -class ImageGeneratorWorker(QRunnable): - def __init__(self, fn, *args, **kwargs): - super(ImageGeneratorWorker, self).__init__() - self.fn = fn - self.args = args - self.kwargs = kwargs - self.signals = WorkerSignals() - - @pyqtSlot() - def run(self): - try: - result = self.fn(*self.args, **self.kwargs) - except: - traceback.print_exc() - exctype, value = sys.exc_info()[:2] - self.signals.error.emit((exctype, value, traceback.format_exc())) - else: - self.signals.result.emit(result) - finally: - self.signals.finished.emit() diff --git a/frontend/gui/ui.py b/frontend/gui/ui.py deleted file mode 100644 index 9250bf676da1f3dc8a2f5435095b9cec9b08041e..0000000000000000000000000000000000000000 --- a/frontend/gui/ui.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import List -from frontend.gui.app_window import MainWindow -from PyQt5.QtWidgets import QApplication -import sys -from app_settings import AppSettings - - -def start_gui( - argv: List[str], - app_settings: AppSettings, -): - app = QApplication(sys.argv) - window = MainWindow(app_settings) - window.show() - app.exec() diff --git a/frontend/utils.py b/frontend/utils.py deleted file mode 100644 index f7024d8fdcb0b2dbcc5b9de22b9562d853ddaf6e..0000000000000000000000000000000000000000 --- a/frontend/utils.py +++ /dev/null @@ -1,54 +0,0 @@ -from constants import DEVICE -from typing import List -import platform -from backend.device import is_openvino_device - - -def is_reshape_required( - prev_width: int, - cur_width: int, - prev_height: int, - cur_height: int, - prev_model: int, - cur_model: int, - prev_num_of_images: int, - cur_num_of_images: int, -) -> bool: - reshape_required = False - if ( - prev_width != cur_width - or prev_height != cur_height - or prev_model != cur_model - or prev_num_of_images != cur_num_of_images - ): - print("Reshape and compile") - reshape_required = True - - return reshape_required - - -def enable_openvino_controls() -> bool: - return is_openvino_device() and platform.system().lower() != "darwin" - - -def get_valid_model_id( - models: List, - model_id: str, - default_model: str = "", -) -> str: - if len(models) == 0: - print("Error: model configuration file is empty,please add some models.") - return "" - if model_id == "": - if default_model: - return default_model - else: - return models[0] - - if model_id in models: - return model_id - else: - print( - f"Error:{model_id} Model not found in configuration file,so using first model : {models[0]}" - ) - return models[0] diff --git a/frontend/webui/__pycache__/realtime_ui.cpython-311.pyc b/frontend/webui/__pycache__/realtime_ui.cpython-311.pyc deleted file mode 100644 index 7f43fff77f566aa4af1a2d2d8d8ef4df316fd934..0000000000000000000000000000000000000000 Binary files a/frontend/webui/__pycache__/realtime_ui.cpython-311.pyc and /dev/null differ diff --git a/frontend/webui/__pycache__/text_to_image_ui.cpython-311.pyc b/frontend/webui/__pycache__/text_to_image_ui.cpython-311.pyc deleted file mode 100644 index 49f27196968bd41ecbf00527e3206435943762e5..0000000000000000000000000000000000000000 Binary files a/frontend/webui/__pycache__/text_to_image_ui.cpython-311.pyc and /dev/null differ diff --git a/frontend/webui/__pycache__/ui.cpython-311.pyc b/frontend/webui/__pycache__/ui.cpython-311.pyc deleted file mode 100644 index 4e701415e5a79378e61f226893b235d7748c6a09..0000000000000000000000000000000000000000 Binary files a/frontend/webui/__pycache__/ui.cpython-311.pyc and /dev/null differ diff --git a/frontend/webui/css/style.css b/frontend/webui/css/style.css deleted file mode 100644 index 216e9f54bd789851bb1aa091cc8beaf98ddbe75d..0000000000000000000000000000000000000000 --- a/frontend/webui/css/style.css +++ /dev/null @@ -1,22 +0,0 @@ -footer { - visibility: hidden -} - -#generate_button { - color: white; - border-color: #007bff; - background: #2563eb; - -} - -#save_button { - color: white; - border-color: #028b40; - background: #01b97c; - width: 200px; -} - -#settings_header { - background: rgb(245, 105, 105); - -} \ No newline at end of file diff --git a/frontend/webui/generation_settings_ui.py b/frontend/webui/generation_settings_ui.py deleted file mode 100644 index 0262cc35d78aaded44d240063f6874d8a8f7bb2e..0000000000000000000000000000000000000000 --- a/frontend/webui/generation_settings_ui.py +++ /dev/null @@ -1,140 +0,0 @@ -import gradio as gr -from state import get_settings - -app_settings = get_settings() - - -def on_change_inference_steps(steps): - app_settings.settings.lcm_diffusion_setting.inference_steps = steps - - -def on_change_image_width(img_width): - app_settings.settings.lcm_diffusion_setting.image_width = img_width - - -def on_change_image_height(img_height): - app_settings.settings.lcm_diffusion_setting.image_height = img_height - - -def on_change_num_images(num_images): - app_settings.settings.lcm_diffusion_setting.number_of_images = num_images - - -def on_change_guidance_scale(guidance_scale): - app_settings.settings.lcm_diffusion_setting.guidance_scale = guidance_scale - - -def on_change_seed_value(seed): - app_settings.settings.lcm_diffusion_setting.seed = seed - - -def on_change_seed_checkbox(seed_checkbox): - app_settings.settings.lcm_diffusion_setting.use_seed = seed_checkbox - - -def on_change_safety_checker_checkbox(safety_checker_checkbox): - app_settings.settings.lcm_diffusion_setting.use_safety_checker = ( - safety_checker_checkbox - ) - - -def on_change_tiny_auto_encoder_checkbox(tiny_auto_encoder_checkbox): - app_settings.settings.lcm_diffusion_setting.use_tiny_auto_encoder = ( - tiny_auto_encoder_checkbox - ) - - -def on_offline_checkbox(offline_checkbox): - app_settings.settings.lcm_diffusion_setting.use_offline_model = offline_checkbox - - -def get_generation_settings_ui() -> None: - with gr.Blocks(): - with gr.Row(): - with gr.Column(): - num_inference_steps = gr.Slider( - 1, - 25, - value=app_settings.settings.lcm_diffusion_setting.inference_steps, - step=1, - label="Inference Steps", - interactive=True, - ) - - image_height = gr.Slider( - 256, - 1024, - value=app_settings.settings.lcm_diffusion_setting.image_height, - step=256, - label="Image Height", - interactive=True, - ) - image_width = gr.Slider( - 256, - 1024, - value=app_settings.settings.lcm_diffusion_setting.image_width, - step=256, - label="Image Width", - interactive=True, - ) - num_images = gr.Slider( - 1, - 50, - value=app_settings.settings.lcm_diffusion_setting.number_of_images, - step=1, - label="Number of images to generate", - interactive=True, - ) - guidance_scale = gr.Slider( - 1.0, - 2.0, - value=app_settings.settings.lcm_diffusion_setting.guidance_scale, - step=0.1, - label="Guidance Scale", - interactive=True, - ) - - seed = gr.Slider( - value=app_settings.settings.lcm_diffusion_setting.seed, - minimum=0, - maximum=999999999, - label="Seed", - step=1, - interactive=True, - ) - seed_checkbox = gr.Checkbox( - label="Use seed", - value=app_settings.settings.lcm_diffusion_setting.use_seed, - interactive=True, - ) - - safety_checker_checkbox = gr.Checkbox( - label="Use Safety Checker", - value=app_settings.settings.lcm_diffusion_setting.use_safety_checker, - interactive=True, - ) - tiny_auto_encoder_checkbox = gr.Checkbox( - label="Use tiny auto encoder for SD", - value=app_settings.settings.lcm_diffusion_setting.use_tiny_auto_encoder, - interactive=True, - ) - offline_checkbox = gr.Checkbox( - label="Use locally cached model or downloaded model folder(offline)", - value=app_settings.settings.lcm_diffusion_setting.use_offline_model, - interactive=True, - ) - - num_inference_steps.change(on_change_inference_steps, num_inference_steps) - image_height.change(on_change_image_height, image_height) - image_width.change(on_change_image_width, image_width) - num_images.change(on_change_num_images, num_images) - guidance_scale.change(on_change_guidance_scale, guidance_scale) - seed.change(on_change_seed_value, seed) - seed_checkbox.change(on_change_seed_checkbox, seed_checkbox) - safety_checker_checkbox.change( - on_change_safety_checker_checkbox, safety_checker_checkbox - ) - tiny_auto_encoder_checkbox.change( - on_change_tiny_auto_encoder_checkbox, tiny_auto_encoder_checkbox - ) - offline_checkbox.change(on_offline_checkbox, offline_checkbox) diff --git a/frontend/webui/hf_demo.py b/frontend/webui/hf_demo.py deleted file mode 100644 index 1194c30efc597ebb531858b06a22a513d147eb6d..0000000000000000000000000000000000000000 --- a/frontend/webui/hf_demo.py +++ /dev/null @@ -1,176 +0,0 @@ -import gradio as gr -from backend.lcm_text_to_image import LCMTextToImage -from backend.models.lcmdiffusion_setting import LCMLora, LCMDiffusionSetting -from constants import DEVICE, LCM_DEFAULT_MODEL_OPENVINO -from time import perf_counter -import numpy as np -from cv2 import imencode -import base64 -from backend.device import get_device_name -from constants import APP_VERSION -from backend.device import is_openvino_device -from PIL import Image -from backend.models.lcmdiffusion_setting import DiffusionTask -from backend.safety_check import is_safe_image -from pprint import pprint -from transformers import pipeline - -lcm_text_to_image = LCMTextToImage() -lcm_lora = LCMLora( - base_model_id="Lykon/dreamshaper-7", - lcm_lora_id="latent-consistency/lcm-lora-sdv1-5", -) -classifier = pipeline( - "image-classification", - model="Falconsai/nsfw_image_detection", -) - - -# https://github.com/gradio-app/gradio/issues/2635#issuecomment-1423531319 -def encode_pil_to_base64_new(pil_image): - image_arr = np.asarray(pil_image)[:, :, ::-1] - _, byte_data = imencode(".png", image_arr) - base64_data = base64.b64encode(byte_data) - base64_string_opencv = base64_data.decode("utf-8") - return "data:image/png;base64," + base64_string_opencv - - -# monkey patching encode pil -gr.processing_utils.encode_pil_to_base64 = encode_pil_to_base64_new - - -def predict( - prompt, - steps, - seed, - use_seed, -): - print(f"prompt - {prompt}") - lcm_diffusion_setting = LCMDiffusionSetting() - lcm_diffusion_setting.lcm_model_id = "rupeshs/hyper-sd-sdxl-1-step" - lcm_diffusion_setting.diffusion_task = DiffusionTask.text_to_image.value - lcm_diffusion_setting.openvino_lcm_model_id = "rupeshs/sd-turbo-openvino" - lcm_diffusion_setting.use_lcm_lora = False - lcm_diffusion_setting.prompt = prompt - lcm_diffusion_setting.guidance_scale = 1.0 - lcm_diffusion_setting.inference_steps = steps - lcm_diffusion_setting.seed = seed - lcm_diffusion_setting.use_seed = use_seed - lcm_diffusion_setting.use_safety_checker = True - lcm_diffusion_setting.use_tiny_auto_encoder = False - # lcm_diffusion_setting.image_width = 320 if is_openvino_device() else 512 - # lcm_diffusion_setting.image_height = 320 if is_openvino_device() else 512 - lcm_diffusion_setting.image_width = 512 - lcm_diffusion_setting.image_height = 512 - lcm_diffusion_setting.use_openvino = True - lcm_diffusion_setting.use_tiny_auto_encoder = True - pprint(lcm_diffusion_setting.model_dump()) - lcm_text_to_image.init(lcm_diffusion_setting=lcm_diffusion_setting) - start = perf_counter() - images = lcm_text_to_image.generate(lcm_diffusion_setting) - latency = perf_counter() - start - print(f"Latency: {latency:.2f} seconds") - result = images[0] - if is_safe_image( - classifier, - result, - ): - return result # .resize([512, 512], Image.LANCZOS) - else: - print("Unsafe image detected") - return Image.new("RGB", (512, 512), (0, 0, 0)) - - -css = """ -#container{ - margin: 0 auto; - max-width: 40rem; -} -#intro{ - max-width: 100%; - text-align: center; - margin: 0 auto; -} -#generate_button { - color: white; - border-color: #007bff; - background: #007bff; - width: 200px; - height: 50px; -} -footer { - visibility: hidden -} -""" - - -def _get_footer_message() -> str: - version = f"

{APP_VERSION} " - footer_msg = version + ( - ' © 2025 ' - " Rupesh Sreeraman

" - ) - warning_msg = "

Please note that this is a minimal demo app.


" - return warning_msg + footer_msg - - -with gr.Blocks(css=css) as demo: - with gr.Column(elem_id="container"): - use_openvino = "" if is_openvino_device() else "" - gr.Markdown( - f"""# FastSD CPU demo {use_openvino} - **Device : {DEVICE.upper()} , {get_device_name()} | OpenVINO** - """, - elem_id="intro", - ) - gr.HTML( - f""" - - """ - ) - - with gr.Row(): - with gr.Row(): - prompt = gr.Textbox( - placeholder="Describe the image you'd like to see", - scale=5, - container=False, - ) - generate_btn = gr.Button( - "Generate", - scale=1, - elem_id="generate_button", - ) - - image = gr.Image(type="filepath") - with gr.Accordion("Advanced options", open=False): - steps = gr.Slider( - label="Steps", - value=1, - minimum=1, - maximum=3, - step=1, - ) - seed = gr.Slider( - randomize=True, - minimum=0, - maximum=999999999, - label="Seed", - step=1, - ) - seed_checkbox = gr.Checkbox( - label="Use seed", - value=False, - interactive=True, - ) - gr.HTML(_get_footer_message()) - - inputs = [prompt, steps, seed, seed_checkbox] - generate_btn.click(fn=predict, inputs=inputs, outputs=image) - - -def start_demo_text_to_image(share=False): - demo.queue() - demo.launch(share=share) diff --git a/frontend/webui/image_to_image_ui.py b/frontend/webui/image_to_image_ui.py deleted file mode 100644 index ef081480b04e7f9b701d75d1823660416fab29d0..0000000000000000000000000000000000000000 --- a/frontend/webui/image_to_image_ui.py +++ /dev/null @@ -1,123 +0,0 @@ -from typing import Any -import gradio as gr -from backend.models.lcmdiffusion_setting import DiffusionTask -from models.interface_types import InterfaceType -from frontend.utils import is_reshape_required -from constants import DEVICE -from state import get_settings, get_context -from concurrent.futures import ThreadPoolExecutor - -app_settings = get_settings() - -context = get_context(InterfaceType.WEBUI) -previous_width = 0 -previous_height = 0 -previous_model_id = "" -previous_num_of_images = 0 - - -def generate_image_to_image( - prompt, - negative_prompt, - init_image, - strength, -) -> Any: - global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings - - app_settings.settings.lcm_diffusion_setting.prompt = prompt - app_settings.settings.lcm_diffusion_setting.negative_prompt = negative_prompt - app_settings.settings.lcm_diffusion_setting.init_image = init_image - app_settings.settings.lcm_diffusion_setting.strength = strength - - app_settings.settings.lcm_diffusion_setting.diffusion_task = ( - DiffusionTask.image_to_image.value - ) - model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id - reshape = False - image_width = app_settings.settings.lcm_diffusion_setting.image_width - image_height = app_settings.settings.lcm_diffusion_setting.image_height - num_images = app_settings.settings.lcm_diffusion_setting.number_of_images - if app_settings.settings.lcm_diffusion_setting.use_openvino: - reshape = is_reshape_required( - previous_width, - image_width, - previous_height, - image_height, - previous_model_id, - model_id, - previous_num_of_images, - num_images, - ) - - with ThreadPoolExecutor(max_workers=1) as executor: - future = executor.submit( - context.generate_text_to_image, - app_settings.settings, - reshape, - DEVICE, - ) - images = future.result() - # images = context.generate_text_to_image( - # app_settings.settings, - # reshape, - # DEVICE, - # ) - previous_width = image_width - previous_height = image_height - previous_model_id = model_id - previous_num_of_images = num_images - return images - - -def get_image_to_image_ui() -> None: - with gr.Blocks(): - with gr.Row(): - with gr.Column(): - input_image = gr.Image(label="Init image", type="pil") - with gr.Row(): - prompt = gr.Textbox( - show_label=False, - lines=3, - placeholder="A fantasy landscape", - container=False, - ) - - generate_btn = gr.Button( - "Generate", - elem_id="generate_button", - scale=0, - ) - negative_prompt = gr.Textbox( - label="Negative prompt (Works in LCM-LoRA mode, set guidance > 1.0):", - lines=1, - placeholder="", - ) - strength = gr.Slider( - 0.1, - 1, - value=app_settings.settings.lcm_diffusion_setting.strength, - step=0.01, - label="Strength", - ) - - input_params = [ - prompt, - negative_prompt, - input_image, - strength, - ] - - with gr.Column(): - output = gr.Gallery( - label="Generated images", - show_label=True, - elem_id="gallery", - columns=2, - height=512, - ) - - generate_btn.click( - fn=generate_image_to_image, - inputs=input_params, - outputs=output, - ) diff --git a/frontend/webui/image_variations_ui.py b/frontend/webui/image_variations_ui.py deleted file mode 100644 index 5de8589aaa2f227ac8af7ff09fb8fc8297434c5d..0000000000000000000000000000000000000000 --- a/frontend/webui/image_variations_ui.py +++ /dev/null @@ -1,105 +0,0 @@ -from typing import Any -import gradio as gr -from backend.models.lcmdiffusion_setting import DiffusionTask -from context import Context -from models.interface_types import InterfaceType -from frontend.utils import is_reshape_required -from constants import DEVICE -from state import get_settings, get_context -from concurrent.futures import ThreadPoolExecutor - -app_settings = get_settings() - -context = get_context(InterfaceType.WEBUI) -previous_width = 0 -previous_height = 0 -previous_model_id = "" -previous_num_of_images = 0 - - -def generate_image_variations( - init_image, - variation_strength, -) -> Any: - global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings - - app_settings.settings.lcm_diffusion_setting.init_image = init_image - app_settings.settings.lcm_diffusion_setting.strength = variation_strength - app_settings.settings.lcm_diffusion_setting.prompt = "" - app_settings.settings.lcm_diffusion_setting.negative_prompt = "" - - app_settings.settings.lcm_diffusion_setting.diffusion_task = ( - DiffusionTask.image_to_image.value - ) - model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id - reshape = False - image_width = app_settings.settings.lcm_diffusion_setting.image_width - image_height = app_settings.settings.lcm_diffusion_setting.image_height - num_images = app_settings.settings.lcm_diffusion_setting.number_of_images - if app_settings.settings.lcm_diffusion_setting.use_openvino: - reshape = is_reshape_required( - previous_width, - image_width, - previous_height, - image_height, - previous_model_id, - model_id, - previous_num_of_images, - num_images, - ) - - with ThreadPoolExecutor(max_workers=1) as executor: - future = executor.submit( - context.generate_text_to_image, - app_settings.settings, - reshape, - DEVICE, - ) - images = future.result() - - previous_width = image_width - previous_height = image_height - previous_model_id = model_id - previous_num_of_images = num_images - return images - - -def get_image_variations_ui() -> None: - with gr.Blocks(): - with gr.Row(): - with gr.Column(): - input_image = gr.Image(label="Init image", type="pil") - with gr.Row(): - generate_btn = gr.Button( - "Generate", - elem_id="generate_button", - scale=0, - ) - - variation_strength = gr.Slider( - 0.1, - 1, - value=0.4, - step=0.01, - label="Variations Strength", - ) - - input_params = [ - input_image, - variation_strength, - ] - - with gr.Column(): - output = gr.Gallery( - label="Generated images", - show_label=True, - elem_id="gallery", - columns=2, - height=512, - ) - - generate_btn.click( - fn=generate_image_variations, - inputs=input_params, - outputs=output, - ) diff --git a/frontend/webui/models_ui.py b/frontend/webui/models_ui.py deleted file mode 100644 index f5e8e6ca69a67422dd74773934dbd01532627d50..0000000000000000000000000000000000000000 --- a/frontend/webui/models_ui.py +++ /dev/null @@ -1,85 +0,0 @@ -from app_settings import AppSettings -from typing import Any -import gradio as gr -from constants import LCM_DEFAULT_MODEL, LCM_DEFAULT_MODEL_OPENVINO -from state import get_settings -from frontend.utils import get_valid_model_id - -app_settings = get_settings() -app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id = get_valid_model_id( - app_settings.openvino_lcm_models, - app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id, -) - - -def change_lcm_model_id(model_id): - app_settings.settings.lcm_diffusion_setting.lcm_model_id = model_id - - -def change_lcm_lora_model_id(model_id): - app_settings.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = model_id - - -def change_lcm_lora_base_model_id(model_id): - app_settings.settings.lcm_diffusion_setting.lcm_lora.base_model_id = model_id - - -def change_openvino_lcm_model_id(model_id): - app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id = model_id - - -def get_models_ui() -> None: - with gr.Blocks(): - with gr.Row(): - lcm_model_id = gr.Dropdown( - app_settings.lcm_models, - label="LCM model", - info="Diffusers LCM model ID", - value=get_valid_model_id( - app_settings.lcm_models, - app_settings.settings.lcm_diffusion_setting.lcm_model_id, - LCM_DEFAULT_MODEL, - ), - interactive=True, - ) - with gr.Row(): - lcm_lora_model_id = gr.Dropdown( - app_settings.lcm_lora_models, - label="LCM LoRA model", - info="Diffusers LCM LoRA model ID", - value=get_valid_model_id( - app_settings.lcm_lora_models, - app_settings.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id, - ), - interactive=True, - ) - lcm_lora_base_model_id = gr.Dropdown( - app_settings.stable_diffsuion_models, - label="LCM LoRA base model", - info="Diffusers LCM LoRA base model ID", - value=get_valid_model_id( - app_settings.stable_diffsuion_models, - app_settings.settings.lcm_diffusion_setting.lcm_lora.base_model_id, - ), - interactive=True, - ) - with gr.Row(): - lcm_openvino_model_id = gr.Dropdown( - app_settings.openvino_lcm_models, - label="LCM OpenVINO model", - info="OpenVINO LCM-LoRA fused model ID", - value=get_valid_model_id( - app_settings.openvino_lcm_models, - app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id, - ), - interactive=True, - ) - - lcm_model_id.change(change_lcm_model_id, lcm_model_id) - lcm_lora_model_id.change(change_lcm_lora_model_id, lcm_lora_model_id) - lcm_lora_base_model_id.change( - change_lcm_lora_base_model_id, lcm_lora_base_model_id - ) - lcm_openvino_model_id.change( - change_openvino_lcm_model_id, lcm_openvino_model_id - ) diff --git a/frontend/webui/realtime_ui.py b/frontend/webui/realtime_ui.py deleted file mode 100644 index 0a1214ddacc288cd83faff33992c7913be990ee7..0000000000000000000000000000000000000000 --- a/frontend/webui/realtime_ui.py +++ /dev/null @@ -1,144 +0,0 @@ -import gradio as gr -from backend.lcm_text_to_image import LCMTextToImage -from backend.models.lcmdiffusion_setting import LCMLora, LCMDiffusionSetting -from constants import DEVICE, LCM_DEFAULT_MODEL_OPENVINO -from time import perf_counter -import numpy as np -from cv2 import imencode -import base64 -from backend.device import get_device_name -from constants import APP_VERSION -from backend.device import is_openvino_device - -lcm_text_to_image = LCMTextToImage() -lcm_lora = LCMLora( - base_model_id="Lykon/dreamshaper-8", - lcm_lora_id="latent-consistency/lcm-lora-sdv1-5", -) - - -# https://github.com/gradio-app/gradio/issues/2635#issuecomment-1423531319 -def encode_pil_to_base64_new(pil_image): - image_arr = np.asarray(pil_image)[:, :, ::-1] - _, byte_data = imencode(".png", image_arr) - base64_data = base64.b64encode(byte_data) - base64_string_opencv = base64_data.decode("utf-8") - return "data:image/png;base64," + base64_string_opencv - - -# monkey patching encode pil -gr.processing_utils.encode_pil_to_base64 = encode_pil_to_base64_new - - -def predict( - prompt, - steps, - seed, -): - lcm_diffusion_setting = LCMDiffusionSetting() - lcm_diffusion_setting.openvino_lcm_model_id = "rupeshs/LCM-dreamshaper-v7-openvino" - lcm_diffusion_setting.prompt = prompt - lcm_diffusion_setting.guidance_scale = 1.0 - lcm_diffusion_setting.inference_steps = steps - lcm_diffusion_setting.seed = seed - lcm_diffusion_setting.use_seed = True - lcm_diffusion_setting.image_width = 256 if is_openvino_device() else 512 - lcm_diffusion_setting.image_height = 256 if is_openvino_device() else 512 - lcm_diffusion_setting.use_openvino = True if is_openvino_device() else False - lcm_text_to_image.init( - DEVICE, - lcm_diffusion_setting, - ) - start = perf_counter() - - images = lcm_text_to_image.generate(lcm_diffusion_setting) - latency = perf_counter() - start - print(f"Latency: {latency:.2f} seconds") - return images[0] - - -css = """ -#container{ - margin: 0 auto; - max-width: 40rem; -} -#intro{ - max-width: 100%; - text-align: center; - margin: 0 auto; -} -#generate_button { - color: white; - border-color: #007bff; - background: #007bff; - width: 200px; - height: 50px; -} -footer { - visibility: hidden -} -""" - - -def _get_footer_message() -> str: - version = f"

{APP_VERSION} " - footer_msg = version + ( - ' © 2023 ' - " Rupesh Sreeraman

" - ) - return footer_msg - - -with gr.Blocks(css=css) as demo: - with gr.Column(elem_id="container"): - use_openvino = "- OpenVINO" if is_openvino_device() else "" - gr.Markdown( - f"""# Realtime FastSD CPU {use_openvino} - **Device : {DEVICE} , {get_device_name()}** - """, - elem_id="intro", - ) - - with gr.Row(): - with gr.Row(): - prompt = gr.Textbox( - placeholder="Describe the image you'd like to see", - scale=5, - container=False, - ) - generate_btn = gr.Button( - "Generate", - scale=1, - elem_id="generate_button", - ) - - image = gr.Image(type="filepath") - with gr.Accordion("Advanced options", open=False): - steps = gr.Slider( - label="Steps", - value=4 if is_openvino_device() else 3, - minimum=1, - maximum=6, - step=1, - ) - seed = gr.Slider( - randomize=True, - minimum=0, - maximum=999999999, - label="Seed", - step=1, - ) - gr.HTML(_get_footer_message()) - - inputs = [prompt, steps, seed] - prompt.input(fn=predict, inputs=inputs, outputs=image, show_progress=False) - generate_btn.click( - fn=predict, inputs=inputs, outputs=image, show_progress=False - ) - steps.change(fn=predict, inputs=inputs, outputs=image, show_progress=False) - seed.change(fn=predict, inputs=inputs, outputs=image, show_progress=False) - - -def start_realtime_text_to_image(share=False): - demo.queue() - demo.launch(share=share) diff --git a/frontend/webui/text_to_image_ui.py b/frontend/webui/text_to_image_ui.py deleted file mode 100644 index 6624aa60442211345de561613030fe55c056b37f..0000000000000000000000000000000000000000 --- a/frontend/webui/text_to_image_ui.py +++ /dev/null @@ -1,103 +0,0 @@ -import gradio as gr -from typing import Any -from backend.models.lcmdiffusion_setting import DiffusionTask -from models.interface_types import InterfaceType -from constants import DEVICE -from state import get_settings, get_context -from frontend.utils import is_reshape_required -from concurrent.futures import ThreadPoolExecutor -from pprint import pprint - -app_settings = get_settings() -context = get_context(InterfaceType.WEBUI) -previous_width = 0 -previous_height = 0 -previous_model_id = "" -previous_num_of_images = 0 - - -def generate_text_to_image( - prompt, - neg_prompt, -) -> Any: - global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings - app_settings.settings.lcm_diffusion_setting.prompt = prompt - app_settings.settings.lcm_diffusion_setting.negative_prompt = neg_prompt - app_settings.settings.lcm_diffusion_setting.diffusion_task = ( - DiffusionTask.text_to_image.value - ) - model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id - reshape = False - image_width = app_settings.settings.lcm_diffusion_setting.image_width - image_height = app_settings.settings.lcm_diffusion_setting.image_height - num_images = app_settings.settings.lcm_diffusion_setting.number_of_images - if app_settings.settings.lcm_diffusion_setting.use_openvino: - reshape = is_reshape_required( - previous_width, - image_width, - previous_height, - image_height, - previous_model_id, - model_id, - previous_num_of_images, - num_images, - ) - - with ThreadPoolExecutor(max_workers=1) as executor: - future = executor.submit( - context.generate_text_to_image, - app_settings.settings, - reshape, - DEVICE, - ) - images = future.result() - # images = context.generate_text_to_image( - # app_settings.settings, - # reshape, - # DEVICE, - # ) - previous_width = image_width - previous_height = image_height - previous_model_id = model_id - previous_num_of_images = num_images - return images - - -def get_text_to_image_ui() -> None: - with gr.Blocks(): - with gr.Row(): - with gr.Column(): - with gr.Row(): - prompt = gr.Textbox( - show_label=False, - lines=3, - placeholder="A fantasy landscape", - container=False, - ) - - generate_btn = gr.Button( - "Generate", - elem_id="generate_button", - scale=0, - ) - negative_prompt = gr.Textbox( - label="Negative prompt (Works in LCM-LoRA mode, set guidance > 1.0) :", - lines=1, - placeholder="", - ) - - input_params = [prompt, negative_prompt] - - with gr.Column(): - output = gr.Gallery( - label="Generated images", - show_label=True, - elem_id="gallery", - columns=2, - height=512, - ) - generate_btn.click( - fn=generate_text_to_image, - inputs=input_params, - outputs=output, - ) diff --git a/frontend/webui/ui.py b/frontend/webui/ui.py deleted file mode 100644 index b5a409177a0920d8e62e5b12a43f44315058e4ba..0000000000000000000000000000000000000000 --- a/frontend/webui/ui.py +++ /dev/null @@ -1,73 +0,0 @@ -import gradio as gr -from constants import APP_VERSION -from frontend.webui.text_to_image_ui import get_text_to_image_ui -from frontend.webui.image_to_image_ui import get_image_to_image_ui -from frontend.webui.generation_settings_ui import get_generation_settings_ui -from frontend.webui.models_ui import get_models_ui -from frontend.webui.image_variations_ui import get_image_variations_ui -from paths import FastStableDiffusionPaths -from state import get_settings - -app_settings = get_settings() - - -def _get_footer_message() -> str: - version = f"

{APP_VERSION} " - footer_msg = version + ( - ' © 2023 ' - " Rupesh Sreeraman

" - ) - return footer_msg - - -def get_web_ui() -> gr.Blocks: - def change_mode(mode): - global app_settings - app_settings.settings.lcm_diffusion_setting.use_lcm_lora = False - app_settings.settings.lcm_diffusion_setting.use_openvino = False - if mode == "LCM-LoRA": - app_settings.settings.lcm_diffusion_setting.use_lcm_lora = True - elif mode == "LCM-OpenVINO": - app_settings.settings.lcm_diffusion_setting.use_openvino = True - - with gr.Blocks( - css=FastStableDiffusionPaths.get_css_path(), - title="FastSD CPU", - ) as fastsd_web_ui: - gr.HTML("

FastSD CPU

") - current_mode = "LCM" - if app_settings.settings.lcm_diffusion_setting.use_openvino: - current_mode = "LCM-OpenVINO" - elif app_settings.settings.lcm_diffusion_setting.use_lcm_lora: - current_mode = "LCM-LoRA" - - mode = gr.Radio( - ["LCM", "LCM-LoRA", "LCM-OpenVINO"], - label="Mode", - info="Current working mode", - value=current_mode, - ) - mode.change(change_mode, inputs=mode) - - with gr.Tabs(): - with gr.TabItem("Text to Image"): - get_text_to_image_ui() - with gr.TabItem("Image to Image"): - get_image_to_image_ui() - with gr.TabItem("Image Variations"): - get_image_variations_ui() - with gr.TabItem("Generation Settings"): - get_generation_settings_ui() - with gr.TabItem("Models"): - get_models_ui() - - gr.HTML(_get_footer_message()) - - return fastsd_web_ui - - -def start_webui( - share: bool = False, -): - webui = get_web_ui() - webui.launch(share=share) diff --git a/image_ops.py b/image_ops.py deleted file mode 100644 index b60e911d37616bf29592b15fca9901f404a6e397..0000000000000000000000000000000000000000 --- a/image_ops.py +++ /dev/null @@ -1,15 +0,0 @@ -from PIL import Image - - -def resize_pil_image( - pil_image: Image, - image_width, - image_height, -): - return pil_image.convert("RGB").resize( - ( - image_width, - image_height, - ), - Image.Resampling.LANCZOS, - ) diff --git a/install-mac.sh b/install-mac.sh deleted file mode 100644 index 617b32b1477b83921b6d428373ba6ec0dd7d8abc..0000000000000000000000000000000000000000 --- a/install-mac.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -echo Starting FastSD CPU env installation... -set -e -PYTHON_COMMAND="python3" - -if ! command -v python3 &>/dev/null; then - if ! command -v python &>/dev/null; then - echo "Error: Python not found, please install python 3.8 or higher and try again" - exit 1 - fi -fi - -if command -v python &>/dev/null; then - PYTHON_COMMAND="python" -fi - -echo "Found $PYTHON_COMMAND command" - -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version : $python_version" - -if ! command -v uv &>/dev/null; then - echo "Error: uv command not found,please install https://docs.astral.sh/uv/getting-started/installation/#__tabbed_1_1 ,for termux "pkg install uv" and try again." - exit 1 -fi - -BASEDIR=$(pwd) - -uv venv --python 3.11.6 "$BASEDIR/env" -# shellcheck disable=SC1091 -source "$BASEDIR/env/bin/activate" -uv pip install torch -uv pip install -r "$BASEDIR/requirements.txt" -chmod +x "start.sh" -chmod +x "start-webui.sh" -read -n1 -r -p "FastSD CPU installation completed,press any key to continue..." key \ No newline at end of file diff --git a/install.bat b/install.bat deleted file mode 100644 index 81ffda6bc4cc31fe344e45c63ca5366fb453a92d..0000000000000000000000000000000000000000 --- a/install.bat +++ /dev/null @@ -1,38 +0,0 @@ - -@echo off -setlocal -echo Starting FastSD CPU env installation... - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found,please install Python(Recommended : Python 3.10 or Python 3.11) and try again." - pause - exit /b 1 - -) - -call uv --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo uv command check :OK -) else ( - echo "Error: uv command not found,please install it using "pip install uv" command,for termux "pkg install uv" and try again." - pause - exit /b 1 - -) -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -uv venv --python 3.11.6 "%~dp0env" -call "%~dp0env\Scripts\activate.bat" && uv pip install torch --index-url https://download.pytorch.org/whl/cpu -call "%~dp0env\Scripts\activate.bat" && uv pip install -r "%~dp0requirements.txt" -echo FastSD CPU env installation completed. -pause \ No newline at end of file diff --git a/install.sh b/install.sh deleted file mode 100644 index 805e29b14f1be9b1939e27a0d959764700adc435..0000000000000000000000000000000000000000 --- a/install.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash -echo Starting FastSD CPU env installation... -set -e -PYTHON_COMMAND="python3" - -if ! command -v python3 &>/dev/null; then - if ! command -v python &>/dev/null; then - echo "Error: Python not found, please install python 3.8 or higher and try again" - exit 1 - fi -fi - -if command -v python &>/dev/null; then - PYTHON_COMMAND="python" -fi - -echo "Found $PYTHON_COMMAND command" - -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version : $python_version" - -if ! command -v uv &>/dev/null; then - echo "Error: uv command not found,please install https://docs.astral.sh/uv/getting-started/installation/#__tabbed_1_1 ,for termux "pkg install uv" and try again." - exit 1 -fi - -BASEDIR=$(pwd) - -uv venv --python 3.11.6 "$BASEDIR/env" -# shellcheck disable=SC1091 -source "$BASEDIR/env/bin/activate" -uv pip install torch==2.2.2 --index-url https://download.pytorch.org/whl/cpu -if [[ "$1" == "--disable-gui" ]]; then - #! For termux , we don't need Qt based GUI - packages="$(grep -v "^ *#\|^PyQt5" requirements.txt | grep .)" - # shellcheck disable=SC2086 - uv pip install $packages -else - uv pip install -r "$BASEDIR/requirements.txt" -fi - -chmod +x "start.sh" -chmod +x "start-webui.sh" -read -n1 -r -p "FastSD CPU installation completed,press any key to continue..." key \ No newline at end of file diff --git a/lora_models/Readme.txt b/lora_models/Readme.txt deleted file mode 100644 index e4748a642837930fdcb903e42273ffaf5ccda888..0000000000000000000000000000000000000000 --- a/lora_models/Readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Place your lora models in this folder. -You can download lora model (.safetensors/Safetensor) from Civitai (https://civitai.com/) or Hugging Face(https://huggingface.co/) -E.g: https://civitai.com/models/207984/cutecartoonredmond-15v-cute-cartoon-lora-for-liberteredmond-sd-15?modelVersionId=234192 \ No newline at end of file diff --git a/models/__pycache__/interface_types.cpython-311.pyc b/models/__pycache__/interface_types.cpython-311.pyc deleted file mode 100644 index 8a2500af01c19ce6f6172fb154ccfe587a6c206c..0000000000000000000000000000000000000000 Binary files a/models/__pycache__/interface_types.cpython-311.pyc and /dev/null differ diff --git a/models/__pycache__/settings.cpython-311.pyc b/models/__pycache__/settings.cpython-311.pyc deleted file mode 100644 index 13d0f6549e04110ce579e00325a9c5c7f4cad903..0000000000000000000000000000000000000000 Binary files a/models/__pycache__/settings.cpython-311.pyc and /dev/null differ diff --git a/models/gguf/clip/readme.txt b/models/gguf/clip/readme.txt deleted file mode 100644 index 48b307e2be7fbaf7cce08d578e8c8e7e6037936f..0000000000000000000000000000000000000000 --- a/models/gguf/clip/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Place CLIP model files here" diff --git a/models/gguf/diffusion/readme.txt b/models/gguf/diffusion/readme.txt deleted file mode 100644 index 4625665b369085b5941d284b63b42afd3c22629a..0000000000000000000000000000000000000000 --- a/models/gguf/diffusion/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Place your diffusion gguf model files here diff --git a/models/gguf/t5xxl/readme.txt b/models/gguf/t5xxl/readme.txt deleted file mode 100644 index e9c586e46a0201cef38fc5a759a730eab48086d0..0000000000000000000000000000000000000000 --- a/models/gguf/t5xxl/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Place T5-XXL model files here diff --git a/models/gguf/vae/readme.txt b/models/gguf/vae/readme.txt deleted file mode 100644 index 15c39ec7f9d9ae275f6bceab50acd6bb9cf83714..0000000000000000000000000000000000000000 --- a/models/gguf/vae/readme.txt +++ /dev/null @@ -1 +0,0 @@ -Place VAE model files here diff --git a/models/interface_types.py b/models/interface_types.py deleted file mode 100644 index fcab144facabbf7342331129410183ea0b6075ee..0000000000000000000000000000000000000000 --- a/models/interface_types.py +++ /dev/null @@ -1,7 +0,0 @@ -from enum import Enum - - -class InterfaceType(Enum): - WEBUI = "Web User Interface" - GUI = "Graphical User Interface" - CLI = "Command Line Interface" diff --git a/models/settings.py b/models/settings.py deleted file mode 100644 index f72dde5e7d27ff8b53e7d7497fdb05f702df23ea..0000000000000000000000000000000000000000 --- a/models/settings.py +++ /dev/null @@ -1,8 +0,0 @@ -from pydantic import BaseModel -from backend.models.lcmdiffusion_setting import LCMDiffusionSetting, LCMLora -from paths import FastStableDiffusionPaths - - -class Settings(BaseModel): - results_path: str = FastStableDiffusionPaths().get_results_path() - lcm_diffusion_setting: LCMDiffusionSetting = LCMDiffusionSetting(lcm_lora=LCMLora()) diff --git a/paths.py b/paths.py deleted file mode 100644 index 2de5631faffd165999fcb75dc3302d89f6c52a1b..0000000000000000000000000000000000000000 --- a/paths.py +++ /dev/null @@ -1,61 +0,0 @@ -import os -import constants - - -def join_paths( - first_path: str, - second_path: str, -) -> str: - return os.path.join(first_path, second_path) - - -def get_app_path() -> str: - app_dir = os.path.dirname(__file__) - work_dir = os.path.dirname(app_dir) - return work_dir - - -def get_configs_path() -> str: - config_path = join_paths(get_app_path(), constants.CONFIG_DIRECTORY) - return config_path - - -class FastStableDiffusionPaths: - @staticmethod - def get_app_settings_path() -> str: - configs_path = get_configs_path() - settings_path = join_paths( - configs_path, - constants.APP_SETTINGS_FILE, - ) - return settings_path - - @staticmethod - def get_results_path() -> str: - results_path = join_paths(get_app_path(), constants.RESULTS_DIRECTORY) - return results_path - - @staticmethod - def get_css_path() -> str: - app_dir = os.path.dirname(__file__) - css_path = os.path.join( - app_dir, - "frontend", - "webui", - "css", - "style.css", - ) - return css_path - - @staticmethod - def get_models_config_path(model_config_file: str) -> str: - configs_path = get_configs_path() - models_path = join_paths( - configs_path, - model_config_file, - ) - return models_path - - -def get_base_folder_name(path: str) -> str: - return os.path.basename(path) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 152c7ea5ce2e89b210693374be56e3c8cc5684f9..0000000000000000000000000000000000000000 --- a/requirements.txt +++ /dev/null @@ -1,20 +0,0 @@ -accelerate==0.33.0 -diffusers==0.30.0 -transformers==4.41.2 -PyQt5 -Pillow==9.4.0 -openvino==2024.4.0 -optimum-intel==1.18.2 -onnx==1.16.0 -onnxruntime==1.17.3 -pydantic -typing-extensions==4.8.0 -pyyaml==6.0.1 -gradio==5.6.0 -peft==0.6.1 -opencv-python==4.8.1.78 -omegaconf==2.3.0 -controlnet-aux==0.0.7 -mediapipe>=0.10.9 -tomesd==0.1.3 -fastapi-mcp \ No newline at end of file diff --git a/start-mcpserver.bat b/start-mcpserver.bat deleted file mode 100644 index 6bc259d3ac411ec542bf756f9bb87ff4dc47626d..0000000000000000000000000000000000000000 --- a/start-mcpserver.bat +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal -echo Starting fastsdcpu... - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -set PATH=%PATH%;%~dp0env\Lib\site-packages\openvino\libs -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% "%~dp0\src\app.py" --mcp \ No newline at end of file diff --git a/start-mcpserver.sh b/start-mcpserver.sh deleted file mode 100644 index e12c495b3f524f1d28047e034ccd27bfdcf3f73c..0000000000000000000000000000000000000000 --- a/start-mcpserver.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -echo Starting FastSD CPU please wait... -set -e -PYTHON_COMMAND="python3" - -if ! command -v python3 &>/dev/null; then - if ! command -v python &>/dev/null; then - echo "Error: Python not found, please install python 3.8 or higher and try again" - exit 1 - fi -fi - -if command -v python &>/dev/null; then - PYTHON_COMMAND="python" -fi - -echo "Found $PYTHON_COMMAND command" - -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version : $python_version" - -BASEDIR=$(pwd) -# shellcheck disable=SC1091 -source "$BASEDIR/env/bin/activate" -$PYTHON_COMMAND src/app.py --mcp \ No newline at end of file diff --git a/start-realtime.bat b/start-realtime.bat deleted file mode 100644 index 060268beb597047e9ac2b08d9c6c3eaadf7d90a8..0000000000000000000000000000000000000000 --- a/start-realtime.bat +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal -echo Starting fastsdcpu... - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -set PATH=%PATH%;%~dp0env\Lib\site-packages\openvino\libs -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% "%~dp0\src\app.py" --r \ No newline at end of file diff --git a/start-realtime.sh b/start-realtime.sh deleted file mode 100644 index b5b9c4aed9a5c428e5310e095a2e30b233a3f2ed..0000000000000000000000000000000000000000 --- a/start-realtime.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -set -e # Exit immediately if a command exits with a non-zero status - -echo "Starting fastsdcpu..." - -PYTHON_COMMAND="python3" - -# Check if Python is installed -if command -v $PYTHON_COMMAND >/dev/null 2>&1; then - echo "Python command check: OK" -else - echo "Error: Python command not found, please install Python (Recommended: Python 3.10 or Python 3.11) and try again" - exit 1 -fi - -# Get Python version -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version: $python_version" - -echo $PATH -# Activate virtual environment and run the application -source "$(dirname "$0")/env/bin/activate" && $PYTHON_COMMAND "$(dirname "$0")/src/app.py" --r diff --git a/start-webserver.bat b/start-webserver.bat deleted file mode 100644 index 2228ee0dcb06da315c94fba9deb7589a9725df51..0000000000000000000000000000000000000000 --- a/start-webserver.bat +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal -echo Starting fastsdcpu... - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -set PATH=%PATH%;%~dp0env\Lib\site-packages\openvino\libs -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% "%~dp0\src\app.py" --api \ No newline at end of file diff --git a/start-webserver.sh b/start-webserver.sh deleted file mode 100644 index 29b40572df75d26f0c9f7aafbe5862990b60fc24..0000000000000000000000000000000000000000 --- a/start-webserver.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -echo Starting FastSD CPU please wait... -set -e -PYTHON_COMMAND="python3" - -if ! command -v python3 &>/dev/null; then - if ! command -v python &>/dev/null; then - echo "Error: Python not found, please install python 3.8 or higher and try again" - exit 1 - fi -fi - -if command -v python &>/dev/null; then - PYTHON_COMMAND="python" -fi - -echo "Found $PYTHON_COMMAND command" - -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version : $python_version" - -BASEDIR=$(pwd) -# shellcheck disable=SC1091 -source "$BASEDIR/env/bin/activate" -$PYTHON_COMMAND src/app.py --api \ No newline at end of file diff --git a/start-webui.bat b/start-webui.bat deleted file mode 100644 index 7db54c43784924ab96e45a885c793ec408274110..0000000000000000000000000000000000000000 --- a/start-webui.bat +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal -echo Starting fastsdcpu... - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -set PATH=%PATH%;%~dp0env\Lib\site-packages\openvino\libs -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% "%~dp0\src\app.py" -w \ No newline at end of file diff --git a/start-webui.sh b/start-webui.sh deleted file mode 100644 index 758cdfd1f9da69b68dabfd1c013baa5ac82eafd3..0000000000000000000000000000000000000000 --- a/start-webui.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -echo Starting FastSD CPU please wait... -set -e -PYTHON_COMMAND="python3" - -if ! command -v python3 &>/dev/null; then - if ! command -v python &>/dev/null; then - echo "Error: Python not found, please install python 3.8 or higher and try again" - exit 1 - fi -fi - -if command -v python &>/dev/null; then - PYTHON_COMMAND="python" -fi - -echo "Found $PYTHON_COMMAND command" - -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version : $python_version" - -BASEDIR=$(pwd) -# shellcheck disable=SC1091 -source "$BASEDIR/env/bin/activate" -$PYTHON_COMMAND src/app.py -w \ No newline at end of file diff --git a/start.bat b/start.bat deleted file mode 100644 index 886f7c27c48b5d365ee2229b399b98fcb16ddb76..0000000000000000000000000000000000000000 --- a/start.bat +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -setlocal -echo Starting fastsdcpu... - -set "PYTHON_COMMAND=python" - -call python --version > nul 2>&1 -if %errorlevel% equ 0 ( - echo Python command check :OK -) else ( - echo "Error: Python command not found, please install Python (Recommended : Python 3.10 or Python 3.11) and try again" - pause - exit /b 1 - -) - -:check_python_version -for /f "tokens=2" %%I in ('%PYTHON_COMMAND% --version 2^>^&1') do ( - set "python_version=%%I" -) - -echo Python version: %python_version% - -set PATH=%PATH%;%~dp0env\Lib\site-packages\openvino\libs -call "%~dp0env\Scripts\activate.bat" && %PYTHON_COMMAND% "%~dp0\src\app.py" --gui \ No newline at end of file diff --git a/start.sh b/start.sh deleted file mode 100644 index d35cbc7ec2474e096b32ea6d6a0c24343dc61f6b..0000000000000000000000000000000000000000 --- a/start.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -echo Starting FastSD CPU please wait... -set -e -PYTHON_COMMAND="python3" - -if ! command -v python3 &>/dev/null; then - if ! command -v python &>/dev/null; then - echo "Error: Python not found, please install python 3.8 or higher and try again" - exit 1 - fi -fi - -if command -v python &>/dev/null; then - PYTHON_COMMAND="python" -fi - -echo "Found $PYTHON_COMMAND command" - -python_version=$($PYTHON_COMMAND --version 2>&1 | awk '{print $2}') -echo "Python version : $python_version" - -BASEDIR=$(pwd) -# shellcheck disable=SC1091 -source "$BASEDIR/env/bin/activate" -$PYTHON_COMMAND src/app.py --gui \ No newline at end of file diff --git a/state.py b/state.py deleted file mode 100644 index 6c0c4d5599c192840646f8d655cc16e4fbb8c6b2..0000000000000000000000000000000000000000 --- a/state.py +++ /dev/null @@ -1,32 +0,0 @@ -from app_settings import AppSettings -from typing import Optional - -from context import Context -from models.interface_types import InterfaceType - - -class _AppState: - _instance: Optional["_AppState"] = None - settings: Optional[AppSettings] = None - context: Optional[Context] = None - - -def get_state() -> _AppState: - if _AppState._instance is None: - _AppState._instance = _AppState() - return _AppState._instance - - -def get_settings(skip_file: bool = False) -> AppSettings: - state = get_state() - if state.settings is None: - state.settings = AppSettings() - state.settings.load(skip_file) - return state.settings - - -def get_context(interface_type: InterfaceType) -> Context: - state = get_state() - if state.context is None: - state.context = Context(interface_type) - return state.context diff --git a/utils.py b/utils.py deleted file mode 100644 index f10f89c207833a7fdc86d11e0e4d0fffd402a739..0000000000000000000000000000000000000000 --- a/utils.py +++ /dev/null @@ -1,21 +0,0 @@ -import platform -from typing import List - - -def show_system_info(): - try: - print(f"Running on {platform.system()} platform") - print(f"OS: {platform.platform()}") - print(f"Processor: {platform.processor()}") - except Exception as ex: - print(f"Error ocurred while getting system information {ex}") - - -def get_models_from_text_file(file_path: str) -> List: - models = [] - with open(file_path, "r") as file: - lines = file.readlines() - for repo_id in lines: - if repo_id.strip() != "": - models.append(repo_id.strip()) - return models