bahi-bh commited on
Commit
3be5359
·
verified ·
1 Parent(s): 5d2e139

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -186
app.py CHANGED
@@ -1,34 +1,26 @@
1
  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
6
  import asyncio
7
  import json
8
- import time
9
  import uuid
 
10
 
11
  import g4f
12
- import g4f.models
13
 
14
- # =========================================================
15
  # CONFIG
16
- # =========================================================
17
 
18
- API_KEY = "sk-your-secret-key"
19
 
20
- # =========================================================
21
  # APP
22
- # =========================================================
23
-
24
- app = FastAPI(
25
- title="DuckAI Gateway",
26
- version="3.0.0"
27
- )
28
 
29
- # =========================================================
30
- # CORS
31
- # =========================================================
32
 
33
  app.add_middleware(
34
  CORSMiddleware,
@@ -38,20 +30,33 @@ app.add_middleware(
38
  allow_headers=["*"],
39
  )
40
 
41
- # =========================================================
 
 
 
 
 
 
 
 
 
 
 
 
42
  # PROVIDERS
43
- # =========================================================
44
 
45
- PROVIDERS = [
46
- g4f.Provider.DuckDuckGo,
47
- g4f.Provider.Blackbox,
48
- g4f.Provider.Free2GPT,
49
- g4f.Provider.Bing
50
- ]
51
 
52
- # =========================================================
53
- # MODELS
54
- # =========================================================
 
 
 
 
 
 
55
 
56
  class Message(BaseModel):
57
  role: str
@@ -61,128 +66,62 @@ class ChatRequest(BaseModel):
61
  model: str
62
  messages: List[Message]
63
  stream: bool = False
64
- temperature: float = 0.7
65
- max_tokens: int = 4096
66
 
67
- # =========================================================
68
  # AUTH
69
- # =========================================================
70
 
71
- def verify_api_key(req: Request):
72
 
73
  auth = req.headers.get("Authorization")
74
 
75
  if not auth:
76
- raise HTTPException(
77
- status_code=401,
78
- detail="Missing Authorization Header"
79
- )
80
 
81
  if not auth.startswith("Bearer "):
82
- raise HTTPException(
83
- status_code=401,
84
- detail="Invalid Authorization Format"
85
- )
86
 
87
  token = auth.replace("Bearer ", "")
88
 
89
  if token != API_KEY:
90
- raise HTTPException(
91
- status_code=403,
92
- detail="Invalid API Key"
93
- )
94
 
95
- # =========================================================
96
  # ROOT
97
- # =========================================================
98
 
99
  @app.get("/")
100
  async def root():
101
 
102
  return {
103
- "status": "online",
104
- "service": "DuckAI Gateway"
105
  }
106
 
107
- # =========================================================
108
  # MODELS
109
- # =========================================================
110
 
111
  @app.get("/v1/models")
112
- async def models():
113
-
114
- data = []
115
-
116
- try:
117
-
118
- all_models = list(g4f.models._all_models)
119
 
120
- for model_name in all_models:
121
-
122
- data.append({
123
- "id": str(model_name),
 
124
  "object": "model",
125
  "created": int(time.time()),
126
  "owned_by": "g4f"
127
- })
128
-
129
- except Exception:
130
-
131
- fallback = [
132
- "gpt-4o-mini",
133
- "gpt-4",
134
- "claude-3-haiku",
135
- "llama-3.1-70b",
136
- "mixtral-8x7b"
137
  ]
138
-
139
- for model_name in fallback:
140
-
141
- data.append({
142
- "id": model_name,
143
- "object": "model",
144
- "created": int(time.time()),
145
- "owned_by": "g4f"
146
- })
147
-
148
- return {
149
- "object": "list",
150
- "data": data
151
  }
152
 
153
- # =========================================================
154
- # NORMAL RESPONSE
155
- # =========================================================
156
 
157
- def generate_response(model, messages):
158
-
159
- last_error = None
160
-
161
- for provider in PROVIDERS:
162
-
163
- try:
164
-
165
- response = g4f.ChatCompletion.create(
166
- model=model,
167
- provider=provider,
168
- messages=messages
169
- )
170
-
171
- return response
172
-
173
- except Exception as e:
174
-
175
- last_error = str(e)
176
-
177
- continue
178
-
179
- raise Exception(last_error or "All providers failed")
180
-
181
- # =========================================================
182
- # STREAM RESPONSE
183
- # =========================================================
184
-
185
- async def generate_stream(model, messages):
186
 
187
  last_error = None
188
 
@@ -208,11 +147,9 @@ async def generate_stream(model, messages):
208
  "model": model,
209
  "choices": [
210
  {
211
- "index": 0,
212
  "delta": {
213
  "content": chunk
214
- },
215
- "finish_reason": None
216
  }
217
  ]
218
  }
