HilmanBey commited on
Commit
95e544d
·
verified ·
1 Parent(s): de49f0b

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +97 -252
main.py CHANGED
@@ -2,18 +2,18 @@ import os
2
  import requests
3
  import sqlite3
4
  from fastapi import FastAPI, Header, HTTPException, Request
5
- from fastapi.responses import HTMLResponse, JSONResponse
6
  from pydantic import BaseModel
7
  from duckduckgo_search import DDGS
8
 
9
- app = FastAPI(title="HilmanAI Cloud Proxy Gateway")
10
 
11
- # --- ÇEVRE DEĞİŞKENLERİ ---
12
- MY_SECRET_KEY = os.getenv("MY_SECRET_KEY", "sk-hilman-cloud-proxy-2026")
13
  OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
14
  ANTIGRAVITY_API_KEY = os.getenv("ANTIGRAVITY_API_KEY")
15
 
16
- # --- VERİTABANI VE KALICI HAFIZA ---
17
  DB_PATH = "hilman_space_memory.db"
18
 
19
  def init_db():
@@ -45,7 +45,7 @@ def save_message(role, content):
45
  except Exception as e:
46
  print(f"DB Kayıt Hatası: {e}")
47
 
48
- # --- İNTERNET ARAMA MOTORU (DuckDuckGo) ---
49
  def web_search(query: str) -> str:
50
  try:
51
  print(f"[İNTERNET ARAMASI]: '{query}' aranıyor...")
@@ -63,278 +63,123 @@ def web_search(query: str) -> str:
63
  return f"Arama sırasında hata oluştu: {e}"
64
 
65
  class ChatRequest(BaseModel):
66
- provider: str = "antigravity"
67
- model: str = "gemini-2.0-flash"
68
  messages: list
 
69
 
