ginipick commited on
Commit
cd1d8d4
ยท
verified ยท
1 Parent(s): b5d3eac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +315 -11
app.py CHANGED
@@ -16,14 +16,318 @@ from diffusers import AutoencoderKL, EulerDiscreteScheduler
16
 
17
  from huggingface_hub import snapshot_download
18
 
19
- import ast #์ถ”๊ฐ€ ์‚ฝ์ž…, requirements: albumentations ์ถ”๊ฐ€
20
- script_repr = os.getenv("APP")
21
- if script_repr is None:
22
- print("Error: Environment variable 'APP' not set.")
23
- sys.exit(1)
24
-
25
- try:
26
- exec(script_repr)
27
- except Exception as e:
28
- print(f"Error executing script: {e}")
29
- sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  from huggingface_hub import snapshot_download
18
 
19
+
20
+ device = "cuda"
21
+ root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
22
+ ckpt_dir = f'{root_dir}/weights/Kolors'
23
+
24
+ snapshot_download(repo_id="Kwai-Kolors/Kolors", local_dir=ckpt_dir)
25
+ snapshot_download(repo_id="Kwai-Kolors/Kolors-IP-Adapter-Plus", local_dir=f"{root_dir}/weights/Kolors-IP-Adapter-Plus")
26
+
27
+ # Load models
28
+ text_encoder = ChatGLMModel.from_pretrained(f'{ckpt_dir}/text_encoder', torch_dtype=torch.float16).half().to(device)
29
+ tokenizer = ChatGLMTokenizer.from_pretrained(f'{ckpt_dir}/text_encoder')
30
+ vae = AutoencoderKL.from_pretrained(f"{ckpt_dir}/vae", revision=None).half().to(device)
31
+ scheduler = EulerDiscreteScheduler.from_pretrained(f"{ckpt_dir}/scheduler")
32
+ unet = UNet2DConditionModel.from_pretrained(f"{ckpt_dir}/unet", revision=None).half().to(device)
33
+
34
+ image_encoder = CLIPVisionModelWithProjection.from_pretrained(
35
+ f'{root_dir}/weights/Kolors-IP-Adapter-Plus/image_encoder',
36
+ ignore_mismatched_sizes=True
37
+ ).to(dtype=torch.float16, device=device)
38
+
39
+ ip_img_size = 336
40
+ clip_image_processor = CLIPImageProcessor(size=ip_img_size, crop_size=ip_img_size)
41
+
42
+ pipe = StableDiffusionXLPipeline(
43
+ vae=vae,
44
+ text_encoder=text_encoder,
45
+ tokenizer=tokenizer,
46
+ unet=unet,
47
+ scheduler=scheduler,
48
+ image_encoder=image_encoder,
49
+ feature_extractor=clip_image_processor,
50
+ force_zeros_for_empty_prompt=False
51
+ ).to(device)
52
+
53
+ if hasattr(pipe.unet, 'encoder_hid_proj'):
54
+ pipe.unet.text_encoder_hid_proj = pipe.unet.encoder_hid_proj
55
+
56
+ pipe.load_ip_adapter(f'{root_dir}/weights/Kolors-IP-Adapter-Plus', subfolder="", weight_name=["ip_adapter_plus_general.bin"])
57
+
58
+ MAX_SEED = np.iinfo(np.int32).max
59
+ MAX_IMAGE_SIZE = 1024
60
+
61
+ # ----------------------------------------------
62
+ # infer ํ•จ์ˆ˜ (๊ธฐ์กด ๋กœ์ง ๊ทธ๋Œ€๋กœ ์œ ์ง€)
63
+ # ----------------------------------------------
64
+ @spaces.GPU(duration=80)
65
+ def infer(
66
+ user_prompt,
67
+ ip_adapter_image,
68
+ ip_adapter_scale=0.5,
69
+ negative_prompt="",
70
+ seed=100,
71
+ randomize_seed=False,
72
+ width=1024,
73
+ height=1024,
74
+ guidance_scale=5.0,
75
+ num_inference_steps=50,
76
+ progress=gr.Progress(track_tqdm=True)
77
+ ):
78
+ # ์ˆจ๊ฒจ์ง„(๊ธฐ๋ณธ/ํ•„์ˆ˜) ํ”„๋กฌํ”„ํŠธ
79
+ hidden_prompt = (
80
+ "Ghibli Studio style, Charming hand-drawn anime-style illustration"
81
+ )
82
+
83
+ # ์‹ค์ œ๋กœ ํŒŒ์ดํ”„๋ผ์ธ์— ์ „๋‹ฌํ•  ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ
84
+ prompt = f"{hidden_prompt}, {user_prompt}"
85
+
86
+ if randomize_seed:
87
+ seed = random.randint(0, MAX_SEED)
88
+
89
+ generator = torch.Generator(device="cuda").manual_seed(seed)
90
+ pipe.to("cuda")
91
+ image_encoder.to("cuda")
92
+ pipe.image_encoder = image_encoder
93
+ pipe.set_ip_adapter_scale([ip_adapter_scale])
94
+
95
+ image = pipe(
96
+ prompt=prompt,
97
+ ip_adapter_image=[ip_adapter_image],
98
+ negative_prompt=negative_prompt,
99
+ height=height,
100
+ width=width,
101
+ num_inference_steps=num_inference_steps,
102
+ guidance_scale=guidance_scale,
103
+ num_images_per_prompt=1,
104
+ generator=generator,
105
+ ).images[0]
106
+
107
+ return image, seed
108
+
109
+ examples = [
110
+ [
111
+ "background alps",
112
+ "gh0.webp",
113
+ 0.5
114
+ ],
115
+ [
116
+ "dancing",
117
+ "gh5.jpg",
118
+ 0.5
119
+ ],
120
+ [
121
+ "smile",
122
+ "gh2.jpg",
123
+ 0.5
124
+ ],
125
+ [
126
+ "3d style",
127
+ "gh3.webp",
128
+ 0.6
129
+ ],
130
+ [
131
+ "with Pikachu",
132
+ "gh4.jpg",
133
+ 0.5
134
+ ],
135
+ [
136
+ "Ghibli Studio style, Charming hand-drawn anime-style illustration",
137
+ "gh7.jpg",
138
+ 0.5
139
+ ],
140
+ [
141
+ "Ghibli Studio style, Charming hand-drawn anime-style illustration",
142
+ "gh1.jpg",
143
+ 0.5
144
+ ],
145
+ ]
146
+
147
+ # --------------------------
148
+ # ๊ฐœ์„ ๋œ UI๋ฅผ ์œ„ํ•œ CSS
149
+ # --------------------------
150
+ css = """
151
+ body {
152
+ background: linear-gradient(135deg, #f5f7fa, #c3cfe2);
153
+ font-family: 'Helvetica Neue', Arial, sans-serif;
154
+ color: #333;
155
+ margin: 0;
156
+ padding: 0;
157
+ }
158
+
159
+ #col-container {
160
+ margin: 0 auto !important;
161
+ max-width: 720px;
162
+ background: rgba(255,255,255,0.85);
163
+ border-radius: 16px;
164
+ padding: 2rem;
165
+ box-shadow: 0 8px 24px rgba(0,0,0,0.1);
166
+ }
167
+
168
+ #header-title {
169
+ text-align: center;
170
+ font-size: 2rem;
171
+ font-weight: bold;
172
+ margin-bottom: 1rem;
173
+ }
174
+
175
+ #prompt-row {
176
+ display: flex;
177
+ gap: 0.5rem;
178
+ align-items: center;
179
+ margin-bottom: 1rem;
180
+ }
181
+
182
+ #prompt-text {
183
+ flex: 1;
184
+ }
185
+
186
+ #result img {
187
+ object-position: top;
188
+ border-radius: 8px;
189
+ }
190
+
191
+ #result .image-container {
192
+ height: 100%;
193
+ }
194
+
195
+ .gr-button {
196
+ background-color: #2E8BFB !important;
197
+ color: white !important;
198
+ border: none !important;
199
+ transition: background-color 0.2s ease;
200
+ }
201
+
202
+ .gr-button:hover {
203
+ background-color: #186EDB !important;
204
+ }
205
+
206
+ .gr-slider input[type=range] {
207
+ accent-color: #2E8BFB !important;
208
+ }
209
+
210
+ .gr-box {
211
+ background-color: #fafafa !important;
212
+ border: 1px solid #ddd !important;
213
+ border-radius: 8px !important;
214
+ padding: 1rem !important;
215
+ }
216
+
217
+ #advanced-settings {
218
+ margin-top: 1rem;
219
+ border-radius: 8px;
220
+ }
221
+ """
222
+
223
+ with gr.Blocks(theme="apriel", css=css) as demo:
224
+ with gr.Column(elem_id="col-container"):
225
+ gr.Markdown("<div id='header-title'>Ghibli Meme Studio</div>")
226
+ gr.Markdown("<div id='header-title' style='font-size: 12px;'>Community: https://discord.gg/openfreeai</div>")
227
+
228
+ # ์ƒ๋‹จ: ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ + ์‹คํ–‰ ๋ฒ„ํŠผ
229
+ with gr.Row(elem_id="prompt-row"):
230
+ prompt = gr.Text(
231
+ label="Prompt",
232
+ show_label=False,
233
+ max_lines=1,
234
+ placeholder="Enter your prompt",
235
+ elem_id="prompt-text",
236
+ )
237
+ run_button = gr.Button("Run", elem_id="run-button")
238
+
239
+ # ๊ฐ€์šด๋ฐ: ์ด๋ฏธ์ง€ ์ž…๋ ฅ๊ณผ ์Šฌ๋ผ์ด๋”, ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€
240
+ with gr.Row():
241
+ with gr.Column():
242
+ ip_adapter_image = gr.Image(label="IP-Adapter Image", type="pil")
243
+ ip_adapter_scale = gr.Slider(
244
+ label="Image influence scale",
245
+ info="Use 1 for creating variations",
246
+ minimum=0.0,
247
+ maximum=1.0,
248
+ step=0.05,
249
+ value=0.5,
250
+ )
251
+ result = gr.Image(label="Result", elem_id="result")
252
+
253
+ # ํ•˜๋‹จ: ๊ณ ๊ธ‰ ์„ค์ •(Accordion)
254
+ with gr.Accordion("Advanced Settings", open=False, elem_id="advanced-settings"):
255
+ negative_prompt = gr.Text(
256
+ label="Negative prompt",
257
+ max_lines=2,
258
+ placeholder=(
259
+ "Copy(worst quality, low quality:1.4), bad anatomy, bad hands, text, error, "
260
+ "missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, "
261
+ "normal quality, jpeg artifacts, signature, watermark, username, blurry, "
262
+ "artist name, (deformed iris, deformed pupils:1.2), (semi-realistic, cgi, "
263
+ "3d, render:1.1), amateur, (poorly drawn hands, poorly drawn face:1.2)"
264
+ ),
265
+ )
266
+ seed = gr.Slider(
267
+ label="Seed",
268
+ minimum=0,
269
+ maximum=MAX_SEED,
270
+ step=1,
271
+ value=0,
272
+ )
273
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
274
+ with gr.Row():
275
+ width = gr.Slider(
276
+ label="Width",
277
+ minimum=256,
278
+ maximum=MAX_IMAGE_SIZE,
279
+ step=32,
280
+ value=1024,
281
+ )
282
+ height = gr.Slider(
283
+ label="Height",
284
+ minimum=256,
285
+ maximum=MAX_IMAGE_SIZE,
286
+ step=32,
287
+ value=1024,
288
+ )
289
+ with gr.Row():
290
+ guidance_scale = gr.Slider(
291
+ label="Guidance scale",
292
+ minimum=0.0,
293
+ maximum=10.0,
294
+ step=0.1,
295
+ value=5.0,
296
+ )
297
+ num_inference_steps = gr.Slider(
298
+ label="Number of inference steps",
299
+ minimum=1,
300
+ maximum=100,
301
+ step=1,
302
+ value=50,
303
+ )
304
+
305
+ # ์˜ˆ์‹œ๋“ค
306
+ gr.Examples(
307
+ examples=examples,
308
+ fn=infer,
309
+ inputs=[prompt, ip_adapter_image, ip_adapter_scale],
310
+ outputs=[result, seed],
311
+ cache_examples="lazy"
312
+ )
313
+
314
+ # ๋ฒ„ํŠผ ํด๋ฆญ/ํ”„๋กฌํ”„ํŠธ ์—”ํ„ฐ ์‹œ ์‹คํ–‰
315
+ gr.on(
316
+ triggers=[run_button.click, prompt.submit],
317
+ fn=infer,
318
+ inputs=[
319
+ prompt,
320
+ ip_adapter_image,
321
+ ip_adapter_scale,
322
+ negative_prompt,
323
+ seed,
324
+ randomize_seed,
325
+ width,
326
+ height,
327
+ guidance_scale,
328
+ num_inference_steps
329
+ ],
330
+ outputs=[result, seed]
331
+ )
332
+
333
+ demo.queue().launch()