@@ -221,22 +158,6 @@ async def generate_stream(model, messages):
221
 
222
  await asyncio.sleep(0)
223
 
224
- done_payload = {
225
- "id": f"chatcmpl-{uuid.uuid4().hex}",
226
- "object": "chat.completion.chunk",
227
- "created": int(time.time()),
228
- "model": model,
229
- "choices": [
230
- {
231
- "index": 0,
232
- "delta": {},
233
- "finish_reason": "stop"
234
- }
235
- ]
236
- }
237
-
238
- yield f"data: {json.dumps(done_payload)}\n\n"
239
-
240
  yield "data: [DONE]\n\n"
241
 
242
  return
@@ -247,26 +168,22 @@ async def generate_stream(model, messages):
247
 
248
  continue
249
 
250
- error_payload = {
251
  "error": {
252
- "message": last_error or "All providers failed",
253
- "type": "server_error"
254
  }
255
  }
256
 
257
- yield f"data: {json.dumps(error_payload)}\n\n"
258
 
259
- # =========================================================
260
- # CHAT COMPLETIONS
261
- # =========================================================
262
 
263
  @app.post("/v1/chat/completions")
264
- async def chat_completions(
265
- req: Request,
266
- body: ChatRequest
267
- ):
268
 
269
- verify_api_key(req)
270
 
