Kims12 commited on
Commit
331f45a
ยท
verified ยท
1 Parent(s): 0fee2a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -54
app.py CHANGED
@@ -26,7 +26,6 @@ def preprocess_prompt(prompt, image1, image2, image3):
26
  """
27
  ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ธฐ๋Šฅ ๋ช…๋ น์„ ํ•ด์„
28
  """
29
- # ๊ธฐ์กด preprocess_prompt ํ•จ์ˆ˜ ์ฝ”๋“œ ์œ ์ง€
30
  # ์ด๋ฏธ์ง€ ์—†๋Š” ์ฐธ์กฐ ํ™•์ธ ๋ฐ ์ฒ˜๋ฆฌ
31
  has_img1 = image1 is not None
32
  has_img2 = image2 is not None
@@ -48,9 +47,8 @@ def preprocess_prompt(prompt, image1, image2, image3):
48
  else:
49
  prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
50
 
51
- # ๊ธฐ๋Šฅ ๋ช…๋ น ํ•ด์„
52
  if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
53
- # ์„ค๋ช… ์ถ”์ถœ์„ ์‹œ๋„ํ•˜์ง€๋งŒ ์‹คํŒจํ•ด๋„ ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์ œ๊ณต
54
  desc_match = re.search(r'#1์„ "(.*?)"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ', prompt)
55
  if desc_match:
56
  description = desc_match.group(1)
@@ -59,7 +57,6 @@ def preprocess_prompt(prompt, image1, image2, image3):
59
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
60
 
61
  elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
62
- # ์ง€์šธ ํ…์ŠคํŠธ ์ถ”์ถœ์„ ์‹œ๋„ํ•˜์ง€๋งŒ ์‹คํŒจํ•ด๋„ ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์ œ๊ณต
63
  text_match = re.search(r'#1์—์„œ "(.*?)"๋ฅผ ์ง€์›Œ๋ผ', prompt)
64
  if text_match:
65
  text_to_remove = text_match.group(1)
@@ -71,7 +68,6 @@ def preprocess_prompt(prompt, image1, image2, image3):
71
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์–ผ๊ตด์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์–ผ๊ตด๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์–ผ๊ตด์˜ ํ‘œ์ •๊ณผ ํŠน์ง•์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
72
 
73
  elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
74
- # ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
75
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
76
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
77
  else:
@@ -81,7 +77,6 @@ def preprocess_prompt(prompt, image1, image2, image3):
81
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
82
 
83
  elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
84
- # ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
85
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
86
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ, ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ์ž˜ ๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
87
  else:
@@ -90,11 +85,9 @@ def preprocess_prompt(prompt, image1, image2, image3):
90
  elif "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)" in prompt:
91
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋‚ด์šฉ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด์™€ ๊ตฌ๋„๋Š” ์œ ์ง€ํ•˜๋˜, ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜ˆ์ˆ ์  ์Šคํƒ€์ผ, ์ƒ‰์ƒ, ์งˆ๊ฐ์„ ์ ์šฉํ•ด์ฃผ์„ธ์š”."
92
 
93
- # ๊ฐ„๋‹จํ•œ ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์š”์ฒญ ์ฒ˜๋ฆฌ
94
  elif "์„ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt or "๋ฅผ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt:
95
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋ถ‰์€์ƒ‰ ํ†ค์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ „์ฒด์ ์ธ ์ƒ‰์ƒ์„ ๋ถ‰์€ ๊ณ„์—ด๋กœ ์กฐ์ •ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋А๋‚Œ์„ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
96
 
97
- # ๋ช…ํ™•ํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์š”์ฒญ ์ถ”๊ฐ€
98
  prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
99
 
100
  return prompt
@@ -104,29 +97,22 @@ def generate_with_images(prompt, images):
104
  ๊ณต์‹ ๋ฌธ์„œ์— ๊ธฐ๋ฐ˜ํ•œ ์˜ฌ๋ฐ”๋ฅธ API ํ˜ธ์ถœ ๋ฐฉ์‹ ๊ตฌํ˜„
