bahi-bh commited on
Commit
1265910
·
verified ·
1 Parent(s): 6922ffb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +179 -106
app.py CHANGED
@@ -1,56 +1,75 @@
1
- import asyncio
2
- import json
3
- from concurrent.futures import ThreadPoolExecutor
4
- from typing import List
5
-
6
- import g4f
7
-
8
- from fastapi import FastAPI, HTTPException, Header
9
  from fastapi.middleware.cors import CORSMiddleware
10
- from fastapi.responses import StreamingResponse
11
  from pydantic import BaseModel
 
 
 
 
 
 
12
 
13
- # =====================================
14
  # CONFIG
15
- # =====================================
16
 
17
  API_KEY = "sk-your-secret-key"
18
 
19
- executor = ThreadPoolExecutor(max_workers=5)
20
-
21
- # =====================================
22
- # APP
23
- # =====================================
24
 
25
  app = FastAPI(
26
- title="AI Gateway"
 
27
  )
28
 
 
 
 
 
29
  app.add_middleware(
30
  CORSMiddleware,
31
  allow_origins=["*"],
 
32
  allow_methods=["*"],
33
  allow_headers=["*"],
34
  )
35
 
36
- # =====================================
37
  # MODELS
38
- # =====================================
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  class Message(BaseModel):
41
  role: str
42
  content: str
43
 
44
  class ChatRequest(BaseModel):
45
- model: str = "gpt-4o-mini"
46
  messages: List[Message]
47
  stream: bool = False
 
 
48
 
49
- # =====================================
50
  # AUTH
51
- # =====================================
52
 
53
- def verify_api_key(auth: str):
 
 
54
 
55
  if not auth:
56
  raise HTTPException(
@@ -61,7 +80,7 @@ def verify_api_key(auth: str):
61
  if not auth.startswith("Bearer "):
62
  raise HTTPException(
63
  status_code=401,
64
- detail="Invalid Authorization"
65
  )
66
 
67
  token = auth.replace("Bearer ", "")
@@ -72,117 +91,171 @@ def verify_api_key(auth: str):
72
  detail="Invalid API Key"
73
  )
74
 
75
- # =====================================
76
- # GENERATE
77
- # =====================================
78
 
79
- def generate(model, messages):
 
80
 
81
- response = g4f.ChatCompletion.create(
82
- model=model,
83
- messages=messages
84
- )
 
 
 
85
 
86
- return response
 
87
 
88
- # =====================================
89
- # STREAM
90
- # =====================================
 
 
 
 
 
 
 
 
 
91
 
92
- async def stream_generate(model, messages):
 
 
93
 
94
- loop = asyncio.get_event_loop()
 
 
 
 
95
 
96
- response = await loop.run_in_executor(
97
- executor,
98
- lambda: g4f.ChatCompletion.create(
99
- model=model,
100
- messages=messages,
101
- stream=True
102
- )
103
- )
104
 
105
- for chunk in response:
 
 
 
 
 
 
106
 
107
- if chunk:
108
 
109
- payload = {
110
- "choices": [
111
- {
112
- "delta": {
113
- "content": chunk
114
- }
115
- }
116
- ]
117
- }
118
 
119
- yield f"data: {json.dumps(payload)}\\n\\n"
120
 
121
- yield "data: [DONE]\\n\\n"
122
 
123
- # =====================================
124
- # HOME
125
- # =====================================
126
 
127
- @app.get("/")
128
- async def home():
 
 
 
 
129
 
130
- return {
131
- "status": "online"
132
- }
133
 
134
- # =====================================
135
- # CHAT
136
- # =====================================
137
 
138
- @app.post("/v1/chat/completions")
139
- async def chat(
140
- req: ChatRequest,
141
- authorization: str = Header(None)
142
- ):
 
 
 
 
 
 
 
 
 
 
143
 
144
- verify_api_key(authorization)
145
 
146
- messages = [
147
- m.model_dump()
148
- for m in req.messages
149
- ]
150
 
151
- # =========================
152
- # STREAM
153
- # =========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
- if req.stream:
156
 
157
  return StreamingResponse(
158
- stream_generate(
159
- req.model,
160
- messages
161
- ),
162
  media_type="text/event-stream"
163
  )
164
 
165
- # =========================
166
- # NORMAL
167
- # =========================
168
 
169
- loop = asyncio.get_event_loop()
170
 
171
- response = await loop.run_in_executor(
172
- executor,
173
- lambda: generate(
174
- req.model,
175
- messages
176
  )
177
- )
178
 
179
- return {
180
- "choices": [
181
- {
182
- "message": {
183
- "role": "assistant",
184
- "content": response
 
 
 
 
 
 
 
185
  }
 
 
 
 
 
186
  }
187
- ]
188
- }
 
 
 
 
 
 
 
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 json
7
+ import uuid
8
+ import time
9
+ import asyncio
10
+ import g4f
11
 
12
+ # =========================================
13
  # CONFIG
14
+ # =========================================
15
 
16
  API_KEY = "sk-your-secret-key"
17
 
18
+ # =========================================
19
+ # FASTAPI
20
+ # =========================================
 
 
21
 
22
  app = FastAPI(
23
+ title="Universal OpenAI API",
24
+ version="1.0.0"
25
  )
26
 
27
+ # =========================================
28
+ # CORS
29
+ # =========================================
30
+
31
  app.add_middleware(
32
  CORSMiddleware,
33
  allow_origins=["*"],
34
+ allow_credentials=True,
35
  allow_methods=["*"],
36
  allow_headers=["*"],
37
  )
38
 
39
+ # =========================================
40
  # MODELS
