Kims12 commited on
Commit
7bb926b
Β·
verified Β·
1 Parent(s): fd41e09

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -103
app.py CHANGED
@@ -6,9 +6,7 @@ import logging
6
  import re
7
  import time
8
  import json
9
-
10
- from google import genai
11
- from google.genai import types
12
  from dotenv import load_dotenv
13
 
14
  load_dotenv()
@@ -19,7 +17,6 @@ logger = logging.getLogger(__name__)
19
 
20
  # Gemini API ν‚€ μ„€μ •
21
  GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
22
- genai.configure(api_key=GEMINI_API_KEY)
23
 
24
  # λ°°κ²½ JSON 파일 경둜 μ„€μ •
25
  BACKGROUNDS_DIR = "./background"
@@ -29,87 +26,37 @@ if not os.path.exists(BACKGROUNDS_DIR):
29
  os.makedirs(BACKGROUNDS_DIR)
30
  logger.info(f"λ°°κ²½ 디렉토리λ₯Ό μƒμ„±ν–ˆμŠ΅λ‹ˆλ‹€: {BACKGROUNDS_DIR}")
31
 
32
- # JSON 파일 λ‘œλ“œ ν•¨μˆ˜
33
- def load_background_json(filename):
34
- file_path = os.path.join(BACKGROUNDS_DIR, filename)
35
- try:
36
- with open(file_path, 'r', encoding='utf-8') as f:
37
- data = json.load(f)
38
- logger.info(f"{filename} νŒŒμΌμ„ μ„±κ³΅μ μœΌλ‘œ λ‘œλ“œν–ˆμŠ΅λ‹ˆλ‹€. {len(data)} ν•­λͺ© 포함.")
39
- return data
40
- except FileNotFoundError:
41
- logger.warning(f"κ²½κ³ : {filename} νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. 기본값을 μ‚¬μš©ν•©λ‹ˆλ‹€.")
42
- return {}
43
- except json.JSONDecodeError:
44
- logger.warning(f"κ²½κ³ : {filename} 파일의 JSON ν˜•μ‹μ΄ μ˜¬λ°”λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 기본값을 μ‚¬μš©ν•©λ‹ˆλ‹€.")
45
- return {}
46
- except Exception as e:
47
- logger.warning(f"κ²½κ³ : {filename} 파일 λ‘œλ“œ 쀑 였λ₯˜ λ°œμƒ: {str(e)}. 기본값을 μ‚¬μš©ν•©λ‹ˆλ‹€.")
48
- return {}
49
 
50
- # λ°°κ²½ 데이터 λ‘œλ“œ
51
- SIMPLE_BACKGROUNDS = load_background_json("simple_backgrounds.json")
52
- STUDIO_BACKGROUNDS = load_background_json("studio_backgrounds.json")
53
- NATURE_BACKGROUNDS = load_background_json("nature_backgrounds.json")
54
- INDOOR_BACKGROUNDS = load_background_json("indoor_backgrounds.json")
55
- ABSTRACT_BACKGROUNDS = load_background_json("abstract_backgrounds.json")
56
-
57
- # 배경이 λ‘œλ“œλ˜μ§€ μ•Šμ€ 경우 κΈ°λ³Έκ°’ μ„€μ •
58
- if not SIMPLE_BACKGROUNDS:
59
- SIMPLE_BACKGROUNDS = {"ν™”μ΄νŠΈ λ°°κ²½": "white background"}
60
- if not STUDIO_BACKGROUNDS:
61
- STUDIO_BACKGROUNDS = {"μ œν’ˆ 사진 μŠ€νŠœλ””μ˜€": "product photography studio"}
62
- if not NATURE_BACKGROUNDS:
63
- NATURE_BACKGROUNDS = {"μ—΄λŒ€ ν•΄λ³€": "tropical beach"}
64
- if not INDOOR_BACKGROUNDS:
65
- INDOOR_BACKGROUNDS = {"λͺ¨λ˜ 리빙룸": "modern living room"}
66
- if not ABSTRACT_BACKGROUNDS:
67
- ABSTRACT_BACKGROUNDS = {"λ„€μ˜¨ μ‘°λͺ…": "neon lights"}
68
 
