SuMyatNoe29's picture
Upload app.py
4b3102d verified
import os
import gradio as gr
import torch
import gdown
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
from PIL import Image
# --- Download from Google Drive ---
def download_from_gdrive(file_id, dest_path):
if not os.path.exists(dest_path):
print(f"πŸ“₯ Downloading {dest_path}...")
gdown.download(f"https://drive.google.com/uc?id={file_id}", dest_path, quiet=False)
print(f"βœ… Downloaded {dest_path} from Google Drive")
else:
print(f"βœ… {dest_path} already exists")
# Download base model and LoRA
print("πŸš€ Starting BitKun LoRA Generator...")
ckpt_id = "1OdP2SDB6MyR6JDK6_ekyqFHz91rkT2ZK" # Your base model ID
download_from_gdrive(ckpt_id, "AnyLoRA_noVae_fp16-pruned.ckpt")
# βš™οΈ Configuration
project_name = "bitkun"
epoch_number = 10
lora_path = f"{project_name}-{epoch_number:02d}.safetensors"
base_model_path = "AnyLoRA_noVae_fp16-pruned.ckpt"
output_folder = "generated_images"
os.makedirs(output_folder, exist_ok=True)
# Auto-detect device and set appropriate dtype
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16 if device == "cuda" else torch.float32
print(f"πŸ”§ Using device: {device} with dtype: {dtype}")
# πŸš€ Load Base Model with optimizations
print("πŸ“¦ Loading base model...")
try:
pipe = StableDiffusionPipeline.from_single_file(
base_model_path,
torch_dtype=dtype,
safety_checker=None,
requires_safety_checker=False,
use_safetensors=True
).to(device)
# ⏩ Use faster scheduler
pipe.scheduler = DPMSolverMultistepScheduler.from_config(
pipe.scheduler.config,
use_karras_sigmas=True,
algorithm_type="dpmsolver++"
)
# Enable memory efficient attention if available
if hasattr(pipe, "enable_attention_slicing"):
pipe.enable_attention_slicing()
# Enable memory efficient attention
if hasattr(pipe, "enable_xformers_memory_efficient_attention"):
try:
pipe.enable_xformers_memory_efficient_attention()
print("βœ… XFormers memory efficient attention enabled")
except:
print("⚠️ XFormers not available, using standard attention")
print("βœ… Base model loaded successfully!")
except Exception as e:
print(f"❌ Error loading base model: {e}")
raise e
# πŸ”„ Load LoRA
lora_loaded = False
try:
if os.path.exists(lora_path):
pipe.load_lora_weights(lora_path, adapter_name="default")
pipe.set_adapters(["default"], adapter_weights=[0.8])
lora_loaded = True
print("βœ… LoRA loaded and pipeline ready!")
else:
print(f"⚠️ LoRA file not found: {lora_path}")
print("Pipeline will run with base model only.")
except Exception as e:
print(f"⚠️ Could not load LoRA weights: {e}")
print("Pipeline will run with base model only.")
# 🎨 Optimized Generation Function
def generate_bitkun(prompt, negative_prompt, num_images, steps, guidance_scale, width, height):
if not prompt.strip():
return [], "⚠️ Please enter a prompt!"
# Add bitkun to prompt if not present
if "bitkun" not in prompt.lower():
prompt = f"bitkun, {prompt}"
seed = 42
images = []
for i in range(num_images):
try:
print(f"🎨 Generating image {i + 1}/{num_images}...")
generator = torch.Generator(device=device).manual_seed(seed + i)
# Use autocast only for CUDA
if device == "cuda":
with torch.autocast("cuda"):
result = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=steps,
guidance_scale=guidance_scale,
width=width,
height=height,
generator=generator
)
else:
result = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=steps,
guidance_scale=guidance_scale,
width=width,
height=height,
generator=generator
)
image = result.images[0]
# Save image
filename = f"{project_name}_custom_{i + 1}.png"
filepath = os.path.join(output_folder, filename)
image.save(filepath)
images.append(image)
except Exception as e:
error_msg = f"❌ Error generating image {i + 1}: {str(e)}"
print(error_msg)
continue
if not images:
final_status = "❌ Failed to generate any images. Please try again with different settings."
else:
lora_status = "with LoRA" if lora_loaded else "without LoRA"
final_status = f"πŸŽ‰ Successfully generated {len(images)}/{num_images} image(s) {lora_status}!"
return images, final_status
# 🌐 Gradio UI with Speed Presets
with gr.Blocks(title="BitKun LoRA Generator", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🐢 BitKun LoRA Generator 🎨 (FAST VERSION)
### θ‡ͺη”±γͺγƒ—γƒ­γƒ³γƒ—γƒˆε―ΎεΏœ / Custom Prompt Support
""")
# Show LoRA status
lora_status_text = "βœ… LoRA loaded successfully!" if lora_loaded else "⚠️ Running with base model only (LoRA not found)"
gr.Markdown(f"**Status:** {lora_status_text}")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 🎯 Generation Settings")
custom_prompt = gr.Textbox(
label="πŸ“ γƒ—γƒ­γƒ³γƒ—γƒˆ / Prompt",
placeholder="δΎ‹: happy, smiling, cartoon style, colorful background",
lines=3,
info="'bitkun' will be automatically added if not included"
)
negative_prompt = gr.Textbox(
label="🚫 γƒγ‚¬γƒ†γ‚£γƒ–γƒ—γƒ­γƒ³γƒ—γƒˆ / Negative Prompt",
value="realistic, human skin, photo, blurry, distorted, extra limbs, bad anatomy",
lines=2
)
# Speed Presets
gr.Markdown("### ⚑ Speed Presets")
with gr.Row():
speed_preset = gr.Radio(
choices=[
("πŸš€ Ultra Fast (10 steps, 256x256)", "ultra_fast"),
("⚑ Fast (15 steps, 384x384)", "fast"),
("🎯 Balanced (20 steps, 512x512)", "balanced"),
("🎨 Quality (25 steps, 512x512)", "quality"),
("πŸ”§ Custom", "custom")
],
value="fast",
label="Choose Speed vs Quality"
)
with gr.Row():
num_images = gr.Slider(
label="πŸ–ΌοΈ Number of Images",
minimum=1,
maximum=3,
value=1,
step=1,
info="More images = longer processing time"
)
# Advanced settings (hidden by default)
with gr.Accordion("πŸ”§ Advanced Settings", open=False):
steps = gr.Slider(
label="πŸ”„ Inference Steps",
minimum=5,
maximum=50,
value=15,
step=1,
info="More steps = higher quality but slower"
)
guidance_scale = gr.Slider(
label="🎚️ Guidance Scale",
minimum=1.0,
maximum=15.0,
value=7.5,
step=0.5,
info="Higher = more prompt adherence"
)
with gr.Row():
width = gr.Slider(
label="πŸ“ Width",
minimum=256,
maximum=768,
value=384,
step=64
)
height = gr.Slider(
label="πŸ“ Height",
minimum=256,
maximum=768,
value=384,
step=64
)
generate_btn = gr.Button(
"🎨 η”»εƒγ‚’η”Ÿζˆ / Generate Images",
variant="primary",
size="lg"
)
with gr.Column(scale=1):
gr.Markdown("### πŸ–ΌοΈ Generated Images")
gallery = gr.Gallery(
label="η”Ÿζˆη”»εƒ / Generated Images",
columns=2,
rows=2,
height=400,
show_label=False
)
status_text = gr.Textbox(
label="πŸ“Š Generation Status",
interactive=False,
lines=2
)
# Speed preset change handler
def update_settings(preset):
if preset == "ultra_fast":
return 10, 7.0, 256, 256
elif preset == "fast":
return 15, 7.5, 384, 384
elif preset == "balanced":
return 20, 7.5, 512, 512
elif preset == "quality":
return 25, 8.0, 512, 512
else: # custom
return 15, 7.5, 384, 384
speed_preset.change(
fn=update_settings,
inputs=[speed_preset],
outputs=[steps, guidance_scale, width, height]
)
# Example prompts section
gr.Markdown("""
### πŸ“ Quick Examples / クむック例:
**⚑ For fastest results, try these short prompts:**
- `happy, smiling`
- `sad, crying`
- `angry, red face`
- `surprised, shocked`
- `sleepy, tired`
- `superhero, cape`
""")
# Button click event
generate_btn.click(
fn=generate_bitkun,
inputs=[custom_prompt, negative_prompt, num_images, steps, guidance_scale, width, height],
outputs=[gallery, status_text],
show_progress=True
)
# Launch the app
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
show_error=True
)