Akjava commited on
Commit
5fb4b63
·
1 Parent(s): 59fe747

replace z-image

Browse files
Files changed (1) hide show
  1. app.py +116 -128
app.py CHANGED
@@ -3,15 +3,13 @@ import numpy as np
3
  import random
4
  import os
5
  from PIL import Image
6
- import requests
7
- import json
8
  from dotenv import load_dotenv
9
 
10
  # Load environment variables
11
  load_dotenv()
12
 
13
- # MCP Server configuration
14
- MCP_SERVER_URL = "https://multimodalart-qwen-image-fast.hf.space/gradio_api/mcp/"
15
  HF_TOKEN = os.getenv("HF_TOKEN")
16
 
17
  # --- UI Constants and Helpers ---
@@ -20,32 +18,48 @@ MAX_SEED = np.iinfo(np.int32).max
20
 
21
  def create_prompt(params):
22
  """
23
- MCP サーバーに送信するためのプロンプト文字列を生成する
24
 
25
  Args:
26
- params (dict): プロンプト生成に使用するパラメータ辞書
27
- - label (str): ボタンテキスト
28
- - detail (str): デザイン詳細
29
- - shape (str): ボタン形状
30
- - layout (str): レイアウト配置
31
- - background (str): 背景設定
32
 
33
  Returns:
34
- str: 画像生成用の完全なプロンプト文字列
35
  """
36
- label = params.get("label", "Button")
37
  detail = params.get("detail", "")
38
  shape = params.get("shape", "rounded")
39
  layout = params.get("layout", "horizontal_3")
40
  background = params.get("background", "natural")
41
 
 
 
 
 
 
 
 
42
  layout_config = {
43
- "horizontal_3": {"count": 3, "desc": "3 horizontal rows"},
 
 
 
44
  "vertical_2": {
45
- "count": 2,
46
- "desc": " 2 vertical tall buttons arranged side by side, vertical rectangular shape, 2 columns layout, slender buttons, portrait orientation",
 
 
 
 
 
 
 
47
  },
48
- "box_2x2": {"count": 4, "desc": "2x2 grid arrangement"},
49
  }
50
  shape_descriptions = {
51
  "box": "box shape",
@@ -55,18 +69,23 @@ def create_prompt(params):
55
  }
56
 
57
  config = layout_config.get(layout, layout_config["horizontal_3"])
58
- count = config["count"]
59
  layout_desc = config["desc"]
60
  shape_desc = shape_descriptions.get(shape, "rounded corners")
61
 
62
- if label and label.strip():
63
- base_prompt = f'Create {count} {detail} button design variations with "{label}" text in a 1024x1024 image.\n'
64
- else:
65
- base_prompt = f"Create {count} {detail} button design variations with no text label in a 1024x1024 image.\n"
66
  base_prompt += f"Arranged in {layout_desc}.\n"
67
  base_prompt += f"{shape_desc.capitalize()}.\n"
68
  if detail:
69
  base_prompt += f"{detail.capitalize()} aesthetic: detailed visual elements and color palette.\n"
 
 
 
 
 
 
70
  base_prompt += "Each button is a different design variation exploring the theme.\n"
71
  if background == "natural":
72
  base_prompt += "Natural background with subtle textures and ambient lighting.\n"
@@ -80,91 +99,50 @@ def create_prompt(params):
80
  return base_prompt
81
 
82
 
83
- def call_mcp_server_http(
84
  prompt,
85
  seed,
86
  randomize_seed,
87
  aspect_ratio,
88
- guidance_scale,
89
  num_inference_steps,
90
- prompt_enhance=False,
91
  ):
92
  """
93
- MCP (Model Context Protocol) サーバーに HTTP リクエストを送信して画像生成を行う
94
 
95
  Args:
96
- prompt (str): 画像生成のためのプロンプトテキスト
97
- seed (int): 乱数シード値
98
- randomize_seed (bool): シードをランダム化するかどうか
99
- aspect_ratio (str): 画像のアスペクト比(例: "1:1", "16:9", "4:3"
100
- guidance_scale (float): ガイダンススケール(1.0-5.0)
101
- num_inference_steps (int): 推論ステップ数(4-28)
102
- prompt_enhance (bool, optional): プロンプトエンハンスを使用するかどうか. Defaults to False.
103
 
104
  Returns:
105
- tuple: (image, seed, error) - 画像オブジェクト、使用されたシード、エラーメッセージ
106
  """
107
- import base64
108
- import io
109
-
110
- print(f"Calling MCP Endpoint: {MCP_SERVER_URL}")
111
  try:
112
- payload = {
113
- "jsonrpc": "2.0",
114
- "method": "tools/call",
115
- "params": {
116
- "name": "Qwen_Image_Fast_infer",
117
- "arguments": {
118
- "prompt": prompt,
119
- "seed": seed,
120
- "randomize_seed": randomize_seed,
121
- "aspect_ratio": aspect_ratio,
122
- "guidance_scale": guidance_scale,
123
- "num_inference_steps": num_inference_steps,
124
- "prompt_enhance": prompt_enhance,
125
- },
126
- },
127
- "id": 1,
128
- }
129
- headers = {
130
- "Content-Type": "application/json",
131
- "Accept": "application/json, text/event-stream",
132
- "User-Agent": "mcp-client-python/1.0",
133
  }
134
- if HF_TOKEN:
135
- headers["Authorization"] = f"Bearer {HF_TOKEN}"
136
-
137
- response = requests.post(
138
- MCP_SERVER_URL, headers=headers, data=json.dumps(payload), timeout=120
 
 
 
 
 
 
 
139
  )
140
-
141
- if response.status_code == 200:
142
- try:
143
- result_json = response.json()
144
- except json.JSONDecodeError:
145
- lines = response.text.strip().split("\n")
146
- last_line = lines[-1]
147
- if last_line.startswith("data: "):
148
- result_json = json.loads(last_line[6:])
149
- else:
150
- result_json = json.loads(last_line)
151
-
152
- if "error" in result_json:
153
- return None, seed, str(result_json["error"])
154
-
155
- if "result" in result_json:
156
- content_list = result_json["result"].get("content", [])
157
- for item in content_list:
158
- if item.get("type") == "image" and item.get("data"):
159
- image_bytes = base64.b64decode(item.get("data"))
160
- return Image.open(io.BytesIO(image_bytes)), seed, None
161
- else:
162
- return None, seed, "Unexpected JSON structure"
163
- else:
164
- return None, seed, f"Server Error: {response.status_code}"
165
  except Exception as e:
166
  return None, seed, str(e)
167
- return Image.new("RGB", (1024, 1024), color="gray"), seed, "Unknown error"
168
 
169
 
170
  # --- Main Inference Logic ---
@@ -180,25 +158,27 @@ def run_inference_engine(
180
  aspect_ratio,
181
  guidance_scale,
182
  num_inference_steps,
 
183
  ):
184
  """
185
- MCP サーバーを使用して UI ボタン画像を生成するメイン推論エンジン
186
 
187
  Args:
188
- label (str): ボタンに表示するテキスト
189
- detail (str): デザインの詳細プロンプト
190
- shape (str): ボタンの形状("box", "rounded", "oval", "free"
191
- layout (str): レイアウト配置("horizontal_3", "vertical_2", "box_2x2"
192
- background (str): 背景設定("natural", "white", "black"
193
- seed (int): 乱数シード値
194
- randomize_seed (bool): シードをランダム化するかどうか
195
- aspect_ratio (str): 画像のアスペクト比 (1:1を使うこと)
196
- guidance_scale (float): ガイダンススケール(常に1を使うこと)
197
- num_inference_steps (int): 推論ステップ数 (常に8を使うこと)
198
 
199
  Yields:
200
- tuple: (image, seed, status_message) - 生成された画像、使用されたシード、ステータスメッセージ
201
  """
 
202
  yield None, seed, "Generating..."