41
+ # =========================================
42
+
43
+ AVAILABLE_MODELS = [
44
+ "gpt-4o-mini",
45
+ "gpt-4",
46
+ "claude-3-haiku",
47
+ "llama-3.1-70b",
48
+ "mixtral-8x7b"
49
+ ]
50
+
51
+ # =========================================
52
+ # Pydantic
53
+ # =========================================
54
 
55
  class Message(BaseModel):
56
  role: str
57
  content: str
58
 
59
  class ChatRequest(BaseModel):
60
+ model: str
61
  messages: List[Message]
62
  stream: bool = False
63
+ temperature: float = 0.7
64
+ max_tokens: int = 4096
65
 
66
+ # =========================================
67
  # AUTH
68
+ # =========================================
69
 
70
+ def verify_api_key(req: Request):
71
+
72
+ auth = req.headers.get("Authorization")
73
 
74
  if not auth:
75
  raise HTTPException(
 
80
  if not auth.startswith("Bearer "):
81
  raise HTTPException(
82
  status_code=401,
83
+ detail="Invalid Authorization Format"
84
  )
85
 
86
  token = auth.replace("Bearer ", "")
 
91
  detail="Invalid API Key"
92
  )
93
 
94
+ # =========================================
95
+ # ROOT
96
+ # =========================================
97
 
98
+ @app.get("/")
99
+ async def root():
100
 
101
+ return {
102
+ "status": "online"
103
+ }
104
+
105
+ # =========================================
106
+ # MODELS ENDPOINT
107
+ # =========================================
108
 
109
+ @app.get("/v1/models")
110
+ async def models():
111
 
112
+ return {
113
+ "object": "list",
114
+ "data": [
115
+ {
116
+ "id": model,
117
+ "object": "model",
118
+ "created": int(time.time()),
119
+ "owned_by": "9router"
120
+ }
121
+ for model in AVAILABLE_MODELS
122
+ ]
123
+ }
124
 
125
+ # =========================================
126
+ # CHAT COMPLETIONS
127
+ # =========================================
128
 
129
+ @app.post("/v1/chat/completions")
130
+ async def chat_completions(
131
+ req: Request,
132
+ body: ChatRequest
133
+ ):
134
 
135
+ verify_api_key(req)
 
 
 
 
 
 
 
136
 
137
+ messages = [
138
+ {
139
+ "role": m.role,
140
+ "content": m.content
141
+ }
142
+ for m in body.messages
143
+ ]
144
 
145
+ provider = g4f.Provider.Blackbox
146
 
147
+ # =====================================
148
+ # STREAMING
149
+ # =====================================
 
 
 
 
 
 
150
 
151
+ if body.stream:
152
 
153
+ async def generate_stream():
154
 
155
+ try:
 
 
156
 
157
+ response = g4f.ChatCompletion.create(
158
+ model=body.model,
159
+ provider=provider,
160
+ messages=messages,
161
+ stream=True
162
+ )
163
 
164
+ for chunk in response:
 
 
165
 
166
+ if chunk:
 
 
167
 
168
+ payload = {
169
+ "id": f"chatcmpl-{uuid.uuid4().hex}",
170
+ "object": "chat.completion.chunk",
171
+ "created": int(time.time()),
172
+ "model": body.model,
173
+ "choices": [
174
+ {
175
+ "index": 0,
176
+ "delta": {
177
+ "content": chunk
178
+ },
179
+ "finish_reason": None
180
+ }
181
+ ]
182
+ }
183
 
184
+ yield f"data: {json.dumps(payload)}\n\n"
185
 
186
+ await asyncio.sleep(0)
 
 
 
187
 
188
+ done_payload = {
189
+ "id": f"chatcmpl-{uuid.uuid4().hex}",
190
+ "object": "chat.completion.chunk",
191
+ "created": int(time.time()),
192
+ "model": body.model,
193
+ "choices": [
194
+ {
195
+ "index": 0,
196
+ "delta": {},
197
+ "finish_reason": "stop"
198
+ }
199
+ ]
200
+ }
201
+
202
+ yield f"data: {json.dumps(done_payload)}\n\n"
203
+
204
+ yield "data: [DONE]\n\n"
205
+
206
+ except Exception as e:
207
+
208
+ error_payload = {
209
+ "error": {
210
+ "message": str(e),
211
+ "type": "server_error"
212
+ }
213
+ }
214
 
215
+ yield f"data: {json.dumps(error_payload)}\n\n"
216
 
217
  return StreamingResponse(
218
+ generate_stream(),
 
 
 
219
  media_type="text/event-stream"
220
  )
221
 
222
+ # =====================================
223
+ # NORMAL RESPONSE
224
+ # =====================================
225
 
226
+ try:
227
 
228
+ response = g4f.ChatCompletion.create(
229
+ model=body.model,
230
+ provider=provider,
231
+ messages=messages
 
232
  )
 
233
 
234
+ return JSONResponse({
235
+ "id": f"chatcmpl-{uuid.uuid4().hex}",
236
+ "object": "chat.completion",
237
+ "created": int(time.time()),
238
+ "model": body.model,
239
+ "choices": [
240
+ {
241
+ "index": 0,
242
+ "message": {
243
+ "role": "assistant",
244
+ "content": response
245
+ },
246
+ "finish_reason": "stop"
247
  }
248
+ ],
249
+ "usage": {
250
+ "prompt_tokens": 0,
251
+ "completion_tokens": 0,
252
+ "total_tokens": 0
253
  }
254
+ })
255
+
256
+ except Exception as e:
257
+
258
+ raise HTTPException(
259
+ status_code=500,
260
+ detail=str(e)
261
+ )