bahi-bh commited on
Commit
f535ad2
·
verified ·
1 Parent(s): 4e50709

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -323
app.py CHANGED
@@ -1,377 +1,272 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- import sys
5
- import asyncio
6
-
7
- # تأكد من أنك تستخدم Python 3.10+
8
- if sys.version_info < (3, 10):
9
- print("❌ Python 3.10 or higher is required")
10
- sys.exit(1)
11
-
12
- # باقي الاستيرادات هنا...
13
- from fastapi import FastAPI, Request, HTTPException
14
- from fastapi.middleware.cors import CORSMiddleware
15
- from fastapi.responses import StreamingResponse, JSONResponse
16
- from pydantic import BaseModel
17
- from typing import List, Optional
18
- import json
19
  import time
20
- import uuid
 
21
  import logging
22
 
23
- # محاولة استيراد g4f مع معالجة الأخطاء
24
- try:
25
- from g4f.client import Client
26
- from g4f import Provider
27
- print("✅ g4f imported successfully")
28
- except ImportError as e:
29
- print(f"❌ Failed to import g4f: {e}")
30
- print("📦 Installing required packages...")
31
- import subprocess
32
- subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "g4f"])
33
- from g4f.client import Client
34
- from g4f import Provider
35
 
36
- # =====================================================
37
- # LOGGING
38
- # =====================================================
39
- logging.basicConfig(level=logging.INFO)
40
- logger = logging.getLogger("gateway")
41
 
42
  # =====================================================
43
  # CONFIG
44
  # =====================================================
 
45
  API_KEY = "sk-your-secret-key"
46
- STREAM_TIMEOUT = 90
47
- REQUEST_TIMEOUT = 45
48
 
49
- # =====================================================
50
- # FASTAPI
51
- # =====================================================
52
- app = FastAPI(
53
- title="Universal AI Gateway",
54
- version="10.1"
55
- )
56
 
57
  # =====================================================
58
- # CORS
59
  # =====================================================
60
- app.add_middleware(
61
- CORSMiddleware,
62
- allow_origins=["*"],
63
- allow_credentials=True,
64
- allow_methods=["*"],
65
- allow_headers=["*"],
66
  )
67
 
 
 
68
  # =====================================================
69
- # MODELS
70
  # =====================================================
71
- SUPPORTED_MODELS = [
72
- "gpt-4o-mini",
73
- "gpt-3.5-turbo",
74
- "blackboxai",
75
- "copilot",
76
- ]
77
-
78
- # مزودين مستقرين
79
- STABLE_PROVIDERS = [
80
- (Provider.Copilot, "copilot"),
81
- (Provider.DuckDuckGo, "gpt-4o-mini"),
82
- (Provider.Blackbox, "blackboxai"),
83
- ]
84
-
85
- class Message(BaseModel):
86
- role: str
87
- content: str
88
 
89
- class ChatRequest(BaseModel):
90
- model: str = "gpt-4o-mini"
91
- messages: List[Message]
92
- stream: bool = False
93
- temperature: Optional[float] = 0.7
94
- max_tokens: Optional[int] = 4096
95
 
96
  # =====================================================
97
  # AUTH
98
  # =====================================================
 
99
  def verify_api_key(req: Request):
 
100
  auth = req.headers.get("Authorization")
 
101
  if not auth:
102
- raise HTTPException(status_code=401, detail="Missing Authorization Header")
 
 
 
 
103
  if not auth.startswith("Bearer "):
104
- raise HTTPException(status_code=401, detail="Invalid Authorization Format")
 
 
 
 
105
  token = auth.replace("Bearer ", "").strip()
 
106
  if token != API_KEY:
107
- raise HTTPException(status_code=403, detail="Invalid API Key")
 
 
 
108
 
109
  # =====================================================
110
- # معالج الـ chunks العالمي
111
  # =====================================================
