Kims12 commited on
Commit
d53a3c8
ยท
verified ยท
1 Parent(s): c17a6b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -170
app.py CHANGED
@@ -26,41 +26,40 @@ def preprocess_prompt(prompt, image1, image2, image3):
26
  """
27
  ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ธฐ๋Šฅ ๋ช…๋ น์„ ํ•ด์„
28
  """
29
- # ์ด๋ฏธ์ง€ ์—†๋Š” ์ฐธ์กฐ ํ™•์ธ ๋ฐ ์ฒ˜๋ฆฌ
30
  has_img1 = image1 is not None
31
  has_img2 = image2 is not None
32
  has_img3 = image3 is not None
33
 
34
  # #1, #2, #3 ์ฐธ์กฐ๋ฅผ ์„ค๋ช…์œผ๋กœ ๋ณ€ํ™˜ (์ด๋ฏธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋ฌด์‹œ)
35
- if "#1" in prompt and not has_img1:
36
- prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
37
- else:
38
- prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
39
-
40
- if "#2" in prompt and not has_img2:
41
- prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
42
- else:
43
- prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
44
-
45
- if "#3" in prompt and not has_img3:
46
- prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
47
- else:
48
- prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€")
49
 
50
  # ๊ธฐ๋Šฅ ๋ช…๋ น ํ•ด์„
51
  if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
52
- # ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์ œ๊ณต
53
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
 
 
 
 
54
 
55
  elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
56
- # ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์ œ๊ณต
57
- prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ๊น”๋”ํ•œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
 
 
 
 
58
 
59
  elif "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ" in prompt:
60
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์–ผ๊ตด์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์–ผ๊ตด๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์–ผ๊ตด์˜ ํ‘œ์ •๊ณผ ํŠน์ง•์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
61
 
62
  elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
63
- # ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
64
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
65
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
66
  else:
@@ -70,7 +69,6 @@ def preprocess_prompt(prompt, image1, image2, image3):
70
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
71
 
72
  elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
73
- # ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
74
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
75
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ, ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ์ž˜ ๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
76
  else:
@@ -79,151 +77,86 @@ def preprocess_prompt(prompt, image1, image2, image3):
79
  elif "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)" in prompt:
80
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋‚ด์šฉ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด์™€ ๊ตฌ๋„๋Š” ์œ ์ง€ํ•˜๋˜, ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜ˆ์ˆ ์  ์Šคํƒ€์ผ, ์ƒ‰์ƒ, ์งˆ๊ฐ์„ ์ ์šฉํ•ด์ฃผ์„ธ์š”."
81
 
82
- # ๊ฐ„๋‹จํ•œ ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์š”์ฒญ ์ฒ˜๋ฆฌ
83
  elif "์„ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt or "๋ฅผ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt:
84
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋ถ‰์€์ƒ‰ ํ†ค์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ „์ฒด์ ์ธ ์ƒ‰์ƒ์„ ๋ถ‰์€ ๊ณ„์—ด๋กœ ์กฐ์ •ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ๏ฟฝ๏ฟฝ ๋А๋‚Œ์„ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
85
 
86
- # ๋ช…ํ™•ํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์š”์ฒญ ์ถ”๊ฐ€
87
  prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
88
-
89
  return prompt
90
 
91
- def generate_with_images(prompt, images, max_retries=2):
92
  """
93
- ๊ณต์‹ ๋ฌธ์„œ์— ๊ธฐ๋ฐ˜ํ•œ ์˜ฌ๋ฐ”๋ฅธ API ํ˜ธ์ถœ ๋ฐฉ์‹ ๊ตฌํ˜„
94
- ์‹คํŒจ ์‹œ ์žฌ์‹œ๋„ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
95
  """
