Kims12 commited on
Commit
5dfaa58
ยท
verified ยท
1 Parent(s): 14ca9a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -58
app.py CHANGED
@@ -4,6 +4,7 @@ from PIL import Image
4
  import gradio as gr
5
  import logging
6
  import re
 
7
 
8
  from google import genai
9
  from google.genai import types
@@ -87,6 +88,10 @@ def preprocess_prompt(prompt, image1, image2, image3):
87
  elif "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)" in prompt:
88
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋‚ด์šฉ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด์™€ ๊ตฌ๋„๋Š” ์œ ์ง€ํ•˜๋˜, ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜ˆ์ˆ ์  ์Šคํƒ€์ผ, ์ƒ‰์ƒ, ์งˆ๊ฐ์„ ์ ์šฉํ•ด์ฃผ์„ธ์š”."
89
 
 
 
 
 
90
  # ์ž…๋ ฅ์ด ์œ„ ๊ธฐ๋Šฅ๋“ค์— ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์›๋ณธ ํ”„๋กฌํ”„ํŠธ ์œ ์ง€
91
 
92
  return prompt
@@ -131,27 +136,32 @@ def process_images_with_prompt(image1, image2, image3, prompt):
131
  parts = []
132
 
133
  # ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
134
- parts.append(types.Part.from_text(text=prompt))
 
 
135
 
136
  # ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€
137
  for idx, img in enumerate(images, 1):
138
  if img is not None:
139
  # PIL ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”์ดํŠธ๋กœ ๋ณ€ํ™˜
140
- with tempfile.NamedTemporaryFile(suffix=".png") as tmp:
141
- img_path = tmp.name
142
- img.save(img_path, format="PNG")
143
- with open(img_path, "rb") as f:
144
- image_bytes = f.read()
145
 
146
- # ์ด๋ฏธ์ง€๋ฅผ ํŒŒํŠธ๋กœ ์ถ”๊ฐ€
147
- parts.append(types.Part.from_data(data=image_bytes, mime_type="image/png"))
 
 
 
 
 
148
  logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
149
 
150
  # ์ƒ์„ฑ ์„ค์ •
151
- generate_content_config = types.GenerateContentConfig(
152
- temperature=1,
153
- response_modalities=["image"],
154
- )
155
 
156
  # ์ž„์‹œ ํŒŒ์ผ ์ƒ์„ฑ
157
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
@@ -159,14 +169,21 @@ def process_images_with_prompt(image1, image2, image3, prompt):
159
 
160
  # Gemini ๋ชจ๋ธ๋กœ ์š”์ฒญ ์ „์†ก
161
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}")
 
 
162
  response = client.models.generate_content(
163
  model="gemini-2.0-flash-exp-image-generation",
164
- contents=[types.Content(role="user", parts=parts)],
165
- config=generate_content_config,
 
 
 
166
  )
167
 
168
  # ์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ
169
  image_found = False
 
 
170
  for part in response.candidates[0].content.parts:
171
  if hasattr(part, 'inline_data') and part.inline_data:
172
  save_binary_file(temp_path, part.inline_data.data)
@@ -187,13 +204,27 @@ def process_images_with_prompt(image1, image2, image3, prompt):
187
  logger.exception("์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
188
  return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  # Gradio ์ธํ„ฐํŽ˜์ด์Šค
191
  with gr.Blocks() as demo:
192
  gr.HTML(
193
  """
194
  <div style="text-align: center; margin-bottom: 1rem;">
195
  <h1>๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</h1>
196
- <p>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ๋ฐ”๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ๊ธฐ๋Šฅ ๋ช…๋ น์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</p>
197
  </div>
198
  """
199
  )
@@ -206,6 +237,28 @@ with gr.Blocks() as demo:
206
  image2_input = gr.Image(type="pil", label="#2", image_mode="RGB")
207
  image3_input = gr.Image(type="pil", label="#3", image_mode="RGB")
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์„ ํƒ ์‚ฌํ•ญ)
210
  prompt_input = gr.Textbox(
211
  lines=3,
@@ -213,24 +266,6 @@ with gr.Blocks() as demo:
213
  label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
214
  )
215
 