271
  messages = [
272
  {
@@ -276,56 +193,55 @@ async def chat_completions(
276
  for m in body.messages
277
  ]
278
 
279
- # =====================================================
280
  # STREAM
281
- # =====================================================
282
 
283
  if body.stream:
284
 
285
  return StreamingResponse(
286
- generate_stream(
287
- body.model,
288
- messages
289
- ),
290
  media_type="text/event-stream"
291
  )
292
 
293
- # =====================================================
294
  # NORMAL
295
- # =====================================================
296
 
297
- try:
298
 
299
- response = generate_response(
300
- body.model,
301
- messages
302
- )
303
 
304
- return JSONResponse({
305
- "id": f"chatcmpl-{uuid.uuid4().hex}",
306
- "object": "chat.completion",
307
- "created": int(time.time()),
308
- "model": body.model,
309
- "choices": [
310
- {
311
- "index": 0,
312
- "message": {
313
- "role": "assistant",
314
- "content": response
315
- },
316
- "finish_reason": "stop"
317
- }
318
- ],
319
- "usage": {
320
- "prompt_tokens": 0,
321
- "completion_tokens": 0,
322
- "total_tokens": 0
323
- }
324
- })
325
 
326
- except Exception as e:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
 
328
- raise HTTPException(
329
- status_code=500,
330
- detail=str(e)
331
- )
 
1
  from fastapi import FastAPI, Request, HTTPException
2
+ from fastapi.responses import JSONResponse, StreamingResponse
3
  from fastapi.middleware.cors import CORSMiddleware
 
4
  from pydantic import BaseModel
5
  from typing import List
6
  import asyncio
7
  import json
 
8
  import uuid
9
+ import time
10
 
11
  import g4f
 
12
 
13
+ # ==================================================
14
  # CONFIG
15
+ # ==================================================
16
 
17
+ API_KEY = "sk-123456"
18
 
19
+ # ==================================================
20
  # APP
21
+ # ==================================================
 
 
 
 
 
22
 
23
+ app = FastAPI()
 
 
24
 
25
  app.add_middleware(
26
  CORSMiddleware,
 
30
  allow_headers=["*"],
31
  )
32
 
33
+ # ==================================================
34
+ # MODELS
35
+ # ==================================================
36
+
37
+ MODELS = [
38
+ "gpt-4o-mini",
39
+ "gpt-4",
40
+ "claude-3-haiku",
41
+ "llama-3.1-70b",
42
+ "mixtral-8x7b"
43
+ ]
44
+
45
+ # ==================================================
46
  # PROVIDERS
47
+ # ==================================================
48
 
49
+ PROVIDERS = []
 
 
 
 
 
50
 
51
+ if hasattr(g4f.Provider, "DuckDuckGo"):
52
+ PROVIDERS.append(g4f.Provider.DuckDuckGo)
53
+
54
+ if hasattr(g4f.Provider, "Blackbox"):
55
+ PROVIDERS.append(g4f.Provider.Blackbox)
56
+
57
+ # ==================================================
58
+ # REQUEST MODELS
59
+ # ==================================================
60
 
61
  class Message(BaseModel):
62
  role: str
 
66
  model: str
67
  messages: List[Message]
68
  stream: bool = False
 
 
69
 
70
+ # ==================================================
71
  # AUTH
72
+ # ==================================================
73
 
74
+ def verify_key(req: Request):
75
 
76
  auth = req.headers.get("Authorization")
77
 
78
  if not auth:
79
+ raise HTTPException(status_code=401, detail="Missing API Key")
 
 
 
80
 
81
  if not auth.startswith("Bearer "):
82
+ raise HTTPException(status_code=401, detail="Invalid Auth")
 
 
 
83
 
84
  token = auth.replace("Bearer ", "")
85
 
86
  if token != API_KEY:
87
+ raise HTTPException(status_code=403, detail="Invalid API Key")
 
 
 
88
 
89
+ # ==================================================
90
  # ROOT
91
+ # ==================================================
92
 
93
  @app.get("/")
94
  async def root():
95
 
96
  return {
97
+ "status": "online"
 
98
  }
99
 
100
+ # ==================================================
101
  # MODELS
102
+ # ==================================================
103
 
104
  @app.get("/v1/models")
105
+ async def get_models():
 
 
 
 
 
 
106
 
107
+ return {
108
+ "object": "list",
109
+ "data": [
110
+ {
111
+ "id": model,
112
  "object": "model",
113
  "created": int(time.time()),
114
  "owned_by": "g4f"
115
+ }
116
+ for model in MODELS
 
 
 
 
 
 
 
 
117
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
 
120
+ # ==================================================
121
+ # STREAM
122
+ # ==================================================
123
 
124
+ async def stream_response(model, messages):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
  last_error = None
127
 
 
147
  "model": model,
148
  "choices": [
149
  {
 
150
  "delta": {
151
  "content": chunk
152
+ }
 
153
  }
154
  ]
155
  }
 
158
 
159
  await asyncio.sleep(0)
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  yield "data: [DONE]\n\n"
162
 
163
  return
 
168
 
169
  continue
170
 
171
+ error = {
172
  "error": {
173
+ "message": last_error or "All providers failed"
 
174
  }
175
  }
176
 
177
+ yield f"data: {json.dumps(error)}\n\n"
178
 
179
+ # ==================================================
180
+ # CHAT
181
+ # ==================================================
182
 
183
  @app.post("/v1/chat/completions")
184
+ async def chat(req: Request, body: ChatRequest):
 
 
 
185
 
186
+ verify_key(req)
187
 
188
  messages = [
189
  {
 
193
  for m in body.messages
194
  ]
195
 
196
+ # ==========================================
197
  # STREAM
198
+ # ==========================================
199
 
200
  if body.stream:
201
 
202
  return StreamingResponse(
203
+ stream_response(body.model, messages),
 
 
 
204
  media_type="text/event-stream"
205
  )
206
 
207
+ # ==========================================
208
  # NORMAL
209
+ # ==========================================
210
 
211
+ last_error = None
212
 
213
+ for provider in PROVIDERS:
 
 
 
214
 
215
+ try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
+ response = g4f.ChatCompletion.create(
218
+ model=body.model,
219
+ provider=provider,
220
+ messages=messages
221
+ )
222
+
223
+ return JSONResponse({
224
+ "id": f"chatcmpl-{uuid.uuid4().hex}",
225
+ "object": "chat.completion",
226
+ "created": int(time.time()),
227
+ "model": body.model,
228
+ "choices": [
229
+ {
230
+ "message": {
231
+ "role": "assistant",
232
+ "content": response
233
+ }
234
+ }
235
+ ]
236
+ })
237
+
238
+ except Exception as e:
239
+
240
+ last_error = str(e)
241
+
242
+ continue
243
 
244
+ raise HTTPException(
245
+ status_code=500,
246
+ detail=last_error or "All providers failed"
247
+ )