aiqtech commited on
Commit
b7dd84a
ยท
verified ยท
1 Parent(s): bb8a67b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -133
app.py CHANGED
@@ -22,7 +22,10 @@ client = genai.Client(
22
  api_key=API_KEY,
23
  )
24
 
25
- GEMINI_MODEL_NAME = 'gemini-2.5-flash-image-preview'
 
 
 
26
 
27
  def verify_pro_status(token: Optional[gr.OAuthToken]) -> bool:
28
  """Verifies if the user is a Hugging Face PRO user or part of an enterprise org."""
@@ -45,127 +48,94 @@ def _extract_image_data_from_response(response) -> Optional[bytes]:
45
  # Debug: Print response structure
46
  print(f"Response type: {type(response)}")
47
 
48
- # Try multiple ways to extract image data
49
- # Method 1: Direct image attribute
50
- if hasattr(response, 'image'):
51
- print("Found response.image")
52
- return response.image
53
 
54
- # Method 2: Images array
55
- if hasattr(response, 'images') and response.images:
56
- print(f"Found response.images with {len(response.images)} images")
57
- return response.images[0]
58
-
59
- # Method 3: Candidates with parts
60
- if hasattr(response, 'candidates') and response.candidates:
61
- print(f"Found {len(response.candidates)} candidates")
62
- for i, candidate in enumerate(response.candidates):
63
- print(f"Candidate {i}: {type(candidate)}")
64
-
65
- # Check for content.parts
66
- if hasattr(candidate, 'content'):
67
- print(f" Has content: {type(candidate.content)}")
68
- if hasattr(candidate.content, 'parts') and candidate.content.parts:
69
- print(f" Has {len(candidate.content.parts)} parts")
70
- for j, part in enumerate(candidate.content.parts):
71
- print(f" Part {j}: {type(part)}")
72
-
73
- # Check for inline_data
74
- if hasattr(part, 'inline_data'):
75
- print(f" Has inline_data")
76
- if hasattr(part.inline_data, 'data'):
77
- print(f" Found image data!")
78
- return part.inline_data.data
79
- if hasattr(part.inline_data, 'blob'):
80
- print(f" Found blob data!")
81
- return part.inline_data.blob
82
-
83
- # Check for blob directly
84
- if hasattr(part, 'blob'):
85
- print(f" Has blob")
86
- return part.blob
87
-
88
- # Check for data directly
89
- if hasattr(part, 'data'):
90
- print(f" Has data")
91
- return part.data
92
-
93
- # Method 4: Text response (might need different API configuration)
94
  if hasattr(response, 'text'):
95
- print(f"Response has text but no image: {response.text[:200] if response.text else 'Empty'}")
96
 
97
- print("No image data found in response")
98
  return None
99
 
100
  def run_single_image_logic(prompt: str, image_path: Optional[str] = None, progress=gr.Progress()) -> str:
101
- """Handles text-to-image or single image-to-image using Google Gemini."""
102
  try:
103
  progress(0.2, desc="๐ŸŽจ ์ค€๋น„ ์ค‘...")
104
 
105
- # Prepare the prompt with image generation instruction
106
- generation_prompt = f"Generate an image: {prompt}"
107
-
108
  contents = []
109
  if image_path:
110
- # Image-to-image generation
111
  input_image = Image.open(image_path)
112
  contents.append(input_image)
113
- contents.append(f"Edit this image: {prompt}")
114
  else:
115
- # Text-to-image generation
116
- contents.append(generation_prompt)
117
 
118
  progress(0.5, desc="โœจ ์ƒ์„ฑ ์ค‘...")
119
 
120
- # Try with generation config for images
121
- generation_config = types.GenerationConfig(
122
- temperature=1.0,
123
- max_output_tokens=8192,
124
- )
125
-
126
- response = client.models.generate_content(
127
- model=GEMINI_MODEL_NAME,
128
- contents=contents,
129
- generation_config=generation_config,
130
- )
131
-
132
- # Debug: Print full response
133
- print(f"Full response: {response}")
 
 
 
 
 
 
134
 
