Kims12 commited on
Commit
edf8d31
ยท
verified ยท
1 Parent(s): 8d852cf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -41
app.py CHANGED
@@ -12,7 +12,7 @@ import logging
12
  from google import genai
13
  from google.genai import types
14
 
15
- # .env ํŒŒ์ผ์— ์ €์žฅ๋œ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋กœ๋“œ (python-dotenv ์„ค์น˜ ํ•„์š”: pip install python-dotenv)
16
  from dotenv import load_dotenv
17
  load_dotenv()
18
 
@@ -29,11 +29,11 @@ def save_binary_file(file_name, data):
29
  logger.debug(f"ํŒŒ์ผ ์ €์žฅ ์™„๋ฃŒ: {file_name}")
30
 
31
 
32
- def generate(text, file_name, model="gemini-2.0-flash-exp-image-generation"):
33
- logger.debug(f"generate ํ•จ์ˆ˜ ์‹œ์ž‘ - ํ…์ŠคํŠธ: '{text}', ํŒŒ์ผ๋ช…: '{file_name}', ๋ชจ๋ธ: '{model}'")
34
-
35
  try:
36
- # API ํ‚ค๋Š” ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ๋ถˆ๋Ÿฌ์˜ด
37
  effective_api_key = os.environ.get("GEMINI_API_KEY")
38
  if effective_api_key:
39
  logger.debug("ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๋ถˆ๋Ÿฌ์˜ด")
@@ -44,25 +44,32 @@ def generate(text, file_name, model="gemini-2.0-flash-exp-image-generation"):
44
  client = genai.Client(api_key=effective_api_key)
45
  logger.debug("Gemini ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ.")
46
 
47
- # ํŒŒ์ผ ์—…๋กœ๋“œ
48
- files = [
49
- client.files.upload(file=file_name),
50
- ]
51
- logger.debug(f"ํŒŒ์ผ ์—…๋กœ๋“œ ์™„๋ฃŒ. URI: {files[0].uri}, MIME ํƒ€์ž…: {files[0].mime_type}")
52
-
53
- # ์ปจํ…์ธ  ๊ฐ์ฒด ์ƒ์„ฑ: ํŒŒ์ผ URI์™€ ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ•จ๊ป˜ ํฌํ•จ
54
- contents = [
55
- types.Content(
56
- role="user",
57
- parts=[
58
- types.Part.from_uri(
59
- file_uri=files[0].uri,
60
- mime_type=files[0].mime_type,
61
- ),
62
- types.Part.from_text(text=text),
63
- ],
64
- ),
65
- ]
 
 
 
 
 
 
 
66
  logger.debug(f"์ปจํ…์ธ  ๊ฐ์ฒด ์ƒ์„ฑ ์™„๋ฃŒ: {contents}")
67
 
68
  generate_content_config = types.GenerateContentConfig(
@@ -70,10 +77,7 @@ def generate(text, file_name, model="gemini-2.0-flash-exp-image-generation"):
70
  top_p=0.95,
71
  top_k=40,
72
  max_output_tokens=8192,
73
- response_modalities=[
74
- "image",
75
- "text",
76
- ],
77
  response_mime_type="text/plain",
78
  )
79
  logger.debug(f"์ƒ์„ฑ ์„ค์ •: {generate_content_config}")
@@ -113,19 +117,38 @@ def generate(text, file_name, model="gemini-2.0-flash-exp-image-generation"):
113
  return None # ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ None ๋ฐ˜ํ™˜
114
 
115
 
116
- def process_image_and_prompt(composite_pil, prompt):
117
  logger.debug(f"process_image_and_prompt ํ•จ์ˆ˜ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: '{prompt}'")
118
  try:
 
119
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
120
  composite_path = tmp.name
121
  composite_pil.save(composite_path)
122
- logger.debug(f"ํ•ฉ์„ฑ ์ด๋ฏธ์ง€ ์ €์žฅ ์™„๋ฃŒ: {composite_path}")
123
 
124
- file_name = composite_path
125
- input_text = prompt
126
- model = "gemini-2.0-flash-exp-image-generation"
 
 
 
 
 
 
127
 