69
  def generate_system_instruction():
70
  return """당신은 μƒν’ˆ μ΄λ―Έμ§€μ˜ 배경을 λ³€κ²½ν•˜κΈ° μœ„ν•œ κ³ ν’ˆμ§ˆ ν”„λ‘¬ν”„νŠΈλ₯Ό μƒμ„±ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€.
71
- μ‚¬μš©μžκ°€ μ œκ³΅ν•˜λŠ” μƒν’ˆλͺ…, λ°°κ²½ μœ ν˜•, μΆ”κ°€ μš”μ²­μ‚¬ν•­μ„ λ°”νƒ•μœΌλ‘œ λ―Έλ“œμ €λ‹ˆ(Midjourney)에 μ‚¬μš©ν•  수 μžˆλŠ”
72
- μƒμ„Έν•˜κ³  전문적인 ν”„λ‘¬ν”„νŠΈλ₯Ό μ˜μ–΄λ‘œ μƒμ„±ν•΄μ£Όμ„Έμš”.
73
  λ‹€μŒ κ°€μ΄λ“œλΌμΈμ„ λ°˜λ“œμ‹œ 따라야 ν•©λ‹ˆλ‹€:
74
  1. μƒν’ˆμ„ "#1"둜 μ§€μ •ν•˜μ—¬ μ°Έμ‘°ν•©λ‹ˆλ‹€. (예: "skincare tube (#1)")
75
  2. *** 맀우 μ€‘μš”: μƒν’ˆμ˜ μ›λž˜ νŠΉμ„±(λ””μžμΈ, 색상, ν˜•νƒœ, 둜고, νŒ¨ν‚€μ§€ λ“±)은 μ–΄λ–€ μƒν™©μ—μ„œλ„ μ ˆλŒ€ λ³€κ²½ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ***
76
- 3. *** μƒν’ˆμ˜ 본질적 νŠΉμ„±μ€ μœ μ§€ν•˜λ˜, μžμ—°μŠ€λŸ¬μš΄ ν™˜κ²½ 톡합을 μœ„ν•œ μ‘°λͺ…κ³Ό κ·Έλ¦ΌμžλŠ” ν—ˆμš©ν•©λ‹ˆλ‹€: ***
77
- - μƒν’ˆ 자체의 색상, λ””μžμΈ, ν˜•νƒœ, ν…μŠ€μ²˜λŠ” μ ˆλŒ€ μˆ˜μ •ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
78
- - ν™˜κ²½κ³Ό μžμ—°μŠ€λŸ½κ²Œ μ–΄μšΈλ¦¬λŠ” 그림자, μ£Όλ³€ μ‘°λͺ… νš¨κ³ΌλŠ” ν—ˆμš©λ©λ‹ˆλ‹€.
79
- - μƒν’ˆμ— 물방울, 응좕, 금, 은과 같은 μΆ”κ°€ μš”μ†Œλ‚˜ 물리적 νš¨κ³ΌλŠ” μ μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
80
- - ν™˜κ²½μ— μ–΄μšΈλ¦¬λŠ” μžμ—°μŠ€λŸ¬μš΄ λΉ› λ°˜μ‚¬, μ£Όλ³€ μ‘°λͺ…, κ·Έλ¦ΌμžλŠ” 사싀적 톡합감을 μœ„ν•΄ μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
81
- 4. 이미지 λΉ„μœ¨μ€ μ •ν™•νžˆ 1:1(μ •μ‚¬κ°ν˜•) ν˜•μ‹μœΌλ‘œ μ§€μ •ν•©λ‹ˆλ‹€. ν”„λ‘¬ν”„νŠΈμ— "square format", "1:1 ratio" λ˜λŠ” "aspect ratio 1:1"을 λͺ…μ‹œμ μœΌλ‘œ ν¬ν•¨ν•©λ‹ˆλ‹€.
82
  5. μƒν’ˆμ€ λ°˜λ“œμ‹œ μ •μ‚¬κ°ν˜• κ΅¬λ„μ˜ 정쀑앙에 λ°°μΉ˜λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
83
  6. μƒν’ˆμ„ μ΄λ―Έμ§€μ˜ μ£Όμš” 초점으둜 λΆ€κ°μ‹œν‚€κ³ , μƒν’ˆμ˜ λΉ„μœ¨μ΄ 전체 μ΄λ―Έμ§€μ—μ„œ 크게 μ°¨μ§€ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.
84
  7. μƒν’ˆ 이미지 컷아웃(#1)의 κΈ°λ³Έ ν˜•νƒœμ™€ 색상은 μœ μ§€ν•˜λ©΄μ„œ, μ„ νƒν•œ ν™˜κ²½μ— μžμ—°μŠ€λŸ½κ²Œ ν†΅ν•©λ˜λ„λ‘ ν•©λ‹ˆλ‹€.
85
- 8. κ³ κΈ‰μŠ€λŸ¬μš΄ 상업적 이미지λ₯Ό μœ„ν•œ λ‹€μŒ ν™˜κ²½ μš”μ†Œλ“€μ„ ν¬ν•¨ν•˜μ„Έμš”:
86
- - μƒν’ˆκ³Ό μ–΄μšΈλ¦¬λŠ” μ£Όλ³€ ν™˜κ²½/λ°°κ²½ μš”μ†Œλ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, ν™”μž₯ν’ˆ 주변에 κ½ƒμ΄λ‚˜ ν—ˆλΈŒ, 음료 μ œν’ˆ μ˜†μ— 과일, μ „μžμ œν’ˆ κ·Όμ²˜μ— ν˜„λŒ€μ  μ†Œν’ˆ λ“±.
87
- - ν™˜κ²½μ˜ μ‘°λͺ… 효과(λ¦Ό 라이트, 백라이트, μ†Œν”„νŠΈλ°•μŠ€ λ“±)λ₯Ό μ„€λͺ…ν•©λ‹ˆλ‹€.
88
- - μƒν’ˆμ΄ ν™˜κ²½μ— μžμ—°μŠ€λŸ½κ²Œ μ‘΄μž¬ν•˜λŠ” κ²ƒμ²˜λŸΌ 보이도둝 μ μ ˆν•œ κ·Έλ¦Όμžμ™€ λΉ› ν‘œν˜„μ„ ν¬ν•¨ν•©λ‹ˆλ‹€.
89
- - μƒν’ˆμ˜ μš©λ„λ‚˜ μž₯점을 κ°„μ ‘μ μœΌλ‘œ μ•”μ‹œν•˜λŠ” λ°°κ²½ μš”μ†Œλ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€.
90
- - ν”„λ‘œνŽ˜μ…”λ„ν•œ 상업 사진 효과(선택적 피사계 심도, μ†Œν”„νŠΈ 포컀슀, μŠ€νŠœλ””μ˜€ μ‘°λͺ… λ“±)λ₯Ό λͺ…μ‹œν•©λ‹ˆλ‹€.
91
  9. ν”„λ‘¬ν”„νŠΈμ— λ‹€μŒ μš”μ†Œλ“€μ„ λͺ…μ‹œμ μœΌλ‘œ ν¬ν•¨ν•˜μ„Έμš”:
92
  - "highly detailed commercial photography"
93
  - "award-winning product photography"
94
  - "professional advertising imagery"
95
- - "studio quality"
96
- - "magazine advertisement quality"
97
- 10. λ°°κ²½ ν™˜κ²½ μš”μ†Œλ₯Ό μƒν’ˆ μΉ΄ν…Œκ³ λ¦¬μ— 맞게 μ„ νƒν•©λ‹ˆλ‹€:
98
- - μŠ€ν‚¨μΌ€μ–΄ μ œν’ˆ: κΉ¨λ—ν•œ μš•μ‹€ μ„ λ°˜, μš°μ•„ν•œ ν™”μž₯λŒ€, 슀파 같은 ν™˜κ²½ λ“±
99
- - 음료 μ œν’ˆ: μ„Έλ ¨λœ ν…Œμ΄λΈ”, νŒŒν‹° ν™˜κ²½, μ•Όμ™Έ 피크닉 μž₯λ©΄ λ“±
100
- - μ „μž μ œν’ˆ: μ„Έλ ¨λœ μž‘μ—… 곡간, ν˜„λŒ€μ μΈ κ±°μ‹€, λ―Έλ‹ˆλ©€ν•œ 책상 λ“±
101
- - νŒ¨μ…˜/의λ₯˜: μ„Έλ ¨λœ μ‡Όλ£Έ, λ„μ‹œ 거리, μ—˜λ ˆκ°•μŠ€ν•œ λΌμ΄ν”„μŠ€νƒ€μΌ ν™˜κ²½ λ“±
102
- - μ‹ν’ˆ μ œν’ˆ: κΉ”λ”ν•œ μ£Όλ°©, 식탁, μš”λ¦¬ ν™˜κ²½ λ“±
103
- 11. μ‚¬μš©μžκ°€ μ œκ³΅ν•œ ꡬ체적인 λ°°κ²½κ³Ό μΆ”κ°€ μš”μ²­μ‚¬ν•­μ„ μ •ν™•νžˆ λ°˜μ˜ν•©λ‹ˆλ‹€.
104
- 12. ν”„λ‘¬ν”„νŠΈλŠ” λ―Έλ“œμ €λ‹ˆ AI에 μ΅œμ ν™”λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
105
- 13. ν”„λ‘¬ν”„νŠΈ 끝에 "--ar 1:1 --s 750 --q 2" νŒŒλΌλ―Έν„°λ₯Ό μΆ”κ°€ν•˜μ—¬ λ―Έλ“œμ €λ‹ˆμ—μ„œ κ³ ν’ˆμ§ˆ μ •μ‚¬κ°ν˜• λΉ„μœ¨μ„ κ°•μ œν•©λ‹ˆλ‹€.
106
- 좜λ ₯ ν˜•μ‹μ€ μ˜μ–΄λ‘œ 된 단일 λ‹¨λ½μ˜ μƒμ„Έν•œ ν”„λ‘¬ν”„νŠΈμ—¬μ•Ό ν•˜λ©°, 끝에 λ―Έλ“œμ €λ‹ˆ νŒŒλΌλ―Έν„°κ°€ ν¬ν•¨λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
107
  """
