bahi-bh commited on
Commit
c1213b9
·
verified ·
1 Parent(s): 7b6bfa6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -204
app.py CHANGED
@@ -2,16 +2,23 @@ from fastapi import FastAPI, Request, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi.responses import StreamingResponse, JSONResponse
4
  from pydantic import BaseModel
5
- from typing import List, Optional
6
-
7
  import json
8
  import time
9
  import uuid
10
  import logging
 
11
 
 
12
  import g4f
13
- from g4f.client import Client
14
-
 
 
 
 
 
 
15
 
16
  # =====================================================
17
  # LOGGING
@@ -20,13 +27,11 @@ from g4f.client import Client
20
  logging.basicConfig(level=logging.INFO)
21
  logger = logging.getLogger(__name__)
22
 
23
-
24
  # =====================================================
25
  # CONFIG
26
  # =====================================================
27
 
28
- API_KEY = "sk-your-secret-key"
29
-
30
 
31
  # =====================================================
32
  # FASTAPI
@@ -37,7 +42,6 @@ app = FastAPI(
37
  version="5.3.0"
38
  )
39
 
40
-
41
  # =====================================================
42
  # CORS
43
  # =====================================================
@@ -50,7 +54,6 @@ app.add_middleware(
50
  allow_headers=["*"],
51
  )
52
 
53
-
54
  # =====================================================
55
  # MODELS
56
  # =====================================================
@@ -59,92 +62,64 @@ class Message(BaseModel):
59
  role: str
60
  content: str
61
 
62
-
63
  class ChatRequest(BaseModel):
64
- model: str
65
  messages: List[Message]
66
  stream: bool = False
67
  temperature: Optional[float] = 0.7
68
  max_tokens: Optional[int] = 4096
69
 
70
-
71
  # =====================================================
72
  # AUTH
73
  # =====================================================
74
 
75
  def verify_api_key(req: Request):
76
-
77
  auth = req.headers.get("Authorization")
78
-
79
- # السماح بدون مفتاح للاختبار
80
  if not auth:
81
  return True
82
-
83
  if not auth.startswith("Bearer "):
84
- raise HTTPException(
85
- status_code=401,
86
- detail="Invalid Authorization Format"
87
- )
88
-
89
  token = auth.replace("Bearer ", "").strip()
90
-
91
  if token != API_KEY:
92
- raise HTTPException(
93
- status_code=403,
94
- detail="Invalid API Key"
95
- )
96
-
97
  return True
98
 
99
-
100
  # =====================================================
101
  # ROOT
102
  # =====================================================
103
 
104
  @app.get("/")
105
  async def root():
106
-
107
  return {
108
  "status": "online",
109
  "service": "Universal AI Gateway",
110
- "version": "5.3.0"
 
111
  }
112
 
113
-
114
  # =====================================================
115
  # MODELS
116
  # =====================================================
117
 
118
  @app.get("/v1/models")
119
  async def get_models():
120
-
121
- models_data = []
122
-
123
- try:
124
-
125
- if hasattr(g4f.models, "_all_models"):
126
-
127
- all_models = list(g4f.models._all_models)
128
-
129
- for model in all_models:
130
-
131
- models_data.append({
132
- "id": str(model),
133
- "object": "model",
134
- "created": int(time.time()),
135
- "owned_by": "g4f"
136
- })
137
-
138
- except Exception as e:
139
-
140
- logger.error(f"Models error: {e}")
141
-
142
  return {
143
  "object": "list",
144
  "data": models_data
145
  }
146
 
147
-
148
  # =====================================================
149
  # CHAT COMPLETIONS
150
  # =====================================================
@@ -154,64 +129,37 @@ async def chat_completions(
154
  req: Request,
155
  body: ChatRequest
156
  ):
157
-
158
  verify_api_key(req)
159
-
 
160
  messages = [
161
- {
162
- "role": m.role,
163
- "content": m.content
164
- }
165
  for m in body.messages
166
  ]
167
-
168
- logger.info(
169
- f"Request model={body.model} stream={body.stream}"
170
- )
171
-
172
  # =================================================