112
- def extract_content_from_chunk(chunk) -> Optional[str]:
113
- if not chunk:
114
- return None
115
-
116
- if isinstance(chunk, str):
117
- return chunk if chunk.strip() else None
118
-
119
- if hasattr(chunk, 'choices') and chunk.choices:
120
- try:
121
- if hasattr(chunk.choices[0], 'delta') and chunk.choices[0].delta:
122
- content = chunk.choices[0].delta.content
123
- if content:
124
- return content
125
- if hasattr(chunk.choices[0], 'message') and chunk.choices[0].message:
126
- content = chunk.choices[0].message.content
127
- if content:
128
- return content
129
- except:
130
- pass
131
-
132
- try:
133
- if isinstance(chunk, dict) and 'choices' in chunk:
134
- return chunk['choices'][0].get('delta', {}).get('content', '')
135
- except:
136
- pass
137
-
138
  try:
139
- text = str(chunk)
140
- if text and text not in ['', 'None', 'null']:
141
- return text
142
- except:
143
- pass
144
-
145
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  # =====================================================
148
- # STREAMING
149
  # =====================================================
150
- async def safe_stream_from_provider(provider, model, messages):
151
- client = Client(provider=provider)
152
-
153
- def sync_stream():
154
- return client.chat.completions.create(
155
- model=model,
156
- messages=messages,
157
- stream=True
158
- )
159
-
160
- try:
161
- stream = await asyncio.wait_for(
162
- asyncio.to_thread(sync_stream),
163
- timeout=15.0
164
- )
165
- except asyncio.TimeoutError:
166
- raise Exception("Timeout while initializing stream")
167
- except Exception as e:
168
- raise Exception(f"Stream initialization error: {e}")
169
-
170
- async def generator():
171
- chunk_count = 0
172
- try:
173
- async with asyncio.timeout(STREAM_TIMEOUT):
174
- for raw_chunk in stream:
175
- chunk_count += 1
176
- content = extract_content_from_chunk(raw_chunk)
177
- if content and content.strip():
178
- yield content.strip()
179
- if chunk_count > 1000:
180
- break
181
- await asyncio.sleep(0.005)
182
- except asyncio.TimeoutError:
183
- if chunk_count == 0:
184
- yield "[Timeout - No response received]"
185
- except Exception as e:
186
- if chunk_count == 0:
187
- yield f"[Error: {str(e)[:50]}]"
188
-
189
- return generator()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  # =====================================================
192
- # NORMAL RESPONSE
193
  # =====================================================
194
- async def safe_normal_completion(provider, model, messages):
195
- client = Client(provider=provider)
196
-
197
- def sync_request():
198
- return client.chat.completions.create(
199
- model=model,
200
- messages=messages,
201
- stream=False
202
- )
203
-
204
- response = await asyncio.wait_for(
205
- asyncio.to_thread(sync_request),
206
- timeout=REQUEST_TIMEOUT
207
- )
208
-
209
- try:
210
- if hasattr(response, 'choices') and response.choices:
211
- content = response.choices[0].message.content
212
- if content:
213
- return content
214
- except:
215
- pass
216
-
217
- return str(response) if response else "No response received"
218
 
219
  # =====================================================
220
- # ENDPOINTS
221
  # =====================================================
 
222
  @app.get("/")
 
223
  async def root():
 
224
  return {
225
  "status": "online",
226
- "version": "10.1",
227
- "auth_required": True,
228
- "providers": [p[0].__name__ for p in STABLE_PROVIDERS]
229
  }
230
 
231
- @app.get("/v1/models")
232
- async def models():
 
 
233
  return {
234
- "object": "list",
235
- "data": [
236
- {"id": m, "object": "model", "created": int(time.time()), "owned_by": "g4f"}
237
- for m in SUPPORTED_MODELS
238
- ]
239
  }
240
 
241
- @app.post("/v1/chat/completions")
242
- async def chat_completions(req: Request, body: ChatRequest):
 
 
243
  verify_api_key(req)
