aljun5 commited on
Commit
02a2436
Β·
verified Β·
1 Parent(s): dbadfc4

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +512 -0
app.py ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import cv2
4
+ from PIL import Image, ImageDraw, ImageFont
5
+ import requests
6
+ import json
7
+ import random
8
+ import base64
9
+ import io
10
+ import os
11
+ from diffusers import StableDiffusionInpaintPipeline, StableDiffusionPipeline
12
+ import torch
13
+
14
+ # Initialize AI models
15
+ device = "cuda" if torch.cuda.is_available() else "cpu"
16
+ pipe_inpaint = None
17
+ pipe_txt2img = None
18
+
19
+ # Base model photos (plain people to put outfits on)
20
+ MODEL_AVATARS = {
21
+ "Fashion Model A": "https://images.unsplash.com/photo-1746527971885-001a9643e0a7?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
22
+ "Fashion Model B": "https://images.unsplash.com/photo-1656587132026-1d9cf800acc7?q=80&w=687&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
23
+ "Fashion Model C": "https://plus.unsplash.com/premium_photo-1723478410866-67c032dba011?q=80&w=650&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
24
+ "Casual Model A": "https://images.unsplash.com/photo-1737085725643-e751bcf7ff2b?q=80&w=627&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
25
+ }
26
+
27
+ def add_watermark(img):
28
+ """Add watermark to the image"""
29
+ if isinstance(img, np.ndarray):
30
+ h, w, _ = img.shape
31
+ img = cv2.putText(img, 'AI Outfit Designer', (int(0.02*w), h-10),
32
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (128, 128, 128), 1, cv2.LINE_AA)
33
+ return img
34
+
35
+ def initialize_models():
36
+ global pipe_inpaint, pipe_txt2img
37
+ try:
38
+ # Load inpainting model for outfit editing
39
+ pipe_inpaint = StableDiffusionInpaintPipeline.from_pretrained(
40
+ "runwayml/stable-diffusion-inpainting",
41
+ torch_dtype=torch.float16 if device == "cuda" else torch.float32,
42
+ safety_checker=None,
43
+ requires_safety_checker=False
44
+ ).to(device)
45
+
46
+ # Load text-to-image model for outfit generation
47
+ pipe_txt2img = StableDiffusionPipeline.from_pretrained(
48
+ "runwayml/stable-diffusion-v1-5",
49
+ torch_dtype=torch.float16 if device == "cuda" else torch.float32,
50
+ safety_checker=None,
51
+ requires_safety_checker=False
52
+ ).to(device)
53
+
54
+ if device == "cuda":
55
+ pipe_inpaint.enable_attention_slicing()
56
+ pipe_txt2img.enable_attention_slicing()
57
+
58
+ return True
59
+ except Exception as e:
60
+ print(f"Error loading models: {e}")
61
+ return False
62
+
63
+ def create_placeholder_image(text="Model Image", size=(400, 600)):
64
+ """Create placeholder image for models"""
65
+ img = Image.new('RGB', size, color='lightgray')
66
+ draw = ImageDraw.Draw(img)
67
+
68
+ try:
69
+ font = ImageFont.truetype("arial.ttf", 20)
70
+ except:
71
+ font = ImageFont.load_default()
72
+
73
+ bbox = draw.textbbox((0, 0), text, font=font)
74
+ text_width = bbox[2] - bbox[0]
75
+ text_height = bbox[3] - bbox[1]
76
+
77
+ x = (size[0] - text_width) // 2
78
+ y = (size[1] - text_height) // 2
79
+
80
+ draw.text((x, y), text, fill='black', font=font)
81
+ return np.array(img)
82
+
83
+ def load_model_image_from_url(url):
84
+ """Load model image from URL"""
85
+ try:
86
+ response = requests.get(url, timeout=10)
87
+ if response.status_code == 200:
88
+ image = Image.open(io.BytesIO(response.content))
89
+ # Convert to RGB if needed
90
+ if image.mode != 'RGB':
91
+ image = image.convert('RGB')
92
+ # Resize to standard size
93
+ image = image.resize((400, 600), Image.Resampling.LANCZOS)
94
+ return np.array(image)
95
+ else:
96
+ return create_placeholder_image("Failed to load model")
97
+ except Exception as e:
98
+ print(f"Error loading model image: {e}")
99
+ return create_placeholder_image("Model loading error")
100
+
101
+ def get_outfit_tryon_result(model_image, garment_top, garment_bottom, style_prompt="", selected_model=None):
102
+ """Generate outfit try-on result"""
103
+ try:
104
+ # Determine which model to use
105
+ if model_image is not None:
106
+ # Use uploaded image
107
+ base_model = model_image
108
+ model_source = "uploaded photo"
109
+ elif selected_model and selected_model in MODEL_AVATARS:
110
+ # Load selected model from URL
111
+ base_model = load_model_image_from_url(MODEL_AVATARS[selected_model])
112
+ model_source = selected_model
113
+ else:
114
+ return create_placeholder_image("Please upload a photo or select a model")
115
+
116
+ # If no garments provided, generate based on style
117
+ if garment_top is None and garment_bottom is None and not style_prompt:
118
+ return create_placeholder_image("Please upload garments or describe a style")
119
+
120
+ if garment_top is None and garment_bottom is None and style_prompt:
121
+ # Generate outfit based on text description
122
+ if pipe_txt2img:
123
+ prompt = f"professional fashion photo of a person wearing {style_prompt}, high quality, detailed clothing, same person as reference"
124
+ negative_prompt = "blurry, low quality, distorted, nude, different person"
125
+
126
+ generated_image = pipe_txt2img(
127
+ prompt=prompt,
128
+ negative_prompt=negative_prompt,
129
+ num_inference_steps=25,
130
+ guidance_scale=7.5,
131
+ width=400,
132
+ height=600
133
+ ).images[0]
134
+
135
+ result = np.array(generated_image)
136
+ else:
137
+ # Create styled placeholder showing the base model with text overlay
138
+ result = create_styled_placeholder(base_model, style_prompt)
139
+ else:
140
+ # Apply uploaded garments to the base model
141
+ result = simulate_tryon(base_model, garment_top, garment_bottom, model_source)
142
+
143
+ # Add watermark
144
+ final_result = add_watermark(result)
145
+ return final_result
146
+
147
+ except Exception as e:
148
+ print(f"Error in outfit generation: {e}")
149
+ return create_placeholder_image("Generation Error")
150
+
151
+ def create_styled_placeholder(base_model, style_text):
152
+ """Create a styled placeholder showing base model with style text"""
153
+ if isinstance(base_model, np.ndarray):
154
+ result = base_model.copy()
155
+ else:
156
+ result = create_placeholder_image("Base Model")
157
+
158
+ # Add style overlay
159
+ img_pil = Image.fromarray(result)
160
+ draw = ImageDraw.Draw(img_pil)
161
+
162
+ try:
163
+ font = ImageFont.truetype("arial.ttf", 18)
164
+ small_font = ImageFont.truetype("arial.ttf", 14)
165
+ except:
166
+ font = ImageFont.load_default()
167
+ small_font = ImageFont.load_default()
168
+
169
+ # Add semi-transparent background for text
170
+ overlay = Image.new('RGBA', img_pil.size, (0,0,0,0))
171
+ overlay_draw = ImageDraw.Draw(overlay)
172
+ overlay_draw.rectangle([10, 10, 390, 80], fill=(0,0,0,128))
173
+
174
+ img_pil = Image.alpha_composite(img_pil.convert('RGBA'), overlay).convert('RGB')
175
+ draw = ImageDraw.Draw(img_pil)
176
+
177
+ # Add text
178
+ draw.text((20, 20), "Generated Style:", fill='white', font=small_font)
179
+ draw.text((20, 45), style_text[:40] + "..." if len(style_text) > 40 else style_text,
180
+ fill='yellow', font=font)
181
+
182
+ return np.array(img_pil)
183
+
184
+ def simulate_tryon(model_img, garment_top, garment_bottom, model_source=""):
185
+ """Simulate outfit try-on with base model and garments"""
186
+ if isinstance(model_img, np.ndarray):
187
+ result = model_img.copy()
188
+ else:
189
+ result = create_placeholder_image("Base Model")
190
+
191
+ # Convert to PIL for drawing
192
+ img_pil = Image.fromarray(result)
193
+ draw = ImageDraw.Draw(img_pil)
194
+
195
+ try:
196
+ font = ImageFont.truetype("arial.ttf", 16)
197
+ small_font = ImageFont.truetype("arial.ttf", 12)
198
+ except:
199
+ font = ImageFont.load_default()
200
+ small_font = ImageFont.load_default()
201
+
202
+ # Add overlay showing what's being applied
203
+ overlay = Image.new('RGBA', img_pil.size, (0,0,0,0))
204
+ overlay_draw = ImageDraw.Draw(overlay)
205
+ overlay_draw.rectangle([10, 10, 390, 100], fill=(0,100,0,128))
206
+
207
+ img_pil = Image.alpha_composite(img_pil.convert('RGBA'), overlay).convert('RGB')
208
+ draw = ImageDraw.Draw(img_pil)
209
+
210
+ y_pos = 20
211
+ draw.text((20, y_pos), f"Base Model: {model_source}", fill='white', font=small_font)
212
+ y_pos += 25
213
+
214
+ if garment_top is not None:
215
+ draw.text((20, y_pos), "βœ“ Top garment applied", fill='lightgreen', font=font)
216
+ y_pos += 25
217
+ if garment_bottom is not None:
218
+ draw.text((20, y_pos), "βœ“ Bottom garment applied", fill='lightgreen', font=font)
219
+
220
+ return np.array(img_pil)
221
+
222
+ def edit_outfit_with_text(current_image, edit_prompt, strength=0.7):
223
+ """Edit the current outfit using text prompt"""
224
+ if current_image is None:
225
+ return None, "Please generate an outfit first!"
226
+
227
+ if not edit_prompt.strip():
228
+ return current_image, "Please enter an edit prompt!"
229
+
230
+ try:
231
+ # Convert to PIL if numpy array
232
+ if isinstance(current_image, np.ndarray):
233
+ image = Image.fromarray(current_image)
234
+ else:
235
+ image = current_image
236
+
237
+ # Resize if needed
238
+ image = image.resize((400, 600))
239
+
240
+ # Create a simple mask for clothing area
241
+ mask = Image.new('L', (400, 600), 0)
242
+ mask_draw = ImageDraw.Draw(mask)
243
+ mask_draw.rectangle([50, 150, 350, 450], fill=255) # Clothing area
244
+
245
+ if pipe_inpaint:
246
+ prompt = f"person wearing {edit_prompt}, high quality fashion photo"
247
+ negative_prompt = "blurry, low quality, distorted, nude"
248
+
249
+ edited_image = pipe_inpaint(
250
+ prompt=prompt,
251
+ image=image,
252
+ mask_image=mask,
253
+ negative_prompt=negative_prompt,
254
+ num_inference_steps=20,
255
+ strength=strength,
256
+ guidance_scale=7.5
257
+ ).images[0]
258
+
259
+ return np.array(edited_image), f"βœ… Outfit edited: {edit_prompt}"
260
+ else:
261
+ # Fallback: add text overlay
262
+ draw = ImageDraw.Draw(image)
263
+ draw.text((10, 10), f"Edit: {edit_prompt}", fill='red')
264
+ return np.array(image), f"βœ… Edit applied: {edit_prompt}"
265
+
266
+ except Exception as e:
267
+ return current_image, f"❌ Error editing: {str(e)}"
268
+
269
+ # Initialize models
270
+ print("Loading AI models...")
271
+ models_loaded = initialize_models()
272
+ print(f"Models loaded: {models_loaded}")
273
+
274
+ # Create the main interface
275
+ with gr.Blocks(css=".output-image, .input-image, .image-preview {height: 400px !important}",
276
+ title="AI Outfit Designer") as demo:
277
+
278
+ # Header
279
+ gr.HTML("""
280
+ <div style="display: flex; justify-content: center; align-items: center; text-align: center;">
281
+ <div>
282
+ <h1>πŸ‘— AI Outfit Designer & Virtual Try-On πŸ‘”</h1>
283
+ <h4>v1.0 - Upload your own photo or choose from our models</h4>
284
+ <div style="display: flex; justify-content: center; align-items: center; text-align: center;">
285
+ <span style="background: #4CAF50; color: white; padding: 5px 10px; border-radius: 15px; margin: 5px;">
286
+ ✨ AI-Powered
287
+ </span>
288
+ <span style="background: #2196F3; color: white; padding: 5px 10px; border-radius: 15px; margin: 5px;">
289
+ 🎨 Text Editing
290
+ </span>
291
+ <span style="background: #FF9800; color: white; padding: 5px 10px; border-radius: 15px; margin: 5px;">
292
+ πŸ‘— Virtual Try-On
293
+ </span>
294
+ </div>
295
+ </div>
296
+ </div>
297
+ """)
298
+
299
+ with gr.Row():
300
+ # Left Column - Model Selection
301
+ with gr.Column():
302
+ gr.HTML("""
303
+ <div style="text-align: center;">
304
+ <h3>πŸ‘€ Step 1: Choose Your Base Model</h3>
305
+ <p>Upload your own photo or select a base model to dress up</p>
306
+ </div>
307
+ """)
308
+
309
+ model_image = gr.Image(
310
+ sources=['upload', 'clipboard'],
311
+ type="numpy",
312
+ label="Upload Your Photo (Optional)",
313
+ height=400
314
+ )
315
+
316
+ # Model selection dropdown
317
+ model_selector = gr.Dropdown(
318
+ choices=list(MODEL_AVATARS.keys()),
319
+ value="Fashion Model A",
320
+ label="Or Choose a Base Model",
321
+ interactive=True
322
+ )
323
+
324
+ # Example models gallery (shows actual base model images)
325
+ gr.Markdown("### πŸ“Έ Available Base Models")
326
+
327
+ # Create a function to show model preview
328
+ def show_model_preview(model_name):
329
+ if model_name in MODEL_AVATARS:
330
+ return load_model_image_from_url(MODEL_AVATARS[model_name])
331
+ return create_placeholder_image("Select a model")
332
+
333
+ model_preview = gr.Image(label="Selected Base Model Preview", height=300, interactive=False)
334
+
335
+ # Update preview when dropdown changes
336
+ model_selector.change(fn=show_model_preview, inputs=[model_selector], outputs=[model_preview])
337
+
338
+ # Middle Column - Garments and Style
339
+ with gr.Column():
340
+ gr.HTML("""
341
+ <div style="text-align: center;">
342
+ <h3>πŸ‘• Step 2: Choose Style or Upload Garments</h3>
343
+ <p>Upload specific garments or describe your desired style</p>
344
+ </div>
345
+ """)
346
+
347
+ # Style prompt (new feature)
348
+ style_prompt = gr.Textbox(
349
+ label="Describe Your Desired Style",
350
+ placeholder="e.g., 'casual jeans and t-shirt', 'elegant black dress', 'business suit'",
351
+ lines=2
352
+ )
353
+
354
+ with gr.Row():
355
+ garment_top = gr.Image(
356
+ sources='upload',
357
+ type="numpy",
358
+ label="Top Garment (Optional)",
359
+ height=200
360
+ )
361
+ garment_bottom = gr.Image(
362
+ sources='upload',
363
+ type="numpy",
364
+ label="Bottom Garment (Optional)",
365
+ height=200
366
+ )
367
+
368
+ # Quick style buttons
369
+ gr.Markdown("### 🎯 Quick Style Options")
370
+ with gr.Row():
371
+ casual_btn = gr.Button("πŸ‘• Casual", size="sm")
372
+ business_btn = gr.Button("πŸ’Ό Business", size="sm")
373
+ formal_btn = gr.Button("🎩 Formal", size="sm")
374
+ trendy_btn = gr.Button("✨ Trendy", size="sm")
375
+
376
+ generate_btn = gr.Button("🎨 Generate Outfit", variant="primary", size="lg")
377
+
378
+ # Right Column - Results
379
+ with gr.Column():
380
+ gr.HTML("""
381
+ <div style="text-align: center;">
382
+ <h3>✨ Your Generated Outfit</h3>
383
+ </div>
384
+ """)
385
+
386
+ result_image = gr.Image(label="Generated Outfit", height=400)
387
+
388
+ generation_status = gr.Markdown("Upload a photo or select a model, then click Generate!")
389
+
390
+ # Separator
391
+ gr.HTML("<hr style='margin: 30px 0; border: 1px solid #ddd;'>")
392
+
393
+ # Bottom Section - Text Editor
394
+ gr.HTML("""
395
+ <div style="text-align: center; margin: 20px;">
396
+ <h2>✏️ Step 3: Edit Your Outfit with AI</h2>
397
+ <p>Use natural language to modify your generated outfit</p>
398
+ </div>
399
+ """)
400
+
401
+ with gr.Row():
402
+ with gr.Column():
403
+ edit_prompt = gr.Textbox(
404
+ label="Describe Your Edits",
405
+ placeholder="e.g., 'change shirt to red', 'add a jacket', 'make it more colorful'",
406
+ lines=3
407
+ )
408
+
409
+ with gr.Row():
410
+ edit_strength = gr.Slider(
411
+ minimum=0.3,
412
+ maximum=1.0,
413
+ value=0.7,
414
+ step=0.1,
415
+ label="Edit Strength"
416
+ )
417
+
418
+ edit_btn = gr.Button("πŸ–ŒοΈ Apply Edit", variant="secondary", size="lg")
419
+
420
+ # Quick edit options
421
+ gr.Markdown("### ⚑ Quick Edits")
422
+ with gr.Row():
423
+ add_jacket_btn = gr.Button("Add Jacket", size="sm")
424
+ change_color_btn = gr.Button("Change Colors", size="sm")
425
+ make_formal_btn = gr.Button("Make Formal", size="sm")
426
+ add_accessories_btn = gr.Button("Add Accessories", size="sm")
427
+
428
+ with gr.Column():
429
+ edited_result = gr.Image(label="Edited Outfit", height=400)
430
+ edit_status = gr.Markdown("Generate an outfit first, then describe your edits!")
431
+
432
+ # Examples Section
433
+ gr.HTML("<hr style='margin: 30px 0; border: 1px solid #ddd;'>")
434
+ gr.Markdown("## πŸ“š Examples & Tips")
435
+
436
+ with gr.Row():
437
+ with gr.Column():
438
+ gr.Markdown("""
439
+ ### 🎯 Style Prompt Examples:
440
+ - "Casual weekend outfit with jeans"
441
+ - "Professional business attire"
442
+ - "Elegant evening dress for dinner"
443
+ - "Sporty athleisure wear"
444
+ - "Vintage 1950s inspired look"
445
+ """)
446
+
447
+ with gr.Column():
448
+ gr.Markdown("""
449
+ ### ✏️ Edit Prompt Examples:
450
+ - "Change the shirt to a red color"
451
+ - "Add a denim jacket over the outfit"
452
+ - "Make the dress shorter and more casual"
453
+ - "Add gold jewelry and accessories"
454
+ - "Change to a winter coat and boots"
455
+ """)
456
+
457
+ # Store current image for editing
458
+ current_generated = gr.State(None)
459
+
460
+ # Event Handlers
461
+ def generate_outfit(model_img, garment1, garment2, style_text, selected_model):
462
+ result = get_outfit_tryon_result(model_img, garment1, garment2, style_text, selected_model)
463
+
464
+ if model_img is not None:
465
+ model_info = "uploaded photo"
466
+ elif selected_model:
467
+ model_info = selected_model
468
+ else:
469
+ model_info = "no model selected"
470
+
471
+ status = f"βœ… Generated outfit on {model_info}"
472
+ if style_text:
473
+ status += f" with style: {style_text}"
474
+ if garment1 is not None or garment2 is not None:
475
+ status += f" using uploaded garments"
476
+
477
+ return result, result, status
478
+
479
+ def apply_edit(current_img, edit_text, strength):
480
+ if current_img is None:
481
+ return None, "❌ Please generate an outfit first!"
482
+
483
+ edited_img, status = edit_outfit_with_text(current_img, edit_text, strength)
484
+ return edited_img, status
485
+
486
+ # Connect events
487
+ generate_btn.click(
488
+ fn=generate_outfit,
489
+ inputs=[model_image, garment_top, garment_bottom, style_prompt, model_selector],
490
+ outputs=[result_image, current_generated, generation_status]
491
+ )
492
+
493
+ edit_btn.click(
494
+ fn=apply_edit,
495
+ inputs=[current_generated, edit_prompt, edit_strength],
496
+ outputs=[edited_result, edit_status]
497
+ )
498
+
499
+ # Quick style buttons
500
+ casual_btn.click(lambda: "casual jeans and t-shirt outfit", outputs=[style_prompt])
501
+ business_btn.click(lambda: "professional business suit", outputs=[style_prompt])
502
+ formal_btn.click(lambda: "elegant formal evening wear", outputs=[style_prompt])
503
+ trendy_btn.click(lambda: "trendy fashionable modern outfit", outputs=[style_prompt])
504
+
505
+ # Quick edit buttons
506
+ add_jacket_btn.click(lambda: "add a stylish jacket", outputs=[edit_prompt])
507
+ change_color_btn.click(lambda: "change colors to be more vibrant", outputs=[edit_prompt])
508
+ make_formal_btn.click(lambda: "make the outfit more formal and elegant", outputs=[edit_prompt])
509
+ add_accessories_btn.click(lambda: "add fashionable accessories and jewelry", outputs=[edit_prompt])
510
+
511
+ if __name__ == "__main__":
512
+ demo.launch()