173
  # STREAMING
174
  # =================================================
175
-
176
  if body.stream:
177
-
178
- def generate_stream():
179
-
180
- chunk_id = f"chatcmpl-{uuid.uuid4().hex}"
181
-
182
  try:
183
-
184
- client = Client()
185
-
186
- response = client.chat.completions.create(
187
  model=body.model,
188
  messages=messages,
189
- stream=True
 
190
  )
191
-
192
- has_content = False
193
-
194
- for chunk in response:
195
-
196
- try:
197
-
198
- content = ""
199
-
200
- if (
201
- hasattr(chunk, "choices")
202
- and chunk.choices
203
- and len(chunk.choices) > 0
204
- and hasattr(chunk.choices[0], "delta")
205
- and chunk.choices[0].delta
206
- and chunk.choices[0].delta.content
207
- ):
208
- content = chunk.choices[0].delta.content
209
-
210
- if not content:
211
- continue
212
-
213
- has_content = True
214
-
215
  payload = {
216
  "id": chunk_id,
217
  "object": "chat.completion.chunk",
@@ -220,44 +168,14 @@ async def chat_completions(
220
  "choices": [
221
  {
222
  "index": 0,
223
- "delta": {
224
- "content": content
225
- },
226
  "finish_reason": None
227
  }
228
  ]
229
  }
230
-
231
- yield (
232
- "data: "
233
- + json.dumps(
234
- payload,
235
- ensure_ascii=False
236
- )
237
- + "\n\n"
238
- )
239
-
240
- except Exception as chunk_error:
241
-
242
- logger.error(
243
- f"Chunk error: {chunk_error}"
244
- )
245
-
246
- if not has_content:
247
-
248
- error_payload = {
249
- "error": {
250
- "message": "Provider returned empty stream",
251
- "type": "empty_stream"
252
- }
253
- }
254
-
255
- yield (
256
- "data: "
257
- + json.dumps(error_payload)
258
- + "\n\n"
259
- )
260
-
261
  final_payload = {
262
  "id": chunk_id,
263
  "object": "chat.completion.chunk",
@@ -271,124 +189,73 @@ async def chat_completions(
271
  }
272
  ]
273
  }
274
-
275
- yield (
276
- "data: "
277
- + json.dumps(final_payload)
278
- + "\n\n"
279
- )
280
-
281
  yield "data: [DONE]\n\n"
282
-
283
  except Exception as e:
284
-
285
- logger.error(
286
- f"Streaming error: {e}"
287
- )
288
-
289
- error_payload = {
290
- "error": {
291
- "message": str(e),
292
- "type": "server_error"
293
- }
294
- }
295
-
296
- yield (
297
- "data: "
298
- + json.dumps(error_payload)
299
- + "\n\n"
300
- )
301
-
302
  yield "data: [DONE]\n\n"
303
-
304
  return StreamingResponse(
305
  generate_stream(),
306
  media_type="text/event-stream",
307
  headers={
308
  "Cache-Control": "no-cache",
309
  "Connection": "keep-alive",
310
- "X-Accel-Buffering": "no"
311
  }
312
  )
313
-
314
  # =================================================
315
  # NORMAL RESPONSE
316
  # =================================================
317
-
318
  try:
319
-
320
- client = Client()
321
-
322
- response = client.chat.completions.create(
323
  model=body.model,
324
  messages=messages,
325
- stream=False
 
326
  )
327
-
328
- assistant_message = ""
329
-
330
- try:
331
-
332
- assistant_message = (
333
- response
334
- .choices[0]
335
- .message
336
- .content
337
- )
338
-
339
- except Exception:
340
-
341
- assistant_message = str(response)
342
-
343
  return JSONResponse({
344
-
345
- "id": (
346
- f"chatcmpl-{uuid.uuid4().hex}"
347
- ),
348
-
349
  "object": "chat.completion",
350
-
351
  "created": int(time.time()),
352
-
353
  "model": body.model,
354
-
355
  "choices": [
356
  {
357
  "index": 0,
358
  "message": {
359
  "role": "assistant",
360
- "content": assistant_message
361
  },
362
  "finish_reason": "stop"
363
  }
364
  ],
365
-
366
  "usage": {
367
  "prompt_tokens": 0,
368
  "completion_tokens": 0,
369
  "total_tokens": 0
370
  }
371
-
372
  })
