Kims12 commited on
Commit
4718cfc
ยท
verified ยท
1 Parent(s): 1d396b2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +174 -65
app.py CHANGED
@@ -24,15 +24,79 @@ def save_binary_file(file_name, data):
24
 
25
  def preprocess_prompt(prompt, image1, image2, image3):
26
  """
27
- ์ž…๋ ฅ๋œ ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์˜์–ด๋กœ๋งŒ ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ ,
28
- ๋‹จ์ˆœํžˆ "Please generate the image."๋ฅผ ๋ง๋ถ™์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
29
  """
30
- # ํ”„๋กฌํ”„ํŠธ์— ํ•œ๊ธ€์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ
31
- if re.search(r'[ใ„ฑ-ใ…Ž๊ฐ€-ํžฃ]', prompt):
32
- raise ValueError("Error: Prompt must be in English only.")
33
-
34
- # ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ ๊ด€๋ จ ์ฒ˜๋ฆฌ๋Š” ์ œ๊ฑฐํ•˜๊ณ  ๋‹จ์ˆœ ๋ช…๋ น์–ด ์ถ”๊ฐ€
35
- prompt = prompt.strip() + " Please generate the image."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  return prompt
37
 
38
  def generate_with_images(prompt, images):
@@ -43,7 +107,7 @@ def generate_with_images(prompt, images):
43
  # API ํ‚ค ํ™•์ธ
44
  api_key = os.environ.get("GEMINI_API_KEY")
45
  if not api_key:
46
- return None, "API key is not set. Please check your environment variables."
47
 
48
  # Gemini ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
49
  client = genai.Client(api_key=api_key)
@@ -56,11 +120,11 @@ def generate_with_images(prompt, images):
56
  # ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
57
  contents.append(prompt)
58
 
59
- # ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ (์ด๋ฏธ์ง€๊ฐ€ ์—†์œผ๋ฉด ํ…์ŠคํŠธ๋งŒ ์ „์†ก)
60
  for idx, img in enumerate(images, 1):
61
  if img is not None:
62
  contents.append(img)
63
- logger.info(f"Image #{idx} added.")
64
 
65
  # ์ƒ์„ฑ ์„ค์ • - ๊ณต์‹ ๋ฌธ์„œ์— ๋”ฐ๋ผ responseModalities ์„ค์ •
