SiddhJagani commited on
Commit
0804ab6
·
verified ·
1 Parent(s): 4589f1c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -34
app.py CHANGED
@@ -146,50 +146,115 @@ async def v1_chat(request: Request, authorization: str = Header(None)):
146
  headers={"Access-Control-Allow-Origin": "*"},
147
  )
148
 
149
- #---------------------------------------------------------------------
150
- #--------------------------/v1 Dall-e---------------------------------
151
- #---------------------------------------------------------------------
152
-
153
  @api.post("/v1/images/generations")
154
- async def image_generation(request: Request, authorization: str = Header(None)):
 
 
 
 
 
 
155
  check_key(authorization)
156
- if not BYTEZ_AUTH:
157
- raise HTTPException(status_code=500, detail="Server BYTEZ_API_KEY not configured")
158
 
159
- # Parse incoming OpenAI-style payload
160
- payload = await request.json()
161
- prompt = payload.get("prompt")
162
- if not prompt:
163
- raise HTTPException(status_code=400, detail="Missing 'prompt' in request body")
 
 
164
 
165
- # Prepare Bytez API payload
166
- bytez_payload = {"text": prompt}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  headers = {
169
- "Authorization": BYTEZ_AUTH,
170
- "Content-Type": "application/json"
171
  }
172
 
173
- # Call Bytez image API
174
- async with httpx.AsyncClient(timeout=60) as client:
175
- r = await client.post(BYTEZ_IMAGE_URL, headers=headers, json=bytez_payload)
176
- try:
177
- bytez_resp = r.json()
178
- except Exception:
179
- raise HTTPException(status_code=502, detail="Upstream returned invalid JSON")
180
-
181
- # Map Bytez output to OpenAI response format
182
- # Adjust this according to actual Bytez API response content/structure
183
- image_url = bytez_resp.get("url") or bytez_resp.get("image") or bytez_resp.get("data", [{}])[0].get("url")
184
- if not image_url:
185
- raise HTTPException(status_code=502, detail="Bytez API did not return an image URL")
186
-
187
- # OpenAI's format
188
- openai_resp = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  "created": int(time.time()),
190
- "data": [{"url": image_url}]
191
  }
192
- return JSONResponse(openai_resp, headers={"Access-Control-Allow-Origin": "*"})
 
193
 
194
 
195
 
 
146
  headers={"Access-Control-Allow-Origin": "*"},
147
  )
148
 
149
+ # ---------------------------------------------------------------------
150
+ # --------------------- /v1/images/generations (FIXED) ---------------
151
+ # ---------------------------------------------------------------------
 
152
  @api.post("/v1/images/generations")
153
+ async def v1_images_generations(request: Request, authorization: str = Header(None)):
154
+ """
155
+ Fully OpenAI-compatible DALL·E-3 via Bytez
156
+ → Accepts `model` field (required by Continue.dev, Cursor, etc.)
157
+ → Ignores it safely (since Bytez uses URL path, not model name)
158
+ → Returns proper OpenAI format with url + b64_json
159
+ """
160
  check_key(authorization)
 
 
161
 
162
+ if not BYTEZ_AUTH_2:
163
+ raise HTTPException(status_code=500, detail="Server BYTEZ_API_KEY_2 not configured")
164
+
165
+ try:
166
+ payload = await request.json()
167
+ except json.JSONDecodeError:
168
+ raise HTTPException(status_code=400, detail="Invalid JSON")
169
 
170
+ prompt = payload.get("prompt")
171
+ if not prompt or not prompt.strip():
172
+ raise HTTPException(status_code=400, detail="Field 'prompt' is required and cannot be empty")
173
+
174
+ # These fields are REQUIRED by UI tools even if we ignore some
175
+ model_name = payload.get("model", "dall-e-3") # just for show — we ignore it
176
+ n = payload.get("n", 1)
177
+ size = payload.get("size", "1024x1024")
178
+ quality = payload.get("quality", "standard")
179
+ style = payload.get("style") # vivid or natural
180
+ response_format = payload.get("response_format", "url") # url or b64_json
181
+
182
+ # Map OpenAI sizes → Bytez accepts the same strings
183
+ if size not in ["1024x1024", "1024x1792", "1792x1024"]:
184
+ size = "1024x1024" # fallback
185
+
186
+ bytez_payload = {
187
+ "text": prompt,
188
+ "num_outputs": n,
189
+ "size": size,
190
+ }
191
+ if quality in ["standard", "hd"]:
192
+ bytez_payload["quality"] = quality
193
+ if style in ["vivid", "natural"]:
194
+ bytez_payload["style"] = style
195
 
196
  headers = {
197
+ "Authorization": BYTEZ_AUTH_2,
198
+ "Content-Type": "application/json",
199
  }
200
 
201
+ async with httpx.AsyncClient(timeout=200) as client:
202
+ try:
203
+ resp = await client.post(
204
+ "https://api.bytez.com/models/v2/openai/dall-e-3",
205
+ json=bytez_payload,
206
+ headers=headers,
207
+ )
208
+ resp.raise_for_status()
209
+ except httpx.HTTPStatusError as e:
210
+ try:
211
+ error_detail = e.response.json()
212
+ except:
213
+ error_detail = e.response.text
214
+ raise HTTPException(status_code=e.response.status_code, detail=error_detail)
215
+ except Exception as e:
216
+ raise HTTPException(status_code=502, detail=f"Bytez unreachable: {str(e)}")
217
+
218
+ try:
219
+ bytez_data = resp.json()
220
+ except json.JSONDecodeError:
221
+ raise HTTPException(status_code=502, detail="Bytez returned invalid JSON")
222
+
223
+ # Handle different possible response shapes from Bytez
224
+ images = bytez_data.get("images") or bytez_data.get("data") or []
225
+ if isinstance(images, str):
226
+ images = [images]
227
+ if not images:
228
+ raise HTTPException(status_code=500, detail="No images returned from Bytez")
229
+
230
+ # Build proper OpenAI response
231
+ openai_images = []
232
+ for img_data in images:
233
+ if img_data.startswith("data:image"):
234
+ b64 = img_data.split("base64,")[-1]
235
+ url = img_data
236
+ else:
237
+ b64 = img_data
238
+ url = f"data:image/png;base64,{img_data}"
239
+
240
+ item = {}
241
+ if response_format == "b64_json" or response_format is None:
242
+ item["b64_json"] = b64
243
+ else:
244
+ item["url"] = url
245
+
246
+ # Optional: include revised_prompt if Bytez returns it
247
+ if "revised_prompt" in bytez_data:
248
+ item["revised_prompt"] = bytez_data["revised_prompt"]
249
+
250
+ openai_images.append(item)
251
+
252
+ final_response = {
253
  "created": int(time.time()),
254
+ "data": openai_images
255
  }
256
+
257
+ return JSONResponse(final_response, headers={"Access-Control-Allow-Origin": "*"})
258
 
259
 
260