bahi-bh commited on
Commit
7b14409
ยท
verified ยท
1 Parent(s): a02eea0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -15
app.py CHANGED
@@ -28,9 +28,12 @@ logger = logging.getLogger(__name__)
28
 
29
  API_KEY = "sk-your-secret-key"
30
 
31
- # timeout ู„ู…ู†ุน ุงู„ุชุนู„ูŠู‚ ุงู„ุฃุจุฏูŠ
32
  REQUEST_TIMEOUT = 45
33
 
 
 
 
34
  # retry ุฎููŠู
35
  MAX_RETRIES = 2
36
 
@@ -41,7 +44,7 @@ MAX_RETRIES = 2
41
 
42
  app = FastAPI(
43
  title="Universal AI Gateway",
44
- version="4.2.0"
45
  )
46
 
47
 
@@ -114,7 +117,7 @@ async def root():
114
  return {
115
  "status": "online",
116
  "service": "Universal AI Gateway",
117
- "version": "4.2.0"
118
  }
119
 
120
 
@@ -128,7 +131,7 @@ async def get_models():
128
  models_data = []
129
 
130
  # =================================================
131
- # MODELS THAT WORK WELL
132
  # =================================================
133
 
134
  fallback_models = [
@@ -141,18 +144,36 @@ async def get_models():
141
 
142
  # Claude
143
  "claude-3-haiku",
 
144
 
145
  # Llama
146
  "llama-3.1-70b",
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  # Mixtral
149
  "mixtral-8x7b",
150
 
151
- # Deepseek
152
- "deepseek-chat",
 
 
 
 
153
 
154
- # Gemini
155
- "gemini-pro",
156
 
157
  # =================================================
158
  # COHERE FAMILY
@@ -162,11 +183,17 @@ async def get_models():
162
  "command-r-plus",
163
  "command-r7b",
164
  "command",
 
 
165
  "command-nightly",
166
 
167
- # Additional Cohere-style names
168
  "cohere-command-r",
169
  "cohere-command-r-plus",
 
 
 
 
170
  ]
171
 
172
  added_models = set()
@@ -177,7 +204,7 @@ async def get_models():
177
 
178
  all_models = list(g4f.models._all_models)
179
 
180
- for model in all_models[:100]:
181
 
182
  model_name = str(model)
183
 
@@ -196,7 +223,10 @@ async def get_models():
196
 
197
  logger.error(f"Models error: {e}")
198
 
199
- # fallback models
 
 
 
200
  for model in fallback_models:
201
 
202
  if model not in added_models:
@@ -212,7 +242,8 @@ async def get_models():
212
 
213
  return {
214
  "object": "list",
215
- "data": models_data
 
216
  }
217
 
218
 
