cpu-img / app.py
CryptoCreeper
Update app.py
bdebad1 verified
Raw
History Blame
4.42 kB
import gradio as gr
import torch
import random
import time
from transformers import AutoTokenizer, AutoModelForCausalLM
from diffusers import DiffusionPipeline, LCMScheduler
from PIL import Image, ImageFilter
# ===============================
# TEXT MODEL (PROMPT ENHANCER)
# ===============================
TEXT_MODEL_ID = "HuggingFaceTB/SmolLM-135M-Instruct"
tokenizer = AutoTokenizer.from_pretrained(TEXT_MODEL_ID)
text_model = AutoModelForCausalLM.from_pretrained(TEXT_MODEL_ID)
def enhance_prompt(user_prompt: str) -> str:
instruction = (
"Please enhance this prompt so it is suitable for an image generator "
"that requires clear instructions. Analyse the prompt, and output as "
"much visual detail as possible about it.\n\n"
f"Prompt to enhance: {user_prompt}\n\n"
"Enhanced prompt:"
)
inputs = tokenizer(instruction, return_tensors="pt")
outputs = text_model.generate(
**inputs,
max_new_tokens=500,
temperature=0.6,
do_sample=True,
)
decoded = tokenizer.decode(outputs[0], skip_special_tokens=True)
if "Enhanced prompt:" in decoded:
decoded = decoded.split("Enhanced prompt:")[-1]
return decoded.strip()
# ===============================
# IMAGE MODEL (CPU)
# ===============================
IMG_MODEL = "runwayml/stable-diffusion-v1-5"
LCM_LORA = "latent-consistency/lcm-lora-sdv1-5"
pipe = DiffusionPipeline.from_pretrained(
IMG_MODEL,
torch_dtype=torch.float32,
safety_checker=None
)
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
pipe.load_lora_weights(LCM_LORA)
pipe.to("cpu")
pipe.enable_attention_slicing()
pipe.enable_vae_slicing()
pipe.set_progress_bar_config(disable=True)
# ===============================
# TIME ESTIMATION
# ===============================
def estimate_time(steps, res):
res = int(res)
steps = int(steps)
base = {512: 12, 768: 25, 1024: 45}[res]
total = steps * base + 5
return f"⏱️ Estimated: ~{total//60}m {total%60}s"
# ===============================
# GENERATION FUNCTION
# ===============================
def generate(prompt, negative, resolution, steps):
size = int(resolution)
# Placeholder while thinking
yield (
[Image.new("RGB", (size, size), "white")],
"🧠 Enhancing prompt..."
)
enhanced = enhance_prompt(prompt)
yield (
[Image.new("RGB", (size, size), "white")],
"🎨 Generating image..."
)
seed = random.randint(0, 1_000_000_000)
generator = torch.Generator("cpu").manual_seed(seed)
pipe.scheduler.set_timesteps(int(steps))
start = time.time()
image = pipe(
prompt=enhanced,
negative_prompt=negative,
num_inference_steps=int(steps),
guidance_scale=1.2,
width=size,
height=size,
generator=generator
).images[0]
elapsed = int(time.time() - start)
# Blur reveal
for i in range(10):
blur = image.filter(ImageFilter.GaussianBlur(radius=(10 - i)))
yield (
[blur],
f"👀 Revealing... ({i+1}/10)"
)
time.sleep(1)
yield (
[image],
f"✅ Done in {elapsed}s | Seed {seed}"
)
# ===============================
# UI
# ===============================
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 👾 Creeper AI Image - CPU")
gr.Markdown(
"1️⃣ The higher the resolution & steps, the longer the image takes.\n\n"
"2️⃣ The more detailed the prompt and negative prompt, the better the result."
)
with gr.Row():
with gr.Column():
prompt = gr.Textbox(label="Prompt")
negative = gr.Textbox(label="Negative Prompt")
resolution = gr.Radio([512, 768, 1024], value=512, label="Resolution")
steps = gr.Slider(6, 8, value=6, step=1, label="Steps")
eta = gr.Markdown("⏱️ Estimated: ~1m")
generate_btn = gr.Button("Generate")
status = gr.Markdown("🟢 Ready")
with gr.Column():
gallery = gr.Gallery(columns=1)
resolution.change(estimate_time, [steps, resolution], eta)
steps.change(estimate_time, [steps, resolution], eta)
generate_btn.click(
generate,
inputs=[prompt, negative, resolution, steps],
outputs=[gallery, status]
)
demo.launch(share=False)