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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -122
app.py CHANGED
@@ -3,22 +3,21 @@ 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
 
@@ -30,33 +29,20 @@ app.add_middleware(
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
@@ -67,42 +53,43 @@ class ChatRequest(BaseModel):
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",
@@ -111,79 +98,69 @@ async def get_models():
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
 
128
- for provider in PROVIDERS:
129
 
130
- try:
131
-
132
- response = g4f.ChatCompletion.create(
133
- model=model,
134
- provider=provider,
135
- messages=messages,
136
- stream=True
137
- )
138
 
139
- for chunk in response:
140
 
141
- if chunk:
142
 
143
- payload = {
144
- "id": f"chatcmpl-{uuid.uuid4().hex}",
145
- "object": "chat.completion.chunk",
146
- "created": int(time.time()),
147
- "model": model,
148
- "choices": [
149
- {
150
- "delta": {
151
- "content": chunk
152
- }
153
  }
154
- ]
155
- }
156
-
157
- yield f"data: {json.dumps(payload)}\n\n"
158
-
159
- await asyncio.sleep(0)
160
-
161
- yield "data: [DONE]\n\n"
162
 
163
- return
164
 
165
- except Exception as e:
166
 
167
- last_error = str(e)
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,55 +170,50 @@ async def chat(req: Request, body: ChatRequest):
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
- )
 
3
  from fastapi.middleware.cors import CORSMiddleware
4
  from pydantic import BaseModel
5
  from typing import List
6
+ import g4f
7
  import json
8
  import uuid
9
  import time
10
+ import asyncio
11
 
12
+ # ======================================================
13
+ # API KEY
14
+ # ======================================================
 
 
15
 
16
  API_KEY = "sk-123456"
17
 
18
+ # ======================================================
19
  # APP
20
+ # ======================================================
21
 
22
  app = FastAPI()
23
 
 
29
  allow_headers=["*"],
30
  )
31
 
32
+ # ======================================================
33
  # MODELS
34
+ # ======================================================
35
 
36
  MODELS = [
37
  "gpt-4o-mini",
38
  "gpt-4",
39
  "claude-3-haiku",
40
  "llama-3.1-70b",
 
41
  ]
42
 
43
+ # ======================================================
44
+ # REQUEST
45
+ # ======================================================
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  class Message(BaseModel):
48
  role: str
 
53
  messages: List[Message]
54
  stream: bool = False
55
 
56
+ # ======================================================
57
  # AUTH
58
+ # ======================================================
59
 
60
+ def verify_api_key(req: Request):
61
 
62
  auth = req.headers.get("Authorization")
63
 
64
  if not auth:
65
+ raise HTTPException(401, "Missing API Key")
66
 
67
  if not auth.startswith("Bearer "):
68
+ raise HTTPException(401, "Invalid Authorization")
69
 
70
  token = auth.replace("Bearer ", "")
71
 
72
  if token != API_KEY:
73
+ raise HTTPException(403, "Invalid API Key")
74
 
75
+ # ======================================================
76
  # ROOT
77
+ # ======================================================
78
 
79
  @app.get("/")
80
  async def root():
81
 
82
  return {
83
+ "status": "online",
84
+ "provider": "Duck.ai"
85
  }
86
 
87
+ # ======================================================
88
  # MODELS
89
+ # ======================================================
90
 
91
  @app.get("/v1/models")
92
+ async def models():
93
 
94
  return {
95
  "object": "list",
 
98
  "id": model,
99
  "object": "model",
100
  "created": int(time.time()),
101
+ "owned_by": "duck.ai"
102
  }
103
  for model in MODELS
104
  ]
105
  }
106
 
107
+ # ======================================================
108
  # STREAM
109
+ # ======================================================
 
 
110
 
111
+ async def stream_generator(model, messages):
112
 
113
+ try:
114
 
115
+ response = g4f.ChatCompletion.create(
116
+ model=model,
117
+ provider=g4f.Provider.DuckDuckGo,
118
+ messages=messages,
119
+ stream=True
120
+ )
 
 
121
 
122
+ for chunk in response:
123
 
124
+ if chunk:
125
 
126
+ payload = {
127
+ "id": f"chatcmpl-{uuid.uuid4().hex}",
128
+ "object": "chat.completion.chunk",
129
+ "created": int(time.time()),
130
+ "model": model,
131
+ "choices": [
132
+ {
133
+ "delta": {
134
+ "content": chunk
 
135
  }
136
+ }
137
+ ]
138
+ }
 
 
 
 
 
139
 
140
+ yield f"data: {json.dumps(payload)}\n\n"
141
 
142
+ await asyncio.sleep(0)
143
 
144
+ yield "data: [DONE]\n\n"
145
 
146
+ except Exception as e:
147
 
148
+ error = {
149
+ "error": {
150
+ "message": str(e)
151
+ }
152
  }
 
153
 
154
+ yield f"data: {json.dumps(error)}\n\n"
155
 
156
+ # ======================================================
157
  # CHAT
158
+ # ======================================================
159
 
160
  @app.post("/v1/chat/completions")
161
  async def chat(req: Request, body: ChatRequest):
162
 
163
+ verify_api_key(req)
164
 
165
  messages = [
166
  {
 
170
  for m in body.messages
171
  ]
172
 
173
+ # ==================================================
174
  # STREAM
175
+ # ==================================================
176
 
177
  if body.stream:
178
 
179
  return StreamingResponse(
180
+ stream_generator(
181
+ body.model,
182
+ messages
183
+ ),
184
  media_type="text/event-stream"
185
  )
186
 
187
+ # ==================================================
188
  # NORMAL
189
+ # ==================================================
 
 
190
 
191
+ try:
192
 
193
+ response = g4f.ChatCompletion.create(
194
+ model=body.model,
195
+ provider=g4f.Provider.DuckDuckGo,
196
+ messages=messages
197
+ )
 
 
198
 
199
+ return JSONResponse({
200
+ "id": f"chatcmpl-{uuid.uuid4().hex}",
201
+ "object": "chat.completion",
202
+ "created": int(time.time()),
203
+ "model": body.model,
204
+ "choices": [
205
+ {
206
+ "message": {
207
+ "role": "assistant",
208
+ "content": response
 
209
  }
210
+ }
211
+ ]
212
+ })
 
 
 
213
 
214
+ except Exception as e:
215
 
216
+ raise HTTPException(
217
+ status_code=500,
218
+ detail=str(e)
219
+ )