244
-
245
- if body.model not in SUPPORTED_MODELS:
246
- body.model = "gpt-4o-mini"
247
-
248
- messages = [{"role": m.role, "content": m.content} for m in body.messages]
249
-
250
- if body.stream:
251
- async def generate():
252
- chunk_id = f"chatcmpl-{uuid.uuid4().hex[:8]}"
253
-
254
- for provider, provider_model in STABLE_PROVIDERS:
255
- try:
256
- stream_gen = await safe_stream_from_provider(provider, body.model, messages)
257
- content_received = False
258
-
259
- async for content in stream_gen:
260
- if content:
261
- content_received = True
262
- payload = {
263
- "id": chunk_id,
264
- "object": "chat.completion.chunk",
265
- "created": int(time.time()),
266
- "model": body.model,
267
- "choices": [{
268
- "index": 0,
269
- "delta": {"content": content},
270
- "finish_reason": None
271
- }]
272
- }
273
- yield f"data: {json.dumps(payload)}\n\n"
274
- await asyncio.sleep(0.01)
275
-
276
- if content_received:
277
- yield f"data: {json.dumps({
278
- 'id': chunk_id, 'object': 'chat.completion.chunk',
279
- 'created': int(time.time()), 'model': body.model,
280
- 'choices': [{'index': 0, 'delta': {}, 'finish_reason': 'stop'}]
281
- })}\n\n"
282
- yield "data: [DONE]\n\n"
283
- return
284
-
285
- except Exception as e:
286
- logger.warning(f"{provider.__name__} failed: {e}")
287
- continue
288
-
289
- yield f"data: {json.dumps({'error': {'message': 'All providers failed', 'type': 'server_error'}})}\n\n"
290
-
291
- return StreamingResponse(generate(), media_type="text/event-stream")
292
-
293
- # Non-streaming
294
- for provider, provider_model in STABLE_PROVIDERS:
295
- try:
296
- content = await safe_normal_completion(provider, body.model, messages)
297
- if content:
298
- return JSONResponse({
299
- "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
300
- "object": "chat.completion",
301
- "created": int(time.time()),
302
- "model": body.model,
303
- "choices": [{
304
- "index": 0,
305
- "message": {"role": "assistant", "content": content},
306
- "finish_reason": "stop"
307
- }]
308
- })
309
- except Exception as e:
310
- logger.warning(f"{provider.__name__} failed: {e}")
311
- continue
312
-
313
- raise HTTPException(status_code=500, detail="All providers failed")
314
-
315
- @app.get("/test")
316
- async def test_ui():
317
- return """
318
- <!DOCTYPE html>
319
- <html>
320
- <head><title>AI Gateway Test</title>
321
- <style>
322
- body { font-family: Arial; max-width: 800px; margin: 50px auto; }
323
- #chat { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 10px; }
324
- .user { background: #007bff; color: white; padding: 8px; margin: 5px; border-radius: 10px; text-align: right; }
325
- .bot { background: #e9ecef; padding: 8px; margin: 5px; border-radius: 10px; }
326
- .input-area { display: flex; gap: 10px; margin-top: 10px; }
327
- #input { flex: 1; padding: 10px; }
328
- #send { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }
329
- </style>
330
- </head>
331
- <body>
332
- <h2>AI Gateway Test</h2>
333
- <div id="chat"></div>
334
- <div class="input-area">
335
- <input type="text" id="input" placeholder="Type your message...">
336
- <button id="send">Send</button>
337
- </div>
338
- <script>
339
- const API_KEY = "sk-your-secret-key";
340
- async function send() {
341
- const input = document.getElementById('input');
342
- const msg = input.value.trim();
343
- if (!msg) return;
344
- const chat = document.getElementById('chat');
345
- chat.innerHTML += `<div class="user">${msg}</div>`;
346
- input.value = '';
347
- const botDiv = document.createElement('div');
348
- botDiv.className = 'bot';
349
- botDiv.textContent = 'Thinking...';
350
- chat.appendChild(botDiv);
351
- try {
352
- const res = await fetch('/v1/chat/completions', {
353
- method: 'POST',
354
- headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + API_KEY},
355
- body: JSON.stringify({model: 'gpt-4o-mini', messages: [{role: 'user', content: msg}]})
356
- });
357
- const data = await res.json();
358
- botDiv.textContent = data.choices[0].message.content;
359
- } catch(e) { botDiv.textContent = 'Error: ' + e.message; }
360
- }
361
- document.getElementById('send').onclick = send;
362
- document.getElementById('input').onkeypress = (e) => { if(e.key === 'Enter') send(); };
363
- </script>
364
- </body>
365
- </html>
366
- """
367
 
