CryptoCreeper commited on
Commit
0e797f9
·
verified ·
1 Parent(s): 674b2f8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +140 -97
app.py CHANGED
@@ -1,121 +1,164 @@
1
  import gradio as gr
2
  import torch
3
  import random
4
- from diffusers import DiffusionPipeline, LCMScheduler
5
  import time
6
  import re
 
 
 
7
 
8
- # Load Model
 
 
9
  model_id = "runwayml/stable-diffusion-v1-5"
10
  adapter_id = "latent-consistency/lcm-lora-sdv1-5"
11
 
12
- pipe = DiffusionPipeline.from_pretrained(model_id, safety_checker=None, torch_dtype=torch.float32)
 
 
 
 
13
  pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
14
  pipe.load_lora_weights(adapter_id)
15
  pipe.to("cpu")
16
 
17
- def analyze_prompt_logic(prompt):
18
- """
19
- Fast Analysis Engine (Under 1s)
20
- Determines if the user wants a single object or a complex scene.
21
- """
 
 
22
  p = prompt.lower()
23
- # Check for number intent
24
- has_count = re.search(r'\b(one|1|single|sole)\b', p)
25
- is_scene = any(k in p for k in ["room", "forest", "city", "street", "landscape", "background", "detailed"])
26
-
27
- if has_count and not is_scene:
28
- # Inject strict focus for single objects
29
- return f"((centered single isolated {prompt})), minimalist background, sharp focus, masterpiece"
30
- return f"{prompt}, high quality, highly detailed"
31
-
32
- def generate_process(prompt, neg_prompt, size, steps, is_random, manual_seed, bulk_count, auto_res):
33
- all_images = []
34
- start_total = time.time()
35
-
36
- # --- ANALYSIS PHASE (The 'Thinking' part) ---
37
- yield None, "🤔 **Thinking... Analyzing prompt intent**"
38
- time.sleep(1.5) # Simulated for UI feedback, actual logic is instant
39
-
40
- optimized_prompt = analyze_prompt_logic(prompt)
41
-
42
- # Auto-Resolution Logic
43
- if auto_res:
44
- w, h = (448, 448) if "scene" not in optimized_prompt else (512, 512)
45
  else:
46
- w, h = int(size), int(size)
47
-
48
- # --- GENERATION PHASE ---
49
- for i in range(int(bulk_count)):
50
- yield all_images, f"🧠 **Thinking... Strategy: {optimized_prompt[:40]}...**"
51
-
52
- current_seed = random.randint(0, 10**6) if (is_random or bulk_count > 1) else int(manual_seed)
53
- gen = torch.Generator(device="cpu").manual_seed(current_seed)
54
-
55
- img = pipe(
56
- prompt=optimized_prompt,
57
- negative_prompt=neg_prompt if neg_prompt else "duplicate, multiple, split, blurry",
58
- num_inference_steps=int(steps),
59
- guidance_scale=2.5, # High guidance for strict instruction following
60
- width=w, height=h,
61
- generator=gen
62
- ).images[0]
63
-
64
- all_images.append(img)
65
- yield all_images, f"🎨 **Generating... ({i+1}/{bulk_count})**"
66
-
67
- total_duration = round(time.time() - start_total, 2)
68
- yield all_images, f"✅ **Finished in {total_duration}s** | Seed: {current_seed}"
69
-
70
- def update_estimate(steps, size, bulk, auto):
71
- # Precise 2-vCPU calibration
72
- res_val = 448 if auto else int(size)
73
- time_per_step = 14.8 * ((res_val / 512) ** 2)
74
- # Add 2 seconds for the Analysis Phase
75
- est = round((steps * time_per_step * bulk) + 2, 1)
76
- return f"⚡ **Estimated Wait:** ~{est} seconds"
77
-
78
- css = """
79
- .gradio-container { background-color: #0b0f19 !important; color: #00ffcc !important; }
80
- .generate-btn { background: linear-gradient(90deg, #00ffcc, #0077ff) !important; color: white !important; font-weight: bold !important; border: none !important; }
81
- .side-panel { border: 1px solid #00ffcc; padding: 15px; border-radius: 12px; background: rgba(0,255,204,0.05); }
82
- #title { text-shadow: 0 0 10px #00ffcc; }
83
- """
84
-
85
- with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
86
- gr.Markdown("# 👾 CREEPER AI - V2.3 LOGIC CORE", elem_id="title")
87
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  with gr.Row():
89
- with gr.Column(elem_classes="side-panel"):
90
- prompt_in = gr.Textbox(label="Main Instruction", placeholder="e.g. One red apple", lines=3)
91
- neg_in = gr.Textbox(label="Negative Prompt", placeholder="Optional...")
92
-
93
- with gr.Accordion("⚙️ Engine Parameters", open=True):
94
- bulk_slider = gr.Slider(1, 3, value=1, step=1, label="Bulk Count")
95
- auto_res_check = gr.Checkbox(label="Auto-Optimize Resolution", value=False)
96
- size_choice = gr.Radio(choices=[512, 768], label="Fixed Resolution", value=512)
97
- step_slider = gr.Slider(1, 6, value=4, step=1, label="Steps")
98
-
99
- with gr.Row():
100
- random_seed = gr.Checkbox(label="Random Seed", value=True)
101
- seed_val = gr.Number(label="Manual Seed", visible=False, value=42)
102
-
103
- est_box = gr.Markdown("⚡ **Estimated Wait:** ~61.2 seconds")
104
- gen_btn = gr.Button("INITIALIZE GENERATION", variant="primary", elem_classes="generate-btn")
105
 