216
- # ๊ธฐ๋Šฅ ๋ช…๋ น ์„ค๋ช…
217
- gr.HTML(
218
- """
219
- <div style="margin: 0.5rem 0; padding: 0.5rem; background-color: #f0f0f0; border-radius: 0.5rem;">
220
- <h4>๊ธฐ๋Šฅ ๋ช…๋ น ๋ชฉ๋ก:</h4>
221
- <ol style="margin-left: 1.5rem;">
222
- <li>์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ: <code>#1์„ "์„ค๋ช…ํ•ด์ฃผ์„ธ์š”"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ</code></li>
223
- <li>๊ธ€์ž์ง€์šฐ๊ธฐ: <code>#1์—์„œ "์ค‘๊ตญ์–ด"๋ฅผ ์ง€์›Œ๋ผ</code></li>
224
- <li>์–ผ๊ตด๋ฐ”๊พธ๊ธฐ: <code>#1์˜ ์ธ๋ฌผ์„ #2์˜ ์–ผ๊ตด๋กœ ๋ฐ”๊ฟ”๋ผ</code></li>
225
- <li>์˜ท๋ฐ”๊พธ๊ธฐ: <code>#1์˜ ์ธ๋ฌผ์— #2 ๋˜๋Š” #3์˜ ์˜ท์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ผ</code></li>
226
- <li>๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ: <code>#1์˜ ์ด๋ฏธ์ง€์— #2์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ”๋ผ</code></li>
227
- <li>์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ): <code>#1์™€ #2 ๋˜๋Š” #3์˜ ๋ฅผ ํ•ฉ์„ฑํ•˜๋ผ</code></li>
228
- <li>์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ): <code>#1์™€ #2๋ฅผ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•˜๋ผ</code></li>
229
- </ol>
230
- </div>
231
- """
232
- )
233
-
234
  # ์ƒ์„ฑ ๋ฒ„ํŠผ
235
  submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
236
 
@@ -242,28 +277,39 @@ with gr.Blocks() as demo:
242
  # ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
243
  prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
244
 
 
 
 
 
 
 
 
245
  # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
246
  def process_and_show_prompt(image1, image2, image3, prompt):
247
  # ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ํ™•์ธ
248
  images = [image1, image2, image3]
249
  valid_images = [img for img in images if img is not None]
250
 
251
- # ์ž๋™ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋˜๋Š” ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ
252
- auto_prompt = prompt
253
- if not prompt or not prompt.strip():
254
- if len(valid_images) == 1:
255
- auto_prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
256
- elif len(valid_images) == 2:
257
- auto_prompt = "์ด ๋‘ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋‘ ์ด๋ฏธ์ง€์˜ ์š”์†Œ๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
 
 
 
258
  else:
259
- auto_prompt = "์ด ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋˜ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ผ๊ด€๋œ ํ•˜๋‚˜์˜ ์žฅ๋ฉด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
260
- else:
261
- auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
262
-
263
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ
264
- result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
265
-
266
- return result_img, status, auto_prompt
 
267
 
268
  submit_btn.click(
269
  fn=process_and_show_prompt,
@@ -271,17 +317,17 @@ with gr.Blocks() as demo:
271
  outputs=[output_image, output_text, prompt_display],
272
  )
273
 
274
- gr.HTML(
275
  """
276
- <div style="margin-top: 1rem; padding: 1rem; background-color: #f8f9fa; border-radius: 0.5rem;">
277
- <h3>์‚ฌ์šฉ ๋ฐฉ๋ฒ•:</h3>
278
- <ul>
279
- <li><strong>์ž๋™ ํ•ฉ์„ฑ:</strong> ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค</li>
280
- <li><strong>๊ธฐ๋Šฅ ๋ช…๋ น:</strong> ์œ„ ๋ชฉ๋ก์˜ ๊ธฐ๋Šฅ ๋ช…๋ น์„ ๋ณต์‚ฌํ•˜์—ฌ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ์ฐฝ์— ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ›„ ํ•„์š”์— ๋งž๊ฒŒ ์ˆ˜์ •ํ•˜์„ธ์š”</li>
281
- <li><strong>์ด๋ฏธ์ง€ ์ฐธ์กฐ:</strong> #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
282
- <li><strong>์ผ๋ถ€ ์ด๋ฏธ์ง€๋งŒ:</strong> ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค</li>
283
- </ul>
284
- </div>
285
  """
286
  )
287
 
 
4
  import gradio as gr
5
  import logging
6
  import re
7
+ import io
8
 
9
  from google import genai
10
  from google.genai import types
 
88
  elif "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)" in prompt:
89
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋‚ด์šฉ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด์™€ ๊ตฌ๋„๋Š” ์œ ์ง€ํ•˜๋˜, ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜ˆ์ˆ ์  ์Šคํƒ€์ผ, ์ƒ‰์ƒ, ์งˆ๊ฐ์„ ์ ์šฉํ•ด์ฃผ์„ธ์š”."
90
 