105
  """
106
  try:
107
- # API ํ‚ค ํ™•์ธ
108
  api_key = os.environ.get("GEMINI_API_KEY")
109
  if not api_key:
110
  return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
111
 
112
- # Gemini ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
113
  client = genai.Client(api_key=api_key)
114
 
115
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}")
116
 
117
- # ์ปจํ…์ธ  ์ค€๋น„
118
  contents = []
119
-
120
- # ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
121
  contents.append(prompt)
122
 
123
- # ์ด๋ฏธ์ง€ ์ถ”๊ฐ€
124
  for idx, img in enumerate(images, 1):
125
  if img is not None:
126
  contents.append(img)
127
  logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
128
 
129
- # ์ƒ์„ฑ ์„ค์ • - ๊ณต์‹ ๋ฌธ์„œ์— ๋”ฐ๋ผ responseModalities ์„ค์ •
130
  response = client.models.generate_content(
131
  model="gemini-2.0-flash-exp-image-generation",
132
  contents=contents,
@@ -139,14 +125,12 @@ def generate_with_images(prompt, images):
139
  )
140
  )
141
 
142
- # ์ž„์‹œ ํŒŒ์ผ ์ƒ์„ฑ
143
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
144
  temp_path = tmp.name
145
 
146
  result_text = ""
147
  image_found = False
148
 
149
- # ์‘๋‹ต ์ฒ˜๋ฆฌ
150
  for part in response.candidates[0].content.parts:
151
  if hasattr(part, 'text') and part.text:
152
  result_text += part.text
@@ -159,7 +143,6 @@ def generate_with_images(prompt, images):
159
  if not image_found:
160
  return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
161
 
162
- # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋ฐ˜ํ™˜
163
  result_img = Image.open(temp_path)
164
  if result_img.mode == "RGBA":
165
  result_img = result_img.convert("RGB")
@@ -175,16 +158,13 @@ def process_images_with_prompt(image1, image2, image3, prompt):
175
  3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜
176
  """
177
  try:
178
- # ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ํ™•์ธ
179
  images = [image1, image2, image3]
180
  valid_images = [img for img in images if img is not None]
181
 
182
  if not valid_images:
183
  return None, "์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
184
 
185
- # ํ”„๋กฌํ”„ํŠธ ์ฒ˜๋ฆฌ
186
  if not prompt or not prompt.strip():
187
- # ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์—†์œผ๋ฉด ์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ ์ˆ˜์— ๋”ฐ๋ผ ์ž๋™ ํ•ฉ์„ฑ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์˜์–ด๋กœ ์ƒ์„ฑ
188
  if len(valid_images) == 1:
189
  prompt = "Please creatively transform this image into a more vivid and artistic version."
190
  logger.info("Default prompt generated for single image")
@@ -195,17 +175,36 @@ def process_images_with_prompt(image1, image2, image3, prompt):
195
  prompt = "Please creatively composite these three images, combining their main elements into a cohesive and natural scene."
196
  logger.info("Default prompt generated for three images")
197
  else:
198
- # ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ ๋ฐ ๊ธฐ๋Šฅ ๋ช…๋ น ํ•ด์„
199
  prompt = preprocess_prompt(prompt, image1, image2, image3)
200
 
201
- # ์ƒˆ๋กœ์šด API ํ˜ธ์ถœ ๋ฐฉ์‹ ์‚ฌ์šฉ
202
  return generate_with_images(prompt, valid_images)
203
 
204
  except Exception as e:
205
  logger.exception("์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
206
  return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
207
 
208
- # (๊ธฐ๋Šฅ ์„ ํƒ ๊ด€๋ จ ์ฝ”๋“œ ์ „์ฒด ์‚ญ์ œ๋จ)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  # Gradio ์ธํ„ฐํŽ˜์ด์Šค
211
  with gr.Blocks() as demo:
@@ -233,44 +232,38 @@ with gr.Blocks() as demo:
233
  label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
234
  )
235
 
 
 
 
 
 
 
 
 
 
 
 
236
  # ์ƒ์„ฑ ๋ฒ„ํŠผ
237
  submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
238
 
239
  with gr.Column():
240
- # ๊ฒฐ๊ณผ ์ถœ๋ ฅ
241
  output_image = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€")
242
  output_text = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€")
243
-
244
- # ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
245
  prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
