bahi-bh commited on
Commit
ed1e830
·
verified ·
1 Parent(s): ab33dd3

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +246 -158
main.py CHANGED
@@ -1,224 +1,312 @@
1
- import os import json import time import logging import g4f from fastapi import FastAPI, HTTPException, Header from fastapi.responses import StreamingResponse from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import List, Optional
 
 
 
 
2
 
3
- ---------------- Logging ----------------
 
 
 
 
4
 
5
- logging.basicConfig(level=logging.INFO) logger = logging.getLogger(name)
6
 
7
- ---------------- App ----------------
8
 
9
- app = FastAPI( title="G4F OpenAI Compatible API", version="1.0" )
 
10
 
11
- app.add_middleware( CORSMiddleware, allow_origins=[""], allow_credentials=False, allow_methods=[""], allow_headers=["*"] )
12
 
13
- API_KEY = os.getenv("API_KEY", "your_fallback_secret")
14
 
15
- ---------------- Models ----------------
 
 
 
16
 
17
- class ChatMessage(BaseModel): role: str content: str
 
 
 
 
 
 
18
 
19
- class ChatRequest(BaseModel): model: str = "gpt-4o-mini" messages: List[ChatMessage] stream: bool = False provider: Optional[str] = None max_tokens: Optional[int] = 2048 temperature: Optional[float] = 0.7
20
 
21
- ---------------- Auth ----------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  def verify_key(auth: str):
24
 
25
- if not auth:
26
- raise HTTPException(
27
- status_code=401,
28
- detail="Missing Authorization"
29
- )
30
 
31
- parts = auth.split()
32
 
33
- if len(parts) != 2 or parts[0] != "Bearer":
34
- raise HTTPException(
35
- status_code=401,
36
- detail="Malformed Authorization"
37
- )
38
 
39
- if parts[1] != API_KEY:
40
- raise HTTPException(
41
- status_code=401,
42
- detail="Invalid API Key"
43
- )
44
 
45
- ---------------- Health ----------------
 
 
 
 
46
 
47
- @app.get("/") async def health(): return { "status": "online" }
48
 
49
- ---------------- Dynamic Models ----------------
50
 
51
- @app.get("/v1/models") async def models( authorization: str = Header(None) ):
 
52
 
53
- verify_key(authorization)
 
 
54
 
55
- try:
56
 
57
- model_data=[]
58
 
59
- # الطريقة الأكثر استقرارًا مع g4f
60
- if hasattr(g4f,"ModelUtils"):
 
 
61
 
62
- for model_name in g4f.ModelUtils.convert.keys():
63
 
64
- model_data.append({
65
- "id":str(model_name),
66
- "object":"model"
67
- })
68
 
69
- # fallback
70
- if not model_data:
71
 
 
72
  for name in dir(g4f.models):
73
 
74
  if name.startswith("_"):
75
  continue
76
 
77
- value=getattr(
78
  g4f.models,
79
- name,
80
- None
81
  )
82
 