373
-
374
  except Exception as e:
375
-
376
- logger.error(f"Chat error: {e}")
377
-
378
  raise HTTPException(
379
  status_code=500,
380
- detail=str(e)
381
  )
382
 
383
-
384
  # =====================================================
385
  # RUN
386
  # =====================================================
387
 
388
  if __name__ == "__main__":
389
-
390
  import uvicorn
391
-
392
  uvicorn.run(
393
  app,
394
  host="0.0.0.0",
 
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi.responses import StreamingResponse, JSONResponse
4
  from pydantic import BaseModel
5
+ from typing import List, Optional, AsyncGenerator
 
6
  import json
7
  import time
8
  import uuid
9
  import logging
10
+ import asyncio
11
 
12
+ # استيراد g4f بالطريقة الصحيحة
13
  import g4f
14
+ from g4f import ChatCompletion
15
+ from g4f.Provider import (
16
+ Bing,
17
+ OpenaiChat,
18
+ Gemini,
19
+ You,
20
+ AIChat
21
+ )
22
 
23
  # =====================================================
24
  # LOGGING
 
27
  logging.basicConfig(level=logging.INFO)
28
  logger = logging.getLogger(__name__)
29
 
 
30
  # =====================================================
31
  # CONFIG
32
  # =====================================================
33
 
34
+ API_KEY = "sk-your-secret-key" # غيّر هذا
 
35
 
36
  # =====================================================
37
  # FASTAPI
 
42
  version="5.3.0"
43
  )
44
 
 
45
  # =====================================================
46
  # CORS
47
  # =====================================================
 
54
  allow_headers=["*"],
55
  )
56
 
 
57
  # =====================================================
58
  # MODELS
59
  # =====================================================
 
62
  role: str
63
  content: str
64
 
 
65
  class ChatRequest(BaseModel):
66
+ model: str = "gpt-3.5-turbo"
67
  messages: List[Message]
68
  stream: bool = False
69
  temperature: Optional[float] = 0.7
70
  max_tokens: Optional[int] = 4096
71
 
 
72
  # =====================================================
73
  # AUTH
74
  # =====================================================
75
 
76
  def verify_api_key(req: Request):
77
+ # للاختبار: السماح بدون مفتاح
78
  auth = req.headers.get("Authorization")
 
 
79
  if not auth:
80
  return True
81
+
82
  if not auth.startswith("Bearer "):
83
+ raise HTTPException(status_code=401, detail="Invalid Authorization Format")
84
+
 
 
 
85
  token = auth.replace("Bearer ", "").strip()
 
86
  if token != API_KEY:
87
+ raise HTTPException(status_code=403, detail="Invalid API Key")
88
+
 
 
 
89
  return True
90
 
 
91
  # =====================================================
92
  # ROOT
93
  # =====================================================
94
 
95
  @app.get("/")
96
  async def root():
 
97
  return {
98
  "status": "online",
99
  "service": "Universal AI Gateway",
100
+ "version": "5.3.0",
101
+ "providers": ["Bing", "OpenaiChat", "Gemini", "You"]
102
  }
103
 
 
104
  # =====================================================
105
  # MODELS
106
  # =====================================================
107
 
108
  @app.get("/v1/models")
109
  async def get_models():
110
+ # قائمة النماذج المدعومة فعلياً
111
+ models_data = [
112
+ {"id": "gpt-3.5-turbo", "object": "model", "owned_by": "g4f"},
113
+ {"id": "gpt-4", "object": "model", "owned_by": "g4f"},
114
+ {"id": "gpt-4o-mini", "object": "model", "owned_by": "g4f"},
115
+ {"id": "gemini", "object": "model", "owned_by": "g4f"},
116
+ ]
117
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  return {
119
  "object": "list",
120
  "data": models_data
121
  }