108
 
109
- def save_binary_file(file_name, data):
110
- with open(file_name, "wb") as f:
111
- f.write(data)
112
-
113
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
114
  if not GEMINI_API_KEY:
115
  return "Gemini API ν‚€κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. ν™˜κ²½ λ³€μˆ˜ GEMINI_API_KEYλ₯Ό μ„€μ •ν•˜κ±°λ‚˜ μ½”λ“œμ— 직접 μž…λ ₯ν•˜μ„Έμš”."
@@ -128,25 +75,14 @@ def generate_prompt_with_gemini(product_name, background_info, additional_info="
128
  5. ν™˜κ²½κ³Όμ˜ μžμ—°μŠ€λŸ¬μš΄ 톡합을 μœ„ν•œ μ‘°λͺ… νš¨κ³Όμ™€ κ·Έλ¦ΌμžλŠ” ν¬ν•¨ν•΄μ£Όμ„Έμš”.
129
  6. μƒν’ˆμ„ 더 λ‹λ³΄μ΄κ²Œ ν•˜λŠ” λ°°κ²½ ν™˜κ²½μ„ μ„€λͺ…ν•΄μ£Όμ„Έμš”.
130
  7. κ³ κΈ‰μŠ€λŸ¬μš΄ 상업 κ΄‘κ³  ν’ˆμ§ˆμ˜ 이미지가 λ˜λ„λ‘ ν™˜κ²½ μ„€λͺ…을 ν•΄μ£Όμ„Έμš”.
131
- 8. ν”„λ‘¬ν”„νŠΈ 끝에 λ―Έλ“œμ €λ‹ˆ νŒŒλΌλ―Έν„° "--ar 1:1 --s 750 --q 2"λ₯Ό μΆ”κ°€ν•΄μ£Όμ„Έμš”.
132
  ν•œκ΅­μ–΄ μž…λ ₯ λ‚΄μš©μ„ μ˜μ–΄λ‘œ 적절히 λ²ˆμ—­ν•˜μ—¬ λ°˜μ˜ν•΄μ£Όμ„Έμš”.
133
  """
134
- model = genai.GenerativeModel(
135
- 'gemini-2.0-flash',
136
- system_instruction=generate_system_instruction()
137
- )
138
- response = model.generate_content(
139
- prompt_request,
140
- generation_config=genai.types.GenerationConfig(
141
- temperature=0.7,
142
- top_p=0.95,
143
- top_k=64,
144
- max_output_tokens=1024,
145
- )
146
- )
147
  response_text = response.text.strip()
148
- if "--ar 1:1" not in response_text:
149
- response_text = response_text.rstrip(".") + ". --ar 1:1 --s 750 --q 2"
150
 
151
  # λ―Έλ“œμ €λ‹ˆ νŒŒλΌλ―Έν„° μ œκ±°ν•˜κ³  λ°˜ν™˜ (이미지 μƒμ„±μ—μ„œλŠ” ν•„μš”μ—†μŒ)
152
  cleaned_response = re.sub(r'--ar \d+:\d+|--s \d+|--q \d+', '', response_text).strip()
@@ -198,7 +134,7 @@ def generate_with_images(prompt, images, variation_index=0):
198
  if not api_key:
199
  return None, "API ν‚€κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. ν™˜κ²½λ³€μˆ˜λ₯Ό ν™•μΈν•΄μ£Όμ„Έμš”."
200
 
201
- client = genai.Client(api_key=api_key)
202
  logger.info(f"Gemini API μš”μ²­ μ‹œμž‘ - ν”„λ‘¬ν”„νŠΈ: {prompt}, λ³€ν˜• 인덱슀: {variation_index}")
203
 
204
  variation_suffixes = [
@@ -213,37 +149,44 @@ def generate_with_images(prompt, images, variation_index=0):
213
  else:
214
  prompt = prompt + " Do not add any text, watermarks, or labels to the image."
215
 
216
- contents = [prompt]
217
- for idx, img in enumerate(images, 1):
 
 
218
  if img is not None:
219
- contents.append(img)
220
- logger.info(f"이미지 #{idx} 좔가됨")
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
- response = client.models.generate_content(
223
- model="gemini-2.0-flash-exp-image-generation",
224
- contents=contents,
225
- config=types.GenerateContentConfig(
226
- response_modalities=['Text', 'Image'],
227
- temperature=1,
228
- top_p=0.95,
229
- top_k=40,
230
- max_output_tokens=8192
231
- )
232
- )
233
 
234
  # μž„μ‹œ νŒŒμΌμ€ 항상 JPG ν™•μž₯자둜 생성
235
  with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
236
  temp_path = tmp.name
237
  result_text = ""
238
  image_found = False
239
- for part in response.candidates[0].content.parts:
 
240
  if hasattr(part, 'text') and part.text:
241
  result_text += part.text
242
  logger.info(f"응닡 ν…μŠ€νŠΈ: {part.text}")
243
  elif hasattr(part, 'inline_data') and part.inline_data:
244
- save_binary_file(temp_path, part.inline_data.data)
 
245
  image_found = True
246
  logger.info("μ‘λ‹΅μ—μ„œ 이미지 μΆ”μΆœ 성곡")
 
247
  if not image_found:
248
  return None, f"APIμ—μ„œ 이미지λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. 응닡 ν…μŠ€νŠΈ: {result_text}"
249
 
 
6
  import re
7
  import time
8
  import json
9
+ import google.generativeai as genai
 
 
10
  from dotenv import load_dotenv
11
 
12
  load_dotenv()
 
17
 
18
  # Gemini API ν‚€ μ„€μ •
19
  GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
 
20
 
21
  # λ°°κ²½ JSON 파일 경둜 μ„€μ •
22
  BACKGROUNDS_DIR = "./background"
 
26
  os.makedirs(BACKGROUNDS_DIR)
27
  logger.info(f"λ°°κ²½ 디렉토리λ₯Ό μƒμ„±ν–ˆμŠ΅λ‹ˆλ‹€: {BACKGROUNDS_DIR}")
28
 
29
+ # κΈ°λ³Έ λ°°κ²½ 생성
30
+ SIMPLE_BACKGROUNDS = {"ν™”μ΄νŠΈ λ°°κ²½": "white background", "λΈ”λž™ λ°°κ²½": "black background", "그레이 λ°°κ²½": "gray background"}
31
+ STUDIO_BACKGROUNDS = {"μ œν’ˆ 사진 μŠ€νŠœλ””μ˜€": "product photography studio", "λ―Έλ‹ˆλ©€ μŠ€νŠœλ””μ˜€": "minimal studio setup"}
32
+ NATURE_BACKGROUNDS = {"μ—΄λŒ€ ν•΄λ³€": "tropical beach", "μˆ²μ†": "lush forest", "μ‚°μ•… 풍경": "mountain landscape"}
33
+ INDOOR_BACKGROUNDS = {"λͺ¨λ˜ 리빙룸": "modern living room", "λŸ­μ…”λ¦¬ μ‡Όλ£Έ": "luxury showroom", "카페": "cozy cafe"}
34
+ ABSTRACT_BACKGROUNDS = {"λ„€μ˜¨ μ‘°λͺ…": "neon lights", "κ·ΈλΌλ°μ΄μ…˜": "gradient background", "κΈ°ν•˜ν•™μ  νŒ¨ν„΄": "geometric pattern"}
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ def save_binary_file(file_name, data):
37
+ with open(file_name, "wb") as f:
38
+ f.write(data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  def generate_system_instruction():
41
  return """당신은 μƒν’ˆ μ΄λ―Έμ§€μ˜ 배경을 λ³€κ²½ν•˜κΈ° μœ„ν•œ κ³ ν’ˆμ§ˆ ν”„λ‘¬ν”„νŠΈλ₯Ό μƒμ„±ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€.
42
+ μ‚¬μš©μžκ°€ μ œκ³΅ν•˜λŠ” μƒν’ˆλͺ…, λ°°κ²½ μœ ν˜•, μΆ”κ°€ μš”μ²­μ‚¬ν•­μ„ λ°”νƒ•μœΌλ‘œ κ³ ν’ˆμ§ˆ ν”„λ‘¬ν”„νŠΈλ₯Ό μ˜μ–΄λ‘œ μƒμ„±ν•΄μ£Όμ„Έμš”.
 
43
  λ‹€μŒ κ°€μ΄λ“œλΌμΈμ„ λ°˜λ“œμ‹œ 따라야 ν•©λ‹ˆλ‹€:
44
  1. μƒν’ˆμ„ "#1"둜 μ§€μ •ν•˜μ—¬ μ°Έμ‘°ν•©λ‹ˆλ‹€. (예: "skincare tube (#1)")
45
  2. *** 맀우 μ€‘μš”: μƒν’ˆμ˜ μ›λž˜ νŠΉμ„±(λ””μžμΈ, 색상, ν˜•νƒœ, 둜고, νŒ¨ν‚€μ§€ λ“±)은 μ–΄λ–€ μƒν™©μ—μ„œλ„ μ ˆλŒ€ λ³€κ²½ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ***
46
+ 3. *** μƒν’ˆμ˜ 본질적 νŠΉμ„±μ€ μœ μ§€ν•˜λ˜, μžμ—°μŠ€λŸ¬μš΄ ν™˜κ²½ 톡합을 μœ„ν•œ μ‘°λͺ…κ³Ό κ·Έλ¦ΌμžλŠ” ν—ˆμš©ν•©λ‹ˆλ‹€ ***
47
+ 4. 이미지 λΉ„μœ¨μ€ μ •ν™•νžˆ 1:1(μ •μ‚¬κ°ν˜•) ν˜•μ‹μœΌλ‘œ μ§€μ •ν•©λ‹ˆλ‹€.
 
 
 
 
48
  5. μƒν’ˆμ€ λ°˜λ“œμ‹œ μ •μ‚¬κ°ν˜• κ΅¬λ„μ˜ 정쀑앙에 λ°°μΉ˜λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.
49
  6. μƒν’ˆμ„ μ΄λ―Έμ§€μ˜ μ£Όμš” 초점으둜 λΆ€κ°μ‹œν‚€κ³ , μƒν’ˆμ˜ λΉ„μœ¨μ΄ 전체 μ΄λ―Έμ§€μ—μ„œ 크게 μ°¨μ§€ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.
50
  7. μƒν’ˆ 이미지 컷아웃(#1)의 κΈ°λ³Έ ν˜•νƒœμ™€ 색상은 μœ μ§€ν•˜λ©΄μ„œ, μ„ νƒν•œ ν™˜κ²½μ— μžμ—°μŠ€λŸ½κ²Œ ν†΅ν•©λ˜λ„λ‘ ν•©λ‹ˆλ‹€.
51
+ 8. κ³ κΈ‰μŠ€λŸ¬μš΄ 상업적 이미지λ₯Ό μœ„ν•œ ν™˜κ²½ μš”μ†Œλ“€μ„ ν¬ν•¨ν•˜μ„Έμš”.
 
 
 
 
 
52
  9. ν”„λ‘¬ν”„νŠΈμ— λ‹€μŒ μš”μ†Œλ“€μ„ λͺ…μ‹œμ μœΌλ‘œ ν¬ν•¨ν•˜μ„Έμš”:
53
  - "highly detailed commercial photography"
54
  - "award-winning product photography"
55
  - "professional advertising imagery"
56
+ 10. μ‚¬μš©μžκ°€ μ œκ³΅ν•œ ꡬ체적인 λ°°κ²½κ³Ό μΆ”κ°€ μš”μ²­μ‚¬ν•­μ„ μ •ν™•νžˆ λ°˜μ˜ν•©λ‹ˆλ‹€.
57
+ 좜λ ₯ ν˜•μ‹μ€ μ˜μ–΄λ‘œ 된 단일 λ‹¨λ½μ˜ μƒμ„Έν•œ ν”„λ‘¬ν”„νŠΈμ—¬μ•Ό ν•©λ‹ˆλ‹€.
 
 
 
 
 
 
 
 
 
 
58
  """
59
 
 
 
 
 
60
  def generate_prompt_with_gemini(product_name, background_info, additional_info=""):
61
  if not GEMINI_API_KEY:
62
  return "Gemini API ν‚€κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. ν™˜κ²½ λ³€μˆ˜ GEMINI_API_KEYλ₯Ό μ„€μ •ν•˜κ±°λ‚˜ μ½”λ“œμ— 직접 μž…λ ₯ν•˜μ„Έμš”."
 
75
  5. ν™˜κ²½κ³Όμ˜ μžμ—°μŠ€λŸ¬μš΄ 톡합을 μœ„ν•œ μ‘°λͺ… νš¨κ³Όμ™€ κ·Έλ¦ΌμžλŠ” ν¬ν•¨ν•΄μ£Όμ„Έμš”.
76
  6. μƒν’ˆμ„ 더 λ‹λ³΄μ΄κ²Œ ν•˜λŠ” λ°°κ²½ ν™˜κ²½μ„ μ„€λͺ…ν•΄μ£Όμ„Έμš”.
77
  7. κ³ κΈ‰μŠ€λŸ¬μš΄ 상업 κ΄‘κ³  ν’ˆμ§ˆμ˜ 이미지가 λ˜λ„λ‘ ν™˜κ²½ μ„€λͺ…을 ν•΄μ£Όμ„Έμš”.
 
78
  ν•œκ΅­μ–΄ μž…λ ₯ λ‚΄μš©μ„ μ˜μ–΄λ‘œ 적절히 λ²ˆμ—­ν•˜μ—¬ λ°˜μ˜ν•΄μ£Όμ„Έμš”.
79
  """
80
+ genai.configure(api_key=GEMINI_API_KEY)
81
+
82
+ model = genai.GenerativeModel('gemini-2.0-flash')
83
+
84
+ response = model.generate_content(prompt_request)
 
 
 
 
 
 
 
 
85
  response_text = response.text.strip()
 
 
86
 
87
  # λ―Έλ“œμ €λ‹ˆ νŒŒλΌλ―Έν„° μ œκ±°ν•˜κ³  λ°˜ν™˜ (이미지 μƒμ„±μ—μ„œλŠ” ν•„μš”μ—†μŒ)
88
  cleaned_response = re.sub(r'--ar \d+:\d+|--s \d+|--q \d+', '', response_text).strip()
 
134
  if not api_key:
135
  return None, "API ν‚€κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. ν™˜κ²½λ³€μˆ˜λ₯Ό ν™•μΈν•΄μ£Όμ„Έμš”."
136
 
137
+ genai.configure(api_key=api_key)
138
  logger.info(f"Gemini API μš”μ²­ μ‹œμž‘ - ν”„λ‘¬ν”„νŠΈ: {prompt}, λ³€ν˜• 인덱슀: {variation_index}")
139
 
140
  variation_suffixes = [
 
149
  else:
150
  prompt = prompt + " Do not add any text, watermarks, or labels to the image."
151
 
152
+ model = genai.GenerativeModel('gemini-1.5-flash')
153
+
154
+ parts = [prompt]
155
+ for img in images:
156
  if img is not None:
157
+ if isinstance(img, str): # If it's a file path
158
+ with open(img, "rb") as f:
159
+ img_data = f.read()
160
+ parts.append({"mime_type": "image/jpeg", "data": img_data})
161
+ else: # If it's a PIL Image
162
+ img_bytes = tempfile.NamedTemporaryFile(suffix=".jpg", delete=False)
163
+ img.save(img_bytes, format="JPEG")
164
+ img_bytes.close()
165
+
166
+ with open(img_bytes.name, "rb") as f:
167
+ img_data = f.read()
168
+
169
+ parts.append({"mime_type": "image/jpeg", "data": img_data})
170
+ os.unlink(img_bytes.name) # Clean up temp file
171
 
172
+ response = model.generate_content(parts)
 
 
 
 
 
 
 
 
 
 
173
 
174
  # μž„μ‹œ νŒŒμΌμ€ 항상 JPG ν™•μž₯자둜 생성
175
  with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
176
  temp_path = tmp.name
177
  result_text = ""
178
  image_found = False
179
+
180
+ for part in response.parts:
181
  if hasattr(part, 'text') and part.text:
182
  result_text += part.text
183
  logger.info(f"응닡 ν…μŠ€νŠΈ: {part.text}")
184
  elif hasattr(part, 'inline_data') and part.inline_data:
185
+ img_data = part.inline_data.data
186
+ save_binary_file(temp_path, img_data)
187
  image_found = True
188
  logger.info("μ‘λ‹΅μ—μ„œ 이미지 μΆ”μΆœ 성곡")
189
+
190
  if not image_found:
191
  return None, f"APIμ—μ„œ 이미지λ₯Ό μƒμ„±ν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. 응닡 ν…μŠ€νŠΈ: {result_text}"
192