File size: 5,309 Bytes
069396c
 
6cd8c22
 
 
 
 
 
0dfe3cb
 
 
 
 
 
564f386
0dfe3cb
564f386
0dfe3cb
 
564f386
0dfe3cb
 
 
 
 
 
 
 
 
 
564f386
0dfe3cb
 
 
 
 
 
 
 
6cd8c22
 
 
 
 
 
 
0dfe3cb
 
 
 
 
 
 
6cd8c22
0dfe3cb
 
 
 
 
 
 
 
 
 
 
 
 
 
069396c
0dfe3cb
069396c
 
 
0dfe3cb
 
069396c
564f386
069396c
 
0dfe3cb
069396c
0dfe3cb
 
 
 
 
6cd8c22
0dfe3cb
069396c
0dfe3cb
 
 
 
 
069396c
0dfe3cb
 
 
 
6cd8c22
 
0dfe3cb
6cd8c22
069396c
 
0dfe3cb
 
 
 
 
 
 
 
 
 
 
6cd8c22
 
 
 
 
 
0dfe3cb
 
 
 
 
 
 
069396c
 
0dfe3cb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import gradio as gr
import torch
from diffusers import (
    StableDiffusionXLPipeline,
    EulerDiscreteScheduler,
    AutoencoderKL,
    DPMSolverSinglestepScheduler,
)
from huggingface_hub import hf_hub_download

# --- Configuration ---
# The base model your LoRA was trained on.
base_model_id = "stabilityai/stable-diffusion-xl-base-1.0"

# --- CORRECTED REPOSITORY PATH ---
# The path to your LoRA file on the Hugging Face Hub.
lora_repo_id = "TuringSolutions/EmilyH"  # Corrected from "TuringsSolutions"
lora_filename = "emilyh.safetensors"

# --- Load the Pipeline (No token needed for public repos) ---
# Use a recommended VAE for SDXL
vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16)
pipe = StableDiffusionXLPipeline.from_pretrained(
    base_model_id,
    vae=vae,
    torch_dtype=torch.float16,
    variant="fp16",
    use_safetensors=True
)

# --- Load and Fuse the LoRA (No token needed for public repos) ---
# Download the LoRA file and load the state dict.
lora_file_path = hf_hub_download(repo_id=lora_repo_id, filename=lora_filename)
pipe.load_lora_weights(lora_file_path)

# Move the pipeline to the GPU
pipe.to("cuda")

# --- Default Settings from your Recommendations ---
default_positive_prompt = "masterpiece, best quality, ultra-detailed, realistic skin, intricate details, highres"
default_negative_prompt = "low quality, worst quality, blurry, (deformed:1.3), extra fingers, cartoon, 3d, anime, bad anatomy"
default_sampler = "DPM++ 2M Karras"
default_cfg = 6.0
default_steps = 30
trigger_word = "emilyh"
lora_tag_main = "<lora:emilyh:0.9>"


# --- Define the Inference Function ---
def generate_image(prompt, negative_prompt, sampler, steps, cfg, width, height, seed):
    """
    Function to generate an image based on user inputs.
    """
    # Combine the user prompt with the trigger word and LoRA tag
    full_prompt = f"{lora_tag_main}, {trigger_word}, {prompt}"

    # Set the scheduler (sampler)
    if sampler == "DPM++ 2M Karras":
        pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True)
    elif sampler == "DPM++ SDE Karras":
        pipe.scheduler = DPMSolverSinglestepScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True, algorithm_type="sde-dpmsolver++")
    else: # Default to DPM++ 2M Karras
        pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True)

    # Set seed for reproducibility
    generator = torch.Generator("cuda").manual_seed(seed) if seed != -1 else None

    # Generate the image
    image = pipe(
        prompt=full_prompt,
        negative_prompt=negative_prompt,
        width=width,
        height=height,
        guidance_scale=cfg,
        num_inference_steps=steps,
        generator=generator,
        cross_attention_kwargs={"scale": 0.9} 
    ).images[0]

    return image

# --- Create the Gradio Interface ---
with gr.Blocks(css="style.css") as demo:
    gr.Markdown("# `emilyh` LoRA Image Generator")
    gr.Markdown(
        "A Gradio interface for the `emilyh` LoRA. "
        "Based on the recommendations provided."
    )

    with gr.Row():
        with gr.Column():
            prompt = gr.Textbox(label="Positive Prompt", value=default_positive_prompt, lines=3)
            negative_prompt = gr.Textbox(label="Negative Prompt", value=default_negative_prompt, lines=3)
            
            with gr.Row():
                sampler = gr.Radio(
                    label="Sampler",
                    choices=["DPM++ 2M Karras", "DPM++ SDE Karras"],
                    value=default_sampler,
                )
                steps = gr.Slider(label="Steps", minimum=15, maximum=50, value=default_steps, step=1)
            
            cfg = gr.Slider(label="CFG Scale", minimum=1.0, maximum=10.0, value=default_cfg, step=0.5)

            with gr.Row():
                width = gr.Slider(label="Width", minimum=512, maximum=1024, value=1024, step=64)
                height = gr.Slider(label="Height", minimum=512, maximum=1024, value=1024, step=64)

            seed = gr.Slider(label="Seed", minimum=-1, maximum=999999999, step=1, value=-1, info="Use -1 for a random seed.")
            
            generate_button = gr.Button("Generate Image", variant="primary")

        with gr.Column():
            output_image = gr.Image(label="Generated Image", type="pil")
            gr.Markdown(
                """
                ### πŸ”§ Usage Guide
                * The trigger word `emilyh` and the LoRA tag `<lora:emilyh:0.9>` are automatically added to your prompt.
                * For best results, generate images in batches and choose the most consistent ones.
                * The LoRA captures the subject's appearance well across various poses and outfits.
                * A weight of 0.9 provides a good balance of likeness and flexibility. Using a weight closer to 1.0 can increase consistency but may cause stiffness.
                * This interface does not include ADetailer, which is recommended for final face refinement.
                """
            )

    generate_button.click(
        fn=generate_image,
        inputs=[prompt, negative_prompt, sampler, steps, cfg, width, height, seed],
        outputs=output_image
    )

demo.launch()