Kims12 commited on
Commit
aedf707
ยท
verified ยท
1 Parent(s): 08b9282

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -88
app.py CHANGED
@@ -33,7 +33,6 @@ COLORFUL_PATTERN_BACKGROUNDS = {}
33
  ABSTRACT_BACKGROUNDS = {}
34
  JEWELRY_BACKGROUNDS = {} # ์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ ์ „์—ญ ๋ณ€์ˆ˜ ์ถ”๊ฐ€
35
 
36
-
37
  # ------------------- ๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๋กœ๋“œ ํ•จ์ˆ˜ -------------------
38
  def load_background_json(filename):
39
  """๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๋กœ๋“œ ํ•จ์ˆ˜"""
@@ -56,22 +55,18 @@ def initialize_backgrounds():
56
  global SIMPLE_BACKGROUNDS, STUDIO_BACKGROUNDS, NATURE_BACKGROUNDS, INDOOR_BACKGROUNDS
57
  global TECHNOLOGY_BACKGROUNDS, COLORFUL_PATTERN_BACKGROUNDS, ABSTRACT_BACKGROUNDS
58
  global JEWELRY_BACKGROUNDS # ์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ ์ถ”๊ฐ€
59
-
60
 
61
- # ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด ๋ชจ๋“  ํŒŒ์ผ ๋กœ๊น…
62
  logger.info(f"Backgrounds ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ: {BACKGROUNDS_DIR}")
63
  logger.info(f"๋””๋ ‰ํ† ๋ฆฌ ๋‚ด ํŒŒ์ผ ๋ชฉ๋ก: {os.listdir(BACKGROUNDS_DIR)}")
64
 
65
- # ๊ฐ ๋ฐฐ๊ฒฝ ํŒŒ์ผ ๋กœ๋“œ
66
  SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
67
  STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
68
  NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
69
  INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
70
- TECHNOLOGY_BACKGROUNDS = load_background_json("tech-backgrounds-final.json") # ํŒŒ์ผ ์ด๋ฆ„ ์ˆ˜์ •
71
- COLORFUL_PATTERN_BACKGROUNDS = load_background_json("colorful-pattern-backgrounds.json") # ํŒŒ์ผ ์ด๋ฆ„ ์ˆ˜์ •
72
  ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
73
  JEWELRY_BACKGROUNDS = load_background_json("jewelry_backgrounds.json")
74
-
75
 
76
  # ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • (ํŒŒ์ผ์ด ์—†๊ฑฐ๋‚˜ ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ)
77
  if not SIMPLE_BACKGROUNDS:
@@ -93,10 +88,9 @@ def initialize_backgrounds():
93
 
94
  logger.info("๋ชจ๋“  ๋ฐฐ๊ฒฝ ์˜ต์…˜ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ")
95
 
96
- # ๋ฐฐ๊ฒฝ ๋“œ๋กญ๋‹ค์šด ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜ ์ถ”๊ฐ€
97
  def initialize_dropdowns():
98
  """๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜"""
99
- # ๊ฐ ๋ฐฐ๊ฒฝ ์œ ํ˜•๋ณ„ ๋“œ๋กญ๋‹ค์šด ์„ ํƒ ๋ชฉ๋ก ์ƒ์„ฑ
100
  simple_choices = list(SIMPLE_BACKGROUNDS.keys())
101
  studio_choices = list(STUDIO_BACKGROUNDS.keys())
102
  nature_choices = list(NATURE_BACKGROUNDS.keys())
@@ -105,8 +99,6 @@ def initialize_dropdowns():
105
  colorful_choices = list(COLORFUL_PATTERN_BACKGROUNDS.keys())
106
  abstract_choices = list(ABSTRACT_BACKGROUNDS.keys())
107
  jewelry_choices = list(JEWELRY_BACKGROUNDS.keys())
108
-
109
-
110
 
111
  return {
112
  "simple": simple_choices,
@@ -116,10 +108,9 @@ def initialize_dropdowns():
116
  "tech": tech_choices,
117
  "colorful": colorful_choices,
118
  "abstract": abstract_choices,
119
- "jewelry": jewelry_choices, # ์ƒˆ๋กœ ์ถ”๊ฐ€
120
  }
121
 
122
-
123
  # ------------------- ๊ธฐ๋ณธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ -------------------
124
  def save_binary_file(file_name, data):
125
  with open(file_name, "wb") as f:
@@ -191,7 +182,6 @@ def generate_with_images(prompt, images, variation_index=0):
191
  client = genai.Client(api_key=api_key)
192
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
193
 