135
  progress(0.8, desc="๐Ÿ–ผ๏ธ ๋งˆ๋ฌด๋ฆฌ ์ค‘...")
136
- image_data = _extract_image_data_from_response(response)
137
 
138
- if not image_data:
139
- # Try alternative approach - generate_images if available
140
- if hasattr(client.models, 'generate_images'):
141
- print("Trying generate_images method...")
142
- response = client.models.generate_images(
143
- model=GEMINI_MODEL_NAME,
144
- prompt=prompt,
145
- n=1,
146
- )
147
- if hasattr(response, 'images') and response.images:
148
- image_data = response.images[0]
149
 
150
- if not image_data:
151
- raise ValueError("No image data found in the model response. The API might not support image generation or the model name might be incorrect.")
152
-
153
- # Save the generated image to a temporary file to return its path
154
- pil_image = Image.open(BytesIO(image_data))
155
- with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmpfile:
156
- pil_image.save(tmpfile.name)
157
- progress(1.0, desc="โœ… ์™„๋ฃŒ!")
158
- return tmpfile.name
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  except Exception as e:
161
  print(f"Error details: {e}")
162
  print(f"Error type: {type(e)}")
163
- raise gr.Error(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹คํŒจ: {e}")
164
 
165
 
166
  def run_multi_image_logic(prompt: str, images: List[str], progress=gr.Progress()) -> str:
167
  """
168
- Handles multi-image editing by sending a list of images and a prompt.
169
  """
170
  if not images:
171
  raise gr.Error("'์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€' ํƒญ์—์„œ ์ตœ์†Œ ํ•œ ๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.")
@@ -177,39 +147,42 @@ def run_multi_image_logic(prompt: str, images: List[str], progress=gr.Progress()
177
  if isinstance(image_path, (list, tuple)):
178
  image_path = image_path[0]
179
  contents.append(Image.open(image_path))
180
- contents.append(f"Combine/edit these images: {prompt}")
181
 
182
- progress(0.5, desc="โœจ ์ƒ์„ฑ ์ค‘...")
183
-
184
- generation_config = types.GenerationConfig(
185
- temperature=1.0,
186
- max_output_tokens=8192,
187
- )
188
 
 
189
  response = client.models.generate_content(
190
  model=GEMINI_MODEL_NAME,
191
  contents=contents,
192
- generation_config=generation_config,
193
  )
194
 
195
- # Debug: Print full response
196
- print(f"Multi-image response: {response}")
197
-
198
  progress(0.8, desc="๐Ÿ–ผ๏ธ ๋งˆ๋ฌด๋ฆฌ ์ค‘...")
199
- image_data = _extract_image_data_from_response(response)
200
-
201
- if not image_data:
202
- raise ValueError("No image data found in the model response. The API might not support multi-image generation.")
 
 
 
 
 
203
 
204
- pil_image = Image.open(BytesIO(image_data))
205
- with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmpfile:
206
- pil_image.save(tmpfile.name)
207
- progress(1.0, desc="โœ… ์™„๋ฃŒ!")
208
- return tmpfile.name
 
 
 
 
 
 
209
 
210
  except Exception as e:
211
  print(f"Multi-image error details: {e}")
212
- raise gr.Error(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹คํŒจ: {e}")
213
 
214
 
215
  # --- Gradio App UI ---
@@ -394,7 +367,18 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
394
  ๐ŸŒ Real Nano Banana
395
  </h1>
396
  <p class="header-subtitle">
397
- Google Gemini 2.5 Flash Image Preview๋กœ ๊ตฌ๋™๋˜๋Š” AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ
 
 
 
 
 
 
 
 
 
 
 
398
  </p>
399
  </div>
400
  ''')
@@ -435,7 +419,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
435
  )
436
  gr.HTML('''
437
  <p style="text-align: center; color: #6b7280; font-size: 0.9rem; margin-top: 0.5rem;">
438
- ๐Ÿ’ก ํ…์ŠคํŠธโ†’์ด๋ฏธ์ง€ ์ƒ์„ฑ์€ ๋น„์›Œ๋‘์„ธ์š”
439
  </p>
440
  ''')
441
 
@@ -456,14 +440,14 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
456
  prompt_input = gr.Textbox(
457
  label="",
458
  info="AI์—๊ฒŒ ์›ํ•˜๋Š” ๊ฒƒ์„ ์„ค๋ช…ํ•˜์„ธ์š”",
459
- placeholder="์˜ˆ: ๋ง›์žˆ์–ด ๋ณด์ด๋Š” ํ”ผ์ž, ์šฐ์ฃผ๋ฅผ ๋ฐฐ๊ฒฝ์œผ๋กœ ํ•œ ๊ณ ์–‘์ด, ๋ฏธ๋ž˜์ ์ธ ๋„์‹œ ํ’๊ฒฝ...",
460
  lines=3,
461
  elem_classes="prompt-input"
462
  )
463
 
464
  # Generate Button
465
  generate_button = gr.Button(
466
- "๐Ÿš€ ์ƒ์„ฑํ•˜๊ธฐ",
467
  variant="primary",
468
  elem_classes="generate-btn"
469
  )
@@ -472,11 +456,11 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
472
  with gr.Accordion("๐Ÿ’ก ์˜ˆ์ œ ํ”„๋กฌํ”„ํŠธ", open=False):
473
  gr.Examples(
474
  examples=[
475
- ["์น˜์ฆˆ๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๋ง›์žˆ์–ด ๋ณด์ด๋Š” ํ”ผ์ž"],
476
- ["์šฐ์ฃผ๋ณต์„ ์ž…์€ ๊ณ ์–‘์ด๊ฐ€ ๋‹ฌ ํ‘œ๋ฉด์„ ๊ฑท๊ณ  ์žˆ๋Š” ๋ชจ์Šต"],
477
- ["๋„ค์˜จ ๋ถˆ๋น›์ด ๋น›๋‚˜๋Š” ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ ๋„์‹œ์˜ ์•ผ๊ฒฝ"],
478
- ["๋ด„๋‚  ๋ฒš๊ฝƒ์ด ๋งŒ๊ฐœํ•œ ์ผ๋ณธ ์ •์›"],
479
- ["ํŒํƒ€์ง€ ์„ธ๊ณ„์˜ ๋งˆ๋ฒ•์‚ฌ ํƒ‘"],
480
  ],
481
  inputs=prompt_input
482
  )
@@ -485,7 +469,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
485
 
486
  with gr.Column(scale=1):
487
  gr.HTML('<div class="card">')
488
- gr.HTML('<h3 style="margin-top: 0;">๐ŸŽจ ์ƒ์„ฑ ๊ฒฐ๊ณผ</h3>')
489
 
490
  output_image = gr.Image(
491
  label="",
@@ -494,7 +478,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
494
  )
495
 
496
  use_image_button = gr.Button(
497
- "โ™ป๏ธ ์ด ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์Œ ํŽธ์ง‘์— ์‚ฌ์šฉ",
498
  elem_classes="use-btn",
499
  visible=False
500
  )
@@ -505,8 +489,8 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
505
  <h4 style="margin-top: 0; color: #0369a1;">๐Ÿ’ก ํŒ</h4>
506
  <ul style="margin: 0; padding-left: 1.5rem; color: #0c4a6e;">
507
  <li>๊ตฌ์ฒด์ ์ด๊ณ  ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”</li>
508
- <li>์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
509
- <li>๋‹ค์ค‘ ์ด๋ฏธ์ง€ ๋ชจ๋“œ๋กœ ์—ฌ๋Ÿฌ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
510
  </ul>
511
  </div>
512
  ''')
@@ -518,7 +502,7 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
518
  <div style="text-align: center; margin-top: 2rem; padding: 1rem;
519
  border-top: 1px solid #e5e7eb;">
520
  <p style="color: #6b7280;">
521
- Made with ๐Ÿ’œ by Hugging Face PRO | Powered by Google Gemini 2.5 Flash
522
  </p>
523
  </div>
524
  ''')
@@ -572,16 +556,16 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
572
  <div class="pro-message">
573
  <h2>โœจ PRO ์‚ฌ์šฉ์ž ์ „์šฉ ๊ธฐ๋Šฅ</h2>
574
  <p style="font-size: 1.1rem; margin: 1rem 0;">
575
- ์ด ๊ฐ•๋ ฅํ•œ AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋„๊ตฌ๋Š” Hugging Face <strong>PRO</strong> ๋ฉค๋ฒ„ ์ „์šฉ์ž…๋‹ˆ๋‹ค.
576
  </p>
577
  <p style="margin: 1rem 0;">
578
  PRO ๊ตฌ๋…์œผ๋กœ ๋‹ค์Œ์„ ๋ˆ„๋ฆฌ์„ธ์š”:
579
  </p>
580
  <ul style="text-align: left; display: inline-block; margin: 1rem 0;">
581
- <li>๐Ÿš€ Google Gemini 2.5 Flash ๋ฌด์ œํ•œ ์•ก์„ธ์Šค</li>
582
- <li>โšก ๋น ๋ฅธ ์ด๋ฏธ์ง€ ์ƒ์„ฑ</li>
583
- <li>๐ŸŽจ ๊ณ ํ’ˆ์งˆ ๊ฒฐ๊ณผ๋ฌผ</li>
584
- <li>๐Ÿ”ง ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๊ธฐ๋Šฅ</li>
585
  </ul>
586
  <a href="https://huggingface.co/pro" target="_blank"
587
  style="display: inline-block; margin-top: 1rem; padding: 1rem 2rem;
 
22
  api_key=API_KEY,
23
  )
24
 
25
+ # Note: Gemini models don't directly generate images - they analyze/describe them
26
+ # For image generation, you'd need to use a different API like Imagen
27
+ # This code is updated to work with text generation about images
28
+ GEMINI_MODEL_NAME = 'gemini-2.0-flash-exp' # Updated model name
29
 
30
  def verify_pro_status(token: Optional[gr.OAuthToken]) -> bool:
31
  """Verifies if the user is a Hugging Face PRO user or part of an enterprise org."""
 
48
  # Debug: Print response structure
49
  print(f"Response type: {type(response)}")
50
 
51
+ # Note: Gemini doesn't generate images directly
52
+ # This would need to be replaced with actual image generation API
53
+ # For now, return None to indicate no image was generated
 
 
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  if hasattr(response, 'text'):
56
+ print(f"Response text: {response.text[:200] if response.text else 'Empty'}")
57
 
 
58
  return None
59
 
60
  def run_single_image_logic(prompt: str, image_path: Optional[str] = None, progress=gr.Progress()) -> str:
61
+ """Handles text or image analysis using Google Gemini."""
62
  try:
63
  progress(0.2, desc="๐ŸŽจ ์ค€๋น„ ์ค‘...")
64
 
 
 
 
65
  contents = []
66
  if image_path:
67
+ # Image analysis
68
  input_image = Image.open(image_path)
69
  contents.append(input_image)
70
+ contents.append(f"Describe what you see and how it could be modified based on: {prompt}")
71
  else:
72
+ # Text-only prompt
73
+ contents.append(f"Describe an image concept for: {prompt}")
74
 
75
  progress(0.5, desc="โœจ ์ƒ์„ฑ ์ค‘...")
76
 
77
+ # Remove the generation_config parameter that's causing the error
78
+ # Use the simpler API call format
79
+ try:
80
+ response = client.models.generate_content(
81
+ model=GEMINI_MODEL_NAME,
82
+ contents=contents,
83
+ )
84
+ except Exception as api_error:
85
+ # Fallback: try with just the contents as a simple string/list
86
+ print(f"First attempt failed: {api_error}")
87
+ if image_path:
88
+ # For image input, we need to handle it differently
89
+ # The API might expect a different format
90
+ raise gr.Error("์ด๋ฏธ์ง€ ์ž…๋ ฅ์€ ํ˜„์žฌ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Gemini API๋Š” ์ด๋ฏธ์ง€ ์ƒ์„ฑ์ด ์•„๋‹Œ ๋ถ„์„์šฉ์ž…๋‹ˆ๋‹ค.")
91
+ else:
92
+ # For text-only, try a simpler approach
93
+ response = client.models.generate_content(
94
+ model=GEMINI_MODEL_NAME,
95
+ contents=prompt
96
+ )
97
 
98
  progress(0.8, desc="๐Ÿ–ผ๏ธ ๋งˆ๋ฌด๋ฆฌ ์ค‘...")
 
99
 
100
+ # Since Gemini doesn't generate images, we'll need to handle this differently
101
+ # For demonstration, create a placeholder or use a different service
102
+ if hasattr(response, 'text') and response.text:
103
+ # Return the text response for now
104
+ # In production, you'd call an actual image generation API here
105
+ description = response.text
 
 
 
 
 
106
 
107
+ # Create a placeholder image with the description
108
+ from PIL import Image, ImageDraw, ImageFont
109
+ img = Image.new('RGB', (512, 512), color='white')
110
+ draw = ImageDraw.Draw(img)
111
+
112
+ # Add text to explain the situation
113
+ text = "Gemini API๋Š” ์ด๋ฏธ์ง€ ์ƒ์„ฑ์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.\n\n"
114
+ text += "์ƒ์„ฑ๋œ ์„ค๋ช…:\n" + description[:200] + "..."
115
+
116
+ # Simple text wrapping
117
+ y_position = 50
118
+ for line in text.split('\n'):
119
+ draw.text((20, y_position), line, fill='black')
120
+ y_position += 30
121
+
122
+ # Save the placeholder image
123
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmpfile:
124
+ img.save(tmpfile.name)
125
+ progress(1.0, desc="โœ… ์™„๋ฃŒ!")
126
+ return tmpfile.name
127
+ else:
128
+ raise ValueError("API ์‘๋‹ต์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.")
129
 
130
  except Exception as e:
131
  print(f"Error details: {e}")
132
  print(f"Error type: {type(e)}")
133
+ raise gr.Error(f"์ฒ˜๋ฆฌ ์‹คํŒจ: {e}")
134
 
135
 
136
  def run_multi_image_logic(prompt: str, images: List[str], progress=gr.Progress()) -> str:
137
  """
138
+ Handles multi-image analysis.
139
  """
140
  if not images:
141
  raise gr.Error("'์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€' ํƒญ์—์„œ ์ตœ์†Œ ํ•œ ๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”.")
 
147
  if isinstance(image_path, (list, tuple)):
148
  image_path = image_path[0]
149
  contents.append(Image.open(image_path))
150
+ contents.append(f"Analyze these images based on: {prompt}")
151
 
152
+ progress(0.5, desc="โœจ ๋ถ„์„ ์ค‘...")
 
 
 
 
 
153
 
154
+ # Simple API call without generation_config
155
  response = client.models.generate_content(
156
  model=GEMINI_MODEL_NAME,
157
  contents=contents,
 
158
  )
159
 
 
 
 
160
  progress(0.8, desc="๐Ÿ–ผ๏ธ ๋งˆ๋ฌด๋ฆฌ ์ค‘...")
161
+
162
+ # Create a result image with the analysis
163
+ if hasattr(response, 'text') and response.text:
164
+ from PIL import Image, ImageDraw
165
+ img = Image.new('RGB', (512, 512), color='white')
166
+ draw = ImageDraw.Draw(img)
167
+
168
+ text = "๋‹ค์ค‘ ์ด๋ฏธ์ง€ ๋ถ„์„ ๊ฒฐ๊ณผ:\n\n"
169
+ text += response.text[:300] + "..."
170
 
171
+ y_position = 50
172
+ for line in text.split('\n'):
173
+ draw.text((20, y_position), line, fill='black')
174
+ y_position += 30
175
+
176
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmpfile:
177
+ img.save(tmpfile.name)
178
+ progress(1.0, desc="โœ… ์™„๋ฃŒ!")
179
+ return tmpfile.name
180
+ else:
181
+ raise ValueError("API ์‘๋‹ต์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.")
182
 
183
  except Exception as e:
184
  print(f"Multi-image error details: {e}")
185
+ raise gr.Error(f"์ฒ˜๋ฆฌ ์‹คํŒจ: {e}")
186
 
187
 
188
  # --- Gradio App UI ---
 
367
  ๐ŸŒ Real Nano Banana
368
  </h1>
369
  <p class="header-subtitle">
370
+ Google Gemini API๋กœ ๊ตฌ๋™๋˜๋Š” AI ์ด๋ฏธ์ง€ ๋ถ„์„๊ธฐ
371
+ </p>
372
+ </div>
373
+ ''')
374
+
375
+ # Important Notice
376
+ gr.HTML('''
377
+ <div style="background: #fef2f2; border-radius: 0.5rem; padding: 1rem; margin-bottom: 1.5rem;
378
+ border-left: 4px solid #ef4444;">
379
+ <p style="margin: 0; color: #991b1b; font-weight: 600;">
380
+ โš ๏ธ ์ฐธ๊ณ : Gemini API๋Š” ์ด๋ฏธ์ง€ ์ƒ์„ฑ์ด ์•„๋‹Œ ๋ถ„์„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
381
+ ์‹ค์ œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ์„ ์›ํ•˜์‹œ๋ฉด DALL-E, Midjourney, Stable Diffusion ๋“ฑ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
382
  </p>
383
  </div>
384
  ''')
 
419
  )