96
- retries = 0
97
- last_error = None
98
-
99
- while retries <= max_retries:
100
- try:
101
- # API ํ‚ค ํ™•์ธ
102
- api_key = os.environ.get("GEMINI_API_KEY")
103
- if not api_key:
104
- return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
105
-
106
- # Gemini ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
107
- client = genai.Client(api_key=api_key)
108
-
109
- logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt} (์‹œ๋„: {retries+1}/{max_retries+1})")
110
-
111
- # ์ด๋ฏธ์ง€ ๋ฐ ํ…์ŠคํŠธ ์ปจํ…์ธ  ์ค€๋น„
112
- parts = []
113
-
114
- # ์ด๋ฏธ์ง€ ํŒŒํŠธ ์ถ”๊ฐ€
115
- for idx, img in enumerate(images, 1):
116
- if img is not None:
117
- # ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”์ดํŠธ๋กœ ๋ณ€ํ™˜
118
- buffered = BytesIO()
119
- img.save(buffered, format="PNG")
120
- image_bytes = buffered.getvalue()
121
-
122
- # ์ด๋ฏธ์ง€ ํŒŒํŠธ ์ƒ์„ฑ
123
- parts.append({
124
- 'inlineData': {
125
- 'mimeType': 'image/png',
126
- 'data': base64.b64encode(image_bytes).decode('utf-8')
127
- }
128
- })
129
- logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
130
-
131
- # ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
132
- parts.append({
133
- 'text': prompt
134
- })
135
 
136
- # ๋ชจ๋ธ ์ƒ์„ฑ ์š”์ฒญ
137
- request = {
138
- 'contents': [{
139
- 'parts': parts
140
- }],
141
- 'generation_config': {
142
- 'temperature': 1.0,
143
- 'topP': 0.95,
144
- 'topK': 40,
145
- 'maxOutputTokens': 8192,
146
- 'responseMimeType': 'image/png'
147
- }
148
- }
 
 
 
 
 
 
 
 
 
 
 
149
 
150
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ API ํ˜ธ์ถœ
151
- model = client.get_model('gemini-pro-vision')
152
- response = model.generate_content(request)
153
 
154
- # ์‘๋‹ต ์œ ํšจ์„ฑ ํ™•์ธ
155
- if not response or not response.parts:
156
- if retries < max_retries:
157
- retries += 1
158
- logger.warning(f"์œ ํšจํ•œ ์‘๋‹ต์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์žฌ์‹œ๋„ ์ค‘... ({retries}/{max_retries})")
159
- continue
160
- return None, "์ด๋ฏธ์ง€ ์ƒ์„ฑ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ์œ ํšจํ•œ ์‘๋‹ต์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค."
 
161
 
