bahi-bh commited on
Commit
5c91445
·
verified ·
1 Parent(s): 08aa762

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +214 -0
app.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import random
4
+ import traceback
5
+
6
+ from fastapi import FastAPI, Depends, HTTPException, Security
7
+ from fastapi.security.api_key import APIKeyHeader
8
+ from pydantic import BaseModel
9
+ import uvicorn
10
+
11
+ from g4f.client import Client
12
+ from g4f.Provider import __providers__
13
+
14
+ MODEL = "gpt-4o-mini"
15
+
16
+ MAX_RETRIES = 10
17
+ TIMEOUT = 60
18
+
19
+ # --- إعدادات مفاتيح الأمان من البيئة المستضافة ---
20
+ # قراءة مفتاح حمايتك الخاص لـ FastAPI (إذا لم تجده سيضع قيمة افتراضية لحين ضبطه في الـ Secrets)
21
+ MY_API_KEY = os.getenv("MY_PROJECT_API_KEY", "my_fallback_secret_key_123")
22
+ api_key_header = APIKeyHeader(name="Authorization", auto_error=False)
23
+
24
+ # قراءة مفتاح سيرفر Context7 من الـ Secrets الخاصة بـ Hugging Face
25
+ CONTEXT7_KEY = os.getenv("CONTEXT7_API_KEY", "")
26
+
27
+ # بناء قالب تكوين الـ MCP الخاص بـ Context7 برمجياً
28
+ MCP_CONFIG = {
29
+ "mcpServers": {
30
+ "context7": {
31
+ "url": "https://mcp.context7.com/mcp",
32
+ "headers": {
33
+ "Authorization": f"Bearer {CONTEXT7_KEY}"
34
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ async def get_api_key(api_key_header: str = Security(api_key_header)):
40
+ """دالة التحقق من أن العميل الخارجي يرسل مفتاح الـ API الصحيح"""
41
+ if not api_key_header:
42
+ raise HTTPException(status_code=403, detail="Missing API Key in Authorization header")
43
+
44
+ # دعم صيغتي النقل العادية والمسبوقة بـ Bearer
45
+ token = api_key_header.replace("Bearer ", "").strip()
46
+ if token != MY_API_KEY:
47
+ raise HTTPException(status_code=403, detail="Invalid API Key. Access Denied.")
48
+ return token
49
+
50
+
51
+ SAFE_PROVIDERS = []
52
+
53
+ for provider in __providers__:
54
+ try:
55
+ name = provider.__name__.lower()
56
+
57
+ if not getattr(provider, "working", False):
58
+ continue
59
+
60
+ if getattr(provider, "needs_auth", False):
61
+ continue
62
+
63
+ if getattr(provider, "use_nodriver", False):
64
+ continue
65
+
66
+ blocked = [
67
+ "openai",
68
+ "qwen",
69
+ "copilot",
70
+ "gemini",
71
+ "claude",
72
+ ]
73
+
74
+ if any(x in name for x in blocked):
75
+ continue
76
+
77
+ SAFE_PROVIDERS.append(provider)
78
+ except:
79
+ pass
80
+
81
+ random.shuffle(SAFE_PROVIDERS)
82
+
83
+ print(f"[+] SAFE PROVIDERS: {len(SAFE_PROVIDERS)}")
84
+
85
+ client = Client()
86
+
87
+
88
+ class SmartG4F:
89
+
90
+ def __init__(self):
91
+ self.good = []
92
+ self.bad = {}
93
+
94
+ def mark_bad(self, provider, cooldown=300):
95
+ self.bad[provider.__name__] = time.time() + cooldown
96
+
97
+ def is_bad(self, provider):
98
+ expire = self.bad.get(provider.__name__)
99
+ if not expire:
100
+ return False
101
+ if time.time() > expire:
102
+ del self.bad[provider.__name__]
103
+ return False
104
+ return True
105
+
106
+ def provider_pool(self):
107
+ providers = []
108
+ providers.extend(self.good)
109
+ for p in SAFE_PROVIDERS:
110
+ if p not in providers and not self.is_bad(p):
111
+ providers.append(p)
112
+ random.shuffle(providers)
113
+ return providers
114
+
115
+ def ask(self, prompt):
116
+ errors = []
117
+
118
+ for attempt in range(MAX_RETRIES):
119
+ pool = self.provider_pool()
120
+ if not pool:
121
+ return {
122
+ "success": False,
123
+ "error": "No providers available"
124
+ }
125
+
126
+ provider = random.choice(pool)
127
+ print(f"[TRY {attempt+1}] {provider.__name__}")
128
+
129
+ try:
130
+ # دمج إعداد الـ MCP لـ Context7 عبر الـ extra_body لضمان استدعائه مع الموديل المختار
131
+ response = client.chat.completions.create(
132
+ model=MODEL,
133
+ provider=provider,
134
+ messages=[
135
+ {
136
+ "role": "user",
137
+ "content": prompt
138
+ }
139
+ ],
140
+ timeout=TIMEOUT,
141
+ extra_body={
142
+ "mcp_config": MCP_CONFIG
143
+ } if CONTEXT7_KEY else {} # يتم تفعيله فقط في حال وجود المفتاح لحمايتك من الأخطاء
144
+ )
145
+
146
+ text = response.choices[0].message.content
147
+
148
+ if not text:
149
+ raise Exception("Empty response")
150
+
151
+ if provider not in self.good:
152
+ self.good.append(provider)
153
+
154
+ return {
155
+ "success": True,
156
+ "provider": provider.__name__,
157
+ "response": text
158
+ }
159
+
160
+ except Exception as e:
161
+ err = str(e).lower()
162
+ traceback.print_exc()
163
+
164
+ errors.append({
165
+ "provider": provider.__name__,
166
+ "error": str(e)
167
+ })
168
+
169
+ if "429" in err:
170
+ self.mark_bad(provider, 600)
171
+ time.sleep(random.randint(10, 20))
172
+ elif "cloudflare" in err:
173
+ self.mark_bad(provider, 1200)
174
+ time.sleep(20)
175
+ elif "timeout" in err:
176
+ self.mark_bad(provider, 300)
177
+ else:
178
+ self.mark_bad(provider, 180)
179
+ continue
180
+
181
+ return {
182
+ "success": False,
183
+ "errors": errors
184
+ }
185
+
186
+
187
+ app = FastAPI()
188
+ ai = SmartG4F()
189
+
190
+
191
+ class Query(BaseModel):
192
+ prompt: str
193
+
194
+
195
+ @app.get("/")
196
+ async def home():
197
+ return {
198
+ "status": "running",
199
+ "providers": len(SAFE_PROVIDERS)
200
+ }
201
+
202
+
203
+ # تفعيل الحماية بـ Depends(get_api_key) لمنع أي استهلاك خارجي غير مصرح به
204
+ @app.post("/ask")
205
+ async def ask(query: Query, token: str = Depends(get_api_key)):
206
+ return ai.ask(query.prompt)
207
+
208
+
209
+ if __name__ == "__main__":
210
+ uvicorn.run(
211
+ app,
212
+ host="0.0.0.0",
213
+ port=7860
214
+ )