246
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
248
- def process_and_show_prompt(image1, image2, image3, prompt):
249
- # ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ํ™•์ธ
250
- images = [image1, image2, image3]
251
- valid_images = [img for img in images if img is not None]
252
-
253
- try:
254
- # ์ž๋™ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋˜๋Š” ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ
255
- auto_prompt = prompt
256
- if not prompt or not prompt.strip():
257
- if len(valid_images) == 1:
258
- auto_prompt = "Please creatively transform this image into a more vivid and artistic version."
259
- elif len(valid_images) == 2:
260
- auto_prompt = "Please seamlessly composite these two images, integrating their key elements harmoniously into a single image."
261
- else:
262
- auto_prompt = "Please creatively composite these three images, combining their main elements into a cohesive and natural scene."
263
- else:
264
- auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
265
-
266
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ
267
- result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
268
-
269
- return result_img, status, auto_prompt
270
- except Exception as e:
271
- logger.exception("์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
272
- return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}", prompt
273
-
274
  submit_btn.click(
275
  fn=process_and_show_prompt,
276
  inputs=[image1_input, image2_input, image3_input, prompt_input],
@@ -284,11 +277,11 @@ with gr.Blocks() as demo:
284
  1. **์ž๋™ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.
285
  2. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
286
  3. **์ผ๋ถ€ ์ด๋ฏธ์ง€๋งŒ**: ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
 
287
 
288
  > **ํŒ**: ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
289
  """
290
  )
291
 
292
- # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰
293
  if __name__ == "__main__":
294
  demo.launch(share=True)
 
26
  """
27
  ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ธฐ๋Šฅ ๋ช…๋ น์„ ํ•ด์„
28
  """
 
29
  # ์ด๋ฏธ์ง€ ์—†๋Š” ์ฐธ์กฐ ํ™•์ธ ๋ฐ ์ฒ˜๋ฆฌ
30
  has_img1 = image1 is not None
31
  has_img2 = image2 is not None
 
47
  else:
48
  prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
49
 
50
+ # ๊ธฐ๋Šฅ ๋ช…๋ น ํ•ด์„ (์›๋ณธ ๊ธฐ๋Šฅ ์œ ์ง€)
51
  if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
 
52
  desc_match = re.search(r'#1์„ "(.*?)"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ', prompt)
53
  if desc_match:
54
  description = desc_match.group(1)
 
57
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
58
 
59
  elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
 
60
  text_match = re.search(r'#1์—์„œ "(.*?)"๋ฅผ ์ง€์›Œ๋ผ', prompt)
61
  if text_match:
62
  text_to_remove = text_match.group(1)
 
68
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์–ผ๊ตด์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์–ผ๊ตด๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์–ผ๊ตด์˜ ํ‘œ์ •๊ณผ ํŠน์ง•์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
69
 
70
  elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
 
71
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
72
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
73
  else:
 
77
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
78
 
79
  elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
 
80
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
81
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ, ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ์ž˜ ๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
82
  else:
 
85
  elif "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)" in prompt:
86
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋‚ด์šฉ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด์™€ ๊ตฌ๋„๋Š” ์œ ์ง€ํ•˜๋˜, ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜ˆ์ˆ ์  ์Šคํƒ€์ผ, ์ƒ‰์ƒ, ์งˆ๊ฐ์„ ์ ์šฉํ•ด์ฃผ์„ธ์š”."
87
 
 
88
  elif "์„ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt or "๋ฅผ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt:
89
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋ถ‰์€์ƒ‰ ํ†ค์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ „์ฒด์ ์ธ ์ƒ‰์ƒ์„ ๋ถ‰์€ ๊ณ„์—ด๋กœ ์กฐ์ •ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ์šด ๋А๋‚Œ์„ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
90
 
 
91
  prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
92
 
93
  return prompt
 
97
  ๊ณต์‹ ๋ฌธ์„œ์— ๊ธฐ๋ฐ˜ํ•œ ์˜ฌ๋ฐ”๋ฅธ API ํ˜ธ์ถœ ๋ฐฉ์‹ ๊ตฌํ˜„
98
  """
99
  try:
 
100
  api_key = os.environ.get("GEMINI_API_KEY")
101
  if not api_key:
102
  return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
103
 
 
104
  client = genai.Client(api_key=api_key)
105
 
106
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}")
107
 
 
108
  contents = []
 
 
109
  contents.append(prompt)
110
 
 
111
  for idx, img in enumerate(images, 1):
112
  if img is not None:
113
  contents.append(img)
114
  logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
115
 
 
116
  response = client.models.generate_content(
117
  model="gemini-2.0-flash-exp-image-generation",
118
  contents=contents,
 
125
  )
126
  )
127
 
 
128
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
129
  temp_path = tmp.name
130
 
131
  result_text = ""
132
  image_found = False
133
 
 
134
  for part in response.candidates[0].content.parts:
135
  if hasattr(part, 'text') and part.text:
136
  result_text += part.text
 