106
  with gr.Column():
107
- status = gr.Markdown("🟢 **System Ready**")
108
- gallery = gr.Gallery(label="Output", columns=1, height="auto", preview=True)
109
 
110
  random_seed.change(lambda x: gr.update(visible=not x), random_seed, seed_val)
111
-
112
- for ctrl in [bulk_slider, auto_res_check, size_choice, step_slider]:
113
- ctrl.change(update_estimate, [step_slider, size_choice, bulk_slider, auto_res_check], est_box)
114
 
115
- gen_btn.click(
116
- fn=generate_process,
117
- inputs=[prompt_in, neg_in, size_choice, step_slider, random_seed, seed_val, bulk_slider, auto_res_check],
118
  outputs=[gallery, status]
119
  )
120
 
121
- demo.launch()
 
1
  import gradio as gr
2
  import torch
3
  import random
 
4
  import time
5
  import re
6
+ import numpy as np
7
+ from diffusers import DiffusionPipeline, LCMScheduler
8
+ from PIL import Image
9
 
10
+ # -------------------------------------------------
11
+ # MODEL SETUP (CPU-ONLY, FAST)
12
+ # -------------------------------------------------
13
  model_id = "runwayml/stable-diffusion-v1-5"
14
  adapter_id = "latent-consistency/lcm-lora-sdv1-5"
15
 
16
+ pipe = DiffusionPipeline.from_pretrained(
17
+ model_id,
18
+ torch_dtype=torch.float32,
19
+ safety_checker=None
20
+ )
21
  pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
22
  pipe.load_lora_weights(adapter_id)
23
  pipe.to("cpu")
24
 
25
+ pipe.enable_attention_slicing()
26
+ pipe.enable_vae_slicing()
27
+
28
+ # -------------------------------------------------
29
+ # FAST PROMPT ANALYZER (NO DELAYS)
30
+ # -------------------------------------------------
31
+ def analyze_prompt(prompt: str):
32
  p = prompt.lower()
33
+
34
+ # Detect single-object intent
35
+ single_object = not re.search(r"\b(two|three|multiple|many|group|pile)\b", p)
36
+
37
+ # Detect scene
38
+ is_scene = any(k in p for k in [
39
+ "room", "street", "city", "forest", "landscape", "background"
40
+ ])
41
+
42
+ if single_object and not is_scene:
43
+ optimized = (
44
+ f"single centered {prompt}, isolated object, plain background, "
45
+ f"sharp focus, product photo"
46
+ )
47
+ neg = (
48
+ "multiple objects, duplicates, crowd, background objects, clutter"
49
+ )
 
 
 
 
 
50
  else:
