Update app.py
Browse files
app.py
CHANGED
@@ -108,8 +108,8 @@ def generate_with_images(prompt, images, max_retries=2):
|
|
108 |
|
109 |
logger.info(f"Gemini API ์์ฒญ ์์ - ํ๋กฌํํธ: {prompt} (์๋: {retries+1}/{max_retries+1})")
|
110 |
|
111 |
-
# ์ด๋ฏธ์ง
|
112 |
-
|
113 |
|
114 |
# ์ด๋ฏธ์ง ํํธ ์ถ๊ฐ
|
115 |
for idx, img in enumerate(images, 1):
|
@@ -120,34 +120,39 @@ def generate_with_images(prompt, images, max_retries=2):
|
|
120 |
image_bytes = buffered.getvalue()
|
121 |
|
122 |
# ์ด๋ฏธ์ง ํํธ ์์ฑ
|
123 |
-
|
124 |
-
'
|
125 |
-
'
|
126 |
-
'data': image_bytes
|
127 |
}
|
128 |
})
|
129 |
logger.info(f"์ด๋ฏธ์ง #{idx} ์ถ๊ฐ๋จ")
|
130 |
|
131 |
# ํ
์คํธ ํ๋กฌํํธ ์ถ๊ฐ
|
132 |
-
|
133 |
'text': prompt
|
134 |
})
|
135 |
|
136 |
-
# ์์ฑ
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
temperature
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
148 |
|
149 |
# ์๋ต ์ ํจ์ฑ ํ์ธ
|
150 |
-
if not response or not response.
|
151 |
if retries < max_retries:
|
152 |
retries += 1
|
153 |
logger.warning(f"์ ํจํ ์๋ต์ ๋ฐ์ง ๋ชปํ์ต๋๋ค. ์ฌ์๋ ์ค... ({retries}/{max_retries})")
|
@@ -161,27 +166,21 @@ def generate_with_images(prompt, images, max_retries=2):
|
|
161 |
result_text = ""
|
162 |
image_found = False
|
163 |
|
164 |
-
#
|
165 |
-
for
|
166 |
-
if
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
logger.info(
|
173 |
-
|
174 |
-
# ์ด๋ฏธ์ง ์ถ์ถ
|
175 |
-
for part in candidate.content.parts:
|
176 |
-
if hasattr(part, 'inline_data') and part.inline_data:
|
177 |
-
save_binary_file(temp_path, part.inline_data.data)
|
178 |
-
image_found = True
|
179 |
-
logger.info("์๋ต์์ ์ด๋ฏธ์ง ์ถ์ถ ์ฑ๊ณต")
|
180 |
-
break
|
181 |
-
|
182 |
-
if image_found:
|
183 |
break
|
184 |
|
|
|
|
|
|
|
|
|
185 |
if not image_found:
|
186 |
if retries < max_retries:
|
187 |
retries += 1
|
|
|
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):
|
|
|
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})")
|
|
|
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
|