Update app.py
Browse files
app.py
CHANGED
@@ -12,7 +12,7 @@ import logging
|
|
12 |
from google import genai
|
13 |
from google.genai import types
|
14 |
|
15 |
-
# .env ํ์ผ์ ์ ์ฅ๋ ํ๊ฒฝ๋ณ์ ๋ก๋ (
|
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,
|
33 |
-
logger.debug(f"generate ํจ์ ์์ - ํ
์คํธ: '{text}',
|
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 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
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"
|
123 |
|
124 |
-
|
125 |
-
|
126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
|
128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
|
|
|
|
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=[
|
177 |
outputs=output_gallery,
|
178 |
)
|
179 |
|
180 |
# --- ํ
์คํธ ์ฝ๋ ---
|
181 |
-
|
182 |
-
|
183 |
-
|
|
|
184 |
|
185 |
logger.info("process_image_and_prompt ํจ์๋ฅผ ์ง์ ํธ์ถํฉ๋๋ค...")
|
186 |
-
result = process_image_and_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}")
|