@@ -238,7 +269,6 @@ async def safe_completion(
238
 
239
  client = Client()
240
 
241
- # timeout ู„ู…ู†ุน ุงู„ุชุนู„ูŠู‚ ุงู„ุฃุจุฏูŠ
242
  response = await asyncio.wait_for(
243
  asyncio.to_thread(
244
  client.chat.completions.create,
@@ -276,6 +306,15 @@ async def safe_completion(
276
  raise Exception(last_error)
277
 
278
 
 
 
 
 
 
 
 
 
 
279
  # =====================================================
280
  # CHAT COMPLETIONS
281
  # =====================================================
@@ -320,12 +359,52 @@ async def chat_completions(
320
 
321
  has_content = False
322
 
323
- for chunk in response:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
  try:
326
 
327
  content = ""
328
 
 
 
 
 
 
 
 
 
 
329
  if (
330
  hasattr(chunk, "choices")
331
  and chunk.choices
@@ -367,7 +446,7 @@ async def chat_completions(
367
  f"Chunk error: {chunk_error}"
368
  )
369
 
370
- # provider ูุชุญ stream ุจุฏูˆู† ู…ุญุชูˆู‰
371
  if not has_content:
372
 
373
  error_payload = {
 
28
 
29
  API_KEY = "sk-your-secret-key"
30
 
31
+ # timeout ุนุงู…
32
  REQUEST_TIMEOUT = 45
33
 
34
+ # timeout ู„ู„ู€ stream ู†ูุณู‡
35
+ STREAM_CHUNK_TIMEOUT = 20
36
+
37
  # retry ุฎููŠู
38
  MAX_RETRIES = 2
39
 
 
44
 
45
  app = FastAPI(
46
  title="Universal AI Gateway",
47
+ version="4.3.0"
48
  )
49
 
50
 
 
117
  return {
118
  "status": "online",
119
  "service": "Universal AI Gateway",
120
+ "version": "4.3.0"
121
  }
122
 
123
 
 
131
  models_data = []
132
 
133
  # =================================================
134
+ # CURATED MODELS
135
  # =================================================
136
 
137
  fallback_models = [
 
144
 
145
  # Claude
146
  "claude-3-haiku",
147
+ "claude-3-sonnet",
148
 
149
  # Llama
150
  "llama-3.1-70b",
151
+ "llama-3.1-8b",
152
+
153
+ # Qwen
154
+ "qwen-2-72b",
155
+ "qwen-2.5-72b",
156
+
157
+ # DeepSeek
158
+ "deepseek-chat",
159
+ "deepseek-v3",
160
+ "deepseek-r1-distill-qwen-14b",
161
+
162
+ # Kimi
163
+ "kimi-k2",
164
 
165
  # Mixtral
166
  "mixtral-8x7b",
167
 
168
+ # Aria
169
+ "aria",
170
+
171
+ # Sonar
172
+ "sonar-reasoning",
173
+ "sonar-reasoning-pro",
174
 
175
+ # Nemotron
176
+ "nemotron-70b",
177
 
178
  # =================================================
179
  # COHERE FAMILY
 
183
  "command-r-plus",
184
  "command-r7b",
185
  "command",
186
+ "command-light",
187
+ "command-light-nightly",
188
  "command-nightly",
189
 
190
+ # Cohere advanced
191
  "cohere-command-r",
192
  "cohere-command-r-plus",
193
+
194
+ # Additional aliases
195
+ "c4ai-command-r-plus",
196
+ "c4ai-command-r-v01",
197
  ]
198
 
199
  added_models = set()
 
204
 
205
  all_models = list(g4f.models._all_models)
206
 
207
+ for model in all_models[:120]:
208
 
209
  model_name = str(model)
210
 
 
223
 
224
  logger.error(f"Models error: {e}")
225
 
226
+ # =================================================
227
+ # ADD CURATED MODELS
228
+ # =================================================
229
+
230
  for model in fallback_models:
231
 
232
  if model not in added_models:
 
242
 
243
  return {
244
  "object": "list",
245
+ "data": models_data,
246
+ "total": len(models_data)
247
  }
248
 
249
 
 
269
 
270
  client = Client()
271
 
 
272
  response = await asyncio.wait_for(
273
  asyncio.to_thread(
274
  client.chat.completions.create,
 
306
  raise Exception(last_error)
307
 
308
 
309
+ # =====================================================
310
+ # STREAM WATCHDOG
311
+ # =====================================================
312
+
313
+ async def next_chunk(iterator):
314
+
315
+ return await asyncio.to_thread(next, iterator)
316
+
317
+
318
  # =====================================================
319
  # CHAT COMPLETIONS
320
  # =====================================================
 
359
 
360
  has_content = False
361
 
362
+ while True:
363
+
364
+ try:
365
+
366
+ # watchdog ู„ู„ู€ stream
367
+ chunk = await asyncio.wait_for(
368
+ next_chunk(response),
369
+ timeout=STREAM_CHUNK_TIMEOUT
370
+ )
371
+
372
+ except StopIteration:
373
+ break
374
+
375
+ except asyncio.TimeoutError:
376
+
377
+ logger.warning(
378
+ f"Stream stalled | model={body.model}"
379
+ )
380
+
381
+ error_payload = {
382
+ "error": {
383
+ "message": "Stream timeout",
384
+ "type": "stream_timeout"
385
+ }
386
+ }
387
+
388
+ yield (
389
+ f"data: "
390
+ f"{json.dumps(error_payload)}\n\n"
391
+ )
392
+
393
+ break
394
 
395
  try:
396
 
397
  content = ""
398
 
399
+ # ุญู…ุงูŠุฉ ู…ู† ImageResponse
400
+ if hasattr(chunk, "images"):
401
+
402
+ logger.warning(
403
+ f"Image model detected | model={body.model}"
404
+ )
405
+
406
+ continue
407
+
408
  if (
409
  hasattr(chunk, "choices")
410
  and chunk.choices
 
446
  f"Chunk error: {chunk_error}"
447
  )
448
 
449
+ # stream ูุงุฑุบ
450
  if not has_content:
451
 
452
  error_payload = {