ovi054 commited on
Commit
4002df7
·
verified ·
1 Parent(s): e914a06

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -296
app.py CHANGED
@@ -7,102 +7,6 @@ from longcat_image.models import LongCatImageTransformer2DModel
7
  from longcat_image.pipelines import LongCatImageEditPipeline, LongCatImagePipeline
8
  import numpy as np
9
 
10
- # 1. DEFINE THE CUSTOM APPLE THEME
11
- class AppleStyleTheme(gr.themes.Base):
12
- def __init__(
13
- self,
14
- # Apple Core Colors: System Blue, Cool Grays
15
- primary_hue=gr.themes.colors.blue,
16
- secondary_hue=gr.themes.colors.gray,
17
- neutral_hue=gr.themes.colors.gray,
18
- # Sizing: Rounded corners (iOS style) and generous spacing
19
- radius_size=gr.themes.sizes.radius_lg,
20
- # Fonts: The stack that prioritizes San Francisco (Apple's font)
21
- font=[
22
- "system-ui",
23
- "-apple-system",
24
- "BlinkMacSystemFont",
25
- "Segoe UI",
26
- "Roboto",
27
- "Helvetica Neue",
28
- "Arial",
29
- "sans-serif"
30
- ],
31
- font_mono=gr.themes.GoogleFont("IBM Plex Mono"),
32
- spacing_size=gr.themes.sizes.spacing_lg,
33
- text_size=gr.themes.sizes.text_md,
34
- **kwargs
35
- ):
36
- super().__init__(
37
- primary_hue=primary_hue,
38
- secondary_hue=secondary_hue,
39
- neutral_hue=neutral_hue,
40
- radius_size=radius_size,
41
- font=font,
42
- font_mono=font_mono,
43
- spacing_size=spacing_size,
44
- text_size=text_size,
45
- **kwargs
46
- )
47
-
48
- # Override specific CSS variables for the "Apple Look"
49
- self.set(
50
- # Backgrounds: Very light gray background, pure white cards
51
- body_background_fill="#F5F5F7", # Apple's signature light gray
52
- body_text_color="#1d1d1f", # Corrected from 'text_color'
53
- block_background_fill="#FFFFFF",
54
- block_label_background_fill="#FFFFFF",
55
-
56
- # Borders: Very subtle, thin borders
57
- block_border_color="#E5E5EA",
58
- block_border_width="1px",
59
- block_shadow="0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03)",
60
- block_padding="*spacing_lg",
61
-
62
- # Inputs: Light gray background for inputs (like iOS grouped tables)
63
- input_background_fill="#F2F2F7",
64
- input_border_color="transparent",
65
- input_shadow="none",
66
- input_shadow_focus="0 0 0 2px #007AFF", # Apple Blue focus ring
67
-
68
- # Buttons: Flat Apple Blue button
69
- button_primary_background_fill="#007AFF",
70
- button_primary_background_fill_hover="#0071E3",
71
- button_primary_text_color="white",
72
- button_primary_border_color="transparent",
73
- button_primary_shadow="none",
74
-
75
- # Text
76
- block_label_text_color="*neutral_500",
77
- block_title_text_color="*neutral_900",
78
- )
79
-
80
- # Instantiate the theme
81
- apple_theme = AppleStyleTheme()
82
-
83
- # 2. CUSTOM CSS FOR DARK MODE FIXES
84
- # This CSS targets the HTML elements specifically when Gradio is in "dark" mode.
85
- custom_css = """
86
- /* Force title color in dark mode */
87
- .dark #app-title {
88
- color: #F5F5F7 !important;
89
- }
90
- .dark #app-subtitle {
91
- color: #A1A1A6 !important;
92
- }
93
-
94
- /* Dark mode adjustments for the custom theme colors */
95
- .dark .gradio-container {
96
- background-color: #000000 !important;
97
- }
98
- .dark .block.panel {
99
- background-color: #1C1C1E !important; /* Apple Dark Mode Gray */
100
- border-color: #2C2C2E !important;
101
- }
102
- .dark input, .dark textarea, .dark .gr-input {
103
- background-color: #2C2C2E !important;
104
- }
105
- """
106
 
107
  # --- Model Loading ---
108
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
@@ -155,39 +59,68 @@ edit_pipe.to(device, torch.bfloat16)
155
 
156
  print(f"✅ Image Edit model loaded successfully on {device}")
157
 
158
- # --- Core Functions ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  @spaces.GPU(duration=120)
160
- def generate_image(
161
- prompt: str,
162
- width: int,
163
- height: int,
164
- seed: int,
165
- progress=gr.Progress()
166
- ):
167
- """Generate image from text prompt"""
168
- if not prompt or prompt.strip() == "":
169
- raise gr.Error("Please enter a prompt")
170
  try:
171
- progress(0.1, desc="Preparing generation...")
172
- progress(0.2, desc="Generating image...")
173
- generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
174
- with torch.inference_mode():
175
- output = t2i_pipe(
176
- prompt,
177
- negative_prompt="",
178
- height=height,
179
- width=width,
180
- guidance_scale=4.5,
181
- num_inference_steps=50,
182
- num_images_per_prompt=1,
183
- generator=generator,
184
- enable_cfg_renorm=True,
185
- enable_prompt_rewrite=True
186
- )
187
- progress(1.0, desc="Done!")
188
- return output.images[0]
189
- except Exception as e:
190
- raise gr.Error(f"Error during image generation: {str(e)}")
191
 
192
  @spaces.GPU(duration=120)
193
  def edit_image(
@@ -222,180 +155,81 @@ def edit_image(
222
  except Exception as e:
223
  raise gr.Error(f"Error during image editing: {str(e)}")
224
 
225
- # --- Examples ---
226
- edit_example_image_url = "https://huggingface.co/datasets/huggingface/brand-assets/resolve/main/hf-logo.png"
227
- edit_example_data = [
228
- [edit_example_image_url, "Add a mustache", 42],
229
- ]
230
 
231
- t2i_example_prompts = [
232
- ["一个年轻的亚裔女性,身穿黄色针织衫,搭配白色项链。她的双手放在膝盖上,表情恬静。背景是一堵粗糙的砖墙,午后的阳光温暖地洒在她身上,营造出一种宁静而温馨的氛围。", 1344, 768, 43],
233
- ["A serene mountain landscape at sunset with golden clouds", 1344, 768, 42],
234
- ["A cute robot sitting at a desk, digital art style", 1024, 1024, 44],
235
  ]
236
-
237
- # Build Gradio interface
238
- # Theme and CSS are PASSED IN LAUNCH()
239
- with gr.Blocks(fill_width=True) as demo:
240
 
241
- # Header with IDs for CSS targeting
242
- gr.HTML("""
243
- <div style="text-align: center; padding: 40px 20px 30px 20px;">
244
- <h1 id="app-title" style="font-size: 48px; font-weight: 700; margin: 0; color: #1d1d1f; letter-spacing: -0.02em;">
245
- LongCat Studio
246
- </h1>
247
- <p id="app-subtitle" style="font-size: 20px; color: #86868b; margin-top: 12px; font-weight: 400;">
248
- AI-powered image generation and editing
249
- </p>
250
- </div>
251
- """)
252
-
253
- with gr.Tabs(selected=0):
254
- # Image Edit Tab
255
- with gr.TabItem("Edit Image", id=0):
256
- with gr.Row():
257
- # Left Column: Inputs
258
- with gr.Column(scale=1, variant="panel"):
259
- gr.Markdown("### 🖼️ Input Image & Controls")
260
- input_image = gr.Image(
261
- label="Upload Image",
262
- type="pil",
263
- sources=["upload", "clipboard"],
264
- height=450,
265
- )
266
-
267
- prompt = gr.Textbox(
268
- label="What would you like to change?",
269
- placeholder="e.g., Add a mustache, Change to sunset, Make it vintage...",
270
- lines=2,
271
- max_lines=3
272
- )
273
-
274
- seed = gr.Slider(
275
- minimum=0,
276
- maximum=999999,
277
- value=42,
278
- step=1,
279
- label="Seed",
280
- visible=False
281
- )
282
-
283
- edit_btn = gr.Button("Edit Image", variant="primary", size="lg")
284
-
285
- # Right Column: Output
286
- with gr.Column(scale=1, variant="panel"):
287
- gr.Markdown("### ✨ Result")
288
- output_image = gr.Image(
289
- label="Result",
290
- type="pil",
291
- format="png",
292
- height=450,
293
- )
294
-
295
- gr.HTML("<div style='margin: 30px 0 20px 0;'></div>")
296
-
297
- gr.Examples(
298
- examples=edit_example_data,
299
- inputs=[input_image, prompt, seed],
300
- outputs=output_image,
301
- fn=edit_image,
302
- cache_examples=False,
303
- label="Try an example",
304
- examples_per_page=3
305
- )
306
-
307
- # Text-to-Image Tab
308
- with gr.TabItem("Generate Image", id=1):
309
- with gr.Row():
310
- # Left Column: Inputs
311
- with gr.Column(scale=1, variant="panel"):
312
- gr.Markdown("### 🎨 Generation Controls")
313
- t2i_prompt = gr.Textbox(
314
- label="Describe your image",
315
- placeholder="e.g., A serene mountain landscape at sunset...",
316
- lines=4,
317
- max_lines=6
318
- )
319
-
320
- # Hidden Sliders
321
- t2i_width = gr.Slider(
322
- minimum=512,
323
- maximum=2048,
324
- value=1344,
325
- step=64,
326
- label="Width",
327
- visible=False,
328
- )
329
-
330
- t2i_height = gr.Slider(
331
- minimum=512,
332
- maximum=2048,
333
- value=768,
334
- step=64,
335
- label="Height",
336
- visible=False,
337
- )
338
-
339
- t2i_seed = gr.Slider(
340
- minimum=0,
341
- maximum=999999,
342
- value=42,
343
- step=1,
344
- label="Seed",
345
- visible=False
346
- )
347
-
348
- generate_btn = gr.Button("Generate Image", variant="primary", size="lg")
349
-
350
- # Right Column: Output
351
- with gr.Column(scale=1, variant="panel"):
352
- gr.Markdown("### ✨ Result")
353
- t2i_output = gr.Image(
354
- label="Result",
355
- type="pil",
356
- height=550,
357
- )
358
-
359
- gr.HTML("<div style='margin: 30px 0 20px 0;'></div>")
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  gr.Examples(
362
- examples=t2i_example_prompts,
363
- inputs=[t2i_prompt, t2i_width, t2i_height, t2i_seed],
364
- outputs=t2i_output,
365
- fn=generate_image,
366
- cache_examples=False,
367
- label="Try an example",
368
- examples_per_page=3
369
  )
370
-
371
- # Event handlers
372
- generate_btn.click(
373
- fn=generate_image,
374
- inputs=[t2i_prompt, t2i_width, t2i_height, t2i_seed],
375
- outputs=t2i_output,
376
  )
 
 
 
377
 
378
- edit_btn.click(
379
- fn=edit_image,
380
- inputs=[input_image, prompt, seed],
381
- outputs=output_image,
382
- )
383
-
384
- # Footer
385
- gr.HTML("""
386
- <div style="text-align: center; margin-top: 60px; padding: 30px 20px; border-top: 1px solid #d2d2d7;">
387
- <p style="color: #86868b; font-size: 13px; margin: 0;">
388
- Powered by LongCat • Built with
389
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #007aff; text-decoration: none;">anycoder</a>
390
- </p>
391
- </div>
392
- """)
393
-
394
- # Launch the app
395
- # THEME and CSS moved here for Gradio 6 Compliance
396
- if __name__ == "__main__":
397
- demo.launch(
398
- mcp_server=True,
399
- theme=apple_theme,
400
- css=custom_css
401
- )
 
7
  from longcat_image.pipelines import LongCatImageEditPipeline, LongCatImagePipeline
8
  import numpy as np
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # --- Model Loading ---
12
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
 
59
 
60
  print(f"✅ Image Edit model loaded successfully on {device}")
61
 
62
+ # # --- Core Functions ---
63
+ # @spaces.GPU(duration=120)
64
+ # def generate_image(
65
+ # prompt: str,
66
+ # width: int,
67
+ # height: int,
68
+ # seed: int,
69
+ # progress=gr.Progress()
70
+ # ):
71
+ # """Generate image from text prompt"""
72
+ # if not prompt or prompt.strip() == "":
73
+ # raise gr.Error("Please enter a prompt")
74
+ # try:
75
+ # progress(0.1, desc="Preparing generation...")
76
+ # progress(0.2, desc="Generating image...")
77
+ # generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
78
+ # with torch.inference_mode():
79
+ # output = t2i_pipe(
80
+ # prompt,
81
+ # negative_prompt="",
82
+ # height=height,
83
+ # width=width,
84
+ # guidance_scale=4.5,
85
+ # num_inference_steps=50,
86
+ # num_images_per_prompt=1,
87
+ # generator=generator,
88
+ # enable_cfg_renorm=True,
89
+ # enable_prompt_rewrite=True
90
+ # )
91
+ # progress(1.0, desc="Done!")
92
+ # return output.images[0]
93
+ # except Exception as e:
94
+ # raise gr.Error(f"Error during image generation: {str(e)}")
95
+
96
  @spaces.GPU(duration=120)
97
+ def infer(prompt, seed=42, randomize_seed=False, width=1024, height=1024, guidance_scale=4, num_inference_steps=28, lora_id=None, lora_scale=0.95, progress=gr.Progress(track_tqdm=True)):
98
+ if randomize_seed:
99
+ seed = random.randint(0, MAX_SEED)
100
+ generator = torch.Generator().manual_seed(seed)
101
+
102
+
103
+ if lora_id and lora_id.strip() != "":
104
+ pipe.unload_lora_weights()
105
+ load_lora_auto(pipe, lora_id)
106
+
107
  try:
108
+ image = t2i_pipe(
109
+ prompt=prompt,
110
+ negative_prompt="",
111
+ width=width,
112
+ height=height,
113
+ num_inference_steps=num_inference_steps,
114
+ generator=generator,
115
+ true_cfg_scale=guidance_scale,
116
+ guidance_scale=1.0 # Use a fixed default for distilled guidance
117
+ ).images[0]
118
+ print("Image Generation Completed for: ", prompt, lora_id)
119
+ return image, seed
120
+ finally:
121
+ # Unload LoRA weights if they were loaded
122
+ if lora_id:
123
+ pipe.unload_lora_weights()
 
 
 
 
124
 
125
  @spaces.GPU(duration=120)
126
  def edit_image(
 
155
  except Exception as e:
156
  raise gr.Error(f"Error during image editing: {str(e)}")
157
 
 
 
 
 
 
158
 
159
+ examples = [
160
+ "a tiny astronaut hatching from an egg on the moon",
161
+ "a cat holding a sign that says hello world",
162
+ "an anime illustration of a wiener schnitzel",
163
  ]
 
 
 
 
164
 
165
+ css = """
166
+ #col-container {
167
+ margin: 0 auto;
168
+ max-width: 960px;
169
+ }
170
+ .generate-btn {
171
+ background: linear-gradient(90deg, #4B79A1 0%, #283E51 100%) !important;
172
+ border: none !important;
173
+ color: white !important;
174
+ }
175
+ .generate-btn:hover {
176
+ transform: translateY(-2px);
177
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2);
178
+ }
179
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
+ with gr.Blocks(css=css) as app:
182
+ gr.HTML("<center><h1>Qwen Image with LoRA support</h1></center>")
183
+ with gr.Column(elem_id="col-container"):
184
+ with gr.Row():
185
+ with gr.Column():
186
+ with gr.Row():
187
+ text_prompt = gr.Textbox(label="Prompt", placeholder="Enter a prompt here", lines=3, elem_id="prompt-text-input")
188
+ # with gr.Row():
189
+ # custom_lora = gr.Textbox(label="Custom LoRA (optional)", info="URL or the path to the LoRA weights", placeholder="kudzueye/boreal-qwen-image")
190
+ with gr.Row():
191
+ with gr.Accordion("Advanced Settings", open=False):
192
+
193
+ with gr.Row():
194
+ custom_lora = gr.Textbox(label="Custom LoRA (optional)", info="URL or the path to the LoRA weights", placeholder="kudzueye/boreal-qwen-image")
195
+ lora_scale = gr.Slider(
196
+ label="LoRA Scale",
197
+ minimum=0,
198
+ maximum=2,
199
+ step=0.01,
200
+ value=1,
201
+ )
202
+ with gr.Row():
203
+ width = gr.Slider(label="Width", value=1024, minimum=64, maximum=2048, step=16)
204
+ height = gr.Slider(label="Height", value=1024, minimum=64, maximum=2048, step=16)
205
+ seed = gr.Slider(label="Seed", value=-1, minimum=-1, maximum=4294967296, step=1)
206
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
207
+ with gr.Row():
208
+ steps = gr.Slider(label="Inference steps steps", value=28, minimum=1, maximum=100, step=1)
209
+ cfg = gr.Slider(label="Guidance Scale", value=4, minimum=1, maximum=20, step=0.5)
210
+ # method = gr.Radio(label="Sampling method", value="DPM++ 2M Karras", choices=["DPM++ 2M Karras", "DPM++ SDE Karras", "Euler", "Euler a", "Heun", "DDIM"])
211
+
212
+ with gr.Row():
213
+ # text_button = gr.Button("Run", variant='primary', elem_id="gen-button")
214
+ text_button = gr.Button("✨ Generate Image", variant='primary', elem_classes=["generate-btn"])
215
+ with gr.Column():
216
+ with gr.Row():
217
+ image_output = gr.Image(type="pil", label="Image Output", elem_id="gallery")
218
+
219
+ # gr.Markdown(article_text)
220
+ with gr.Column():
221
  gr.Examples(
222
+ examples = examples,
223
+ inputs = [text_prompt],
 
 
 
 
 
224
  )
225
+ gr.on(
226
+ triggers=[text_button.click, text_prompt.submit],
227
+ fn = infer,
228
+ inputs=[text_prompt, seed, randomize_seed, width, height, cfg, steps, custom_lora, lora_scale],
229
+ outputs=[image_output, seed]
 
230
  )
231
+
232
+ # text_button.click(query, inputs=[custom_lora, text_prompt, steps, cfg, randomize_seed, seed, width, height], outputs=[image_output,seed_output, seed])
233
+ # text_button.click(infer, inputs=[text_prompt, seed, randomize_seed, width, height, cfg, steps, custom_lora, lora_scale], outputs=[image_output,seed_output, seed])
234
 
235
+ app.launch(share=True, mcp_server=True)