143
  if not image_found:
144
  return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
145
 
 
146
  result_img = Image.open(temp_path)
147
  if result_img.mode == "RGBA":
148
  result_img = result_img.convert("RGB")
 
158
  3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜
159
  """
160
  try:
 
161
  images = [image1, image2, image3]
162
  valid_images = [img for img in images if img is not None]
163
 
164
  if not valid_images:
165
  return None, "์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”."
166
 
 
167
  if not prompt or not prompt.strip():
 
168
  if len(valid_images) == 1:
169
  prompt = "Please creatively transform this image into a more vivid and artistic version."
170
  logger.info("Default prompt generated for single image")
 
175
  prompt = "Please creatively composite these three images, combining their main elements into a cohesive and natural scene."
176
  logger.info("Default prompt generated for three images")
177
  else:
 
178
  prompt = preprocess_prompt(prompt, image1, image2, image3)
179
 
 
180
  return generate_with_images(prompt, valid_images)
181
 
182
  except Exception as e:
183
  logger.exception("์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
184
  return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
185
 
186
+ def process_and_show_prompt(image1, image2, image3, prompt):
187
+ images = [image1, image2, image3]
188
+ valid_images = [img for img in images if img is not None]
189
+
190
+ try:
191
+ auto_prompt = prompt
192
+ if not prompt or not prompt.strip():
193
+ if len(valid_images) == 1:
194
+ auto_prompt = "Please creatively transform this image into a more vivid and artistic version."
195
+ elif len(valid_images) == 2:
196
+ auto_prompt = "Please seamlessly composite these two images, integrating their key elements harmoniously into a single image."
197
+ else:
198
+ auto_prompt = "Please creatively composite these three images, combining their main elements into a cohesive and natural scene."
199
+ else:
200
+ auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
201
+
202
+ result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
203
+
204
+ return result_img, status, auto_prompt
205
+ except Exception as e:
206
+ logger.exception("์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
207
+ return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}", prompt
208
 
209
  # Gradio ์ธํ„ฐํŽ˜์ด์Šค
210
  with gr.Blocks() as demo:
 
232
  label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
233
  )
234
 
235
+ # ์„ ํƒ ์˜ต์…˜ (๋งˆํฌ๋‹ค์šด์œผ๋กœ ์•ˆ๋‚ด)
236
+ with gr.Row():
237
+ gr.Markdown(
238
+ "**์„ ํƒ ์˜ต์…˜:**\n\n"
239
+ "- **์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ**: `Change image #1 to [another look]`\n"
240
+ "- **๊ธ€์ž์ง€์šฐ๊ธฐ**: `#1 Remove [all Chinese] from the image.`"
241
+ )
242
+ with gr.Row():
243
+ image_change_btn = gr.Button("์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ")
244
+ text_remove_btn = gr.Button("๊ธ€์ž์ง€์šฐ๊ธฐ")
245
+
246
  # ์ƒ์„ฑ ๋ฒ„ํŠผ
247
  submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
248
 
249
  with gr.Column():
 
250
  output_image = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€")
251
  output_text = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€")
 
 
252
  prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
253
 
254
+ # ์„ ํƒ ์˜ต์…˜ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ๋ž€ ์—…๋ฐ์ดํŠธ
255
+ image_change_btn.click(
256
+ fn=lambda: "Change image #1 to [another look]",
257
+ inputs=[],
258
+ outputs=prompt_input
259
+ )
260
+ text_remove_btn.click(
261
+ fn=lambda: "#1 Remove [all Chinese] from the image.",
262
+ inputs=[],
263
+ outputs=prompt_input
264
+ )
265
+
266
  # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  submit_btn.click(
268
  fn=process_and_show_prompt,
269
  inputs=[image1_input, image2_input, image3_input, prompt_input],
 
277
  1. **์ž๋™ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.
278
  2. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
279
  3. **์ผ๋ถ€ ์ด๋ฏธ์ง€๋งŒ**: ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
280
+ 4. **์„ ํƒ ์˜ต์…˜**: ์œ„์˜ ์„ ํƒ ์˜ต์…˜์—์„œ ์›ํ•˜๋Š” ํ•ญ๋ชฉ์„ ํด๋ฆญํ•˜๋ฉด ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ๋ž€์— ๋ฐ”๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
281
 
282
  > **ํŒ**: ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
283
  """
284
  )
285
 
 
286
  if __name__ == "__main__":
287
  demo.launch(share=True)