SiddhJagani commited on
Commit
aca2b2d
·
verified ·
1 Parent(s): 0de40fa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -28
app.py CHANGED
@@ -10,7 +10,7 @@ import base64
10
  import io
11
 
12
  # ---------------------------------------------------------------------
13
- # Configuration - FIXED TRAILING SPACES AND URLS
14
  # ---------------------------------------------------------------------
15
  BYTEZ_CHAT_URL = "https://api.bytez.com/models/v2/openai/v1/chat/completions"
16
  BYTEZ_MODELS_URL = "https://api.bytez.com/models/v2/list/models"
@@ -63,7 +63,7 @@ async def models(authorization: str = Header(None)):
63
  )
64
 
65
  # ---------------------------------------------------------------------
66
- # /v1/chat/completions - CORRECT STREAMING
67
  # ---------------------------------------------------------------------
68
  @api.post("/v1/chat/completions")
69
  async def chat(request: Request, authorization: str = Header(None)):
@@ -85,13 +85,13 @@ async def chat(request: Request, authorization: str = Header(None)):
85
  line = line.strip()
86
  if not line:
87
  continue
88
- if line.startswith(""):
89
  json_str = line[6:].strip()
90
  else:
91
  json_str = line
92
 
93
  if json_str == "[DONE]":
94
- yield " [DONE]\n\n"
95
  break
96
 
97
  try:
@@ -131,8 +131,8 @@ async def chat(request: Request, authorization: str = Header(None)):
131
  "finish_reason": None,
132
  }],
133
  }
134
- yield f" {json.dumps(openai_chunk)}\n\n"
135
- yield " [DONE]\n\n"
136
 
137
  if stream:
138
  return StreamingResponse(
@@ -141,7 +141,7 @@ async def chat(request: Request, authorization: str = Header(None)):
141
  headers={"Access-Control-Allow-Origin": "*"}
142
  )
143
 
144
- # Non-streaming path
145
  async with httpx.AsyncClient(timeout=120) as c:
146
  r = await c.post(BYTEZ_CHAT_URL, headers=headers, json=payload)
147
  try:
@@ -149,7 +149,8 @@ async def chat(request: Request, authorization: str = Header(None)):
149
  except json.JSONDecodeError:
150
  raise HTTPException(status_code=502, detail="Upstream returned invalid JSON")
151
 
152
- if "choices" not in
 
153
  content = (
154
  data.get("output")
155
  or data.get("response")
@@ -166,33 +167,29 @@ async def chat(request: Request, authorization: str = Header(None)):
166
  return JSONResponse(data, headers={"Access-Control-Allow-Origin": "*"})
167
 
168
  # ---------------------------------------------------------------------
169
- # TTS ENDPOINTS (BOTH STANDARD AND NON-STANDARD)
170
  # ---------------------------------------------------------------------
171
  @api.post("/v1/audio/speech")
172
  @api.post("/v1/tts/audio/speech")
173
  @api.post("/v1/tts")
174
- @api.post("/v1/tts/audio/transcriptions") # For backward compatibility
175
  async def tts_endpoint(
176
- request: Request,
177
  authorization: str = Header(None),
178
- text: str = Form(None), # For form-data requests
179
- file: UploadFile = File(None) # For file uploads (though TTS doesn't need files)
180
  ):
181
  check_key(authorization)
182
  if not BYTEZ_AUTH:
183
  raise HTTPException(status_code=500, detail="Server BYTEZ_API_KEY not configured")
184
 
185
- # Handle JSON payload
186
- if request.headers.get("Content-Type", "").startswith("application/json"):
187
  try:
188
  payload = await request.json()
189
  text = payload.get("input") or payload.get("text", "")
190
  except:
191
  text = ""
192
- # Handle form data
193
- elif text is None and file is not None:
194
- # This shouldn't happen for TTS but handle gracefully
195
- text = ""
196
 
197
  if not text:
198
  raise HTTPException(status_code=400, detail="Missing text for TTS conversion")
@@ -216,19 +213,18 @@ async def tts_endpoint(
216
  # Return raw audio
217
  return Response(
218
  content=r.content,
219
- media_type="audio/mpeg", # Bytez returns MP3
220
  headers={"Access-Control-Allow-Origin": "*"}
221
  )
222
 
223
  # ---------------------------------------------------------------------
224
- # STT ENDPOINTS (BOTH STANDARD AND NON-STANDARD)
225
  # ---------------------------------------------------------------------
226
  @api.post("/v1/audio/transcriptions")
227
  @api.post("/v1/stt")
228
  @api.post("/v1/stt/audio/transcriptions")
229
- @api.post("/v1/audio/voices") # Fake endpoint for compatibility
230
- @api.get("/v1/audio/voices") # Fake GET endpoint
231
- @api.get("/v1/stt/audio/models") # Fake endpoint
232
  async def stt_endpoint(
233
  request: Request = None,
234
  authorization: str = Header(None),
@@ -237,13 +233,12 @@ async def stt_endpoint(
237
  ):
238
  # Handle fake endpoints that just return empty responses
239
  if request and request.url.path in ["/v1/audio/voices", "/v1/stt/audio/models"]:
240
- return JSONResponse({"voices": [], "models": []})
241
 
242
  check_key(authorization)
243
  if not BYTEZ_AUTH:
244
  raise HTTPException(status_code=500, detail="Server BYTEZ_API_KEY not configured")
245
 
246
- # Handle file upload
247
  if file is None:
248
  raise HTTPException(status_code=400, detail="No audio file provided")
249
 
@@ -279,7 +274,6 @@ async def stt_endpoint(
279
  try:
280
  data = r.json()
281
  except json.JSONDecodeError:
282
- # If response isn't JSON, try to extract text from raw response
283
  transcript = r.text.strip()
284
  if not transcript:
285
  raise HTTPException(status_code=502, detail="STT returned empty response")
@@ -305,7 +299,7 @@ with gr.Blocks() as ui:
305
  "- `/v1/chat/completions`\n"
306
  "- `/v1/audio/speech` (TTS)\n"
307
  "- `/v1/audio/transcriptions` (STT)\n\n"
308
- "**Also compatible with non-standard endpoints used by some clients**")
309
 
310
  demo = gr.mount_gradio_app(api, ui, path="/")
311
 
 
10
  import io
11
 
12
  # ---------------------------------------------------------------------
13
+ # Configuration - FIXED TRAILING SPACES
14
  # ---------------------------------------------------------------------
15
  BYTEZ_CHAT_URL = "https://api.bytez.com/models/v2/openai/v1/chat/completions"
16
  BYTEZ_MODELS_URL = "https://api.bytez.com/models/v2/list/models"
 
63
  )
64
 
65
  # ---------------------------------------------------------------------
66
+ # /v1/chat/completions - FIXED STREAMING AND SYNTAX
67
  # ---------------------------------------------------------------------
68
  @api.post("/v1/chat/completions")
69
  async def chat(request: Request, authorization: str = Header(None)):
 
85
  line = line.strip()
86
  if not line:
87
  continue
88
+ if line.startswith("data: "):
89
  json_str = line[6:].strip()
90
  else:
91
  json_str = line
92
 
93
  if json_str == "[DONE]":
94
+ yield "data: [DONE]\n\n"
95
  break
96
 
97
  try:
 
131
  "finish_reason": None,
132
  }],