128
- gemma_edited_image_path = generate(text=input_text, file_name=file_name, model=model)
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  if gemma_edited_image_path:
131
  logger.debug(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์™„๋ฃŒ. ๊ฒฝ๋กœ: {gemma_edited_image_path}")
@@ -157,11 +180,13 @@ with gr.Blocks() as demo:
157
  </div>
158
  """
159
  )
160
- gr.Markdown("์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ , ํŽธ์ง‘ํ•  ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”.")
161
 
162
  with gr.Row():
163
  with gr.Column():
164
- image_input = gr.Image(type="pil", label="์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", image_mode="RGBA")
 
 
165
  prompt_input = gr.Textbox(
166
  lines=2,
167
  placeholder="ํŽธ์ง‘ํ•  ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”...",
@@ -173,17 +198,18 @@ with gr.Blocks() as demo:
173
 
174
  submit_btn.click(
175
  fn=process_image_and_prompt,
176
- inputs=[image_input, prompt_input],
177
  outputs=output_gallery,
178
  )
179
 
180
  # --- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ---
181
- # ํ…Œ์ŠคํŠธ์šฉ ๋”๋ฏธ ์ด๋ฏธ์ง€ (์‹ค์ œ ์ด๋ฏธ์ง€๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅ)
182
- dummy_image = Image.new("RGBA", (100, 100), color="red")
183
- dummy_prompt = "์ด๋ฏธ์ง€๋ฅผ ํŒŒ๋ž€์ƒ‰์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค˜"
 
184
 
185
  logger.info("process_image_and_prompt ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค...")
186
- result = process_image_and_prompt(dummy_image, dummy_prompt)
187
 
188
  if result:
189
  logger.info(f"์ง์ ‘ ํ˜ธ์ถœ ์„ฑ๊ณต. ๊ฒฐ๊ณผ: {result}")
 
12
  from google import genai
13
  from google.genai import types
14
 
15
+ # .env ํŒŒ์ผ์— ์ €์žฅ๋œ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋กœ๋“œ (pip install python-dotenv ํ•„์š”)
16
  from dotenv import load_dotenv
17
  load_dotenv()
18
 
 
29
  logger.debug(f"ํŒŒ์ผ ์ €์žฅ ์™„๋ฃŒ: {file_name}")
30
 
31
 
32
+ def generate(text, composite_file, background_file=None, style_file=None, model="gemini-2.0-flash-exp-image-generation"):
33
+ logger.debug(f"generate ํ•จ์ˆ˜ ์‹œ์ž‘ - ํ…์ŠคํŠธ: '{text}', composite_file: '{composite_file}', "
34
+ f"background_file: '{background_file}', style_file: '{style_file}', ๋ชจ๋ธ: '{model}'")
35
  try:
36
+ # ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
37
  effective_api_key = os.environ.get("GEMINI_API_KEY")
38
  if effective_api_key:
39
  logger.debug("ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๋ถˆ๋Ÿฌ์˜ด")
 
44
  client = genai.Client(api_key=effective_api_key)
45
  logger.debug("Gemini ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ.")
46
 
47
+ # ์—…๋กœ๋“œํ•  ํŒŒ์ผ๋“ค ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ
48
+ files = []
49
+ # ์›๋ณธ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ (ํ•„์ˆ˜)
50
+ composite_upload = client.files.upload(file=composite_file)
51
+ files.append(composite_upload)
52
+ logger.debug(f"์›๋ณธ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์™„๋ฃŒ. URI: {composite_upload.uri}, MIME ํƒ€์ž…: {composite_upload.mime_type}")
53
+
54
+ # ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ (์„ ํƒ)
55
+ if background_file is not None:
56
+ background_upload = client.files.upload(file=background_file)
57
+ files.append(background_upload)
58
+ logger.debug(f"๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์™„๋ฃŒ. URI: {background_upload.uri}, MIME ํƒ€์ž…: {background_upload.mime_type}")
59
+ # ์Šคํƒ€์ผ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ (์„ ํƒ)
60
+ if style_file is not None:
61
+ style_upload = client.files.upload(file=style_file)
62
+ files.append(style_upload)
63
+ logger.debug(f"์Šคํƒ€์ผ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์™„๋ฃŒ. URI: {style_upload.uri}, MIME ํƒ€์ž…: {style_upload.mime_type}")
64
+
65
+ # ํŒŒ์ผ ์—…๋กœ๋“œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ฝ˜ํ…์ธ  ํŒŒํŠธ ์ƒ์„ฑ
66
+ parts = []
67
+ for file_obj in files:
68
+ parts.append(types.Part.from_uri(file_uri=file_obj.uri, mime_type=file_obj.mime_type))
69
+ # ๋งˆ์ง€๋ง‰์— ํ…์ŠคํŠธ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
70
+ parts.append(types.Part.from_text(text=text))
71
+
72
+ contents = [types.Content(role="user", parts=parts)]
73
  logger.debug(f"์ปจํ…์ธ  ๊ฐ์ฒด ์ƒ์„ฑ ์™„๋ฃŒ: {contents}")
74
 
75
  generate_content_config = types.GenerateContentConfig(
 
77
  top_p=0.95,
78
  top_k=40,
79
  max_output_tokens=8192,
80
+ response_modalities=["image", "text"],
 
 
 
81
  response_mime_type="text/plain",
82
  )
83
  logger.debug(f"์ƒ์„ฑ ์„ค์ •: {generate_content_config}")
 
117
  return None # ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ None ๋ฐ˜ํ™˜
118
 
119
 
120
+ def process_image_and_prompt(composite_pil, background_pil, style_pil, prompt):
121
  logger.debug(f"process_image_and_prompt ํ•จ์ˆ˜ ์‹œ์ž‘ - ํ”„๋กฌํ”„ํŠธ: '{prompt}'")
122
  try:
123
+ # ์›๋ณธ ์ด๋ฏธ์ง€ ์ €์žฅ
124
  with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
125
  composite_path = tmp.name
126
  composite_pil.save(composite_path)
127
+ logger.debug(f"์›๋ณธ ์ด๋ฏธ์ง€ ์ €์žฅ ์™„๋ฃŒ: {composite_path}")
128
 
129
+ background_path = None
130
+ style_path = None
131
+
132
+ # ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์ €์žฅ (์ž…๋ ฅ๋œ ๊ฒฝ์šฐ)
133
+ if background_pil is not None:
134
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp2:
135
+ background_path = tmp2.name
136
+ background_pil.save(background_path)
137
+ logger.debug(f"๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ์ €์žฅ ์™„๋ฃŒ: {background_path}")
138
 
139
+ # ์Šคํƒ€์ผ ์ด๋ฏธ์ง€ ์ €์žฅ (์ž…๋ ฅ๋œ ๊ฒฝ์šฐ)
140
+ if style_pil is not None:
141
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp3:
142
+ style_path = tmp3.name
143
+ style_pil.save(style_path)
144
+ logger.debug(f"์Šคํƒ€์ผ ์ด๋ฏธ์ง€ ์ €์žฅ ์™„๋ฃŒ: {style_path}")
145
+
146
+ model = "gemini-2.0-flash-exp-image-generation"
147
+ gemma_edited_image_path = generate(text=prompt,
148
+ composite_file=composite_path,
149
+ background_file=background_path,
150
+ style_file=style_path,
151
+ model=model)
152
 
153
  if gemma_edited_image_path:
154
  logger.debug(f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์™„๋ฃŒ. ๊ฒฝ๋กœ: {gemma_edited_image_path}")
 
180
  </div>
181
  """
182
  )
