Spaces:
Running
on
Zero
Running
on
Zero
| import torch | |
| from diffusers import ( | |
| DiffusionPipeline, | |
| AutoencoderTiny, | |
| AutoencoderKL, | |
| AutoPipelineForImage2Image, | |
| ) | |
| from flux_app.config import DTYPE, DEVICE, BASE_MODEL, TAEF1_MODEL, MAX_SEED # Absolute import | |
| from flux_app.utilities import calculate_shift, retrieve_timesteps, load_image_from_path, calculateDuration # Absolute import | |
| from flux_app.lora_handling import flux_pipe_call_that_returns_an_iterable_of_images # Absolute import | |
| import time | |
| from huggingface_hub import login | |
| import spaces | |
| # Ensure CUDA is available | |
| if not torch.cuda.is_available(): | |
| raise RuntimeError("CUDA is not available. Please run on a GPU-enabled environment.") | |
| class ModelManager: | |
| def __init__(self, hf_token=None): | |
| self.pipe = None | |
| self.pipe_i2i = None | |
| self.good_vae = None | |
| self.taef1 = None | |
| # Clear CUDA memory cache before loading models | |
| torch.cuda.empty_cache() | |
| if hf_token: | |
| login(token=hf_token) # Log in with the provided token | |
| self.initialize_models() | |
| def initialize_models(self): | |
| """Initializes the diffusion pipelines and autoencoders.""" | |
| self.taef1 = AutoencoderTiny.from_pretrained(TAEF1_MODEL, torch_dtype=DTYPE).to(DEVICE) | |
| self.good_vae = AutoencoderKL.from_pretrained(BASE_MODEL, subfolder="vae", torch_dtype=DTYPE).to(DEVICE) | |
| self.pipe = DiffusionPipeline.from_pretrained(BASE_MODEL, torch_dtype=DTYPE, vae=self.taef1).to(DEVICE) | |
| self.pipe_i2i = AutoPipelineForImage2Image.from_pretrained( | |
| BASE_MODEL, | |
| vae=self.good_vae, | |
| transformer=self.pipe.transformer, | |
| text_encoder=self.pipe.text_encoder, | |
| tokenizer=self.pipe.tokenizer, | |
| text_encoder_2=self.pipe.text_encoder_2, | |
| tokenizer_2=self.pipe.tokenizer_2, | |
| torch_dtype=DTYPE | |
| ).to(DEVICE) | |
| setattr(self.pipe, "flux_pipe_call_that_returns_an_iterable_of_images", self.process_images) | |
| def process_images(self, *args, **kwargs): | |
| return flux_pipe_call_that_returns_an_iterable_of_images(self.pipe, *args, **kwargs) | |
| def generate_image(self, prompt_mash, steps, seed, cfg_scale, width, height, lora_scale): | |
| """Generates an image using the FLUX pipeline.""" | |
| self.pipe.to(DEVICE) # Ensure pipeline is on GPU | |
| generator = torch.Generator(device=DEVICE).manual_seed(seed) | |
| with calculateDuration("Generating image"): | |
| for img in self.pipe.flux_pipe_call_that_returns_an_iterable_of_images( | |
| prompt=prompt_mash, | |
| num_inference_steps=steps, | |
| guidance_scale=cfg_scale, | |
| width=width, | |
| height=height, | |
| generator=generator, | |
| joint_attention_kwargs={"scale": lora_scale}, | |
| output_type="pil", | |
| good_vae=self.good_vae, | |
| ): | |
| yield img | |
| def generate_image_to_image(self, prompt_mash, image_input_path, image_strength, steps, cfg_scale, width, height, lora_scale, seed): | |
| """Generates an image using image-to-image processing.""" | |
| generator = torch.Generator(device=DEVICE).manual_seed(seed) | |
| self.pipe_i2i.to(DEVICE) | |
| image_input = load_image_from_path(image_input_path) | |
| final_image = self.pipe_i2i( | |
| prompt=prompt_mash, | |
| image=image_input, | |
| strength=image_strength, | |
| num_inference_steps=steps, | |
| guidance_scale=cfg_scale, | |
| width=width, | |
| height=height, | |
| generator=generator, | |
| joint_attention_kwargs={"scale": lora_scale}, | |
| output_type="pil", | |
| ).images[0] | |
| return final_image | |
| # Ensure the pipeline is properly initialized when running | |
| if __name__ == "__main__": | |
| model_manager = ModelManager() | |
| print("Model Manager initialized successfully with GPU support.") | |