51
+ optimized = f"{prompt}, high quality"
52
+ neg = "blurry, low quality"
53
+
54
+ return optimized, neg, is_scene
55
+
56
+ # -------------------------------------------------
57
+ # SMART AUTO-CROP (FAST, NO ML)
58
+ # -------------------------------------------------
59
+ def smart_crop(img: Image.Image, padding=5):
60
+ gray = np.array(img.convert("L"))
61
+ mask = gray > 20 # detect non-black-ish pixels
62
+
63
+ if not mask.any():
64
+ return img # safety fallback
65
+
66
+ coords = np.argwhere(mask)
67
+ y0, x0 = coords.min(axis=0)
68
+ y1, x1 = coords.max(axis=0)
69
+
70
+ h, w = gray.shape
71
+ x0 = max(0, x0 - padding)
72
+ y0 = max(0, y0 - padding)
73
+ x1 = min(w, x1 + padding)
74
+ y1 = min(h, y1 + padding)
75
+
76
+ return img.crop((x0, y0, x1, y1))
77
+
78
+ # -------------------------------------------------
79
+ # GENERATION CORE (FAST <10s)
80
+ # -------------------------------------------------
81
+ def generate(
82
+ prompt,
83
+ size,
84
+ steps,
85
+ random_seed,
86
+ seed_val,
87
+ auto_res
88
+ ):
89
+ start = time.time()
90
+
91
+ optimized_prompt, neg_prompt, is_scene = analyze_prompt(prompt)
92
+
93
+ # Resolution logic
94
+ if auto_res and not is_scene:
95
+ width = height = 448
96
+ else:
97
+ width = height = int(size)
98
+
99
+ seed = random.randint(0, 999999) if random_seed else int(seed_val)
100
+ gen = torch.Generator("cpu").manual_seed(seed)
101
+
102
+ image = pipe(
103
+ prompt=optimized_prompt,
104
+ negative_prompt=neg_prompt,
105
+ num_inference_steps=int(steps),
106
+ guidance_scale=1.2, # LCM sweet spot
107
+ width=width,
108
+ height=height,
109
+ generator=gen
110
+ ).images[0]
111
+
112
+ # Auto-crop ONLY for single objects
113
+ if auto_res and not is_scene:
114
+ image = smart_crop(image, padding=5)
115
+
116
+ duration = round(time.time() - start, 2)
117
+ status = f"✅ Done in {duration}s | Seed: {seed}"
118
+
119
+ return [image], status
120
+
121
+ # -------------------------------------------------
122
+ # ETA (CPU-REALISTIC)
123
+ # -------------------------------------------------
124
+ def estimate_time(steps, size, auto):
125
+ base = 0.9 # model overhead
126
+ res = 448 if auto else int(size)
127
+ step_cost = 0.22 * (res / 512) ** 2
128
+ est = base + steps * step_cost
129
+ return f"⚡ Estimated: ~{round(est, 1)}s"
130
+
131
+ # -------------------------------------------------
132
+ # UI
133
+ # -------------------------------------------------
134
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
135
+ gr.Markdown("# 👾 CREEPER AI — FAST SMART IMAGE CORE")
136
+
137
  with gr.Row():
138
+ with gr.Column():
139
+ prompt_in = gr.Textbox(label="Prompt", placeholder="apple")
140
+ auto_res = gr.Checkbox(label="Smart Auto-Resolution", value=True)
141
+ size = gr.Radio([512, 768], value=512, label="Base Resolution")
142
+ steps = gr.Slider(2, 6, value=4, step=1, label="Steps")
143
+
144
+ random_seed = gr.Checkbox(label="Random Seed", value=True)
145
+ seed_val = gr.Number(label="Manual Seed", value=42, visible=False)
146
+
147
+ eta = gr.Markdown("⚡ Estimated: ~2.0s")
148
+ btn = gr.Button("Generate")
 
 
 
 
 
149
 
150
  with gr.Column():
151
+ status = gr.Markdown("🟢 Ready")
152
+ gallery = gr.Gallery(columns=1)
153
 
154
  random_seed.change(lambda x: gr.update(visible=not x), random_seed, seed_val)
155
+ for ctrl in [steps, size, auto_res]:
156
+ ctrl.change(estimate_time, [steps, size, auto_res], eta)
 
157
 
158
+ btn.click(
159
+ generate,
160
+ inputs=[prompt_in, size, steps, random_seed, seed_val, auto_res],
161
  outputs=[gallery, status]
162
  )
163
 
164
+ demo.launch()