194
- # ํ–ฅ์ƒ๋œ ๋ณ€ํ˜• ์ ‘๋ฏธ์‚ฌ
195
  variation_suffixes = [
196
  " Create this as a professional studio product shot with precise focus on the product details. Do not add any text, watermarks, or labels to the image.",
197
  " Create this as a high-contrast artistic studio shot with dramatic lighting and shadows. Do not add any text, watermarks, or labels to the image.",
@@ -210,16 +200,15 @@ def generate_with_images(prompt, images, variation_index=0):
210
  contents.append(img)
211
  logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
212
 
213
- # ํ–ฅ์ƒ๋œ ์ƒ์„ฑ ์„ค์ • - ๋” ๋†’์€ temperature๋กœ ์ฐฝ์˜์„ฑ ์ฆ๊ฐ€, ๋” ๋†’์€ max_output_tokens
214
  response = client.models.generate_content(
215
  model="gemini-2.0-flash-exp-image-generation",
216
  contents=contents,
217
  config=types.GenerateContentConfig(
218
  response_modalities=['Text', 'Image'],
219
- temperature=1.05, # ์•ฝ๊ฐ„ ๋†’์€ ์˜จ๋„๋กœ ๋” ๋‹ค์–‘ํ•œ ๊ฒฐ๊ณผ
220
- top_p=0.97, # ์•ฝ๊ฐ„ ๋†’์ž„
221
- top_k=50, # ๋‹ค์–‘์„ฑ ์ฆ๊ฐ€
222
- max_output_tokens=10240 # ๋” ๋†’์€ ํ† ํฐ ํ•œ๋„
223
  )
224
  )
225
 
@@ -274,21 +263,16 @@ def process_images_with_prompt(image1, prompt, variation_index=0, max_retries=3)
274
  # ------------------- ํ”„๋กฌํ”„ํŠธ ๊ด€๋ จ ํ•จ์ˆ˜ -------------------
275
  def filter_prompt_only(prompt):
276
  """Gemini์˜ ์„ค๋ช… ๋ฐ ๋ถˆํ•„์š”ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์‹ค์ œ ํ”„๋กฌํ”„ํŠธ๋งŒ ์ถ”์ถœํ•˜๋Š” ํ•จ์ˆ˜"""
277
-
278
- # ์ฝ”๋“œ ๋ธ”๋ก ๋‚ด๋ถ€์˜ ํ”„๋กฌํ”„ํŠธ ์ฐพ๊ธฐ
279
  code_block_pattern = r"```\s*(.*?)```"
280
  code_match = re.search(code_block_pattern, prompt, re.DOTALL)
281
  if code_match:
282
  return code_match.group(1).strip()
283
 
284
- # Midjourney ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ํ”„๋กฌํ”„ํŠธ ๋ถ€๋ถ„ ์ฐพ๊ธฐ
285
  if "--ar 1:1" in prompt:
286
  lines = prompt.split('\n')
287
  prompt_lines = []
288
  in_prompt = False
289
-
290
  for line in lines:
291
- # ํ”„๋กฌํ”„ํŠธ ์‹œ์ž‘ ๋ถ€๋ถ„ ์ธ์‹ (์ผ๋ฐ˜์ ์ธ ์ œํ’ˆ ์„ค๋ช…์ด๋‚˜ 'Magazine-worthy' ๊ฐ™์€ ํ‚ค์›Œ๋“œ๋กœ ์‹œ์ž‘)
292
  if (not in_prompt and
293
  ("product" in line.lower() or
294
  "magazine" in line.lower() or
@@ -296,18 +280,13 @@ def filter_prompt_only(prompt):
296
  "photography" in line.lower())):
297
  in_prompt = True
298
  prompt_lines.append(line)
299
- # ์ด๋ฏธ ํ”„๋กฌํ”„ํŠธ ์˜์—ญ์— ์žˆ๋Š” ๊ฒฝ์šฐ ๊ณ„์† ์ถ”๊ฐ€
300
  elif in_prompt:
301
- # ์„ค๋ช…์ด๋‚˜ ๋ฉ”ํƒ€ ํ…์ŠคํŠธ๊ฐ€ ์‹œ์ž‘๋˜๋ฉด ์ค‘๋‹จ
302
  if "explanation" in line.lower() or "let me know" in line.lower():
303
  break
304
  prompt_lines.append(line)
305
-
306
- # ํ”„๋กฌํ”„ํŠธ ๋ผ์ธ ํ•ฉ์น˜๊ธฐ
307
  if prompt_lines:
308
  return '\n'.join(prompt_lines).strip()
309
 
310
- # ์œ„ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฐพ์ง€ ๋ชปํ•œ ๊ฒฝ์šฐ ์›๋ณธ ๋ฐ˜ํ™˜
311
  return prompt.strip()
312
 
313
  def get_selected_background_info(bg_type, simple, studio, nature, indoor, tech, colorful, abstract, jewelry):
@@ -354,14 +333,12 @@ def get_selected_background_info(bg_type, simple, studio, nature, indoor, tech,
354
  "name": abstract,
355
  "english": ABSTRACT_BACKGROUNDS.get(abstract, "abstract background")
356
  }
357
-
358
  elif bg_type == "์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ":
359
  return {
360
  "category": "์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ",
361
  "name": jewelry,
362
  "english": JEWELRY_BACKGROUNDS.get(jewelry, "jewelry backdrop")
363
  }
364
-
365
  else:
366
  return {
367
  "category": "๊ธฐ๋ณธ ๋ฐฐ๊ฒฝ",
@@ -369,14 +346,11 @@ def get_selected_background_info(bg_type, simple, studio, nature, indoor, tech,
369
  "english": "white background"
370
  }
371
 
372
- # ------------------- ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ํ•จ์ˆ˜ -------------------
373
  def generate_enhanced_system_instruction():
374
  """ํ–ฅ์ƒ๋œ ์‹œ์Šคํ…œ ์ธ์ŠคํŠธ๋Ÿญ์…˜ ์ƒ์„ฑ ํ•จ์ˆ˜"""
375
  return """๋‹น์‹ ์€ ์ƒํ’ˆ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ์ตœ๊ณ  ํ’ˆ์งˆ์˜ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
376
  ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ƒํ’ˆ๋ช…, ๋ฐฐ๊ฒฝ ์œ ํ˜•, ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฏธ๋“œ์ €๋‹ˆ(Midjourney)์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์˜์–ด๋กœ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
377
-
378
  ๋‹ค์Œ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋ฐ˜๋“œ์‹œ ์ค€์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
379
-
380
  1. ์ƒํ’ˆ์„ "#1"๋กœ ์ง€์ •ํ•˜์—ฌ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: "skincare tube (#1)")
381
  2. *** ๋งค์šฐ ์ค‘์š”: ์ƒํ’ˆ์˜ ์›๋ž˜ ํŠน์„ฑ(๋””์ž์ธ, ์ƒ‰์ƒ, ํ˜•ํƒœ, ๋กœ๊ณ , ํŒจํ‚ค์ง€ ๋“ฑ)์€ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ ์ ˆ๋Œ€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ***
382
  3. *** ์ƒํ’ˆ์˜ ๋ณธ์งˆ์  ํŠน์„ฑ์„ ์œ ์ง€ํ•˜๋˜, ์ƒํ’ˆ์— ํฌ์ปค์Šค๋ฅผ ๋งž์ถฐ ๋ชจ๋“  ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ์„ ๋ช…ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚˜๋„๋ก ํ•˜๋ฉฐ,
@@ -396,8 +370,8 @@ def generate_enhanced_system_instruction():
396
  - "ultra high definition"
397
  - "crystal clear details"
398
  10. ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฐ๊ฒฝ๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ํ”„๋กฌํ”„ํŠธ์— ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•˜๊ณ  ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.
399
- 11. ํ”„๋กฌํ”„ํŠธ ๋์— "--ar 1:1 --s 750 --q 2 --v 5.2" ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฏธ๋“œ์ €๋‹ˆ์—์„œ ๊ณ ํ’ˆ์งˆ ์ •์‚ฌ๊ฐํ˜• ๋น„์œจ์„ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
400
- 12. ๋งค์šฐ ์ค‘์š”: ํ”„๋กฌํ”„ํŠธ ์™ธ์— ๋‹ค๋ฅธ ์„ค๋ช…์ด๋‚˜ ๋ฉ”ํƒ€ ํ…์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด "Here's a prompt for you" ๋˜๋Š” "Let me know if you need adjustments" ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋‚˜ ์„ค๋ช…์„ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”. ์˜ค์ง ํ”„๋กฌํ”„ํŠธ ์ž์ฒด๋งŒ ์ œ๊ณตํ•˜์„ธ์š”.
401
  """
402
 
403
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
@@ -409,14 +383,12 @@ def generate_prompt_with_gemini(product_name, background_info, additional_info="
409
  try:
410
  genai_generative.configure(api_key=GEMINI_API_KEY)
411
 
412
- # ๋” ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ ์š”์ฒญ ํ…œํ”Œ๋ฆฟ
413
  prompt_request = f"""
414
  ์ƒํ’ˆ๋ช…: {product_name}
415
  ๋ฐฐ๊ฒฝ ์œ ํ˜•: {background_info.get('english', 'studio')}
416
  ๋ฐฐ๊ฒฝ ์นดํ…Œ๊ณ ๋ฆฌ: {background_info.get('category', '')}
417
  ๋ฐฐ๊ฒฝ ์ด๋ฆ„: {background_info.get('name', '')}
418
  ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ: {additional_info}
419
-
420
  ์ค‘์š” ์š”๊ตฌ์‚ฌํ•ญ:
421
  1. ์ƒํ’ˆ(#1)์ด ์ด๋ฏธ์ง€ ๊ตฌ๋„์—์„œ ์ค‘์‹ฌ์ ์ธ ์œ„์น˜๋ฅผ ์ฐจ์ง€ํ•˜๋ฉฐ ์ ์ ˆํ•œ ํฌ๊ธฐ(์ด๋ฏธ์ง€์˜ 60-70%)๋กœ ํ‘œํ˜„๋˜๋„๋ก ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
422
  2. ์ด๋ฏธ์ง€๋Š” ์ •ํ™•ํžˆ 1:1 ๋น„์œจ(์ •์‚ฌ๊ฐํ˜•)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
@@ -431,29 +403,25 @@ def generate_prompt_with_gemini(product_name, background_info, additional_info="
431
  7. ์ƒ‰์ƒ ๊ตฌ์„ฑ(color palette, color harmonies)์„ ๋ช…ํ™•ํžˆ ํ•ด์ฃผ์„ธ์š”.
432
  8. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—… ๊ด‘๊ณ  ํ’ˆ์งˆ์˜ ์ด๋ฏธ์ง€๊ฐ€ ๋˜๋„๋ก ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.
433
  9. ํ”„๋กฌํ”„ํŠธ ๋์— ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ "--ar 1:1 --s 750 --q 2 --v 5.2"๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
434
-
435
  ํ•œ๊ตญ์–ด ์ž…๋ ฅ ๋‚ด์šฉ์„ ์ „๋ฌธ์ ์ธ ์˜์–ด๋กœ ๋ฒˆ์—ญํ•˜์—ฌ ๋ฐ˜์˜ํ•ด์ฃผ์„ธ์š”.
436
  """
437
- # ํ–ฅ์ƒ๋œ ์‹œ์Šคํ…œ ์ธ์ŠคํŠธ๋Ÿญ์…˜ ์‚ฌ์šฉ
438
  model = genai_generative.GenerativeModel(
439
  'gemini-2.0-flash',
440
  system_instruction=generate_enhanced_system_instruction()
441
  )
442
 
443
- # ๋” ์ฐฝ์˜์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์œ„ํ•œ ์ƒ์„ฑ ์„ค์ • ์กฐ์ •
444
  response = model.generate_content(
445
  prompt_request,
446
  generation_config=genai_generative.types.GenerationConfig(
447
- temperature=0.8, # ๋” ์ฐฝ์˜์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์œ„ํ•ด ์˜จ๋„ ์ƒํ–ฅ
448
  top_p=0.97,
449
  top_k=64,
450
- max_output_tokens=1600, # ๋” ์ƒ์„ธํ•œ ํ”„๋กฌํ”„ํŠธ ํ—ˆ์šฉ
451
  )
452
  )
453
 
454
  response_text = response.text.strip()
455
 
456
- # ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ์ถ”๊ฐ€
457
  if "--ar 1:1" not in response_text:
458
  response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2 --v 5.2"
459
 
@@ -504,51 +472,34 @@ def generate_product_images(image, bg_type, simple, studio, nature, indoor, tech
504
  result_img, status, _ = process_images_with_prompt(image, final_prompt, variation_index=i)
505
  images_list.append(result_img)
506
  statuses.append(f"์ด๋ฏธ์ง€ #{i+1}: {status}")
507
- time.sleep(1) # ์ˆœ์ฐจ์  ์‹คํ–‰์„ ์œ„ํ•œ ๋”œ๋ ˆ์ด
508
  combined_status = "\n".join(statuses)
509
  return images_list[0], images_list[1], images_list[2], images_list[3], combined_status, final_prompt
510
 
511
  # ------------------- Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ -------------------
512
  def create_app():
513
- # ๋“œ๋กญ๋‹ค์šด ์˜ต์…˜ ์ดˆ๊ธฐํ™”
514
  dropdown_options = initialize_dropdowns()
515
 
516
  with gr.Blocks(title="๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ") as demo:
517
  gr.Markdown("# ๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ")
518
  gr.Markdown(
519
- "์ƒํ’ˆ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ , ์ œํ’ˆ๋ช…, ๋ฐฐ๊ฒฝ ์˜ต์…˜, ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ž…๋ ฅํ•˜๋ฉด Gemini API๋ฅผ ํ†ตํ•ด ์˜์–ด ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•ด๋‹น ํ”„๋กฌํ”„ํŠธ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.\n\n"
520
  "๋‹จ์ผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ณผ 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ชจ๋‘ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."
521
  )
522
 
523
  with gr.Row():
524
- # API ํ‚ค ์ž…๋ ฅ ํ•„๋“œ ์ถ”๊ฐ€
525
  gemini_api_key = gr.Textbox(
526
  label="Gemini API ํ‚ค",
527
  type="password",
528
  placeholder="API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”",
529
  interactive=True
530
  )
531
-
532
- # API ํ‚ค ์„ค์ • ๋ฒ„ํŠผ ์ถ”๊ฐ€
533
- api_key_btn = gr.Button("API ํ‚ค ์„ค์ •")
534
- api_key_status = gr.Textbox(label="API ํ‚ค ์ƒํƒœ", interactive=False)
535
-
536
- def set_api_key(api_key):
537
- os.environ["GEMINI_API_KEY"] = api_key
538
- return "API ํ‚ค๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
539
-
540
- api_key_btn.click(
541
- fn=set_api_key,
542
- inputs=[gemini_api_key],
543
- outputs=[api_key_status]
544
- )
545
-
546
  with gr.Row():
547
  with gr.Column(scale=1):
548
  product_name = gr.Textbox(label="์ƒํ’ˆ๋ช… (ํ•œ๊ตญ์–ด ์ž…๋ ฅ)", placeholder="์˜ˆ: ์Šคํ‚จ์ผ€์–ด ํŠœ๋ธŒ, ์Šค๋งˆํŠธ์›Œ์น˜, ํ–ฅ์ˆ˜, ์šด๋™ํ™” ๋“ฑ", interactive=True)
549
- # ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ๋ฅผ ์ƒํ’ˆ๋ช… ์•„๋ž˜๋กœ ์ด๋™
550
  image_input = gr.Image(label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="pil")
551
-
552
  background_type = gr.Radio(
553
  choices=["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "ํ…Œํฌ๋†€๋กœ์ง€ ๋ฐฐ๊ฒฝ", "์ปฌ๋Ÿฌํ’€ ํŒจํ„ด ๋ฐฐ๊ฒฝ", "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ", "์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ"],
554
  label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
@@ -603,7 +554,6 @@ def create_app():
603
  visible=False,
604
  interactive=True
605
  )
606
-
607
  jewelry_dropdown = gr.Dropdown(
608
  choices=dropdown_options["jewelry"],
609
  value=dropdown_options["jewelry"][0] if dropdown_options["jewelry"] else None,
@@ -611,13 +561,13 @@ def create_app():
611
  visible=False,
612
  interactive=True
613
  )
614
-
615
  additional_info = gr.Textbox(
616
  label="์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ (์„ ํƒ์‚ฌํ•ญ)",
617
  placeholder="์˜ˆ: ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋А๋‚Œ, ๋ฐ์€ ์กฐ๋ช…, ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณด์กฐ ๊ฐ์ฒด ๋“ฑ",
618
  lines=3,
619
  interactive=True
620
  )
 
621
  def update_dropdowns(bg_type):
622
  return {
623
  simple_dropdown: gr.update(visible=(bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ")),
@@ -640,47 +590,45 @@ def create_app():
640
  multi_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ ๋ฐ 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
641
 
642
  with gr.Column(scale=1):
643
- # ๊ณตํ†ต ํ”„๋กฌํ”„ํŠธ ์ถœ๋ ฅ ์˜์—ญ
644
- prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ (์˜์–ด)", lines=6)
645
-
646
- # ์ด๋ฏธ์ง€ ๋ ˆ์ด์•„์›ƒ ๋ณ€๊ฒฝ: 2x2 ๊ทธ๋ฆฌ๋“œ๋กœ ๋ฐฐ์น˜
647
  with gr.Row():
648
  image_output1 = gr.Image(label="์ด๋ฏธ์ง€ #1", type="filepath")
649
  image_output2 = gr.Image(label="์ด๋ฏธ์ง€ #2", type="filepath")
650
-
651
  with gr.Row():
652
  image_output3 = gr.Image(label="์ด๋ฏธ์ง€ #3", type="filepath")
653
  image_output4 = gr.Image(label="์ด๋ฏธ์ง€ #4", type="filepath")
654
-
655
  status_output = gr.Textbox(label="๊ฒฐ๊ณผ ์ •๋ณด", lines=3)
656
 
657
- # ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ•จ์ˆ˜ ์ˆ˜์ •
658
- def modified_single_image_gen(*args):
659
- # ๊ธฐ์กด ํ•จ์ˆ˜ ํ˜ธ์ถœ
660
- result_img, status, prompt = generate_product_image(*args)
661
- # ๋‹จ์ผ ์ด๋ฏธ์ง€๋ฅผ ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€ ์Šฌ๋กฏ์— ๋ฐฐ์น˜ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” None์œผ๋กœ ์„ค์ •
662
- return prompt, result_img, None, None, None, status
663
 
664
  single_btn.click(
665
  fn=modified_single_image_gen,
666
- inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown, jewelry_dropdown, product_name, additional_info],
667
- outputs=[prompt_output, image_output1, image_output2, image_output3, image_output4, status_output]
668
  )
669
 
 
 
 
 
 
 
670
  multi_btn.click(
671
- fn=generate_product_images,
672
- inputs=[image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown, jewelry_dropdown, product_name, additional_info],
673
- outputs=[image_output1, image_output2, image_output3, image_output4, status_output, prompt_output]
674
  )
675
 
676
  return demo
677
 
678
  # ------------------- ๋ฉ”์ธ ์‹คํ–‰ ํ•จ์ˆ˜ -------------------
679
  if __name__ == "__main__":
680
- # ๋ฐฐ๊ฒฝ ์˜ต์…˜ ์ดˆ๊ธฐํ™” - JSON ํŒŒ์ผ์—์„œ ๋กœ๋“œ
681
  initialize_backgrounds()
682
-
683
- # ์•ฑ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰
684
  app = create_app()
685
  app.queue()
686
- app.launch()
 
33
  ABSTRACT_BACKGROUNDS = {}
34
  JEWELRY_BACKGROUNDS = {} # ์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ ์ „์—ญ ๋ณ€์ˆ˜ ์ถ”๊ฐ€
35
 
 
36
  # ------------------- ๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๋กœ๋“œ ํ•จ์ˆ˜ -------------------
37
  def load_background_json(filename):
38
  """๋ฐฐ๊ฒฝ JSON ํŒŒ์ผ ๋กœ๋“œ ํ•จ์ˆ˜"""
 
55
  global SIMPLE_BACKGROUNDS, STUDIO_BACKGROUNDS, NATURE_BACKGROUNDS, INDOOR_BACKGROUNDS
56
  global TECHNOLOGY_BACKGROUNDS, COLORFUL_PATTERN_BACKGROUNDS, ABSTRACT_BACKGROUNDS
57
  global JEWELRY_BACKGROUNDS # ์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ ์ถ”๊ฐ€
 
58
 
 
59
  logger.info(f"Backgrounds ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ: {BACKGROUNDS_DIR}")
60
  logger.info(f"๋””๋ ‰ํ† ๋ฆฌ ๋‚ด ํŒŒ์ผ ๋ชฉ๋ก: {os.listdir(BACKGROUNDS_DIR)}")
61
 
 
62
  SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
63
  STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
64
  NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
65
  INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
66
+ TECHNOLOGY_BACKGROUNDS = load_background_json("tech-backgrounds-final.json")
67
+ COLORFUL_PATTERN_BACKGROUNDS = load_background_json("colorful-pattern-backgrounds.json")
68
  ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
69
  JEWELRY_BACKGROUNDS = load_background_json("jewelry_backgrounds.json")
 
70
 
71
  # ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • (ํŒŒ์ผ์ด ์—†๊ฑฐ๋‚˜ ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ)
72
  if not SIMPLE_BACKGROUNDS:
 
88
 
89
  logger.info("๋ชจ๋“  ๋ฐฐ๊ฒฝ ์˜ต์…˜ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ")
90
 
91
+ # ๋ฐฐ๊ฒฝ ๋“œ๋กญ๋‹ค์šด ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜
92
  def initialize_dropdowns():
93
  """๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜"""
 
94
  simple_choices = list(SIMPLE_BACKGROUNDS.keys())
95
  studio_choices = list(STUDIO_BACKGROUNDS.keys())
96
  nature_choices = list(NATURE_BACKGROUNDS.keys())
 
99
  colorful_choices = list(COLORFUL_PATTERN_BACKGROUNDS.keys())
100
  abstract_choices = list(ABSTRACT_BACKGROUNDS.keys())
101
  jewelry_choices = list(JEWELRY_BACKGROUNDS.keys())
 
 
102
 
103
  return {
104
  "simple": simple_choices,
 
108
  "tech": tech_choices,
109
  "colorful": colorful_choices,
110
  "abstract": abstract_choices,
111
+ "jewelry": jewelry_choices,
112
  }
113
 
 
114
  # ------------------- ๊ธฐ๋ณธ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ -------------------
115
  def save_binary_file(file_name, data):
116
  with open(file_name, "wb") as f:
 
182
  client = genai.Client(api_key=api_key)
183
  logger.info(f"Gemini API ์š”์ฒญ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: {prompt}, ๋ณ€ํ˜• ์ธ๋ฑ์Šค: {variation_index}")
184
 
 
185
  variation_suffixes = [
186
  " Create this as a professional studio product shot with precise focus on the product details. Do not add any text, watermarks, or labels to the image.",
187
  " Create this as a high-contrast artistic studio shot with dramatic lighting and shadows. Do not add any text, watermarks, or labels to the image.",
 
200
  contents.append(img)
201
  logger.info(f"์ด๋ฏธ์ง€ #{idx} ์ถ”๊ฐ€๋จ")
202
 
 
203
  response = client.models.generate_content(
204
  model="gemini-2.0-flash-exp-image-generation",
205
  contents=contents,
206
  config=types.GenerateContentConfig(
207
  response_modalities=['Text', 'Image'],
208
+ temperature=1.05,
209
+ top_p=0.97,
210
+ top_k=50,
211
+ max_output_tokens=10240
212
  )
213
  )
214
 
 
263
  # ------------------- ํ”„๋กฌํ”„ํŠธ ๊ด€๋ จ ํ•จ์ˆ˜ -------------------
264
  def filter_prompt_only(prompt):
265
  """Gemini์˜ ์„ค๋ช… ๋ฐ ๋ถˆํ•„์š”ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ์‹ค์ œ ํ”„๋กฌํ”„ํŠธ๋งŒ ์ถ”์ถœํ•˜๋Š” ํ•จ์ˆ˜"""
 
 
266
  code_block_pattern = r"```\s*(.*?)```"
267
  code_match = re.search(code_block_pattern, prompt, re.DOTALL)
268
  if code_match:
269
  return code_match.group(1).strip()
270
 
 
271
  if "--ar 1:1" in prompt:
272
  lines = prompt.split('\n')
273
  prompt_lines = []
274
  in_prompt = False
 
275
  for line in lines:
 
276
  if (not in_prompt and
277
  ("product" in line.lower() or
278
  "magazine" in line.lower() or
 
280
  "photography" in line.lower())):
281
  in_prompt = True
282
  prompt_lines.append(line)
 
283
  elif in_prompt:
 
284
  if "explanation" in line.lower() or "let me know" in line.lower():
285
  break
286
  prompt_lines.append(line)
 
 
287
  if prompt_lines:
288
  return '\n'.join(prompt_lines).strip()
289
 
 
290
  return prompt.strip()
291
 
292
  def get_selected_background_info(bg_type, simple, studio, nature, indoor, tech, colorful, abstract, jewelry):
 
333
  "name": abstract,
334
  "english": ABSTRACT_BACKGROUNDS.get(abstract, "abstract background")
335
  }
 
336
  elif bg_type == "์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ":
337
  return {
338
  "category": "์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ",
339
  "name": jewelry,
340
  "english": JEWELRY_BACKGROUNDS.get(jewelry, "jewelry backdrop")
341
  }
 
342
  else:
343
  return {
344
  "category": "๊ธฐ๋ณธ ๋ฐฐ๊ฒฝ",
 
346
  "english": "white background"
347
  }
348
 
 
349
  def generate_enhanced_system_instruction():
350
  """ํ–ฅ์ƒ๋œ ์‹œ์Šคํ…œ ์ธ์ŠคํŠธ๋Ÿญ์…˜ ์ƒ์„ฑ ํ•จ์ˆ˜"""
351
  return """๋‹น์‹ ์€ ์ƒํ’ˆ ์ด๋ฏธ์ง€์˜ ๋ฐฐ๊ฒฝ์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ์ตœ๊ณ  ํ’ˆ์งˆ์˜ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
352
  ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ƒํ’ˆ๋ช…, ๋ฐฐ๊ฒฝ ์œ ํ˜•, ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฏธ๋“œ์ €๋‹ˆ(Midjourney)์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์˜์–ด๋กœ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
 
353
  ๋‹ค์Œ ๊ฐ€์ด๋“œ๋ผ์ธ์„ ๋ฐ˜๋“œ์‹œ ์ค€์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
 
354
  1. ์ƒํ’ˆ์„ "#1"๋กœ ์ง€์ •ํ•˜์—ฌ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: "skincare tube (#1)")
355
  2. *** ๋งค์šฐ ์ค‘์š”: ์ƒํ’ˆ์˜ ์›๋ž˜ ํŠน์„ฑ(๋””์ž์ธ, ์ƒ‰์ƒ, ํ˜•ํƒœ, ๋กœ๊ณ , ํŒจํ‚ค์ง€ ๋“ฑ)์€ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ ์ ˆ๋Œ€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ***
356
  3. *** ์ƒํ’ˆ์˜ ๋ณธ์งˆ์  ํŠน์„ฑ์„ ์œ ์ง€ํ•˜๋˜, ์ƒํ’ˆ์— ํฌ์ปค์Šค๋ฅผ ๋งž์ถฐ ๋ชจ๋“  ์„ธ๋ถ€ ์‚ฌํ•ญ์ด ์„ ๋ช…ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚˜๋„๋ก ํ•˜๋ฉฐ,
 
370
  - "ultra high definition"
371
  - "crystal clear details"
372
  10. ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฐ๊ฒฝ๊ณผ ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ํ”„๋กฌํ”„ํŠธ์— ์ •ํ™•ํžˆ ๋ฐ˜์˜ํ•˜๊ณ  ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.
373
+ 11. ํ”„๋กฌํ”„ํŠธ ๋์— ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ "--ar 1:1 --s 750 --q 2 --v 5.2" ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฏธ๋“œ์ €๋‹ˆ์—์„œ ๊ณ ํ’ˆ์งˆ ์ •์‚ฌ๊ฐํ˜• ๋น„์œจ์„ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
374
+ 12. ๋งค์šฐ ์ค‘์š”: ํ”„๋กฌํ”„ํŠธ ์™ธ์— ๋‹ค๋ฅธ ์„ค๋ช…์ด๋‚˜ ๋ฉ”ํƒ€ ํ…์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜์ง€ ๋งˆ์„ธ์š”. ์˜ค์ง ํ”„๋กฌํ”„ํŠธ ์ž์ฒด๋งŒ ์ œ๊ณตํ•˜์„ธ์š”.
375
  """
376
 
377
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
 
383
  try:
384
  genai_generative.configure(api_key=GEMINI_API_KEY)
385
 
 
386
  prompt_request = f"""
387
  ์ƒํ’ˆ๋ช…: {product_name}
388
  ๋ฐฐ๊ฒฝ ์œ ํ˜•: {background_info.get('english', 'studio')}
389
  ๋ฐฐ๊ฒฝ ์นดํ…Œ๊ณ ๋ฆฌ: {background_info.get('category', '')}
390
  ๋ฐฐ๊ฒฝ ์ด๋ฆ„: {background_info.get('name', '')}
391
  ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ: {additional_info}
 
392
  ์ค‘์š” ์š”๊ตฌ์‚ฌํ•ญ:
393
  1. ์ƒํ’ˆ(#1)์ด ์ด๋ฏธ์ง€ ๊ตฌ๋„์—์„œ ์ค‘์‹ฌ์ ์ธ ์œ„์น˜๋ฅผ ์ฐจ์ง€ํ•˜๋ฉฐ ์ ์ ˆํ•œ ํฌ๊ธฐ(์ด๋ฏธ์ง€์˜ 60-70%)๋กœ ํ‘œํ˜„๋˜๋„๋ก ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.
394
  2. ์ด๋ฏธ์ง€๋Š” ์ •ํ™•ํžˆ 1:1 ๋น„์œจ(์ •์‚ฌ๊ฐํ˜•)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
 
403
  7. ์ƒ‰์ƒ ๊ตฌ์„ฑ(color palette, color harmonies)์„ ๋ช…ํ™•ํžˆ ํ•ด์ฃผ์„ธ์š”.
404
  8. ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ์ƒ์—… ๊ด‘๊ณ  ํ’ˆ์งˆ์˜ ์ด๋ฏธ์ง€๊ฐ€ ๋˜๋„๋ก ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.
405
  9. ํ”„๋กฌํ”„ํŠธ ๋์— ๋ฏธ๋“œ์ €๋‹ˆ ํŒŒ๋ผ๋ฏธํ„ฐ "--ar 1:1 --s 750 --q 2 --v 5.2"๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.
 
406
  ํ•œ๊ตญ์–ด ์ž…๋ ฅ ๋‚ด์šฉ์„ ์ „๋ฌธ์ ์ธ ์˜์–ด๋กœ ๋ฒˆ์—ญํ•˜์—ฌ ๋ฐ˜์˜ํ•ด์ฃผ์„ธ์š”.
407
  """
 
408
  model = genai_generative.GenerativeModel(
409
  'gemini-2.0-flash',
410
  system_instruction=generate_enhanced_system_instruction()
411
  )
412
 
 
413
  response = model.generate_content(
414
  prompt_request,
415
  generation_config=genai_generative.types.GenerationConfig(
416
+ temperature=0.8,
417
  top_p=0.97,
418
  top_k=64,
419
+ max_output_tokens=1600,
420
  )
421
  )
422
 
423
  response_text = response.text.strip()
424
 
 
425
  if "--ar 1:1" not in response_text:
426
  response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2 --v 5.2"
427
 
 
472
  result_img, status, _ = process_images_with_prompt(image, final_prompt, variation_index=i)
473
  images_list.append(result_img)
474
  statuses.append(f"์ด๋ฏธ์ง€ #{i+1}: {status}")
475
+ time.sleep(1)
476
  combined_status = "\n".join(statuses)
477
  return images_list[0], images_list[1], images_list[2], images_list[3], combined_status, final_prompt
478
 
479
  # ------------------- Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ -------------------
480
  def create_app():
 
481
  dropdown_options = initialize_dropdowns()
482
 
483
  with gr.Blocks(title="๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ") as demo:
484
  gr.Markdown("# ๊ณ ๊ธ‰ ์ƒํ’ˆ ์ด๋ฏธ์ง€ ๋ฐฐ๊ฒฝ ํ”„๋กฌํ”„ํŠธ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ")
485
  gr.Markdown(
486
+ "์ƒํ’ˆ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ , ์ƒํ’ˆ๋ช…, ๋ฐฐ๊ฒฝ ์˜ต์…˜, ์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ ๋ฐ Gemini API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด Gemini API๋ฅผ ํ†ตํ•ด ์˜์–ด ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•ด๋‹น ํ”„๋กฌํ”„ํŠธ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.\n\n"
487
  "๋‹จ์ผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ๊ณผ 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ชจ๋‘ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."
488
  )
489
 
490
  with gr.Row():
491
+ # API ํ‚ค ์ž…๋ ฅ ํ•„๋“œ๋งŒ ํ‘œ์‹œ (API ํ‚ค ์ƒํƒœ, ์„ค์ • ๋ฒ„ํŠผ ์ œ๊ฑฐ)
492
  gemini_api_key = gr.Textbox(
493
  label="Gemini API ํ‚ค",
494
  type="password",
495
  placeholder="API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”",
496
  interactive=True
497
  )
498
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  with gr.Row():
500
  with gr.Column(scale=1):
501
  product_name = gr.Textbox(label="์ƒํ’ˆ๋ช… (ํ•œ๊ตญ์–ด ์ž…๋ ฅ)", placeholder="์˜ˆ: ์Šคํ‚จ์ผ€์–ด ํŠœ๋ธŒ, ์Šค๋งˆํŠธ์›Œ์น˜, ํ–ฅ์ˆ˜, ์šด๋™ํ™” ๋“ฑ", interactive=True)
 
502
  image_input = gr.Image(label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="pil")
 
503
  background_type = gr.Radio(
504
  choices=["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "ํ…Œํฌ๋†€๋กœ์ง€ ๋ฐฐ๊ฒฝ", "์ปฌ๋Ÿฌํ’€ ํŒจํ„ด ๋ฐฐ๊ฒฝ", "์ถ”์ƒ/ํŠน์ˆ˜ ๋ฐฐ๊ฒฝ", "์ฅฌ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ"],
505
  label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
 
554
  visible=False,
555
  interactive=True
556
  )
 
557
  jewelry_dropdown = gr.Dropdown(
558
  choices=dropdown_options["jewelry"],
559
  value=dropdown_options["jewelry"][0] if dropdown_options["jewelry"] else None,
 
561
  visible=False,
562
  interactive=True
563
  )
 
564
  additional_info = gr.Textbox(
565
  label="์ถ”๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ (์„ ํƒ์‚ฌํ•ญ)",
566
  placeholder="์˜ˆ: ๊ณ ๊ธ‰์Šค๋Ÿฌ์šด ๋А๋‚Œ, ๋ฐ์€ ์กฐ๋ช…, ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณด์กฐ ๊ฐ์ฒด ๋“ฑ",
567
  lines=3,
568
  interactive=True
569
  )
570
+
571
  def update_dropdowns(bg_type):
572
  return {
573
  simple_dropdown: gr.update(visible=(bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ")),
 
590
  multi_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ ๋ฐ 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ", variant="primary")
591
 
592
  with gr.Column(scale=1):
593
+ # ํ”„๋กฌํ”„ํŠธ ์ถœ๋ ฅ UI ์ œ๊ฑฐ, ์ด๋ฏธ์ง€ 4์žฅ๋งŒ ์ถœ๋ ฅ
 
 
 
594
  with gr.Row():
595
  image_output1 = gr.Image(label="์ด๋ฏธ์ง€ #1", type="filepath")
596
  image_output2 = gr.Image(label="์ด๋ฏธ์ง€ #2", type="filepath")
 
597
  with gr.Row():
598
  image_output3 = gr.Image(label="์ด๋ฏธ์ง€ #3", type="filepath")
599
  image_output4 = gr.Image(label="์ด๋ฏธ์ง€ #4", type="filepath")
 
600
  status_output = gr.Textbox(label="๊ฒฐ๊ณผ ์ •๋ณด", lines=3)
601
 
602
+ # ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ƒ์„ฑ์„ ์œ„ํ•œ ํ•จ์ˆ˜ (API ํ‚ค ์ž…๋ ฅ๊ฐ’ ํ™œ์šฉ)
603
+ def modified_single_image_gen(api_key, image, bg_type, simple, studio, nature, indoor, tech, colorful, abstract, jewelry, product_name, additional_info):
604
+ os.environ["GEMINI_API_KEY"] = api_key.strip()
605
+ result_img, status, _ = generate_product_image(image, bg_type, simple, studio, nature, indoor, tech, colorful, abstract, jewelry, product_name, additional_info)
606
+ # ๋‹จ์ผ ์ด๋ฏธ์ง€๋Š” ์ฒซ ๋ฒˆ์งธ ์Šฌ๋กฏ์— ๋ฐฐ์น˜, ๋‚˜๋จธ์ง€๋Š” None ๋ฐ˜ํ™˜
607
+ return result_img, None, None, None, status
608
 
609
  single_btn.click(
610
  fn=modified_single_image_gen,
611
+ inputs=[gemini_api_key, image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown, jewelry_dropdown, product_name, additional_info],
612
+ outputs=[image_output1, image_output2, image_output3, image_output4, status_output]
613
  )
614
 
615
+ # 4์žฅ ์ด๋ฏธ์ง€ ์ƒ์„ฑ์„ ์œ„ํ•œ ํ•จ์ˆ˜ (API ํ‚ค ์ž…๋ ฅ๊ฐ’ ํ™œ์šฉ)
616
+ def modified_multi_image_gen(api_key, image, bg_type, simple, studio, nature, indoor, tech, colorful, abstract, jewelry, product_name, additional_info):
617
+ os.environ["GEMINI_API_KEY"] = api_key.strip()
618
+ img1, img2, img3, img4, status, _ = generate_product_images(image, bg_type, simple, studio, nature, indoor, tech, colorful, abstract, jewelry, product_name, additional_info)
619
+ return img1, img2, img3, img4, status
620
+
621
  multi_btn.click(
622
+ fn=modified_multi_image_gen,
623
+ inputs=[gemini_api_key, image_input, background_type, simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, tech_dropdown, colorful_dropdown, abstract_dropdown, jewelry_dropdown, product_name, additional_info],
624
+ outputs=[image_output1, image_output2, image_output3, image_output4, status_output]
625
  )
626
 
627
  return demo
628
 
629
  # ------------------- ๋ฉ”์ธ ์‹คํ–‰ ํ•จ์ˆ˜ -------------------
630
  if __name__ == "__main__":
 
631
  initialize_backgrounds()
 
 
632
  app = create_app()
633
  app.queue()
634
+ app.launch()