66
  response = client.models.generate_content(
@@ -86,94 +150,140 @@ def generate_with_images(prompt, images):
86
  for part in response.candidates[0].content.parts:
87
  if hasattr(part, 'text') and part.text:
88
  result_text += part.text
89
- logger.info(f"Response text: {part.text}")
90
  elif hasattr(part, 'inline_data') and part.inline_data:
91
  save_binary_file(temp_path, part.inline_data.data)
92
  image_found = True
93
- logger.info("Image extracted successfully from response.")
94
 
95
  if not image_found:
96
- return None, f"API did not generate an image. Response text: {result_text}"
97
 
98
  # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋ฐ˜ํ™˜
99
  result_img = Image.open(temp_path)
100
  if result_img.mode == "RGBA":
101
  result_img = result_img.convert("RGB")
102
 
103
- return result_img, f"Image generated successfully. {result_text}"
104
 
105
  except Exception as e:
106
- logger.exception("Error during image generation:")
107
- return None, f"Error occurred: {str(e)}"
108
 
109
  def process_images_with_prompt(image1, image2, image3, prompt):
110
  """
111
- 3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜.
112
- ์ด๋ฏธ์ง€ ์ž…๋ ฅ์ด ์—†์–ด๋„ ํ”„๋กฌํ”„ํŠธ๋งŒ์œผ๋กœ API ํ˜ธ์ถœ์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
113
  """
114
  try:
115
- # ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ํ™•์ธ (์ด๋ฏธ์ง€ ์—†์ด๋„ ์ง„ํ–‰)
116
  images = [image1, image2, image3]
117
  valid_images = [img for img in images if img is not None]
118
 
119
- # ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์—†์œผ๋ฉด ์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ ์ˆ˜์— ๋”ฐ๋ผ ์ž๋™ ํ•ฉ์„ฑ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ (์˜์–ด)
 
 
 
120
  if not prompt or not prompt.strip():
121
- if len(valid_images) == 0:
122
- prompt = "Please generate an image based on the description."
123
- logger.info("Auto prompt generated for no image input.")
124
- elif len(valid_images) == 1:
125
- prompt = "Please creatively transform this image into a more vivid and artistic version."
126
- logger.info("Auto prompt generated for a single image.")
127
  elif len(valid_images) == 2:
128
- prompt = "Please seamlessly blend these two images, integrating their elements harmoniously into a single image."
129
- logger.info("Auto prompt generated for two images.")
130
  else:
131
- prompt = "Please creatively composite these three images, incorporating their key elements into a natural and coherent scene."
132
- logger.info("Auto prompt generated for three images.")
133
  else:
 
134
  prompt = preprocess_prompt(prompt, image1, image2, image3)
135
 
136
  # ์ƒˆ๋กœ์šด API ํ˜ธ์ถœ ๋ฐฉ์‹ ์‚ฌ์šฉ
137
  return generate_with_images(prompt, valid_images)
138
 
139
  except Exception as e:
140
- logger.exception("Error during image processing:")
141
- return None, f"Error occurred: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค (๊ธฐ๋Šฅ ์„ ํƒ, ๊ธฐ๋Šฅ ์ ์šฉ, ์ปค์Šคํ…€ ํ…์ŠคํŠธ ๊ด€๋ จ ์š”์†Œ ์ œ๊ฑฐ)
144
  with gr.Blocks() as demo:
145
  gr.HTML(
146
  """
147
  <div style="text-align: center; margin-bottom: 1rem;">
148
- <h1>Simple Image Generator</h1>
149
- <p>Upload an image (or leave empty) and click generate to create an image based on the English prompt.</p>
150
  </div>
151
  """
152
  )
153
 
154
  with gr.Row():
155
  with gr.Column():
156
- # 3๊ฐœ์˜ ์ด๋ฏธ์ง€ ์ž…๋ ฅ (์ด๋ฏธ์ง€ ์—†์ด๋„ ์‹คํ–‰ ๊ฐ€๋Šฅ)
157
  with gr.Row():
158
- image1_input = gr.Image(type="pil", label="Image 1", image_mode="RGB")
159
- image2_input = gr.Image(type="pil", label="Image 2", image_mode="RGB")
160
- image3_input = gr.Image(type="pil", label="Image 3", image_mode="RGB")
161
 
162
- # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์˜์–ด๋กœ๋งŒ ์ž…๋ ฅ)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  prompt_input = gr.Textbox(
164
  lines=3,
165
- placeholder="Enter the prompt in English.",
166
- label="Prompt (Required: English only)"
167
  )
168
 
169
  # ์ƒ์„ฑ ๋ฒ„ํŠผ
170
- submit_btn = gr.Button("Generate Image", variant="primary")
171
 
172
  with gr.Column():
173
  # ๊ฒฐ๊ณผ ์ถœ๋ ฅ
174
- output_image = gr.Image(label="Generated Image")
175
- output_text = gr.Textbox(label="Status Message")
176
- prompt_display = gr.Textbox(label="Used Prompt", visible=True)
 
 
 
 
 
 
 
 
 
177
 
178
  # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
179
  def process_and_show_prompt(image1, image2, image3, prompt):
@@ -182,30 +292,25 @@ with gr.Blocks() as demo:
182
  valid_images = [img for img in images if img is not None]
183
 
184
  try:
185
- # ๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ–ˆ๋‹ค๋ฉด ์˜์–ด๋งŒ ํฌํ•จ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
186
- if prompt and re.search(r'[ใ„ฑ-ใ…Ž๊ฐ€-ํžฃ]', prompt):
187
- return None, "Error: Prompt must be in English only.", prompt
188
-
189
- # ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์—†์œผ๋ฉด ์ž๋™ ์ƒ์„ฑ (์˜์–ด)
190
  auto_prompt = prompt
191
  if not prompt or not prompt.strip():
192
- if len(valid_images) == 0:
193
- auto_prompt = "Please generate an image based on the description."
194
- elif len(valid_images) == 1:
195
- auto_prompt = "Please creatively transform this image into a more vivid and artistic version."
196
  elif len(valid_images) == 2:
197
- auto_prompt = "Please seamlessly blend these two images, integrating their elements harmoniously into a single image."
198
  else:
199
- auto_prompt = "Please creatively composite these three images, incorporating their key elements into a natural and coherent scene."
200
  else:
201
  auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
202
 
 
203
  result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
204
 
205
  return result_img, status, auto_prompt
206
  except Exception as e:
207
- logger.exception("Error during processing:")
208
- return None, f"Error occurred: {str(e)}", prompt
209
 
210
  submit_btn.click(
211
  fn=process_and_show_prompt,
@@ -215,14 +320,18 @@ with gr.Blocks() as demo:
215
 
216
  gr.Markdown(
217
  """
218
- ### Instructions:
 
 
 
 
 
 
219
 
220
- 1. **Auto Generation**: You can leave the image upload empty and the system will generate an image based solely on the prompt.
221
- 2. **Prompt Requirement**: Enter the prompt in English only.
222
- 3. **Image Reference**: The app supports up to three image inputs.
223
  """
224
  )
225
 
226
  # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰
227
  if __name__ == "__main__":
228
- demo.launch(share=True)
 
24
 
25
  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
33
+ has_img3 = image3 is not None
34
+
35
+ # #1, #2, #3 ์ฐธ์กฐ๋ฅผ ์„ค๋ช…์œผ๋กœ ๋ณ€ํ™˜ (์ด๋ฏธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋ฌด์‹œ)
36
+ if "#1" in prompt and not has_img1:
37
+ prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
38
+ else:
39
+ prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
40
+
41
+ if "#2" in prompt and not has_img2:
42
+ prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
43
+ else:
44
+ prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
45
+
46
+ if "#3" in prompt and not has_img3:
47
+ prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
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)
57
+ prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ {description}์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์›๋ณธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ๋‚ด์šฉ์€ ์œ ์ง€ํ•˜๋˜ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๊ณผ ๋ถ„์œ„๊ธฐ๋กœ ์žฌํ•ด์„ํ•ด์ฃผ์„ธ์š”."
58
+ else:
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)
66
+ prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ '{text_to_remove}' ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋˜ ๋ถ€๋ถ„์„ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ์ฑ„์›Œ์ฃผ์„ธ์š”."
67
+ else:
68
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ๊น”๋”ํ•œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
69
+
70
+ elif "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ" in prompt:
71
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์–ผ๊ตด์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์–ผ๊ตด๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์–ผ๊ตด์˜ ํ‘œ์ •๊ณผ ํŠน์ง•์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
72
+
73
+ elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
74
+ # ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
75
+ if "#3" in prompt or "๋˜๋Š” #3" in prompt:
76
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
77
+ else:
78
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
79
+
80
+ elif "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ" in prompt:
81
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
82
+
83
+ elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
84
+ # ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
85
+ if "#3" in prompt or "๋˜๋Š” #3" in prompt:
86
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ, ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ์ž˜ ๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
87
+ else:
88
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋‘ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ์ž˜ ๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
89
+
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
101
 