203
  prompt_params = {
204
  "label": label,
@@ -209,18 +189,23 @@ def run_inference_engine(
209
  }
210
  prompt = create_prompt(prompt_params)
211
 
 
 
 
212
  if randomize_seed:
213
  seed = random.randint(0, MAX_SEED)
214
 
215
- image, generated_seed, error = call_mcp_server_http(
216
- prompt, seed, randomize_seed, aspect_ratio, guidance_scale, num_inference_steps
217
  )
 
 
218
 
219
  if image is None:
220
  gr.Warning(f"Error: {error}")
221
  yield None, generated_seed, f"Error: {error}"
222
  else:
223
- yield image, generated_seed, "Done!"
224
 
225
 
226
  # --- UI Customization ---
@@ -230,10 +215,10 @@ body { font-family: 'Helvetica Neue', Arial, sans-serif; }
230
  h1 { text-align: center; font-weight: 800; color: #333; margin-bottom: 0.5em; }
231
  .subtitle { text-align: center; color: #666; margin-bottom: 2em; }
232
 
233
- .generate-btn {
234
- background: linear-gradient(90deg, #6366f1 0%, #a855f7 100%) !important;
235
- border: none !important;
236
- color: white !important;
237
  font-weight: bold !important;
238
  font-size: 1.2em !important;
239
  padding: 20px !important;
@@ -247,15 +232,15 @@ h1 { text-align: center; font-weight: 800; color: #333; margin-bottom: 0.5em; }
247
  box-shadow: 0 5px 15px rgba(99, 102, 241, 0.4);
248
  }
249
 
250
- .examples-container table {
251
- font-size: 0.85em !important;
252
  margin-bottom: 0 !important;
253
  }
254
- .examples-container td {
255
- padding: 4px 8px !important;
256
- white-space: nowrap;
257
- overflow: hidden;
258
- text-overflow: ellipsis;
259
  max-width: 150px;
260
  }
261
  .examples-container label {
@@ -265,9 +250,9 @@ h1 { text-align: center; font-weight: 800; color: #333; margin-bottom: 0.5em; }
265
  display: block;
266
  }
267
 
268
- #result-image {
269
- border-radius: 12px;
270
- box-shadow: 0 10px 30px rgba(0,0,0,0.1);
271
  border: 1px solid #eee;
272
  }
273
  .input-group {
@@ -289,7 +274,7 @@ example_data = [
289
  "box",
290
  "horizontal_3",
291
  "black",
292
- "examples/play.webp",
293
  ],
294
  [
295
  "Buy",
@@ -297,7 +282,7 @@ example_data = [
297
  "rounded",
298
  "vertical_2",
299
  "white",
300
- "examples/buy.webp",
301
  ],
302
  [
303
  "RPG",
@@ -305,7 +290,7 @@ example_data = [
305
  "free",
306
  "box_2x2",
307
  "natural",
308
- "examples/rpg.webp",
309
  ],
310
  [
311
  "Submit",
@@ -320,7 +305,7 @@ example_data = [
320
  with gr.Blocks(css=css, theme=theme, title="UI Button Generator") as demo:
321
  gr.Markdown("# 🎨 AI UI Button Generator")
322
  gr.Markdown(
323
- "<div class='subtitle'>UI button material and design concept generation tool using Qwen Image Fast</div>"
324
  )
325
 
326
  with gr.Column(elem_id="col-container"):
@@ -398,7 +383,7 @@ with gr.Blocks(css=css, theme=theme, title="UI Button Generator") as demo:
398
  # --- 2. Layout Construction Phase (.render()) ---
399
 
400
  with gr.Row(equal_height=False):
401
- # 左カラム
402
  with gr.Column(scale=1, min_width=400):
403
  with gr.Group(elem_classes="input-group"):
404
  gr.Markdown("### 📝 Basic Settings")
@@ -426,18 +411,18 @@ with gr.Blocks(css=css, theme=theme, title="UI Button Generator") as demo:
426
  guidance_scale.render()
427
  num_inference_steps.render()
428
 
429
- # 右カラム
430
  with gr.Column(scale=1):
431
  gr.Markdown("### 🖼️ Generated Button")
432
  result.render()
433
  status_msg.render()
434
- # ボタンとExamplesの行
435
  # gr.Markdown("**Quick Presets (Click to try)**")
436
  # Initialize here with fn, inputs, outputs
437
  gr.Examples(
438
  examples=example_data,
439
  fn=run_inference_engine,
440
- inputs=[label, detail, shape, layout, background, result],
441
  outputs=[result, seed, status_msg],
442
  examples_per_page=3,
443
  run_on_click=False,
@@ -465,4 +450,7 @@ with gr.Blocks(css=css, theme=theme, title="UI Button Generator") as demo:
465
  )
466
 
467
  if __name__ == "__main__":
468
- demo.launch(mcp_server=True)
 
 
 
 
3
  import random
4
  import os
5
  from PIL import Image
6
+ from gradio_client import Client
 
7
  from dotenv import load_dotenv
8
 
9
  # Load environment variables
10
  load_dotenv()
11
 
12
+ # Client configuration
 
13
  HF_TOKEN = os.getenv("HF_TOKEN")
14
 
15
  # --- UI Constants and Helpers ---
 
18
 
19
  def create_prompt(params):
20
  """
21
+ Generate a prompt string for sending to the client
22
 
23
  Args:
24
+ params (dict): Dictionary of parameters used for prompt generation
25
+ - label (str): Comma-separated button texts, will be split into array of 4 labels
26
+ - detail (str): Design details
27
+ - shape (str): Button shape
28
+ - layout (str): Layout arrangement
29
+ - background (str): Background setting
30
 
31
  Returns:
32
+ str: Complete prompt string for image generation
33
  """
34
+ label_str = params.get("label", "Button")
35
  detail = params.get("detail", "")
36
  shape = params.get("shape", "rounded")
37
  layout = params.get("layout", "horizontal_3")
38
  background = params.get("background", "natural")
39
 
40
+ # Split labels by comma, take up to number of positions
41
+ labels = [l.strip() for l in label_str.split(",") if l.strip()]
42
+ if labels:
43
+ # If there are labels, repeat to up to 4
44
+ while len(labels) < 4:
45
+ labels.extend(labels)
46
+
47
  layout_config = {
48
+ "horizontal_3": {
49
+ "positions": ["top", "middle", "bottom"],
50
+ "desc": "3 horizontal rows: top, middle, bottom",
51
+ },
52
  "vertical_2": {
53
+ "positions": [
54
+ "left middle-valign small text",
55
+ "right middle-valign small text",
56
+ ],
57
+ "desc": "2 vertical tall buttons arranged side by side, vertical rectangular shape, 2 columns layout, horizontal text, small text orientation is horizontal",
58
+ },
59
+ "box_2x2": {
60
+ "positions": ["left-top", "right-top", "left-bottom", "right-bottom"],
61
+ "desc": "2x2 grid: left-top, right-top, left-bottom, right-bottom",
62
  },
 
63
  }
64
  shape_descriptions = {
65
  "box": "box shape",
 
69
  }
70
 
71
  config = layout_config.get(layout, layout_config["horizontal_3"])
72
+ positions = config["positions"]
73
  layout_desc = config["desc"]
74
  shape_desc = shape_descriptions.get(shape, "rounded corners")
75
 
76
+ base_prompt = (
77
+ f"Create {len(positions)} {detail} button designs in a 1024x1024 image.\n"
78
+ )
 
79
  base_prompt += f"Arranged in {layout_desc}.\n"
80
  base_prompt += f"{shape_desc.capitalize()}.\n"
81
  if detail:
82
  base_prompt += f"{detail.capitalize()} aesthetic: detailed visual elements and color palette.\n"
83
+ # Describe each button with position and label
84
+ for i, pos in enumerate(positions):
85
+ if i < len(labels):
86
+ base_prompt += f'{pos} button: "{labels[i]}".\n'
87
+ else:
88
+ base_prompt += f"{pos} button: empty text rectangle.\n"
89
  base_prompt += "Each button is a different design variation exploring the theme.\n"
90
  if background == "natural":
91
  base_prompt += "Natural background with subtle textures and ambient lighting.\n"
 
99
  return base_prompt
100
 
101
 
102
+ def call_client(
103
  prompt,
104
  seed,
105
  randomize_seed,
106
  aspect_ratio,
 
107
  num_inference_steps,
 
108
  ):
109
  """
110
+ Call the gradio client for image generation
111
 
112
  Args:
113
+ prompt (str): Prompt text for image generation
114
+ seed (int): Random seed value
115
+ randomize_seed (bool): Whether to randomize the seed
116
+ aspect_ratio (str): Image aspect ratio (e.g., "1:1", "16:9", "4:3")
117
+ num_inference_steps (int): Number of inference steps (4-28)
 
 
118
 
119
  Returns:
120
+ tuple: (image, seed, error) - Image object, used seed, error message
121
  """
 
 
 
 
122
  try:
123
+ # Map aspect_ratio to resolution
124
+ resolution_map = {
125
+ "1:1": "1024x1024 ( 1:1 )",
126
+ "16:9": "1280x720 ( 16:9 )",
127
+ "4:3": "1152x864 ( 4:3 )",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
129
+ resolution = resolution_map.get(aspect_ratio, "1024x1024 ( 1:1 )")
130
+
131
+ client = Client("Tongyi-MAI/Z-Image-Turbo")
132
+ result = client.predict(
133
+ prompt=prompt,
134
+ resolution=resolution,
135
+ seed=seed,
136
+ steps=num_inference_steps,
137
+ shift=3.0,
138
+ random_seed=randomize_seed,
139
+ gallery_images=[],
140
+ api_name="/generate",
141
  )
142
+ # Assume result is PIL Image
143
+ return result, seed, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  except Exception as e:
145
  return None, seed, str(e)
 
146
 
147
 
148
  # --- Main Inference Logic ---
 
158
  aspect_ratio,
159
  guidance_scale,
160
  num_inference_steps,
161
+ hf_token: gr.Header = None,
162
  ):
163
  """
164
+ generate UI button images
165
 
166
  Args:
167
+ label (str): Text to display on the button
168
+ detail (str): Detailed design prompt
169
+ shape (str): Button shape ("box", "rounded", "oval", "free")
170
+ layout (str): Layout arrangement ("horizontal_3", "vertical_2", "box_2x2")
171
+ background (str): Background setting ("natural", "white", "black")
172
+ seed (int): Random seed value
173
+ randomize_seed (bool): Whether to randomize the seed
174
+ aspect_ratio (str): Image aspect ratio (use 1:1)
175
+ guidance_scale (float): Guidance scale (use 1)
176
+ num_inference_steps (int): Number of inference steps (use 8)
177
 
178
  Yields:
179
+ tuple: (image, seed, status_message) - Generated image, used seed, status message
180
  """
181
+ print(hf_token)
182
  yield None, seed, "Generating..."
183
  prompt_params = {
184
  "label": label,
 
189
  }
190
  prompt = create_prompt(prompt_params)
191
 
192
+ # Debug: Print the generated prompt
193
+ print(f"Generated prompt: {prompt}")
194
+
195
  if randomize_seed:
196
  seed = random.randint(0, MAX_SEED)
197
 
198
+ image, generated_seed, error = call_client(
199
+ prompt, seed, randomize_seed, aspect_ratio, num_inference_steps
200
  )
201
+ print(type(image))
202
+ print(image)
203
 
204
  if image is None:
205
  gr.Warning(f"Error: {error}")
206
  yield None, generated_seed, f"Error: {error}"
207
  else:
208
+ yield image[0][0]["image"], generated_seed, "Done!"
209
 
210
 
211
  # --- UI Customization ---
 
215
  h1 { text-align: center; font-weight: 800; color: #333; margin-bottom: 0.5em; }
216
  .subtitle { text-align: center; color: #666; margin-bottom: 2em; }
217
 
218
+ .generate-btn {
219
+ background: linear-gradient(90deg, #6366f1 0%, #a855f7 100%) !important;
220
+ border: none !important;
221
+ color: white !important;
222
  font-weight: bold !important;
223
  font-size: 1.2em !important;
224
  padding: 20px !important;
 
232
  box-shadow: 0 5px 15px rgba(99, 102, 241, 0.4);
233
  }
234
 
235
+ .examples-container table {
236
+ font-size: 0.85em !important;
237
  margin-bottom: 0 !important;
238
  }
239
+ .examples-container td {
240
+ padding: 4px 8px !important;
241
+ white-space: nowrap;
242
+ overflow: hidden;
243
+ text-overflow: ellipsis;
244
  max-width: 150px;
245
  }
246
  .examples-container label {
 
250
  display: block;
251
  }
252
 
253
+ #result-gallery {
254
+ border-radius: 12px;
255
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
256
  border: 1px solid #eee;
257
  }
258
  .input-group {
 
274
  "box",
275
  "horizontal_3",
276
  "black",
277
+ # "examples/play.webp",
278
  ],
279
  [
280
  "Buy",
 
282
  "rounded",
283
  "vertical_2",
284
  "white",
285
+ # "examples/buy.webp",
286
  ],
287
  [
288
  "RPG",
 
290
  "free",
291
  "box_2x2",
292
  "natural",
293
+ # "examples/rpg.webp",
294
  ],
295
  [
296
  "Submit",
 
305
  with gr.Blocks(css=css, theme=theme, title="UI Button Generator") as demo:
306
  gr.Markdown("# 🎨 AI UI Button Generator")
307
  gr.Markdown(
308
+ "<div class='subtitle'>UI button material and design concept generation tool using Z-Image-Turbo</div>"
309
  )
310
 
311
  with gr.Column(elem_id="col-container"):
 
383
  # --- 2. Layout Construction Phase (.render()) ---
384
 
385
  with gr.Row(equal_height=False):
386
+ # Left column
387
  with gr.Column(scale=1, min_width=400):
388
  with gr.Group(elem_classes="input-group"):
389
  gr.Markdown("### 📝 Basic Settings")
 
411
  guidance_scale.render()
412
  num_inference_steps.render()
413
 
414
+ # Right column
415
  with gr.Column(scale=1):
416
  gr.Markdown("### 🖼️ Generated Button")
417
  result.render()
418
  status_msg.render()
419
+ # Row for button and Examples
420
  # gr.Markdown("**Quick Presets (Click to try)**")
421
  # Initialize here with fn, inputs, outputs
422
  gr.Examples(
423
  examples=example_data,
424
  fn=run_inference_engine,
425
+ inputs=[label, detail, shape, layout, background],
426
  outputs=[result, seed, status_msg],
427
  examples_per_page=3,
428
  run_on_click=False,
 
450
  )
451
 
452
  if __name__ == "__main__":
453
+ demo.launch(
454
+ show_error=True,
455
+ mcp_server=True,
456
+ )