420
  gr.HTML('''
421
  <p style="text-align: center; color: #6b7280; font-size: 0.9rem; margin-top: 0.5rem;">
422
+ ๐Ÿ’ก ํ…์ŠคํŠธ ์„ค๋ช…๋งŒ ์›ํ•˜์‹œ๋ฉด ๋น„์›Œ๋‘์„ธ์š”
423
  </p>
424
  ''')
425
 
 
440
  prompt_input = gr.Textbox(
441
  label="",
442
  info="AI์—๊ฒŒ ์›ํ•˜๋Š” ๊ฒƒ์„ ์„ค๋ช…ํ•˜์„ธ์š”",
443
+ placeholder="์˜ˆ: ์ด ์ด๋ฏธ์ง€๋ฅผ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”, ๋ฌด์—‡์ด ๋ณด์ด๋‚˜์š”?, ์ด๋ฏธ์ง€๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?",
444
  lines=3,
445
  elem_classes="prompt-input"
446
  )
447
 
448
  # Generate Button
449
  generate_button = gr.Button(
450
+ "๐Ÿš€ ๋ถ„์„ํ•˜๊ธฐ",
451
  variant="primary",
452
  elem_classes="generate-btn"
453
  )
 
456
  with gr.Accordion("๐Ÿ’ก ์˜ˆ์ œ ํ”„๋กฌํ”„ํŠธ", open=False):
