import torch import gradio as gr from diffusers import DiffusionPipeline, AutoencoderTiny, AutoencoderKL from diffusers.utils import load_image import os import gc from PIL import Image import time # Initialize a dictionary to track LoRA usage loras = [ {"title": "Anime", "repo": "prithivMLmods/Canopus-LoRA-Flux-Anime", "trigger_word": "Anime style", "image": "https://huggingface.co/prithivMLmods/Canopus-LoRA-Flux-Anime/resolve/main/1.jpg"}, {"title": "PixelArt", "repo": "prithivMLmods/Canopus-LoRA-Flux-PixelArt", "trigger_word": "PixelArt style", "image": "https://huggingface.co/prithivMLmods/Canopus-LoRA-Flux-PixelArt/resolve/main/1.jpg"}, {"title": "Ghibli", "repo": "prithivMLmods/Canopus-LoRA-Flux-Ghibli", "trigger_word": "Ghibli style", "image": "https://huggingface.co/prithivMLmods/Canopus-LoRA-Flux-Ghibli/resolve/main/1.jpg"}, {"title": "Realistic", "repo": "prithivMLmods/Canopus-LoRA-Flux-Realistic", "trigger_word": "Realistic style", "image": "https://huggingface.co/prithivMLmods/Canopus-LoRA-Flux-Realistic/resolve/main/1.jpg"}, {"title": "Claymation", "repo": "prithivMLmods/Canopus-LoRA-Flux-Claymation", "trigger_word": "Claymation style", "image": "https://huggingface.co/prithivMLmods/Canopus-LoRA-Flux-Claymation/resolve/main/1.jpg"} ] lora_usage = {lora["title"]: 0 for lora in loras} # Device and dtype setup for CPU device = "cpu" dtype = torch.float32 # Use float32 for CPU compatibility # Initialize a single pipeline with CPU offloading base_model = "black-forest-labs/FLUX.1-dev" taef1 = AutoencoderTiny.from_pretrained("madebyollin/taef1", torch_dtype=dtype) good_vae = AutoencoderKL.from_pretrained("black-forest-labs/FLUX.1-dev", subfolder="vae", torch_dtype=dtype) pipe = DiffusionPipeline.from_pretrained( base_model, torch_dtype=dtype, vae=taef1, ) # Enable CPU offloading to reduce memory usage pipe.enable_model_cpu_offload() # Custom CSS css = """ #title { text-align: center; } #gen_column { display: flex; align-items: flex-end; } #gen_btn { height: 100%; } #gallery img { border-radius: 10px !important; border: 2px solid white !important; } #gallery .svelte-mg0r0q.selected img { border: 2px solid #00ff00 !important; } #progress { width: 100%; } #lora_list { font-size: 12px; } """ # Utility functions def calculateDuration(message): start_time = time.time() yield None end_time = time.time() duration = end_time - start_time print(f"{message}: {duration:.2f} seconds") def update_lora_info(selected_index, custom_lora): if selected_index is None and not custom_lora: return "Select a LoRA to get started!🧨", None, gr.Button(visible=False) if custom_lora: return f"**Custom LoRA**: {custom_lora}", custom_lora, gr.Button(visible=True) selected_lora = loras[selected_index] return f"**Selected LoRA**: {selected_lora['title']}\n**Trigger Word**: {selected_lora['trigger_word']}", None, gr.Button(visible=False) def remove_custom_lora(selected_index): return None, gr.HTML(visible=False), gr.Button(visible=False), gr.Markdown(value=update_lora_info(selected_index, None)[0]) # Image generation function (combined for both text-to-image and image-to-image) def generate_image( prompt_mash, image_input_path, image_strength, steps, seed, cfg_scale, width, height, lora_scale ): generator = torch.Generator(device=device).manual_seed(seed) # Configure pipeline for text-to-image or image-to-image kwargs = { "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": good_vae, } if image_input_path: image_input = load_image(image_input_path) kwargs.update({ "image": image_input, "strength": image_strength, }) with calculateDuration("Generating image-to-image"): result = pipe(**kwargs).images[0] else: with calculateDuration("Generating text-to-image"): result = pipe(**kwargs).images[0] # Clear memory after generation torch.cuda.empty_cache() # No effect on CPU, but harmless gc.collect() return result def run_lora(prompt, image_input, image_strength, cfg_scale, steps, selected_index, randomize_seed, seed, width, height, lora_scale): global lora_usage if selected_index is None: raise gr.Error("You must select a LoRA before proceeding.🧨") selected_lora = loras[selected_index] lora_path = selected_lora["repo"] trigger_word = selected_lora["trigger_word"] # Increment the usage counter for the selected LoRA lora_usage[selected_lora["title"]] += 1 pipe.unload_lora_weights() pipe.load_lora_weights(lora_path) if prompt == "": prompt = trigger_word else: prompt_mash = f"{prompt}, {trigger_word}" if randomize_seed: seed = int(time.time()) # Generate the image final_image = generate_image( prompt_mash, image_input, image_strength, steps, seed, cfg_scale, width, height, lora_scale ) return final_image, seed, gr.Markdown(value=f"**Seed**: {seed}", visible=True) def generate_usage_chart(): sorted_usage = sorted(lora_usage.items(), key=lambda x: x[1], reverse=True)[:5] labels = [item[0] for item in sorted_usage] data = [item[1] for item in sorted_usage] chart_config = { "type": "bar", "data": { "labels": labels, "datasets": [{ "label": "LoRA Usage Count", "data": data, "backgroundColor": [ "#4f46e5", # Indigo "#10b981", # Emerald "#f97316", # Orange "#ef4444", # Red "#3b82f6" # Blue ], "borderColor": [ "#4f46e5", "#10b981", "#f97316", "#ef4444", "#3b82f6" ], "borderWidth": 1 }] }, "options": { "scales": { "y": { "beginAtZero": True, "title": { "display": True, "text": "Usage Count" } }, "x": { "title": { "display": True, "text": "LoRA Title" } } }, "plugins": { "legend": { "display": False }, "title": { "display": True, "text": "Top 5 Most Used LoRAs" } } } } return chart_config # Gradio interface with gr.Blocks(theme="YTheme/Minecraft", css=css, delete_cache=(60, 60)) as app: title = gr.HTML( """