shinkai-style-lora / inference_test.py
KIMCAHLLIE's picture
Upload inference_test.py with huggingface_hub
046772f verified
Raw
History Blame Contribute Delete
6.37 kB
import os
import time
import re
import torch
from diffusers import StableDiffusionPipeline
def slugify(text: str, max_len: int = 40) -> str:
text = text.lower()
text = re.sub(r"[^a-z0-9]+", "_", text).strip("_")
return text[:max_len] if len(text) > max_len else text
def build_pipe(
base_model_id: str = "runwayml/stable-diffusion-v1-5",
dtype: torch.dtype = torch.float16,
device: str = "cuda",
use_xformers: bool = False, # T4์—์„œ ์ด์Šˆ ์žˆ์œผ๋ฉด False ์ถ”์ฒœ
):
pipe = StableDiffusionPipeline.from_pretrained(
base_model_id,
torch_dtype=dtype,
safety_checker=None, # ๊ณผ์ œ/๋กœ์ปฌ ๋ฐ๋ชจ๋ฉด ๋ณดํ†ต ๋”
).to(device)
if use_xformers:
try:
pipe.enable_xformers_memory_efficient_attention()
print("xformers enabled โœ…")
except Exception as e:
print(f"xformers not available (skip): {e}")
return pipe
def try_set_lora_scale(pipe, lora_scale: float) -> bool:
"""
diffusers ๋ฒ„์ „์— ๋”ฐ๋ผ set_adapters ์ง€์› ์—ฌ๋ถ€๊ฐ€ ๋‹ฌ๋ผ์„œ ๋ฐฉ์–ด์ ์œผ๋กœ ์ฒ˜๋ฆฌ.
"""
try:
pipe.set_adapters(["default"], adapter_weights=[float(lora_scale)])
return True
except Exception:
return False
def main():
# ===== ์‚ฌ์šฉ์ž ์„ค์ • =====
trigger_word = "shinkai_makoto_style"
base_model_id = "runwayml/stable-diffusion-v1-5"
# ์ตœ์ข… LoRA ํด๋” (ํ•„์š” ์‹œ checkpoint-1500์œผ๋กœ ๋ฐ”๊ฟ”๋„ ๋จ)
lora_model_path = "./shinkai_lora_output"
# ๊ฒฐ๊ณผ ๊ฐœ์„  ํ•ต์‹ฌ: LoRA ๊ฐ•๋„ ๋‚ฎ์ถ”๊ธฐ
lora_scales = [0.65, 0.75, 0.85]
# guidance๋Š” ๋‚ฎ์ถ˜ ์ชฝ์ด ํ˜•ํƒœ ์•ˆ์ •์— ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ
guidance_scales = [6.5, 7.0]
# ๋””ํ…Œ์ผ์„ ์œ„ํ•ด steps ์‚ด์ง ๋Š˜๋ฆผ
num_inference_steps = 45
# ์žฌํ˜„์„ฑ
seed = 1337
# T4๋ฉด False ์ถ”์ฒœ(์•ˆ์ •), L4/A100์ด๋ฉด True๋„ OK
use_xformers = False
# ===== ํ’๊ฒฝ ํ”„๋กฌํ”„ํŠธ 5๊ฐœ ์„ธํŠธ =====
prompts = [
(
"rainy_neon_city",
f"{trigger_word}, a rainy city street at dusk, neon lights reflecting on wet asphalt, "
"small girl silhouette holding a transparent umbrella, wide shot, cinematic composition, "
"soft lighting, detailed background, anime illustration",
),
(
"sunset_cityscape",
f"{trigger_word}, a vast cityscape under a dramatic sunset sky, glowing clouds, "
"warm orange and pink tones, tiny human figure on a rooftop looking at the sky, "
"wide angle, atmospheric perspective, anime background art",
),
(
"starry_town_night",
f"{trigger_word}, a quiet town under a starry night sky, bright stars, soft clouds drifting, "
"cinematic lighting, calm mood, highly detailed sky, anime background illustration",
),
(
"railway_rain_perspective",
f"{trigger_word}, a railway stretching into the distance during rainfall, wet rails reflecting city lights, "
"empty platform, deep perspective, moody atmosphere, anime cinematic background",
),
(
"rural_after_rain",
f"{trigger_word}, a quiet rural town with fields and houses, dramatic cloudy sky after rain, "
"soft sunlight breaking through clouds, wide shot, peaceful mood, anime background art",
),
]
negative_prompt = (
"lowres, bad anatomy, bad hands, extra fingers, missing fingers, "
"deformed face, cross-eye, distorted, ugly, blurry, noisy, watermark, text"
)
# ===== ์ฒดํฌ =====
if not os.path.exists(lora_model_path):
raise FileNotFoundError(f"LoRA ๊ฒฝ๋กœ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค: {lora_model_path}")
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16 if device == "cuda" else torch.float32
# ===== ํŒŒ์ดํ”„๋ผ์ธ ๋กœ๋“œ(1๋ฒˆ๋งŒ) =====
print("Loading base model:", base_model_id)
pipe = build_pipe(
base_model_id=base_model_id,
dtype=dtype,
device=device,
use_xformers=use_xformers,
)
# LoRA ๋กœ๋“œ(1๋ฒˆ๋งŒ)
print("Loading LoRA from:", lora_model_path)
pipe.load_lora_weights(lora_model_path)
# ===== ์ถœ๋ ฅ ํด๋” =====
out_dir = "inference_outputs_landscape"
os.makedirs(out_dir, exist_ok=True)
ts = time.strftime("%Y%m%d_%H%M%S")
print(f"Output dir: {out_dir}")
print(f"Steps={num_inference_steps}, seed={seed}, lora_scales={lora_scales}, guidance_scales={guidance_scales}")
print("Negative prompt:", negative_prompt)
# ===== ์ƒ์„ฑ =====
total = len(prompts) * len(lora_scales) * len(guidance_scales)
done = 0
for lora_scale in lora_scales:
supported = try_set_lora_scale(pipe, lora_scale)
if supported:
print(f"\nโœ… LoRA scale set ({lora_scale})")
else:
print(f"\nโš ๏ธ set_adapters not supported; using default LoRA strength (requested {lora_scale})")
for gs in guidance_scales:
for name, prompt in prompts:
done += 1
gen = torch.Generator(device=device).manual_seed(seed)
fname = (
f"{out_dir}/"
f"{ts}_p{name}_lora{lora_scale}_gs{gs}_steps{num_inference_steps}_seed{seed}.png"
)
print(f"[{done}/{total}] -> {fname}")
if device == "cuda":
with torch.autocast("cuda", dtype=dtype):
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=num_inference_steps,
guidance_scale=float(gs),
generator=gen,
).images[0]
else:
with torch.no_grad():
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=num_inference_steps,
guidance_scale=float(gs),
).images[0]
image.save(fname)
print("\nโœ… All done!")
print(f"Check: {out_dir}")
if __name__ == "__main__":
main()