122
 
 
123
  # =====================================================
124
  # CHAT COMPLETIONS
125
  # =====================================================
 
129
  req: Request,
130
  body: ChatRequest
131
  ):
132
+ # التحقق من المفتاح
133
  verify_api_key(req)
134
+
135
+ # تحويل الرسائل
136
  messages = [
137
+ {"role": m.role, "content": m.content}
 
 
 
138
  for m in body.messages
139
  ]
140
+
141
+ logger.info(f"Request: model={body.model}, stream={body.stream}")
142
+ logger.info(f"Messages: {messages}")
143
+
 
144
  # =================================================
145
  # STREAMING
146
  # =================================================
147
+
148
  if body.stream:
149
+ async def generate_stream() -> AsyncGenerator[str, None]:
150
+ chunk_id = f"chatcmpl-{uuid.uuid4().hex[:8]}"
151
+
 
 
152
  try:
153
+ # استخدام ChatCompletion.create مع stream=True
154
+ response = await ChatCompletion.create_async(
 
 
155
  model=body.model,
156
  messages=messages,
157
+ stream=True,
158
+ provider=Bing # جرب Bing أو OpenaiChat
159
  )
160
+
161
+ async for chunk in response:
162
+ if chunk:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  payload = {
164
  "id": chunk_id,
165
  "object": "chat.completion.chunk",
 
168
  "choices": [
169
  {
170
  "index": 0,
171
+ "delta": {"content": chunk},
 
 
172
  "finish_reason": None
173
  }
174
  ]
175
  }
176
+ yield f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"
177
+
178
+ # إرسال إشارة النهاية
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  final_payload = {
180
  "id": chunk_id,
181
  "object": "chat.completion.chunk",
 
189
  }
190
  ]
191
  }
192
+ yield f"data: {json.dumps(final_payload)}\n\n"
 
 
 
 
 
 
193
  yield "data: [DONE]\n\n"
194
+
195
  except Exception as e:
196
+ logger.error(f"Streaming error: {e}", exc_info=True)
197
+ error_msg = {"error": {"message": str(e), "type": "stream_error"}}
198
+ yield f"data: {json.dumps(error_msg)}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  yield "data: [DONE]\n\n"
200
+
201
  return StreamingResponse(
202
  generate_stream(),
203
  media_type="text/event-stream",
204
  headers={
205
  "Cache-Control": "no-cache",
206
  "Connection": "keep-alive",
207
+ "Access-Control-Allow-Origin": "*"
208
  }
209
  )
210
+
211
  # =================================================
212
  # NORMAL RESPONSE
213
  # =================================================
214
+
215
  try:
216
+ # استخدام ChatCompletion.create_async
217
+ response = await ChatCompletion.create_async(
 
 
218
  model=body.model,
219
  messages=messages,
220
+ stream=False,
221
+ provider=Bing # جرب مزوداً مختلفاً إذا فشل
222
  )
223
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  return JSONResponse({
225
+ "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
 
 
 
 
226
  "object": "chat.completion",
 
227
  "created": int(time.time()),
 
228
  "model": body.model,
 
229
  "choices": [
230
  {
231
  "index": 0,
232
  "message": {
233
  "role": "assistant",
234
+ "content": response
235
  },
236
  "finish_reason": "stop"
237
  }
238
  ],
 
239
  "usage": {
240
  "prompt_tokens": 0,
241
  "completion_tokens": 0,
242
  "total_tokens": 0
243
  }
 
244
  })
245
+
246
  except Exception as e:
247
+ logger.error(f"Chat error: {e}", exc_info=True)
 
 
248
  raise HTTPException(
249
  status_code=500,
250
+ detail=f"Provider error: {str(e)}"
251
  )
252
 
 
253
  # =====================================================
254
  # RUN
255
  # =====================================================
256
 
257
  if __name__ == "__main__":
 
258
  import uvicorn
 
259
  uvicorn.run(
260
  app,
261
  host="0.0.0.0",