bahi-bh commited on
Commit
8fd063c
·
verified ·
1 Parent(s): cc6e7b3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +188 -0
app.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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(
57
+ status_code=401,
58
+ detail="Missing Authorization Header"
59
+ )
60
+
61
+ if not auth.startswith("Bearer "):
62
+ raise HTTPException(
63
+ status_code=401,
64
+ detail="Invalid Authorization"
65
+ )
66
+
67
+ token = auth.replace("Bearer ", "")
68
+
69
+ if token != API_KEY:
70
+ raise HTTPException(
71
+ status_code=403,
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
+ }