70
- # --- GÖNDERDİĞİN EKRANIN BİREBİR HTML/CSS KODU ---
71
- HTML_DASHBOARD = """
72
- <!DOCTYPE html>
73
- <html lang="tr">
74
- <head>
75
- <meta charset="UTF-8">
76
- <title>HilmanAI - Hizmet Yapılandırması (Cloud VDS)</title>
77
- <style>
78
- body { background-color: #0B0F17; color: #F3F4F6; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 40px; display: flex; justify-content: center; }
79
- .container { width: 100%; max-width: 900px; background: #111827; border: 1px solid #1F2937; border-radius: 16px; padding: 30px; box-shadow: 0 20px 40px rgba(0,0,0,0.8); }
80
- .header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #1F2937; padding-bottom: 20px; margin-bottom: 25px; flex-wrap: wrap; gap: 15px; }
81
- .title-area { display: flex; align-items: center; gap: 10px; font-size: 18px; font-weight: bold; color: #F3F4F6; }
82
- .status-badge { background: rgba(34, 197, 94, 0.1); color: #22C55E; padding: 6px 14px; border-radius: 20px; font-size: 13px; font-weight: bold; display: flex; align-items: center; gap: 8px; border: 1px solid rgba(34, 197, 94, 0.2); }
83
- .stop-btn { background: #DC2626; color: white; border: none; padding: 10px 18px; border-radius: 8px; font-weight: bold; cursor: pointer; display: flex; align-items: center; gap: 6px; transition: 0.2s; }
84
- .stop-btn:hover { background: #B91C1C; }
85
-
86
- .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px; }
87
- @media (max-width: 600px) { .grid-2 { grid-template-columns: 1fr; } }
88
-
89
- .section { background: #0D131F; border: 1px solid #1F2937; border-radius: 12px; padding: 18px; margin-bottom: 20px; }
90
- label { display: block; color: #9CA3AF; font-size: 11px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
91
- input, select { width: 100%; padding: 12px; background: #111827; border: 1px solid #1F2937; color: #F3F4F6; border-radius: 8px; box-sizing: border-box; font-size: 14px; outline: none; }
92
- input:focus { border-color: #3B82F6; }
93
-
94
- .footer-note { color: #6B7280; font-size: 11px; margin-top: 6px; }
95
- .warning-text { color: #F59E0B; font-size: 11px; margin-top: 6px; }
96
-
97
- .input-group { display: flex; gap: 8px; }
98
- .icon-btn { background: #1F2937; border: none; color: #F3F4F6; padding: 0 14px; border-radius: 8px; cursor: pointer; transition: 0.2s; font-size: 14px; }
99
- .icon-btn:hover { background: #374151; }
100
-
101
- .toggle-row { display: flex; justify-content: space-between; align-items: center; }
102
- .switch { position: relative; display: inline-block; width: 44px; height: 24px; }
103
- .switch input { opacity: 0; width: 0; height: 0; }
104
- .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #374151; transition: .3s; border-radius: 24px; }
105
- .slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .3s; border-radius: 50%; }
106
- input:checked + .slider { background-color: #2563EB; }
107
- input:checked + .slider:before { transform: translateX(20px); }
108
- </style>
109
- </head>
110
- <body>
111
- <div class="container">
112
- <div class="header">
113
- <div class="title-area">
114
- ⚙️ Hizmet Yapılandırması
115
- </div>
116
- <div class="status-badge">
117
- ● Hizmet Çalışıyor (7/24 Bulut Aktif)
118
- </div>
119
- <button class="stop-btn" onclick="alert('Bulut sunucu 7/24 kesintisiz çalışmaktadır, Halil!')">
120
- ⛔ Hizmeti Durdur
121
- </button>
122
- </div>
123
-
124
- <div class="grid-2">
125
- <div class="section" style="margin-bottom:0;">
126
- <label>Dinleme Portu ⓘ</label>
127
- <input type="text" value="7860 (Hugging Face Cloud)" readonly>
128
- <div class="footer-note">Bulut sunucu varsayılan portu aktif.</div>
129
- </div>
130
- <div class="section" style="margin-bottom:0;">
131
- <label>İstek Zaman Aşımı ⓘ</label>
132
- <input type="text" value="120" readonly>
133
- <div class="footer-note">Varsayılan 120s, aralık 30-7200s.</div>
134
- </div>
135
- </div>
136
-
137
- <div class="grid-2" style="margin-top: 20px;">
138
- <div class="section" style="margin-bottom:0;">
139
- <div class="toggle-row">
140
- <div>
141
- <label style="margin-bottom:0;">LAN Erişimine İzin Ver ⓘ</label>
142
- <div class="footer-note">Bulut ortamında dış ağa açık.</div>
143
- </div>
144
- <label class="switch">
145
- <input type="checkbox" checked disabled>
146
- <span class="slider"></span>
147
- </label>
148
- </div>
149
- </div>
150
- <div class="section" style="margin-bottom:0;">
151
- <div class="toggle-row">
152
- <div>
153
- <label style="margin-bottom:0;">Yetkilendirme ⓘ</label>
154
- <div class="footer-note">Bearer Token koruması aktif.</div>
155
- </div>
156
- <label class="switch">
157
- <input type="checkbox" checked disabled>
158
- <span class="slider"></span>
159
- </label>
160
- </div>
161
- <div style="margin-top: 10px;">
162
- <select disabled>
163
- <option>Otomatik (Önerilen)</option>
164
- </select>
165
- </div>
166
- </div>
167
- </div>
168
-
169
- <div class="section" style="margin-top: 20px;">
170
- <label>API Anahtarı (Secret Key) ⓘ</label>
171
- <div class="input-group">
172
- <input type="password" id="apiKey" value="%SECRET_KEY%" readonly>
173
- <button class="icon-btn" onclick="togglePass()" title="Göster/Gizle">👁️</button>
174
- <button class="icon-btn" onclick="copyKey()" title="Kopyala">📋</button>
175
- </div>
176
- <div class="warning-text">Not: API anahtarınızı güvende tutun. Paylaşmayın, Halil.</div>
177
- </div>
178
-
179
- <div class="section" style="margin-top: 20px;">
180
- <label>Web UI Yönetici Parolası ⓘ</label>
181
- <div class="input-group">
182
- <input type="text" value="(API Anahtarı ile aynı)" readonly>
183
- <button class="icon-btn" onclick="alert('API Anahtarınız ile korunmaktadır.')" title="Düzenle">✏️</button>
184
- <button class="icon-btn" onclick="copyAdminKey()" title="Kopyala">📋</button>
185
- </div>
186
- <div class="footer-note">İpucu: Bulut dağıtım senaryolarında API anahtarınız güvenlik için esastır.</div>
187
- </div>
188
-
189
- <div class="section" style="margin-top: 20px; margin-bottom: 0;">
190
- <div class="toggle-row">
191
- <div>
192
- <label style="margin-bottom:0;">User-Agent Override ⓘ</label>
193
- <div class="footer-note">Proxy yönlendirmesi için optimize edilmiştir.</div>
194
- </div>
195
- <label class="switch">
196
- <input type="checkbox" checked disabled>
197
- <span class="slider"></span>
198
- </label>
199
- </div>
200
- </div>
201
- </div>
202
-
203
- <script>
204
- function togglePass() {
205
- var x = document.getElementById("apiKey");
206
- x.type = x.type === "password" ? "text" : "password";
207
- }
208
- function copyKey() {
209
- var x = document.getElementById("apiKey");
210
- navigator.clipboard.writeText(x.value);
211
- alert("API Anahtarı panoya kopyalandı Halil!");
212
- }
213
- function copyAdminKey() {
214
- var x = document.getElementById("apiKey");
215
- navigator.clipboard.writeText(x.value);
216
- alert("Yönetici Parolası panoya kopyalandı Halil!");
217
  }
218
- </script>
219
- </body>
220
- </html>
221
- """
222
-
223
- # --- ROUTE'LAR ---
224
- @app.get("/", response_class=HTMLResponse)
225
- def serve_dashboard():
226
- return HTML_DASHBOARD.replace("%SECRET_KEY%", MY_SECRET_KEY)
227
 