457
  gr.Examples(
458
  examples=[
459
+ ["์ด ์ด๋ฏธ์ง€์—์„œ ๋ฌด์—‡์ด ๋ณด์ด๋‚˜์š”?"],
460
+ ["์ด๋ฏธ์ง€์˜ ์ƒ‰์ƒ๊ณผ ๊ตฌ์„ฑ์„ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”"],
461
+ ["์ด ์žฅ๋ฉด์„ ๋” ๊ทน์ ์œผ๋กœ ๋งŒ๋“ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?"],
462
+ ["์ด๋ฏธ์ง€์˜ ๋ถ„์œ„๊ธฐ์™€ ๊ฐ์ •์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”"],
463
+ ["๊ธฐ์ˆ ์ ์ธ ๊ด€์ ์—์„œ ์ด ์ด๋ฏธ์ง€๋ฅผ ํ‰๊ฐ€ํ•ด์ฃผ์„ธ์š”"],
464
  ],
465
  inputs=prompt_input
466
  )
 
469
 
470
  with gr.Column(scale=1):
471
  gr.HTML('<div class="card">')
472
+ gr.HTML('<h3 style="margin-top: 0;">๐ŸŽจ ๋ถ„์„ ๊ฒฐ๊ณผ</h3>')
473
 
474
  output_image = gr.Image(
475
  label="",
 
478
  )