83
- if isinstance(value,str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
- model_data.append({
86
- "id":value,
87
- "object":"model"
88
- })
89
 
90
- unique={}
91
 
92
- for m in model_data:
93
- unique[m["id"]]=m
 
 
 
 
 
 
 
94
 
95
- return {
96
- "object":"list",
97
- "data":sorted(
98
- unique.values(),
99
- key=lambda x:x["id"]
100
- )
101
- }
102
 
103
- except Exception as e:
104
 
105
- logger.exception(e)
 
 
 
 
106
 
107
- return {
108
- "object":"list",
109
- "data":[
 
 
 
 
 
 
 
 
 
 
 
 
110
  {
111
- "id":"gpt-4o-mini",
112
- "object":"model"
113
  }
 
114
  ]
115
- }
116
 
117
- ---------------- Chat ----------------
118
 
119
- @app.post("/v1/chat/completions") async def chat( body: ChatRequest, authorization: str = Header(None) ):
120
 
121
- verify_key(authorization)
122
 
123
- try:
124
 
125
- provider=None
126
 
127
- if body.provider:
 
 
 
 
 
128
 
129
- provider=getattr(
130
- g4f.Provider,
131
- body.provider,
132
- None
133
- )
134
 
135
- if provider is None:
136
- raise HTTPException(
137
- status_code=400,
138
- detail="Invalid provider"
139
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
- messages=[
142
- {
143
- "role":m.role,
144
- "content":m.content
145
- }
146
- for m in body.messages
147
- ]
148
-
149
- # -------- Streaming --------
150
- if body.stream:
151
-
152
- def generate():
153
-
154
- try:
155
-
156
- response=g4f.ChatCompletion.create(
157
- model=body.model,
158
- messages=messages,
159
- provider=provider,
160
- stream=True
161
- )
162
-
163
- for chunk in response:
164
-
165
- payload={
166
- "id":f"chatcmpl-{int(time.time())}",
167
- "object":"chat.completion.chunk",
168
- "created":int(time.time()),
169
- "model":body.model,
170
- "choices":[
171
- {
172
- "delta":{
173
- "content":str(chunk)
174
- },
175
- "index":0,
176
- "finish_reason":None
177
- }
178
- ]
179
  }
180
 
181
- yield f"data: {json.dumps(payload)}\n\n"
 
 
 
 
 
 
 
 
 
182
 
183
- yield "data: [DONE]\n\n"
184
 
185
- except Exception as e:
186
- logger.exception(e)
187
 
188
- return StreamingResponse(
189
- generate(),
190
- media_type="text/event-stream"
 
191
  )
192
 
193
- # -------- Non-stream --------
194
- response=await g4f.ChatCompletion.create_async(
195
- model=body.model,
196
- messages=messages,
197
- provider=provider
198
- )
199
 
200
- return {
201
- "id":f"chatcmpl-{int(time.time())}",
202
- "object":"chat.completion",
203
- "created":int(time.time()),
204
- "model":body.model,
205
- "choices":[
206
- {
207
- "index":0,
208
- "message":{
209
- "role":"assistant",
210
- "content":str(response)
211
- },
212
- "finish_reason":"stop"
213
- }
214
- ]
215
- }
 
 
 
 
 
 
 
216
 
217
- except Exception as e:
218
 
219
- logger.exception(e)
220
 
221
- raise HTTPException(
222
- status_code=503,
223
- detail=f"Provider error: {str(e)}"
224
- )
 
1
+ import os
2
+ import json
3
+ import time
4
+ import logging
5
+ import g4f
6
 
7
+ from fastapi import FastAPI, HTTPException, Header
8
+ from fastapi.responses import StreamingResponse
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+ from pydantic import BaseModel
11
+ from typing import List, Optional
12
 
 
13
 
14
+ # ================= Logging =================
15
 
16
+ logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger(__name__)
18
 
 
19
 
20
+ # ================= App =================
21
 
22
+ app = FastAPI(
23
+ title="G4F OpenAI API",
24
+ version="1.0"
25
+ )
26
 
27
+ app.add_middleware(
28
+ CORSMiddleware,
29
+ allow_origins=["*"],
30
+ allow_credentials=False,
31
+ allow_methods=["*"],
32
+ allow_headers=["*"]
33
+ )
34
 
 
35
 
36
+ API_KEY = os.getenv(
37
+ "API_KEY",
38
+ "your_fallback_secret"
39
+ )
40
+
41
+
42
+ # ================= Models =================
43
+
44
+ class ChatMessage(BaseModel):
45
+ role: str
46
+ content: str
47
+
48
+
49
+ class ChatRequest(BaseModel):
50
+ model: str = "gpt-4o-mini"
51
+ messages: List[ChatMessage]
52
+ stream: bool = False
53
+ provider: Optional[str] = None
54
+ max_tokens: Optional[int] = 2048
55
+ temperature: Optional[float] = 0.7
56
+
57
+
58
+ # ================= Auth =================
59
 
60
  def verify_key(auth: str):
61
 
62
+ if not auth:
63
+ raise HTTPException(
64
+ status_code=401,
65
+ detail="Missing Authorization"
66
+ )
67
 
68
+ parts = auth.split()
69
 
70
+ if len(parts) != 2:
71
+ raise HTTPException(
72
+ status_code=401,
73
+ detail="Malformed Authorization"
74
+ )
75
 
76
+ if parts[0] != "Bearer":
77
+ raise HTTPException(
78
+ status_code=401,
79
+ detail="Invalid Bearer"
80
+ )
81
 
82
+ if parts[1] != API_KEY:
83
+ raise HTTPException(
84
+ status_code=401,
85
+ detail="Invalid API Key"
86
+ )
87
 
 
88
 
89
+ # ================= Health =================
90
 
91
+ @app.get("/")
92
+ async def root():
93
 
94
+ return {
95
+ "status": "online"
96
+ }
97
 
 
98
 
99
+ # ================= Models Endpoint =================
100
 
101
+ @app.get("/v1/models")
102
+ async def models(
103
+ authorization: str = Header(None)
104
+ ):
105
 
106
+ verify_key(authorization)
107
 
108
+ try:
 
 
 
109
 
110
+ found = []
 
111
 
112
+ # استخراج أسماء النماذج تلقائياً
113
  for name in dir(g4f.models):
114
 
115
  if name.startswith("_"):
116
  continue
117
 
118
+ obj = getattr(
119
  g4f.models,
120
+ name
 
121
  )
122
 
123
+ if isinstance(name, str):
124
+ found.append(name)
125
+
126
+ found = sorted(list(set(found)))
127
+
128
+ if not found:
129
+ found = [
130
+ "gpt-4o-mini",
131
+ "gpt-4",
132
+ "gpt-3.5-turbo"
133
+ ]
134
+
135
+ return {
136
+ "object": "list",
137
+ "data": [
138
+ {
139
+ "id": model,
140
+ "object": "model",
141
+ "owned_by": "g4f"
142
+ }
143
+ for model in found
144
+ ]
145
+ }
146
 
147
+ except Exception as e:
 
 
 
148
 
149
+ logger.error(e)
150
 
151
+ return {
152
+ "object": "list",
153
+ "data": [
154
+ {
155
+ "id": "gpt-4o-mini",
156
+ "object": "model"
157
+ }
158
+ ]
159
+ }
160
 
 
 
 
 
 
 
 
161
 
162
+ # ================= Chat =================
163
 
164
+ @app.post("/v1/chat/completions")
165
+ async def chat(
166
+ body: ChatRequest,
167
+ authorization: str = Header(None)
168
+ ):
169
 
170
+ verify_key(authorization)
171
+
172
+ try:
173
+
174
+ provider = None
175
+
176
+ if body.provider:
177
+
178
+ provider = getattr(
179
+ g4f.Provider,
180
+ body.provider,
181
+ None
182
+ )
183
+
184
+ messages = [
185
  {
186
+ "role": m.role,
187
+ "content": m.content
188
  }
189
+ for m in body.messages
190
  ]
 
191
 
 
192
 
193
+ # ================= STREAM =================
194
 
195
+ if body.stream:
196
 
197
+ def generate():
198
 
199
+ try:
200
 
201
+ response = g4f.ChatCompletion.create(
202
+ model=body.model,
203
+ messages=messages,
204
+ provider=provider,
205
+ stream=True
206
+ )
207
 
208
+ for chunk in response:
 
 
 
 
209
 
210
+ if not chunk:
211
+ continue
212
+
213
+ payload = {
214
+
215
+ "id":
216
+ "chatcmpl-"+str(
217
+ int(time.time())
218
+ ),
219
+
220
+ "object":
221
+ "chat.completion.chunk",
222
+
223
+ "created":
224
+ int(time.time()),
225
+
226
+ "model":
227
+ body.model,
228
+
229
+ "choices":[
230
+ {
231
+ "delta":{
232
+ "content":
233
+ str(chunk)
234
+ },
235
+ "index":0
236
+ }
237
+ ]
238
+ }
239
+
240
+ yield (
241
+ "data: "
242
+ + json.dumps(payload)
243
+ + "\n\n"
244
+ )
245
+
246
+ yield "data: [DONE]\n\n"
247
+
248
+ except Exception as e:
249
+
250
+ logger.error(e)
251
+
252
+ error_payload={
253
+
254
+ "error":
255
+ str(e)
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
258
 
259
+ yield (
260
+ "data: "
261
+ + json.dumps(error_payload)
262
+ + "\n\n"
263
+ )
264
+
265
+ return StreamingResponse(
266
+ generate(),
267
+ media_type="text/event-stream"
268
+ )
269
 
 
270
 
271
+ # ================= NORMAL =================
 
272
 
273
+ response = await g4f.ChatCompletion.create_async(
274
+ model=body.model,
275
+ messages=messages,
276
+ provider=provider
277
  )
278
 
279
+ return {
 
 
 
 
 
280
 
281
+ "id":
282
+ "chatcmpl-g4f",
283
+
284
+ "object":
285
+ "chat.completion",
286
+
287
+ "created":
288
+ int(time.time()),
289
+
290
+ "model":
291
+ body.model,
292
+
293
+ "choices":[
294
+ {
295
+ "index":0,
296
+ "message":{
297
+ "role":"assistant",
298
+ "content":str(response)
299
+ },
300
+ "finish_reason":"stop"
301
+ }
302
+ ]
303
+ }
304
 
305
+ except Exception as e:
306
 
307
+ logger.exception(e)
308
 
309
+ raise HTTPException(
310
+ status_code=503,
311
+ detail=str(e)
312
+ )