228
  @app.get("/server-status")
229
  def server_status():
230
- return {"status": "Active", "mode": "Cloud VDS Proxy Gateway"}
 
 
 
 
 
 
 
 
231
 
232
- # --- ORTAK YAPAY ZEKA VE ARAMA ENTEGRASYONU ---
233
- def call_ai_backend(messages_list):
234
- last_user_msg = ""
235
- for m in reversed(messages_list):
236
- if isinstance(m, dict) and m.get("role") == "user":
237
- last_user_msg = m.get("content", "")
238
- break
239
 
 
 
 
 
 
 
 
 
 
 
 
240
  search_keywords = ["bul", "ara", "fiyat", "en ucuz", "nerede", "satın al", "karşılaştır", "incele"]
241
  search_context = ""
242
-
243
  if any(kw in last_user_msg.lower() for kw in search_keywords):
244
  search_results = web_search(last_user_msg)
245
- search_context = f"\n\n[CANLI İNTERNET ARAMA SONUÇLARI]:\n{search_results}\nYukarıdaki güncel internet verilerini kullanarak Halil'e net, fiyatlı, site isimli ve kargo süreleriyle ilgili detaylı bir liste sun."
246
-
247
- compressed_messages = messages_list[-4:] if len(messages_list) > 4 else messages_list
248
 
 
249
  system_instruction = {
250
  "role": "system",
251
  "content": (
252
  "Sen HilmanAI'sın. Kullanıcıya her zaman 'Halil' diye hitap edeceksin. "
253
  "İşletim sistemi WINDOWS'tur. "
254
- "ÖNEMLİ KURAL 1: Halil internetten ürün, fiyat veya araştırma istediğinde, sana sağlanan [CANLI İNTERNET ARAMA SONUÇLARI]'nı incele. "
255
- "ÖNEMLİ KURAL 2: Ürün arama isteklerinde şu formatta detaylı bir liste sun:\n"
256
- "- **Ürün Adı ve Markası**\n- **Site Adı** (Hangi e-ticaret sitesinde olduğu)\n- **Fiyat**\n- **Yorumlar / Güvenilirlik**\n- **Kargo / Gönderim Süresi**\n- **Ürün Linki**\n"
257
- "ÖNEMLİ KURAL 3: Matematiksel hesaplamalarda veya bilgi isteklerinde ASLA komut çalıştırma. "
258
- "ÖNEMLİ KURAL 4: Yalnızca Halil doğrudan bir uygulama/site açmanı veya sistem işlemi yapmanı isterse Windows CMD/PowerShell komut bloğu üret."
259
  )
260
  }
261
 
262
- full_messages = [system_instruction] + compressed_messages
263
  if search_context and len(full_messages) > 1:
264
- full_messages[-1]["content"] += search_context
 
265
 
266
- # --- 1. ANTIGRAVITY ---
 
 
267
  if ANTIGRAVITY_API_KEY:
268
- ag_headers = {
269
- "Authorization": f"Bearer {ANTIGRAVITY_API_KEY.strip()}",
270
- "Content-Type": "application/json"
271
- }
272
- ag_payload = {
273
- "model": "gemini-2.0-flash",
274
- "messages": full_messages,
275
- "temperature": 0.2
276
- }
277
  try:
278
- print("[SİSTEM]: Antigravity API deneniyor...")
279
- ag_res = requests.post("https://api.antigravity.dev/v1/chat/completions", json=ag_payload, headers=ag_headers, timeout=12)
280
- if ag_res.status_code == 200:
281
- print("[BAŞARILI]: Antigravity yanıt verdi!")
282
- data = ag_res.json()
283
- return data["choices"][0]["message"]["content"]
 
 
 
 
 
 
 
 
 
284
  except Exception as e:
285
- print(f"[ANTIGRAVITY YANIT VERMEDİ]: {e}")
286
 