368
  if __name__ == "__main__":
369
- import uvicorn
370
  print("""
371
- ╔══════════════════════════════════════════
372
- AI Gateway v10.1 Running 🚀
373
- ║ http://localhost:7860/test ║
374
- ║ API Key: sk-your-secret-key
375
- ╚══════════════════════════════════════════╝
376
- """)
377
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import time
2
+ import random
3
+ import traceback
4
  import logging
5
 
6
+ from fastapi import FastAPI, HTTPException, Request
7
+ from pydantic import BaseModel
8
+ import uvicorn
 
 
 
 
 
 
 
 
 
9
 
10
+ from g4f.client import Client
11
+ from g4f.Provider import __providers__
 
 
 
12
 
13
  # =====================================================
14
  # CONFIG
15
  # =====================================================
16
+
17
  API_KEY = "sk-your-secret-key"
 
 
18
 
19
+ MODEL = "gpt-4o-mini"
20
+
21
+ MAX_RETRIES = 10
22
+ TIMEOUT = 60
 
 
 
23
 
24
  # =====================================================
25
+ # LOGGING
26
  # =====================================================
27
+
28
+ logging.basicConfig(
29
+ level=logging.INFO,
30
+ format="%(asctime)s [%(levelname)s] %(message)s"
 
 
31
  )
32
 
33
+ logger = logging.getLogger("smart-g4f")
34
+
35
  # =====================================================
36
+ # FASTAPI
37
  # =====================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ app = FastAPI(
40
+ title="Smart G4F Gateway",
41
+ version="1.1"
42
+ )
 
 
43
 
44
  # =====================================================
45
  # AUTH
46
  # =====================================================
47
+
48
  def verify_api_key(req: Request):
49
+
50
  auth = req.headers.get("Authorization")
51
+
52
  if not auth:
53
+ raise HTTPException(
54
+ status_code=401,
55
+ detail="Missing Authorization Header"
56
+ )
57
+
58
  if not auth.startswith("Bearer "):
59
+ raise HTTPException(
60
+ status_code=401,
61
+ detail="Invalid Authorization Format"
62
+ )
63
+
64
  token = auth.replace("Bearer ", "").strip()
65
+
66
  if token != API_KEY:
67
+ raise HTTPException(
68
+ status_code=403,
69
+ detail="Invalid API Key"
70
+ )
71
 
72
  # =====================================================
73
+ # SAFE PROVIDERS
74
  # =====================================================
75
+
76
+ SAFE_PROVIDERS = []
77
+
78
+ for provider in __providers__:
79
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  try:
81
+
82
+ name = provider.__name__.lower()
83
+
84
+ if not getattr(provider, "working", False):
85
+ continue
86
+
87
+ if getattr(provider, "needs_auth", False):
88
+ continue
89
+
90
+ if getattr(provider, "use_nodriver", False):
91
+ continue
92
+
93
+ blocked = [
94
+ "openai",
95
+ "qwen",
96
+ "copilot",
97
+ "gemini",
98
+ "claude",
99
+ ]
100
+
101
+ if any(x in name for x in blocked):
102
+ continue
103
+
104
+ SAFE_PROVIDERS.append(provider)
105
+
106
+ except Exception:
107
+ continue
108
+
109
+ random.shuffle(SAFE_PROVIDERS)
110
+
111
+ logger.info(f"[+] SAFE PROVIDERS: {len(SAFE_PROVIDERS)}")
112
+
113
+ client = Client()
114
 
