2511 / app.py
sanetium's picture
Update app.py
7278b76 verified
import os
import gc
import gradio as gr
import numpy as np
import spaces
import torch
import random
from PIL import Image
from gradio.themes import Soft
from gradio.themes.utils import colors, fonts, sizes
# --- Custom Theme Configuration ---
colors.orange_red = colors.Color(
name="orange_red",
c50="#FFF0E5",
c100="#FFE0CC",
c200="#FFC299",
c300="#FFA366",
c400="#FF8533",
c500="#FF4500",
c600="#E63E00",
c700="#CC3700",
c800="#B33000",
c900="#992900",
c950="#802200",
)
class OrangeRedTheme(Soft):
def __init__(
self,
*,
primary_hue: colors.Color | str = colors.gray,
secondary_hue: colors.Color | str = colors.orange_red,
neutral_hue: colors.Color | str = colors.slate,
text_size: sizes.Size | str = sizes.text_lg,
font=(fonts.GoogleFont("Outfit"), "Arial", "sans-serif"),
font_mono=(fonts.GoogleFont("IBM Plex Mono"), "ui-monospace", "monospace"),
):
super().__init__(
primary_hue=primary_hue,
secondary_hue=secondary_hue,
neutral_hue=neutral_hue,
text_size=text_size,
font=font,
font_mono=font_mono,
)
super().set(
background_fill_primary="*primary_50",
background_fill_primary_dark="*primary_900",
body_background_fill="linear-gradient(135deg, *primary_200, *primary_100)",
body_background_fill_dark="linear-gradient(135deg, *primary_900, *primary_800)",
button_primary_text_color="white",
button_primary_text_color_hover="white",
button_primary_background_fill="linear-gradient(90deg, *secondary_500, *secondary_600)",
button_primary_background_fill_hover="linear-gradient(90deg, *secondary_600, *secondary_700)",
button_primary_background_fill_dark="linear-gradient(90deg, *secondary_600, *secondary_700)",
button_primary_background_fill_hover_dark="linear-gradient(90deg, *secondary_500, *secondary_600)",
button_secondary_text_color="black",
button_secondary_text_color_hover="white",
button_secondary_background_fill="linear-gradient(90deg, *primary_300, *primary_300)",
button_secondary_background_fill_hover="linear-gradient(90deg, *primary_400, *primary_400)",
button_secondary_background_fill_dark="linear-gradient(90deg, *primary_500, *primary_600)",
button_secondary_background_fill_hover_dark="linear-gradient(90deg, *primary_500, *primary_500)",
slider_color="*secondary_500",
slider_color_dark="*secondary_600",
block_title_text_weight="600",
block_border_width="3px",
block_shadow="*shadow_drop_lg",
button_primary_shadow="*shadow_drop_lg",
button_large_padding="11px",
color_accent_soft="*primary_100",
block_label_background_fill="*primary_200",
)
orange_red_theme = OrangeRedTheme()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# --- Model Loading ---
from diffusers import FlowMatchEulerDiscreteScheduler
from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
dtype = torch.bfloat16
pipe = QwenImageEditPlusPipeline.from_pretrained(
"Qwen/Qwen-Image-Edit-2511",
transformer=QwenImageTransformer2DModel.from_pretrained(
"linoyts/Qwen-Image-Edit-Rapid-AIO",
subfolder='transformer',
torch_dtype=dtype,
device_map='cuda'
),
torch_dtype=dtype
).to(device)
try:
pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
except Exception as e:
print(f"Warning: FA3 processor error: {e}")
MAX_SEED = np.iinfo(np.int32).max
LOADED_ADAPTERS = set()
# --- Adapter Definitions ---
ADAPTER_SPECS = {
"Multiple-Angles": {"repo": "dx8152/Qwen-Edit-2509-Multiple-angles", "weights": "镜头转换.safetensors", "adapter_name": "multiple-angles"},
"MNCL": {"repo": "sanetium/Testing", "weights": "qwen_MCNL_v1.0.safetensors", "adapter_name": "MNCL"},
"MMystic": {"repo": "sanetium/mystic", "weights": "Qwen-MysticXXX-v1.safetensors", "adapter_name": "Mystic"},
"next scene": {"repo": "aiqwen/next-scene-qwen-image-lora-2509", "weights": "next-scene_lora_v1-3000.safetensors", "adapter_name": "Next scene"},
"LilSeven": {"repo": "sanetium/Lilseven", "weights": "lilseven8000.safetensors", "adapter_name": "LilSeven"},
"URP": {"repo": "prithivMLmods/Qwen-Image-Edit-2511-Ultra-Realistic-Portrait", "weights": "URP_20.safetensors", "adapter_name": "URP"},
"IEI": {"repo": "peteromallet/Qwen-Image-Edit-InSubject", "weights": "InSubject-0.5.safetensors", "adapter_name": "IEI"},
}
# --- Helper Functions ---
def update_dimensions_on_upload(image):
if image is None: return 1024, 1024
w, h = image.size
aspect = h / w if w > h else w / h
new_w, new_h = (1024, int(1024 * aspect)) if w > h else (int(1024 * aspect), 1024)
return (new_w // 8) * 8, (new_h // 8) * 8
@spaces.GPU
def infer(images, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, lora_strength):
gc.collect()
torch.cuda.empty_cache()
if not images: raise gr.Error("Please upload images.")
pil_images = []
for item in images:
try:
path = item[0] if isinstance(item, (tuple, list)) else item
pil_images.append(Image.open(path).convert("RGB") if isinstance(path, str) else path.convert("RGB"))
except: continue
spec = ADAPTER_SPECS.get(lora_adapter)
adapter_name = spec["adapter_name"]
if adapter_name not in LOADED_ADAPTERS:
pipe.load_lora_weights(spec["repo"], weight_name=spec["weights"], adapter_name=adapter_name)
LOADED_ADAPTERS.add(adapter_name)
pipe.set_adapters([adapter_name], adapter_weights=[lora_strength])
if randomize_seed: seed = random.randint(0, MAX_SEED)
generator = torch.Generator(device=device).manual_seed(seed)
w, h = update_dimensions_on_upload(pil_images[0])
result = pipe(
image=pil_images,
prompt=prompt,
negative_prompt="worst quality, low quality, blurry, text, watermark,extra hands,bad anatomy,blurry face,",
height=h, width=w,
num_inference_steps=steps,
generator=generator,
true_cfg_scale=guidance_scale,
).images[0]
return result, seed
# --- Interface ---
css = "#col-container { margin: 0 auto; max-width: 1000px; } #main-title h1 { font-size: 2.3em !important; }"
with gr.Blocks(theme=orange_red_theme, css=css) as demo:
with gr.Column(elem_id="col-container"):
gr.Markdown("# **Qwen2511**", elem_id="main-title")
with gr.Row():
with gr.Column():
images = gr.Gallery(label="Upload Images", type="filepath", columns=2, height=300)
prompt = gr.Text(label="Edit Prompt", placeholder="e.g., transform into anime..")
run_button = gr.Button("Edit Image", variant="primary")
with gr.Column():
output_image = gr.Image(label="Output Image", interactive=False)
lora_adapter = gr.Dropdown(label="Style", choices=list(ADAPTER_SPECS.keys()), value="Multiple-Angles")
with gr.Accordion("Advanced Settings", open=False):
lora_strength = gr.Slider(label="LoRA Strength", minimum=0.0, maximum=2.0, step=0.01, value=1.0)
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, value=0)
randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
guidance_scale = gr.Slider(label="Guidance", minimum=1.0, maximum=10.0, value=1.0)
steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=4)
gr.Markdown("[*](https://huggingface.co/spaces/prithivMLmods/Qwen-Image-Edit-2511-LoRAs-Fast) Experimental Space.")
run_button.click(
fn=infer,
inputs=[images, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, lora_strength],
outputs=[output_image, seed]
)
if __name__ == "__main__":
demo.queue(max_size=30).launch(ssr_mode=False, show_error=True)