102
  def generate_with_images(prompt, images):
 
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)
 
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(
 
150
  for part in response.candidates[0].content.parts:
151
  if hasattr(part, 'text') and part.text:
152
  result_text += part.text
153
+ logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
154
  elif hasattr(part, 'inline_data') and part.inline_data:
155
  save_binary_file(temp_path, part.inline_data.data)
156
  image_found = True
157
+ logger.info("์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
158
 
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")
166
 
167
+ return result_img, f"์ด๋ฏธ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. {result_text}"
168
 
169
  except Exception as e:
170
+ logger.exception("์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
171
+ return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
172
 
173
  def process_images_with_prompt(image1, image2, image3, prompt):
174
  """
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 = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
190
+ logger.info("๋‹จ์ผ ์ด๋ฏธ์ง€ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
 
 
191
  elif len(valid_images) == 2:
192
+ prompt = "์ด ๋‘ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋‘ ์ด๋ฏธ์ง€์˜ ์š”์†Œ๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
193
+ logger.info("๋‘ ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
194
  else:
195
+ prompt = "์ด ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋˜ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ผ๊ด€๋œ ํ•˜๋‚˜์˜ ์žฅ๋ฉด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
196
+ logger.info("์„ธ ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
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
+ def update_prompt_from_function(function_choice, custom_text=""):
210
+ function_templates = {
211
+ "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ": f'#1์„ "{custom_text if custom_text else "์›ํ•˜๋Š” ์„ค๋ช…"}"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ',
212
+ "2. ๊ธ€์ž์ง€์šฐ๊ธฐ": f'#1์—์„œ "{custom_text if custom_text else "์ง€์šธ ํ…์ŠคํŠธ"}"๋ฅผ ์ง€์›Œ๋ผ',
213
+ "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์„ #2์˜ ์–ผ๊ตด๋กœ ๋ฐ”๊ฟ”๋ผ",
214
+ "4. ์˜ท๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์— #2 ๋˜๋Š” #3์˜ ์˜ท์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ผ",
215
+ "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ด๋ฏธ์ง€์— #2์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ”๋ผ",
216
+ "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)": "#1์™€ #2 ๋˜๋Š” #3์˜ ๋ฅผ ํ•ฉ์„ฑํ•˜๋ผ",
217
+ "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)": "#1์™€ #2๋ฅผ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•˜๋ผ"
218
+ }
219
+
220
+ return function_templates.get(function_choice, "")
221
 
222
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค (๊ธฐ์กด ์ฝ”๋“œ ์œ ์ง€)
223
  with gr.Blocks() as demo:
224
  gr.HTML(
225
  """
226
  <div style="text-align: center; margin-bottom: 1rem;">
227
+ <h1>๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</h1>
228
+ <p>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ  ๋ฐ”๋กœ ์‹คํ–‰ํ•˜๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์•„๋ž˜ ๊ธฐ๋Šฅ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</p>
229
  </div>
230
  """
231
  )
232
 
233
  with gr.Row():
234
  with gr.Column():
235
+ # 3๊ฐœ์˜ ์ด๋ฏธ์ง€ ์ž…๋ ฅ
236
  with gr.Row():
237
+ image1_input = gr.Image(type="pil", label="#1", image_mode="RGB")
238
+ image2_input = gr.Image(type="pil", label="#2", image_mode="RGB")
239
+ image3_input = gr.Image(type="pil", label="#3", image_mode="RGB")
240
 
241
+ # ๊ธฐ๋Šฅ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด๊ณผ ์ปค์Šคํ…€ ํ…์ŠคํŠธ ์ž…๋ ฅ
242
+ with gr.Row():
243
+ function_dropdown = gr.Dropdown(
244
+ choices=[
245
+ "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ",
246
+ "2. ๊ธ€์ž์ง€์šฐ๊ธฐ",
247
+ "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ",
248
+ "4. ์˜ท๋ฐ”๊พธ๊ธฐ",
249
+ "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ",
250
+ "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)",
251
+ "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)"
252
+ ],
253
+ label="๊ธฐ๋Šฅ ์„ ํƒ",
254
+ value=None
255
+ )
256
+ custom_text_input = gr.Textbox(
257
+ label="์ปค์Šคํ…€ ํ…์ŠคํŠธ (1, 2๋ฒˆ ๊ธฐ๋Šฅ์šฉ)",
258
+ placeholder="์˜ˆ: ๋ถ‰์€์ƒ‰, ์ˆ˜์ฑ„ํ™” ์Šคํƒ€์ผ, ์ค‘๊ตญ์–ด..."
259
+ )
260
+
261
+ apply_function_btn = gr.Button("๊ธฐ๋Šฅ ์ ์šฉ")
262
+
263
+ # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์„ ํƒ ์‚ฌํ•ญ)
264
  prompt_input = gr.Textbox(
265
  lines=3,
266
+ placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋น„์›Œ๋‘๋ฉด ์ž๋™ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค.",
267
+ label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
268
  )
269
 
270
  # ์ƒ์„ฑ ๋ฒ„ํŠผ
271
+ submit_btn = gr.Button("์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
272
 
273
  with gr.Column():
274
  # ๊ฒฐ๊ณผ ์ถœ๋ ฅ
275
+ output_image = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€")
276
+ output_text = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€")
277
+
278
+ # ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
279
+ prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
280
+
281
+ # ๊ธฐ๋Šฅ ์ ์šฉ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ
282
+ apply_function_btn.click(
283
+ fn=update_prompt_from_function,
284
+ inputs=[function_dropdown, custom_text_input],
285
+ outputs=[prompt_input]
286
+ )
287
 
288
  # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
289
  def process_and_show_prompt(image1, image2, image3, prompt):
 
292
  valid_images = [img for img in images if img is not None]
293
 
294
  try:
295
+ # ์ž๋™ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋˜๋Š” ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ
 
 
 
 
296
  auto_prompt = prompt
297
  if not prompt or not prompt.strip():
298
+ if len(valid_images) == 1:
299
+ auto_prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
 
 
300
  elif len(valid_images) == 2:
301
+ auto_prompt = "์ด ๋‘ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋‘ ์ด๋ฏธ์ง€์˜ ์š”์†Œ๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
302
  else:
303
+ auto_prompt = "์ด ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋˜ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ผ๊ด€๋œ ํ•˜๋‚˜์˜ ์žฅ๋ฉด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
304
  else:
305
  auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
306
 
307
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ
308
  result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
309
 
310
  return result_img, status, auto_prompt
311
  except Exception as e:
312
+ logger.exception("์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
313
+ return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}", prompt
314
 
315
  submit_btn.click(
316
  fn=process_and_show_prompt,
 
320
 
321
  gr.Markdown(
322
  """
323
+ ### ์‚ฌ์šฉ ๋ฐฉ๋ฒ•:
324
+
325
+ 1. **์ž๋™ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค
326
+ 2. **๊ธฐ๋Šฅ ์‚ฌ์šฉ**: ๋“œ๋กญ๋‹ค์šด์—์„œ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์„ ํƒํ•˜๊ณ  '๊ธฐ๋Šฅ ์ ์šฉ' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”
327
+ 3. **์ปค์Šคํ…€ ํ…์ŠคํŠธ**: ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ์ด๋‚˜ ๊ธ€์ž์ง€์šฐ๊ธฐ ๊ธฐ๋Šฅ์„ ์„ ํƒํ•  ๋•Œ ์ถ”๊ฐ€ ์„ค๋ช…์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
328
+ 4. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
329
+ 5. **์ผ๋ถ€ ์ด๋ฏธ์ง€๋งŒ**: ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค
330
 
331
+ > **ํŒ**: ๊ธฐ๋Šฅ์„ ์„ ํƒํ•œ ํ›„์—๋„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
 
 
332
  """
333
  )
334
 
335
  # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰
336
  if __name__ == "__main__":
337
+ demo.launch(share=True)