162
- # ์ž„์‹œ ํŒŒ์ผ ์ƒ์„ฑ
163
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
164
- temp_path = tmp.name
165
-
166
- result_text = ""
167
- image_found = False
168
-
169
- # ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ ํ™•์ธ ๋ฐ ์ €์žฅ
170
- for part in response.parts:
171
- if hasattr(part, 'mime_type') and part.mime_type.startswith('image/'):
172
- # base64 ๋””์ฝ”๋”ฉ ๋ฐ ์ €์žฅ
173
- img_data = base64.b64decode(part.data)
174
- with open(temp_path, 'wb') as f:
175
- f.write(img_data)
176
- image_found = True
177
- logger.info("์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
178
- break
179
-
180
- # ํ…์ŠคํŠธ ์ถ”์ถœ (์˜ต์…˜)
181
- if hasattr(response, 'text'):
182
- result_text = response.text
183
-
184
- if not image_found:
185
- if retries < max_retries:
186
- retries += 1
187
- logger.warning(f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์žฌ์‹œ๋„ ์ค‘... ({retries}/{max_retries})")
188
- continue
189
- return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
190
-
191
- # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋ฐ˜ํ™˜
192
- result_img = Image.open(temp_path)
193
- if result_img.mode == "RGBA":
194
- result_img = result_img.convert("RGB")
195
 
196
- return result_img, f"์ด๋ฏธ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. {result_text}"
 
 
197
 
198
- except Exception as e:
199
- last_error = str(e)
200
- logger.exception(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ (์‹œ๋„: {retries+1}/{max_retries+1}):")
201
- if retries < max_retries:
202
- retries += 1
203
- logger.info(f"์žฌ์‹œ๋„ ์ค‘... ({retries}/{max_retries})")
204
- continue
205
- return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {last_error}"
206
-
207
- return None, f"์ตœ๋Œ€ ์žฌ์‹œ๋„ ํšŸ์ˆ˜ ์ดˆ๊ณผ. ๋งˆ์ง€๋ง‰ ์˜ค๋ฅ˜: {last_error}"
208
-
209
 
210
  def process_images_with_prompt(image1, image2, image3, prompt):
211
  """
212
- 3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜
213
- ์ด๋ฏธ์ง€ ์—†์ด ํ”„๋กฌํ”„ํŠธ๋งŒ์œผ๋กœ๋„ ๋™์ž‘
 
214
  """
215
  try:
216
- # ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜ ํ™•์ธ
217
  images = [image1, image2, image3]
218
- valid_images = [img for img in images if img is not None]
219
 
220
- # ํ”„๋กฌํ”„ํŠธ ์ฒ˜๋ฆฌ
221
  if not prompt or not prompt.strip():
222
- # ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
223
- if not valid_images:
224
- # ์ด๋ฏธ์ง€๋„ ์—†๊ณ  ํ”„๋กฌํ”„ํŠธ๋„ ์—†๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ
225
- prompt = "์•„๋ฆ„๋‹ค์šด ํ’๊ฒฝ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ํ‘ธ๋ฅธ ํ•˜๋Š˜, ์ดˆ๋ก์ƒ‰ ์–ธ๋•, ๊ทธ๋ฆฌ๊ณ  ๋ง‘์€ ํ˜ธ์ˆ˜๊ฐ€ ์žˆ๋Š” ํ‰ํ™”๋กœ์šด ์ž์—ฐ ํ’๊ฒฝ์„ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
226
- logger.info("์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ ๋ชจ๋‘ ์—†์Œ. ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ")
227
  elif len(valid_images) == 1:
228
  prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
229
  logger.info("๋‹จ์ผ ์ด๋ฏธ์ง€ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
@@ -234,21 +167,30 @@ def process_images_with_prompt(image1, image2, image3, prompt):
234
  prompt = "์ด ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋˜ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ผ๊ด€๋œ ํ•˜๋‚˜์˜ ์žฅ๋ฉด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
235
  logger.info("์„ธ ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
236
  else:
237
- # ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ ๋ฐ ๊ธฐ๋Šฅ ๋ช…๋ น ํ•ด์„
238
  prompt = preprocess_prompt(prompt, image1, image2, image3)
239
 
240
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ
241
- return generate_with_images(prompt, valid_images)
 
 
 
 
 
 
 
242
 
243
  except Exception as e:
244
  logger.exception("์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
245
  return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
246
 
247
- # ๊ธฐ๋Šฅ ์„ ํƒ ์ฝœ๋ฐฑ
248
  def update_prompt_from_function(function_choice):
 
 
 
 
249
  function_templates = {
250
- "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ": "#1์„ ์ฐฝ์˜์ ์œผ๋กœ ๋ฐ”๊ฟ”๋ผ",
251
- "2. ๊ธ€์ž์ง€์šฐ๊ธฐ": "#1์—์„œ ํ…์ŠคํŠธ๋ฅผ ์ง€์›Œ๋ผ",
252
  "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์„ #2์˜ ์–ผ๊ตด๋กœ ๋ฐ”๊ฟ”๋ผ",
253
  "4. ์˜ท๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์— #2 ๋˜๋Š” #3์˜ ์˜ท์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ผ",
254
  "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ด๋ฏธ์ง€์— #2์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ”๋ผ",
@@ -258,26 +200,26 @@ def update_prompt_from_function(function_choice):
258
 
259
  return function_templates.get(function_choice, "")
260
 
261
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค
262
  with gr.Blocks() as demo:
263
  gr.HTML(
264
  """
265
  <div style="text-align: center; margin-bottom: 1rem;">
266
  <h1>๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</h1>
267
- <p>์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”. ๋‘˜ ๋‹ค ์—†์–ด๋„ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.</p>
268
  </div>
269
  """
270
  )
271
 
272
  with gr.Row():
273
  with gr.Column():
274
- # 3๊ฐœ์˜ ์ด๋ฏธ์ง€ ์ž…๋ ฅ
275
  with gr.Row():
276
  image1_input = gr.Image(type="pil", label="#1", image_mode="RGB")
277
  image2_input = gr.Image(type="pil", label="#2", image_mode="RGB")
278
  image3_input = gr.Image(type="pil", label="#3", image_mode="RGB")
279
 
280
- # ๊ธฐ๋Šฅ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด
281
  function_dropdown = gr.Dropdown(
282
  choices=[
283
  "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ",
@@ -295,7 +237,7 @@ with gr.Blocks() as demo:
295
  # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์„ ํƒ ์‚ฌํ•ญ)
296
  prompt_input = gr.Textbox(
297
  lines=3,
298
- placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋น„์›Œ๋‘๋ฉด ์ž๋™ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ ์—†์ด๋„ ํ”„๋กฌํ”„ํŠธ๋งŒ์œผ๋กœ ์ƒ์„ฑ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.",
299
  label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
300
  )
301
 
@@ -310,7 +252,7 @@ with gr.Blocks() as demo:
310
  # ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
311
  prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
312
 
313
- # ๊ธฐ๋Šฅ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด ์ด๋ฒคํŠธ (์ฆ‰์‹œ ํ”„๋กฌํ”„ํŠธ ์—…๋ฐ์ดํŠธ)
314
  function_dropdown.change(
315
  fn=update_prompt_from_function,
316
  inputs=[function_dropdown],
@@ -324,12 +266,10 @@ with gr.Blocks() as demo:
324
  valid_images = [img for img in images if img is not None]
325
 
326
  try:
327
- # ์ž๋™ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋˜๋Š” ํ”„๋กฌํ”„ํŠธ ์ „์ฒ˜๋ฆฌ
328
  auto_prompt = prompt
329
  if not prompt or not prompt.strip():
330
- if not valid_images:
331
- # ์ด๋ฏธ์ง€๋„ ์—†๊ณ  ํ”„๋กฌํ”„ํŠธ๋„ ์—†๋Š” ๊ฒฝ์šฐ
332
- auto_prompt = "์•„๋ฆ„๋‹ค์šด ํ’๊ฒฝ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ํ‘ธ๋ฅธ ํ•˜๋Š˜, ์ดˆ๋ก์ƒ‰ ์–ธ๋•, ๊ทธ๋ฆฌ๊ณ  ๋ง‘์€ ํ˜ธ์ˆ˜๊ฐ€ ์žˆ๋Š” ํ‰ํ™”๋กœ์šด ์ž์—ฐ ํ’๊ฒฝ์„ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
333
  elif len(valid_images) == 1:
334
  auto_prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
335
  elif len(valid_images) == 2:
@@ -339,7 +279,6 @@ with gr.Blocks() as demo:
339
  else:
340
  auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
341
 
342
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ
343
  result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
344
 
345
  return result_img, status, auto_prompt
@@ -357,17 +296,13 @@ with gr.Blocks() as demo:
357
  """
358
  ### ์‚ฌ์šฉ ๋ฐฉ๋ฒ•:
359
 
360
- 1. **์ž๏ฟฝ๏ฟฝ๏ฟฝ ํ•ฉ์„ฑ**: ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•˜๊ณ  ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ํ•ฉ์„ฑ๋ฉ๋‹ˆ๋‹ค
361
- 2. **ํ…์ŠคํŠธ๋งŒ์œผ๋กœ ์ƒ์„ฑ**: ์ด๋ฏธ์ง€ ์—†์ด ํ”„๋กฌํ”„ํŠธ๋งŒ ์ž…๋ ฅํ•ด๋„ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค
362
- 3. **๊ธฐ๋Šฅ ์‚ฌ์šฉ**: ๋“œ๋กญ๋‹ค์šด์—์„œ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์„ ํƒํ•˜๋ฉด ์ž๋™์œผ๋กœ ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค
363
- 4. **์ด๋ฏธ์ง€ ์ฐธ์กฐ**: #1, #2, #3์œผ๋กœ ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
364
- 5. **์ผ๋ถ€ ์ด๋ฏธ์ง€๋งŒ**: ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋งŒ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค
365
- 6. **์žฌ์‹œ๋„ ๊ธฐ๋Šฅ**: ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์ž๋™์œผ๋กœ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค
366
-
367
- > **ํŒ**: ๊ธฐ๋Šฅ์„ ์„ ํƒํ•œ ํ›„์—๋„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
368
  """
369
  )
370
 
371
  # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰
372
  if __name__ == "__main__":
373
- demo.launch(share=True)
 
26
  """
27
  ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ธฐ๋Šฅ ๋ช…๋ น์„ ํ•ด์„
28
  """
29
+ # ์ด๋ฏธ์ง€ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
30
  has_img1 = image1 is not None
31
  has_img2 = image2 is not None
32
  has_img3 = image3 is not None
33
 
34
  # #1, #2, #3 ์ฐธ์กฐ๋ฅผ ์„ค๋ช…์œผ๋กœ ๋ณ€ํ™˜ (์ด๋ฏธ์ง€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๋ฌด์‹œ)
35
+ if "#1" in prompt:
36
+ prompt = prompt.replace("#1", "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€" if has_img1 else "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
37
+ if "#2" in prompt:
38
+ prompt = prompt.replace("#2", "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€" if has_img2 else "๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
39
+ if "#3" in prompt:
40
+ prompt = prompt.replace("#3", "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€" if has_img3 else "์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€(์—†์Œ)")
 
 
 
 
 
 
 
 
41
 
42
  # ๊ธฐ๋Šฅ ๋ช…๋ น ํ•ด์„
43
  if "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ" in prompt:
44
+ desc_match = re.search(r'#1์„ "(.*?)"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ', prompt)
45
+ if desc_match:
46
+ description = desc_match.group(1)
47
+ prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ {description}์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์›๋ณธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ๋‚ด์šฉ์€ ์œ ์ง€ํ•˜๋˜ ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ๊ณผ ๋ถ„์œ„๊ธฐ๋กœ ์žฌํ•ด์„ํ•ด์ฃผ์„ธ์š”."
48
+ else:
49
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
50
 
51
  elif "2. ๊ธ€์ž์ง€์šฐ๊ธฐ" in prompt:
52
+ text_match = re.search(r'#1์—์„œ "(.*?)"๋ฅผ ์ง€์›Œ๋ผ', prompt)
53
+ if text_match:
54
+ text_to_remove = text_match.group(1)
55
+ prompt = f"์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ '{text_to_remove}' ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋˜ ๋ถ€๋ถ„์„ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ์ฑ„์›Œ์ฃผ์„ธ์š”."
56
+ else:
57
+ prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๋ชจ๋“  ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”. ๊น”๋”ํ•œ ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
58
 
59
  elif "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ" in prompt:
60
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์–ผ๊ตด์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์–ผ๊ตด๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์–ผ๊ตด์˜ ํ‘œ์ •๊ณผ ํŠน์ง•์€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
61
 
62
  elif "4. ์˜ท๋ฐ”๊พธ๊ธฐ" in prompt:
 
63
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
64
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ธ๋ฌผ ์˜์ƒ์„ ๋‘ ๋ฒˆ์งธ ๋˜๋Š” ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜์ƒ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์˜์ƒ์˜ ์Šคํƒ€์ผ๊ณผ ์ƒ‰์ƒ์€ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ๋”ฐ๋ฅด๋˜, ์‹ ์ฒด ๋น„์œจ๊ณผ ํฌ์ฆˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
65
  else:
 
69
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ต์ฒดํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด๋Š” ์œ ์ง€ํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ๊ณผ ์กฐํ™”๋กญ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”."
70
 
71
  elif "6. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์ƒํ’ˆํฌํ•จ)" in prompt:
 
72
  if "#3" in prompt or "๋˜๋Š” #3" in prompt:
73
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ, ์„ธ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๊ณ , ํŠนํžˆ ์ƒํ’ˆ์ด ์ž˜ ๋ณด์ด๋„๋ก ์กฐํ™”๋กญ๊ฒŒ ํ†ตํ•ฉํ•ด์ฃผ์„ธ์š”."
74
  else:
 
77
  elif "7. ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ(์Šคํƒ€์ผ์ ์šฉ)" in prompt:
78
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ๋‚ด์šฉ์„ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์Šคํƒ€์ผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์„ธ์š”. ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ํ”ผ์‚ฌ์ฒด์™€ ๊ตฌ๋„๋Š” ์œ ์ง€ํ•˜๋˜, ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ์˜ˆ์ˆ ์  ์Šคํƒ€์ผ, ์ƒ‰์ƒ, ์งˆ๊ฐ์„ ์ ์šฉํ•ด์ฃผ์„ธ์š”."
79
 
 
80
  elif "์„ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt or "๋ฅผ ๋ถ‰์€์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”๋ผ" in prompt:
81
  prompt = "์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€๋ฅผ ๋ถ‰์€์ƒ‰ ํ†ค์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”. ์ „์ฒด์ ์ธ ์ƒ‰์ƒ์„ ๋ถ‰์€ ๊ณ„์—ด๋กœ ์กฐ์ •ํ•˜๊ณ  ์ž์—ฐ์Šค๋Ÿฌ๏ฟฝ๏ฟฝ ๋А๋‚Œ์„ ์œ ์ง€ํ•ด์ฃผ์„ธ์š”."
82
 
 
83
  prompt += " ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
 
84
  return prompt
85
 
86
+ def generate_with_images(prompt, images):
87
  """
88
+ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜
 
89
  """
90
+ try:
91
+ api_key = os.environ.get("GEMINI_API_KEY")
92
+ if not api_key:
93
+ return None, "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ client = genai.Client(api_key=api_key)
96
+ logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}")
97
+
98
+ contents = []
99
+ contents.append(prompt)
100
+ for idx, img in enumerate(images, 1):
101
+ if img is not None:
102
+ contents.append(img)
103
+ logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
104
+
105
+ response = client.models.generate_content(
106
+ model="gemini-2.0-flash-exp-image-generation",
107
+ contents=contents,
108
+ config=types.GenerateContentConfig(
109
+ response_modalities=['Text', 'Image'],
110
+ temperature=1,
111
+ top_p=0.95,
112
+ top_k=40,
113
+ max_output_tokens=8192
114
+ )
115
+ )
116
+
117
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
118
+ temp_path = tmp.name
119
 
120
+ result_text = ""
121
+ image_found = False
 
122
 
123
+ for part in response.candidates[0].content.parts:
124
+ if hasattr(part, 'text') and part.text:
125
+ result_text += part.text
126
+ logger.info(f"์‘๋‹ต ํ…์ŠคํŠธ: {part.text}")
127
+ elif hasattr(part, 'inline_data') and part.inline_data:
128
+ save_binary_file(temp_path, part.inline_data.data)
129
+ image_found = True
130
+ logger.info("์‘๋‹ต์—์„œ ์ด๋ฏธ์ง€ ์ถ”์ถœ ์„ฑ๊ณต")
131
 
132
+ if not image_found:
133
+ return None, f"API์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ํ…์ŠคํŠธ: {result_text}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ result_img = Image.open(temp_path)
136
+ if result_img.mode == "RGBA":
137
+ result_img = result_img.convert("RGB")
138
 
139
+ return result_img, f"์ด๋ฏธ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. {result_text}"
140
+
141
+ except Exception as e:
142
+ logger.exception("์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
143
+ return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
 
 
 
 
 
 
144
 
145
  def process_images_with_prompt(image1, image2, image3, prompt):
146
  """
147
+ 3๊ฐœ์˜ ์ด๋ฏธ์ง€์™€ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜.
148
+ ์ด๋ฏธ์ง€๊ฐ€ ์—…๋กœ๋“œ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋„ ํ”„๋กฌํ”„ํŠธ์— ๋”ฐ๋ผ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ,
149
+ ์ด๋ฏธ์ง€ ์ƒ์„ฑ์— ์‹คํŒจํ•˜๋ฉด ์ตœ๋Œ€ 3ํšŒ๊นŒ์ง€ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
150
  """
151
  try:
 
152
  images = [image1, image2, image3]
153
+ valid_images = [img for img in images if img is not None] # ์ด๋ฏธ์ง€๊ฐ€ ์—†์„ ์ˆ˜๋„ ์žˆ์Œ
154
 
155
+ # ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ (์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ ์ˆ˜์— ๋”ฐ๋ผ)
156
  if not prompt or not prompt.strip():
157
+ if len(valid_images) == 0:
158
+ prompt = "์ด ํ”„๋กฌํ”„ํŠธ์— ๋งž์ถฐ ์ฐฝ์˜์ ์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
159
+ logger.info("ํ…์ŠคํŠธ ์ „์šฉ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
 
 
160
  elif len(valid_images) == 1:
161
  prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
162
  logger.info("๋‹จ์ผ ์ด๋ฏธ์ง€ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
 
167
  prompt = "์ด ์„ธ ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ํ•ฉ์„ฑํ•ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ์ฃผ์š” ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋˜ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ผ๊ด€๋œ ํ•˜๋‚˜์˜ ์žฅ๋ฉด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
168
  logger.info("์„ธ ์ด๋ฏธ์ง€ ํ•ฉ์„ฑ ํ”„๋กฌํ”„ํŠธ ์ž๋™ ์ƒ์„ฑ")
169
  else:
 
170
  prompt = preprocess_prompt(prompt, image1, image2, image3)
171
 
172
+ # ์ตœ๋Œ€ 3ํšŒ๊นŒ์ง€ ์žฌ์‹œ๋„
173
+ max_retries = 3
174
+ for attempt in range(max_retries):
175
+ result_img, status = generate_with_images(prompt, valid_images)
176
+ if result_img is not None:
177
+ return result_img, status
178
+ else:
179
+ logger.info(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹คํŒจ, ์žฌ์‹œ๋„ ์ค‘ ({attempt+1}/{max_retries})")
180
+ return None, f"์ด๋ฏธ์ง€ ์ƒ์„ฑ์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ์ƒํƒœ: {status}"
181
 
182
  except Exception as e:
183
  logger.exception("์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:")
184
  return None, f"์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
185
 
 
186
  def update_prompt_from_function(function_choice):
187
+ """
188
+ ๊ธฐ๋Šฅ ์„ ํƒ์— ๋”ฐ๋ผ ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
189
+ (์ปค์Šคํ…€ ํ…์ŠคํŠธ ์ž…๋ ฅ์€ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.)
190
+ """
191
  function_templates = {
192
+ "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ": '#1์„ "์›ํ•˜๋Š” ์„ค๋ช…"์œผ๋กœ ๋ฐ”๊ฟ”๋ผ',
193
+ "2. ๊ธ€์ž์ง€์šฐ๊ธฐ": '#1์—์„œ "์ง€์šธ ํ…์ŠคํŠธ"๋ฅผ ์ง€์›Œ๋ผ',
194
  "3. ์–ผ๊ตด๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์„ #2์˜ ์–ผ๊ตด๋กœ ๋ฐ”๊ฟ”๋ผ",
195
  "4. ์˜ท๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ธ๋ฌผ์— #2 ๋˜๋Š” #3์˜ ์˜ท์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ผ",
196
  "5. ๋ฐฐ๊ฒฝ๋ฐ”๊พธ๊ธฐ": "#1์˜ ์ด๋ฏธ์ง€์— #2์˜ ๋ฐฐ๊ฒฝ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ”๋ผ",
 
200
 
201
  return function_templates.get(function_choice, "")
202
 
203
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
204
  with gr.Blocks() as demo:
205
  gr.HTML(
206
  """
207
  <div style="text-align: center; margin-bottom: 1rem;">
208
  <h1>๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ธฐ</h1>
209
+ <p>ํ”„๋กฌํ”„ํŠธ๋งŒ ์ž…๋ ฅํ•ด๋„ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๊ธฐ๋Šฅ ์„ ํƒ๋งŒ์œผ๋กœ ํ”„๋กฌํ”„ํŠธ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</p>
210
  </div>
211
  """
212
  )
213
 
214
  with gr.Row():
215
  with gr.Column():
216
+ # 3๊ฐœ์˜ ์ด๋ฏธ์ง€ ์ž…๋ ฅ (์—…๋กœ๋“œํ•˜์ง€ ์•Š์•„๋„ ๋จ)
217
  with gr.Row():
218
  image1_input = gr.Image(type="pil", label="#1", image_mode="RGB")
219
  image2_input = gr.Image(type="pil", label="#2", image_mode="RGB")
220
  image3_input = gr.Image(type="pil", label="#3", image_mode="RGB")
221
 
222
+ # ๊ธฐ๋Šฅ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด (์ปค์Šคํ…€ ํ…์ŠคํŠธ ์ž…๋ ฅ ์ œ๊ฑฐ)
223
  function_dropdown = gr.Dropdown(
224
  choices=[
225
  "1. ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ",
 
237
  # ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ (์„ ํƒ ์‚ฌํ•ญ)
238
  prompt_input = gr.Textbox(
239
  lines=3,
240
+ placeholder="ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋น„์›Œ๋‘๋ฉด ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.",
241
  label="ํ”„๋กฌํ”„ํŠธ (์„ ํƒ ์‚ฌํ•ญ)"
242
  )
243
 
 
252
  # ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ ํ‘œ์‹œ
253
  prompt_display = gr.Textbox(label="์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ", visible=True)
254
 
255
+ # ๊ธฐ๋Šฅ ์„ ํƒ ๋“œ๋กญ๋‹ค์šด ๋ณ€๊ฒฝ ์‹œ ํ”„๋กฌํ”„ํŠธ ์—…๋ฐ์ดํŠธ (apply ๋ฒ„ํŠผ ์—†์ด ๋ฐ”๋กœ ์ ์šฉ)
256
  function_dropdown.change(
257
  fn=update_prompt_from_function,
258
  inputs=[function_dropdown],
 
266
  valid_images = [img for img in images if img is not None]
267
 
268
  try:
 
269
  auto_prompt = prompt
270
  if not prompt or not prompt.strip():
271
+ if len(valid_images) == 0:
272
+ auto_prompt = "์ด ํ”„๋กฌํ”„ํŠธ์— ๋งž์ถฐ ์ฐฝ์˜์ ์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."
 
273
  elif len(valid_images) == 1:
274
  auto_prompt = "์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐฝ์˜์ ์œผ๋กœ ๋ณ€ํ˜•ํ•ด์ฃผ์„ธ์š”. ๋” ์ƒ์ƒํ•˜๊ณ  ์˜ˆ์ˆ ์ ์ธ ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”."
275
  elif len(valid_images) == 2:
 
279
  else:
280
  auto_prompt = preprocess_prompt(prompt, image1, image2, image3)
281
 
 
282
  result_img, status = process_images_with_prompt(image1, image2, image3, prompt)
283
 
284
  return result_img, status, auto_prompt
 
296
  """
297
  ### ์‚ฌ์šฉ ๋ฐฉ๋ฒ•:
298
 
299
+ 1. **ํ…์ŠคํŠธ ์ „์šฉ ์ƒ์„ฑ**: ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜์ง€ ์•Š๊ณ  ํ”„๋กฌํ”„ํŠธ๋งŒ ์ž…๋ ฅํ•ด๋„ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
300
+ 2. **๊ธฐ๋Šฅ ์„ ํƒ**: ๋“œ๋กญ๋‹ค์šด์—์„œ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์„ ํƒํ•˜๋ฉด ํ•ด๋‹น ๊ธฐ๋Šฅ์˜ ํ…œํ”Œ๋ฆฟ์ด ํ”„๋กฌํ”„ํŠธ์— ์ž๋™ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.
301
+ 3. **์ด๋ฏธ์ง€ ์—…๋กœ๋“œ**: ์ผ๋ถ€ ๋˜๋Š” ์ „์ฒด ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด๋„ ๊ธฐ๋Šฅ์ด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
302
+ 4. **์ž๋™ ์žฌ์‹œ๋„**: ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ตœ๋Œ€ 2ํšŒ ์ถ”๊ฐ€ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
 
 
 
 
303
  """
304
  )
305
 
306
  # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰
307
  if __name__ == "__main__":
308
+ demo.launch(share=True)