cpu-img / app.py
CryptoCreeper
Update app.py
e4b37f8 verified
Raw
History Blame
4.35 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
# -------------------------------
# SMALL PROMPT ENHANCER (CPU)
# -------------------------------
ENHANCER_MODEL = "HuggingFaceTB/SmolLM-135M-Instruct"
tokenizer_enhancer = AutoTokenizer.from_pretrained(ENHANCER_MODEL)
model_enhancer = AutoModelForCausalLM.from_pretrained(ENHANCER_MODEL)
def enhance_text(user_prompt, prefix):
"""
Uses a tiny LLM to rewrite user input into a more detailed instruction.
"""
instruction = f"Rewrite this for an image generator with detail: {user_prompt}"
if prefix:
instruction = f"{prefix} {user_prompt}"
inputs = tokenizer_enhancer(instruction, return_tensors="pt")
outputs = model_enhancer.generate(
**inputs,
max_new_tokens=50,
temperature=0.7,
do_sample=True
)
text = tokenizer_enhancer.decode(outputs[0], skip_special_tokens=True)
return text.strip()
# -------------------------------
# IMAGE MODEL SETUP (CPU SAFE)
# -------------------------------
IMG_MODEL_ID = "runwayml/stable-diffusion-v1-5"
IMG_ADAPTER_ID = "latent-consistency/lcm-lora-sdv1-5"
pipe = DiffusionPipeline.from_pretrained(
IMG_MODEL_ID,
torch_dtype=torch.float32,
safety_checker=None
)
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
pipe.load_lora_weights(IMG_ADAPTER_ID)
pipe.to("cpu")
pipe.enable_attention_slicing()
pipe.enable_vae_slicing()
pipe.set_progress_bar_config(disable=True)
# -------------------------------
# ETA
# -------------------------------
def estimate_time(steps, resolution):
steps = int(steps)
resolution = int(resolution)
per_step = {512:12, 768:25, 1024:45}[resolution]
overhead = 2
est = overhead + steps * per_step
mins = est // 60
secs = est % 60
return f"⏱️ Estimated: ~{mins}m {secs}s"
# -------------------------------
# GENERATE WITH PROGRESSIVE BLUR
# -------------------------------
def generate(prompt, neg_prompt, resolution, steps):
# 1️⃣ AI PROMPT ENHANCEMENT
enhanced_prompt = enhance_text(prompt, "")
enhanced_negative = enhance_text(neg_prompt, "Rewrite negative prompt:")
# 2️⃣ White placeholder
placeholder = Image.new("RGB", (int(resolution), int(resolution)), (255,255,255))
yield [placeholder], "🟡 Generating..."
# 3️⃣ CPU IMAGE GENERATION
seed = random.randint(0, 10**9)
gen = torch.Generator("cpu").manual_seed(seed)
pipe.scheduler.set_timesteps(int(steps))
img = pipe(
prompt=enhanced_prompt,
negative_prompt=enhanced_negative,
num_inference_steps=int(steps),
guidance_scale=1.2,
width=int(resolution),
height=int(resolution),
generator=gen
).images[0]
# 4️⃣ BLUR REVEAL
max_blur = 20
for i in range(10):
blur_pct = 100 - i*10
blurred = img.filter(ImageFilter.GaussianBlur(radius=max_blur * blur_pct/100))
yield [blurred], "🟢 Revealing..."
time.sleep(1)
# 5️⃣ FINAL
yield [img], f"✅ Done | Seed: {seed}"
# -------------------------------
# GRADIO UI
# -------------------------------
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 👾 CREEPER AI — SMART IMAGE GENERATOR")
gr.Markdown("1: The higher the resolution & steps, the longer the image takes to make.\n2: The more detailed the prompt and negative prompt, the better the result.")
with gr.Row():
with gr.Column():
prompt_in = gr.Textbox(label="Prompt")
neg_in = 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 0s")
gen_btn = gr.Button("Generate")
status = gr.Markdown("🟢 Ready")
with gr.Column():
gallery = gr.Gallery(columns=1)
for ctrl in [steps, resolution]:
ctrl.change(estimate_time, [steps, resolution], eta)
gen_btn.click(
generate,
inputs=[prompt_in, neg_in, resolution, steps],
outputs=[gallery, status]
)
demo.launch()