479
 
480
  use_image_button = gr.Button(
481
+ "โ™ป๏ธ ์ด ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์Œ ๋ถ„์„์— ์‚ฌ์šฉ",
482
  elem_classes="use-btn",
483
  visible=False
484
  )
 
489
  <h4 style="margin-top: 0; color: #0369a1;">๐Ÿ’ก ํŒ</h4>
490
  <ul style="margin: 0; padding-left: 1.5rem; color: #0c4a6e;">
491
  <li>๊ตฌ์ฒด์ ์ด๊ณ  ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”</li>
492
+ <li>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜์—ฌ AI ๋ถ„์„์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
493
+ <li>๋‹ค์ค‘ ์ด๋ฏธ์ง€ ๋ชจ๋“œ๋กœ ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€๋ฅผ ๋น„๊ต ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
494
  </ul>
495
  </div>
496
  ''')
 
502
  <div style="text-align: center; margin-top: 2rem; padding: 1rem;
503
  border-top: 1px solid #e5e7eb;">
504
  <p style="color: #6b7280;">
505
+ Made with ๐Ÿ’œ by Hugging Face PRO | Powered by Google Gemini API
506
  </p>
507
  </div>
508
  ''')
 
556
  <div class="pro-message">
557
  <h2>โœจ PRO ์‚ฌ์šฉ์ž ์ „์šฉ ๊ธฐ๋Šฅ</h2>
