Skip to content

Commit 7592eba

Browse files
committed
fix(litellm): skip response_format param for Gemini models
LiteLLM rejects response_format=b64_json for Gemini models. Only send it for OpenAI models. Also handle both b64_json and url response formats via _extract_image_bytes helper.
1 parent b6831db commit 7592eba

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

app/services/litellm_service.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,12 @@ async def generate_image(
8080
"prompt": prompt,
8181
"n": n,
8282
"size": size,
83-
"response_format": "b64_json",
8483
}
8584

85+
# response_format is OpenAI-specific; Gemini via LiteLLM doesn't support it
86+
if not self._is_gemini_model(model):
87+
params["response_format"] = "b64_json"
88+
8689
# Add quality parameter only if model supports it
8790
if model_info and model_info.capabilities.supports_quality:
8891
params["quality"] = quality
@@ -101,7 +104,7 @@ async def generate_image(
101104
# Save images and return URLs
102105
urls = []
103106
for image_data in response.data:
104-
image_bytes = base64.b64decode(image_data.b64_json)
107+
image_bytes = self._extract_image_bytes(image_data)
105108
url = await storage_service.save_image(image_bytes, "png")
106109
urls.append(url)
107110

@@ -152,9 +155,12 @@ async def edit_image(
152155
"image": image_file,
153156
"prompt": prompt,
154157
"n": actual_n,
155-
"response_format": "b64_json",
156158
}
157159

160+
# response_format is OpenAI-specific; Gemini via LiteLLM doesn't support it
161+
if not self._is_gemini_model(model):
162+
params["response_format"] = "b64_json"
163+
158164
# Add mask if provided
159165
if mask:
160166
mask_file = io.BytesIO(mask)
@@ -167,13 +173,27 @@ async def edit_image(
167173
# Save images and return URLs
168174
urls = []
169175
for image_data in response.data:
170-
image_bytes = base64.b64decode(image_data.b64_json)
176+
image_bytes = self._extract_image_bytes(image_data)
171177
url = await storage_service.save_image(image_bytes, "png")
172178
urls.append(url)
173179

174180
logger.info(f"Edited image, generated {len(urls)} result(s)")
175181
return urls
176182

183+
@staticmethod
184+
def _extract_image_bytes(image_data: Any) -> bytes:
185+
"""Extract image bytes from a response item (b64_json or url)."""
186+
if hasattr(image_data, "b64_json") and image_data.b64_json:
187+
return base64.b64decode(image_data.b64_json)
188+
if hasattr(image_data, "url") and image_data.url:
189+
# URL response — fetch the image
190+
import httpx
191+
192+
response = httpx.get(image_data.url, timeout=30.0)
193+
response.raise_for_status()
194+
return response.content
195+
raise ValueError("Response contains neither b64_json nor url")
196+
177197
def _get_size(self, aspect_ratio: str) -> str:
178198
"""
179199
Convert aspect ratio to OpenAI size format.

0 commit comments

Comments
 (0)