115
  # =====================================================
116
+ # SMART G4F
117
  # =====================================================
118
+
119
+ class SmartG4F:
120
+
121
+ def __init__(self):
122
+
123
+ self.good = []
124
+ self.bad = {}
125
+
126
+ def mark_bad(self, provider, cooldown=300):
127
+
128
+ self.bad[provider.__name__] = time.time() + cooldown
129
+
130
+ def is_bad(self, provider):
131
+
132
+ if provider.__name__ not in self.bad:
133
+ return False
134
+
135
+ return time.time() < self.bad[provider.__name__]
136
+
137
+ def get_provider(self):
138
+
139
+ random.shuffle(SAFE_PROVIDERS)
140
+
141
+ for provider in SAFE_PROVIDERS:
142
+
143
+ if self.is_bad(provider):
144
+ continue
145
+
146
+ return provider
147
+
148
+ return None
149
+
150
+ def ask(self, prompt):
151
+
152
+ for _ in range(MAX_RETRIES):
153
+
154
+ provider = self.get_provider()
155
+
156
+ if not provider:
157
+ break
158
+
159
+ try:
160
+
161
+ logger.info(f"[+] Trying: {provider.__name__}")
162
+
163
+ response = client.chat.completions.create(
164
+ model=MODEL,
165
+ provider=provider,
166
+ messages=[
167
+ {
168
+ "role": "user",
169
+ "content": prompt
170
+ }
171
+ ],
172
+ timeout=TIMEOUT
173
+ )
174
+
175
+ text = response.choices[0].message.content
176
+
177
+ if text:
178
+
179
+ logger.info(f"[+] Success: {provider.__name__}")
180
+
181
+ return {
182
+ "provider": provider.__name__,
183
+ "response": text
184
+ }
185
+
186
+ except Exception as e:
187
+
188
+ logger.warning(f"[-] Failed: {provider.__name__} -> {e}")
189
+
190
+ self.mark_bad(provider)
191
+
192
+ raise Exception("All providers failed")
193
+
194
+ smart = SmartG4F()
195
 
196
  # =====================================================
197
+ # REQUEST MODEL
198
  # =====================================================
199
+
200
+ class ChatRequest(BaseModel):
201
+
202
+ prompt: str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
  # =====================================================
205
+ # ROUTES
206
  # =====================================================
207
+
208
  @app.get("/")
209
+
210
  async def root():
211
+
212
  return {
213
  "status": "online",
214
+ "providers": len(SAFE_PROVIDERS),
215
+ "model": MODEL
 
216
  }
217
 
218
+ @app.get("/health")
219
+
220
+ async def health():
221
+
222
  return {
223
+ "ok": True
 
 
 
 
224
  }
225
 
226
+ @app.post("/chat")
227
+
228
+ async def chat(req: Request, body: ChatRequest):
229
+
230
  verify_api_key(req)
231
+
232
+ try:
233
+
234
+ result = smart.ask(body.prompt)
235
+
236
+ return {
237
+ "success": True,
238
+ "provider": result["provider"],
239
+ "response": result["response"]
240
+ }
241
+
242
+ except Exception as e:
243
+
244
+ logger.error(traceback.format_exc())
245
+
246
+ raise HTTPException(
247
+ status_code=500,
248
+ detail=str(e)
249
+ )
250
+
251
+ # =====================================================
252
+ # RUN
253
+ # =====================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
  if __name__ == "__main__":
256
+
257
  print("""
258
+ ╔══════════════════════════════╗
259
+ Smart G4F Gateway
260
+ ╠══════════════════════════════╣
261
+ ║ API KEY ENABLED
262
+ ║ MODEL: gpt-4o-mini ║
263
+ ║ /chat ║
264
+ ║ /health ║
265
+ ╚══════════════════════════════╝
266
+ """)
267
+
268
+ uvicorn.run(
269
+ app,
270
+ host="0.0.0.0",
271
+ port=7860
272
+ )