558
  <p style="font-size: 1.1rem; margin: 1rem 0;">
559
+ ์ด ๊ฐ•๋ ฅํ•œ AI ์ด๋ฏธ์ง€ ๋ถ„์„ ๋„๊ตฌ๋Š” Hugging Face <strong>PRO</strong> ๋ฉค๋ฒ„ ์ „์šฉ์ž…๋‹ˆ๋‹ค.
560
  </p>
561
  <p style="margin: 1rem 0;">
562
  PRO ๊ตฌ๋…์œผ๋กœ ๋‹ค์Œ์„ ๋ˆ„๋ฆฌ์„ธ์š”:
563
  </p>
564
  <ul style="text-align: left; display: inline-block; margin: 1rem 0;">
565
+ <li>๐Ÿš€ Google Gemini API ๋ฌด์ œํ•œ ์•ก์„ธ์Šค</li>
566
+ <li>โšก ๋น ๋ฅธ ์ด๋ฏธ์ง€ ๋ถ„์„</li>
567
+ <li>๐ŸŽจ ์ƒ์„ธํ•œ ์ด๋ฏธ์ง€ ์„ค๋ช…</li>
568
+ <li>๐Ÿ”ง ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ๋น„๊ต ๋ถ„์„</li>
569
  </ul>
570
  <a href="https://huggingface.co/pro" target="_blank"
571
  style="display: inline-block; margin-top: 1rem; padding: 1rem 2rem;