133
  }
134
+ yield f"data: {json.dumps(openai_chunk)}\n\n"
135
+ yield "data: [DONE]\n\n"
136
 
137
  if stream:
138
  return StreamingResponse(
 
141
  headers={"Access-Control-Allow-Origin": "*"}
142
  )
143
 
144
+ # Non-streaming path - FIXED SYNTAX ERROR HERE
145
  async with httpx.AsyncClient(timeout=120) as c:
146
  r = await c.post(BYTEZ_CHAT_URL, headers=headers, json=payload)
147
  try:
 
149
  except json.JSONDecodeError:
150
  raise HTTPException(status_code=502, detail="Upstream returned invalid JSON")
151
 
152
+ # FIXED: Complete the condition
153
+ if "choices" not in data:
154
  content = (
155
  data.get("output")
156
  or data.get("response")
 
167
  return JSONResponse(data, headers={"Access-Control-Allow-Origin": "*"})
168
 
169
  # ---------------------------------------------------------------------
170
+ # TTS ENDPOINTS (ALL VARIATIONS)
171
  # ---------------------------------------------------------------------
172
  @api.post("/v1/audio/speech")
173
  @api.post("/v1/tts/audio/speech")
174
  @api.post("/v1/tts")
175
+ @api.post("/v1/tts/audio/transcriptions")
176
  async def tts_endpoint(
177
+ request: Request = None,
178
  authorization: str = Header(None),
179
+ text: str = Form(None),
180
+ file: UploadFile = File(None)
181
  ):
182
  check_key(authorization)
183
  if not BYTEZ_AUTH:
184
  raise HTTPException(status_code=500, detail="Server BYTEZ_API_KEY not configured")
185
 
186
+ # Handle different content types
187
+ if request and request.headers.get("Content-Type", "").startswith("application/json"):
188
  try:
189
  payload = await request.json()
190
  text = payload.get("input") or payload.get("text", "")
191
  except:
192
  text = ""
 
 
 
 
193
 
194
  if not text:
195
  raise HTTPException(status_code=400, detail="Missing text for TTS conversion")
 
213
  # Return raw audio
214
  return Response(
215
  content=r.content,
216
+ media_type="audio/mpeg",
217
  headers={"Access-Control-Allow-Origin": "*"}
218
  )
219
 
220
  # ---------------------------------------------------------------------
221
+ # STT ENDPOINTS (ALL VARIATIONS)
222
  # ---------------------------------------------------------------------
223
  @api.post("/v1/audio/transcriptions")
224
  @api.post("/v1/stt")
225
  @api.post("/v1/stt/audio/transcriptions")
226
+ @api.get("/v1/audio/voices")
227
+ @api.get("/v1/stt/audio/models")
 
228
  async def stt_endpoint(
229
  request: Request = None,
230
  authorization: str = Header(None),
 
233
  ):
234
  # Handle fake endpoints that just return empty responses
235
  if request and request.url.path in ["/v1/audio/voices", "/v1/stt/audio/models"]:
236
+ return JSONResponse({"data": []})
237
 
238
  check_key(authorization)
239
  if not BYTEZ_AUTH:
240
  raise HTTPException(status_code=500, detail="Server BYTEZ_API_KEY not configured")
241
 
 
242
  if file is None:
243
  raise HTTPException(status_code=400, detail="No audio file provided")
244
 
 
274
  try:
275
  data = r.json()
276
  except json.JSONDecodeError:
 
277
  transcript = r.text.strip()
278
  if not transcript:
279
  raise HTTPException(status_code=502, detail="STT returned empty response")
 
299
  "- `/v1/chat/completions`\n"
300
  "- `/v1/audio/speech` (TTS)\n"
301
  "- `/v1/audio/transcriptions` (STT)\n\n"
302
+ "**Also compatible with non-standard endpoints**")
303
 
304
  demo = gr.mount_gradio_app(api, ui, path="/")
305