287
- # --- 2. OPENROUTER ---
288
  if OPENROUTER_API_KEY:
289
- or_headers = {
290
- "Authorization": f"Bearer {OPENROUTER_API_KEY.strip()}",
291
- "Content-Type": "application/json",
292
- "HTTP-Referer": "https://huggingface.co",
293
- "X-Title": "HilmanAI"
294
- }
295
- or_models = [
296
- "google/gemini-2.0-flash-lite-001",
297
- "meta-llama/llama-3.3-70b-instruct",
298
- "deepseek/deepseek-r1-distill-llama-70b"
299
- ]
300
- for m in or_models:
301
- try:
302
- print(f"[SİSTEM]: OpenRouter ({m}) deneniyor...")
303
- or_res = requests.post(
304
- "https://openrouter.ai/api/v1/chat/completions",
305
- json={"model": m, "messages": full_messages, "temperature": 0.2},
306
- headers=or_headers,
307
- timeout=12
308
- )
309
- if or_res.status_code == 200:
310
- print(f"[BAŞARILI]: OpenRouter ({m}) yanıt verdi!")
311
- data = or_res.json()
312
- return data["choices"][0]["message"]["content"]
313
- except Exception:
314
- continue
315
-
316
- return "Tüm yapay zeka servisleri şu an meşgul veya internet araması yapılamadı, Halil."
317
-
318
- # --- ASIL PROXY ENDPOINT ---
319
- @app.post("/v1/chat/completions")
320
- def chat_proxy(req: ChatRequest, authorization: str = Header(None)):
321
- if not authorization or authorization != f"Bearer {MY_SECRET_KEY}":
322
- raise HTTPException(status_code=401, detail="Yetkisiz erişim! Geçersiz Secret Key.")
323
-
324
- for m in req.messages:
325
- if isinstance(m, dict) and "role" in m and "content" in m:
326
- save_message(m["role"], m["content"])
327
-
328
- ai_response_text = call_ai_backend(req.messages)
329
- save_message("assistant", ai_response_text)
330
-
331
- return {
332
- "choices": [
333
- {
334
- "message": {
335
- "role": "assistant",
336
- "content": ai_response_text
337
- }
338
  }
339
- ]
340
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import requests
3
  import sqlite3
4
  from fastapi import FastAPI, Header, HTTPException, Request
5
+ from fastapi.responses import JSONResponse
6
  from pydantic import BaseModel
7
  from duckduckgo_search import DDGS
8
 
9
+ app = FastAPI(title="HilmanAI Real Cloud Proxy Gateway")
10
 
11
+ # --- ÇEVRE DEĞİŞKENLERİ (Hugging Face Secrets'tan çekilir) ---
12
+ MY_SECRET_KEY = os.getenv("MY_SECRET_KEY", "sk-hilman-proxy-2026")
13
  OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
14
  ANTIGRAVITY_API_KEY = os.getenv("ANTIGRAVITY_API_KEY")
15
 
16
+ # --- VERİTABANI (İstek Logları ve Hafıza) ---
17
  DB_PATH = "hilman_space_memory.db"
18
 
19
  def init_db():
 
45
  except Exception as e:
46
  print(f"DB Kayıt Hatası: {e}")
47
 
48
+ # --- İNTERNET ARAMA MOTORU ---
49
  def web_search(query: str) -> str:
50
  try:
51
  print(f"[İNTERNET ARAMASI]: '{query}' aranıyor...")
 
63
  return f"Arama sırasında hata oluştu: {e}"
64
 
65
  class ChatRequest(BaseModel):
66
+ model: str = "google/gemini-2.0-flash-lite-001"
 
67
  messages: list
68
+ temperature: float = 0.2
69
 
70
+ # --- SUNUCU SAĞLIK VE DURUM KONTROLÜ ---
71
+ @app.get("/")
72
+ def root():
73
+ return {
74
+ "status": "online",
75
+ "message": "HilmanAI Cloud Proxy is active and running 24/7, Halil.",
76
+ "endpoints": {
77
+ "chat_completions": "/v1/chat/completions",
78
+ "status": "/server-status"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
+ }
 
 
 
 
 
 
 
 
81
 
82
  @app.get("/server-status")
83
  def server_status():
84
+ return {
85
+ "service": "Running",
86
+ "port": 7860,
87
+ "auth_enabled": True,
88
+ "providers_loaded": {
89
+ "openrouter": bool(OPENROUTER_API_KEY),
90
+ "antigravity": bool(ANTIGRAVITY_API_KEY)
91
+ }
92
+ }
93
 
94
+ # --- GERÇEK PROXY İSTEK YÖNLENDİRİCİSİ ---
95
+ @app.post("/v1/chat/completions")
96
+ def proxy_chat_completions(req: ChatRequest, authorization: str = Header(None)):
97
+ # 1. Güvenlik ve Yetkilendirme Kontrolü
98
+ if not authorization or authorization != f"Bearer {MY_SECRET_KEY}":
99
+ raise HTTPException(status_code=401, detail="Yetkisiz erişim! Geçersiz Secret Key.")
 
100
 
101
+ # 2. Gelen Mesajları Veritabanına Kaydet
102
+ last_user_msg = ""
103
+ for m in req.messages:
104
+ if isinstance(m, dict):
105
+ role = m.get("role", "user")
106
+ content = m.get("content", "")
107
+ if role == "user":
108
+ last_user_msg = content
109
+ save_message(role, content)
110
+
111
+ # 3. Canlı İnternet Arama Tetikleyicisi
112
  search_keywords = ["bul", "ara", "fiyat", "en ucuz", "nerede", "satın al", "karşılaştır", "incele"]
113
  search_context = ""
 
114
  if any(kw in last_user_msg.lower() for kw in search_keywords):
115
  search_results = web_search(last_user_msg)
116
+ search_context = f"\n\n[CANLI İNTERNET ARAMA SONUÇLARI]:\n{search_results}\nYukarıdaki güncel internet verilerini kullanarak Halil'e net, fiyatlı ve detaylı bilgi sun."
 
 
117
 
118
+ # Sistem Talimatı Ekleme
119
  system_instruction = {
120
  "role": "system",
121
  "content": (
122
  "Sen HilmanAI'sın. Kullanıcıya her zaman 'Halil' diye hitap edeceksin. "
123
  "İşletim sistemi WINDOWS'tur. "
124
+ "Halil internetten ürün, fiyat veya araştırma istediğinde sana sağlanan [CANLI İNTERNET ARAMA SONUÇLARI]'nı kullan."
 
 
 
 
125
  )
126
  }
127
 
128
+ full_messages = [system_instruction] + req.messages
129
  if search_context and len(full_messages) > 1:
130
+ if isinstance(full_messages[-1], dict):
131
+ full_messages[-1]["content"] += search_context
132
 
133
+ ai_response_text = "Tüm yapay zeka servisleri şu an yanıt vermiyor."
134
+
135
+ # 4. Antigravity API Üzerinden Proxy İsteği
136
  if ANTIGRAVITY_API_KEY:
 
 
 
 
 
 
 
 
 
137
  try:
138
+ headers = {
139
+ "Authorization": f"Bearer {ANTIGRAVITY_API_KEY.strip()}",
140
+ "Content-Type": "application/json"
141
+ }
142
+ payload = {
143
+ "model": "gemini-2.0-flash",
144
+ "messages": full_messages,
145
+ "temperature": req.temperature
146
+ }
147
+ res = requests.post("https://api.antigravity.dev/v1/chat/completions", json=payload, headers=headers, timeout=15)
148
+ if res.status_code == 200:
149
+ data = res.json()
150
+ ai_response_text = data["choices"][0]["message"]["content"]
151
+ save_message("assistant", ai_response_text)
152
+ return res.json()
153
  except Exception as e:
154
+ print(f"Antigravity Proxy Hatası: {e}")
155
 
156
+ # 5. OpenRouter API Üzerinden Proxy İsteği (Yedek)
157
  if OPENROUTER_API_KEY:
158
+ try:
159
+ headers = {
160
+ "Authorization": f"Bearer {OPENROUTER_API_KEY.strip()}",
161
+ "Content-Type": "application/json",
162
+ "HTTP-Referer": "https://huggingface.co",
163
+ "X-Title": "HilmanAI"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  }
165
+ fallback_models = [
166
+ req.model,
167
+ "google/gemini-2.0-flash-lite-001",
168
+ "meta-llama/llama-3.3-70b-instruct"
169
+ ]
170
+ for model_name in fallback_models:
171
+ payload = {
172
+ "model": model_name,
173
+ "messages": full_messages,
174
+ "temperature": req.temperature
175
+ }
176
+ res = requests.post("https://openrouter.ai/api/v1/chat/completions", json=payload, headers=headers, timeout=15)
177
+ if res.status_code == 200:
178
+ data = res.json()
179
+ ai_response_text = data["choices"][0]["message"]["content"]
180
+ save_message("assistant", ai_response_text)
181
+ return res.json()
182
+ except Exception as e:
183
+ print(f"OpenRouter Proxy Hatası: {e}")
184
+
185
+ raise HTTPException(status_code=500, detail="Hiçbir AI Sağlayıcısından yanıt alınamadı.")