91
+ # ๊ฐ„๋‹จํ•œ ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์š”์ฒญ ์ฒ˜๋ฆฌ
92
+ elif "์„ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt or "๋ฅผ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt:
93
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋ถ‰์€์ƒ‰ ํ†ค์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ „์ฒด์ ์ธ ์ƒ‰์ƒ์„ ๋ถ‰์€ ๊ณ„์—ด๋กœ ์กฐ์ •ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋А๋‚Œ์„ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
94
+
95
  # ์ž…๋ ฅ์ด ์œ„ ๊ธฐ๋Šฅ๋“ค์— ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์›๋ณธ ํ”„๋กฌํ”„ํŠธ ์œ ์ง€
96
 
97
  return prompt
 
136
  parts = []
137
 
138
  # ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
139
+ parts.append({
140
+ "text": prompt
141
+ })
142
 
143
  # ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€
144
  for idx, img in enumerate(images, 1):
145
  if img is not None:
146
  # PIL ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”์ดํŠธ๋กœ ๋ณ€ํ™˜
147
+ img_byte_arr = io.BytesIO()
148
+ img.save(img_byte_arr, format='PNG')
149
+ img_bytes = img_byte_arr.getvalue()
 
 
150
 
151
+ # ์ด๋ฏธ์ง€๋ฅผ ํŒŒํŠธ๋กœ ์ถ”๊ฐ€ (genai.types.Part ๋Œ€์‹  ์ง์ ‘ ๋”•์…”๋„ˆ๋ฆฌ ์‚ฌ์šฉ)
152
+ parts.append({
153
+ "inline_data": {
154
+ "mime_type": "image/png",
155
+ "data": img_bytes
156
+ }
157
+ })
158
  logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
159
 
160
  # ์ƒ์„ฑ ์„ค์ •
161
+ generate_content_config = {
162
+ "temperature": 1.0,
163
+ "response_modalities": ["image"]
164
+ }
165
 
166
  # ์ž„์‹œ ํŒŒ์ผ ์ƒ์„ฑ
167
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
 
169
 
170
  # Gemini ๋ชจ๋ธ๋กœ ์š”์ฒญ ์ „์†ก
171
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}")
172
+
173
+ # API ์š”์ฒญ ํ˜•์‹ ์ˆ˜์ •
174
  response = client.models.generate_content(
175
  model="gemini-2.0-flash-exp-image-generation",
176
+ contents=[{
177
+ "role": "user",
178
+ "parts": parts
179
+ }],
180
+ generation_config=generate_content_config
181
  )
182
 
183
  # ์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ
184
  image_found = False
185
+
186
+ # ์‘๋‹ต ๊ตฌ์กฐ ์ฒ˜๋ฆฌ
187
  for part in response.candidates[0].content.parts:
188
  if hasattr(part, 'inline_data') and part.inline_data:
189
  save_binary_file(temp_path, part.inline_data.data)
 