183
+ gr.Markdown("์›๋ณธ ์ด๋ฏธ์ง€, ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€, ์Šคํƒ€์ผ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•˜๊ณ , ํŽธ์ง‘ํ•  ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”.")
184
 
185
  with gr.Row():
186
  with gr.Column():
187
+ composite_input = gr.Image(type="pil", label="์›๋ณธ ์ด๋ฏธ์ง€", image_mode="RGBA")
188
+ background_input = gr.Image(type="pil", label="๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€", image_mode="RGBA")
189
+ style_input = gr.Image(type="pil", label="์Šคํƒ€์ผ ์ด๋ฏธ์ง€", image_mode="RGBA")
190
  prompt_input = gr.Textbox(
191
  lines=2,
192
  placeholder="ํŽธ์ง‘ํ•  ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”...",
 
198
 
199
  submit_btn.click(
200
  fn=process_image_and_prompt,
201
+ inputs=[composite_input, background_input, style_input, prompt_input],
202
  outputs=output_gallery,
203
  )
204
 
205
  # --- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ---
206
+ dummy_composite = Image.new("RGBA", (100, 100), color="red")
207
+ dummy_background = Image.new("RGBA", (100, 100), color="green")
208
+ dummy_style = Image.new("RGBA", (100, 100), color="blue")
209
+ dummy_prompt = "์ด๋ฏธ์ง€์— ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ์„ ์ ์šฉํ•ด์ค˜"
210
 
211
  logger.info("process_image_and_prompt ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค...")
212
+ result = process_image_and_prompt(dummy_composite, dummy_background, dummy_style, dummy_prompt)
213
 
214
  if result:
215
  logger.info(f"์ง์ ‘ ํ˜ธ์ถœ ์„ฑ๊ณต. ๊ฒฐ๊ณผ: {result}")