204
  logger.exception("์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
205
  return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
206
 
207
+ # ๊ธฐ๋Šฅ ์„ ํƒ ์ฝœ๋ฐฑ
208
+ def update_prompt_from_function(function_choice, custom_text=""):
209
+ function_templates = {
210
+ "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ": f'#1์„ "{custom_text if custom_text else "์›ํ•˜๋Š” ์„ค๋ช…"}"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ',
211
+ "2. ๊ธ€์ž์ง€์šฐ๊ธฐ": f'#1์—์„œ "{custom_text if custom_text else "์ง€์šธ ํ…์ŠคํŠธ"}"๋ฅผ ์ง€์›Œ๋ผ',
212
+ "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์„ #2์˜ ์–ผ๊ตด๋กœ ๋ฐ”๊ฟ”๋ผ",
213
+ "4. ์˜ท๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์— #2 ๋˜๋Š” #3์˜ ์˜ท์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ผ",
214
+ "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ด๋ฏธ์ง€์— #2์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ”๋ผ",
215
+ "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)": "#1์™€ #2 ๋˜๋Š” #3์˜ ๋ฅผ ํ•ฉ์„ฑํ•˜๋ผ",
216
+ "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)": "#1์™€ #2๋ฅผ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•˜๋ผ"
217
+ }
218
+
219
+ return function_templates.get(function_choice, "")
220
+
221
  # Gradio ์ธํ„ฐํŽ˜์ด์Šค
222
  with gr.Blocks() as demo:
223
  gr.HTML(
224
  """
225
  <div style="text-align: center; margin-bottom: 1rem;">
226
  <h1>๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</h1>
227
+ <p>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ๋ฐ”๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์•„๋ž˜ ๊ธฐ๋Šฅ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</p>
228
  </div>
229
  """
230
  )
 
237
  image2_input = gr.Image(type="pil", label="#2", image_mode="RGB")
238
  image3_input = gr.Image(type="pil", label="#3", image_mode="RGB")
239
 
240
+ # ๊ธฐ๋Šฅ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด๊ณผ ์ปค์Šคํ…€ ํ…์ŠคํŠธ ์ž…๋ ฅ
241
+ with gr.Row():
242
+ function_dropdown = gr.Dropdown(
243
+ choices=[
244
+ "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ",
245
+ "2. ๊ธ€์ž์ง€์šฐ๊ธฐ",
246
+ "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ",
247
+ "4. ์˜ท๋ฐ”๊พธ๊ธฐ",
248
+ "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ",
249
+ "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)",
250
+ "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)"
251
+ ],
252
+ label="๊ธฐ๋Šฅ ์„ ํƒ",
253
+ value=None
254
+ )
255
+ custom_text_input = gr.Textbox(
256
+ label="์ปค์Šคํ…€ ํ…์ŠคํŠธ (1, 2๋ฒˆ ๊ธฐ๋Šฅ์šฉ)",
257
+ placeholder="์˜ˆ: ๋ถ‰์€์ƒ‰, ์ˆ˜์ฑ„ํ™” ์Šคํƒ€์ผ, ์ค‘๊ตญ์–ด..."
258
+ )
259
+
260
+ apply_function_btn = gr.Button("๊ธฐ๋Šฅ ์ ์šฉ")
261
+
262
  # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์„ ํƒ ์‚ฌํ•ญ)
263
  prompt_input = gr.Textbox(
264
  lines=3,
 
266
  label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
267
  )
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  # ์ƒ์„ฑ ๋ฒ„ํŠผ
270
  submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
271
 
 
277
  # ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
278
  prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
279
 
280
+ # ๊ธฐ๋Šฅ ์ ์šฉ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ
281
+ apply_function_btn.click(
282
+ fn=update_prompt_from_function,
283
+ inputs=[function_dropdown, custom_text_input],
284
+ outputs=[prompt_input]
285
+ )
286
+
287
  # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
288
  def process_and_show_prompt(image1, image2, image3, prompt):
289
  # ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ํ™•์ธ
290
  images = [image1, image2, image3]
291
  valid_images = [img for img in images if img is not None]
292
 
293
+ try:
294
+ # ์ž๋™ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋˜๋Š” ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ
295
+ auto_prompt = prompt
296
+ if not prompt or not prompt.strip():
297
+ if len(valid_images) == 1:
298
+ auto_prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
299
+ elif len(valid_images) == 2:
300
+ auto_prompt = "์ด ๋‘ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋‘ ์ด๋ฏธ์ง€์˜ ์š”์†Œ๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
301
+ else:
302
+ auto_prompt = "์ด ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ๏ฟฝ๏ฟฝ์†Œ๋ฅผ ํฌํ•จํ•˜๋˜ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ผ๊ด€๋œ ํ•˜๋‚˜์˜ ์žฅ๋ฉด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
303
  else:
304
+ auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
305
+
306
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ
307
+ result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
308
+
309
+ return result_img, status, auto_prompt
310
+ except Exception as e:
311
+ logger.exception("์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
312
+ return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}", prompt
313
 
314
  submit_btn.click(
315
  fn=process_and_show_prompt,
 
317
  outputs=[output_image, output_text, prompt_display],
318
  )
319
 
320
+ gr.Markdown(
321
  """
322
+ ### ์‚ฌ์šฉ ๋ฐฉ๋ฒ•:
323
+
324
+ 1. **์ž๋™ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค
325
+ 2. **๊ธฐ๋Šฅ ์‚ฌ์šฉ**: ๋“œ๋กญ๋‹ค์šด์—์„œ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์„ ํƒํ•˜๊ณ  '๊ธฐ๋Šฅ ์ ์šฉ' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”
326
+ 3. **์ปค์Šคํ…€ ํ…์ŠคํŠธ**: ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ์ด๋‚˜ ๊ธ€์ž์ง€์šฐ๊ธฐ ๊ธฐ๋Šฅ์„ ์„ ํƒํ•  ๋•Œ ์ถ”๊ฐ€ ์„ค๋ช…์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
327
+ 4. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
328
+ 5. **์ผ๋ถ€ ์ด๋ฏธ์ง€๋งŒ**: ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค
329
+
330
+ > **ํŒ**: ๊ธฐ๋Šฅ์„ ์„ ํƒํ•œ ํ›„์—๋„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
331
  """
332
  )
333