Zenkad commited on
Commit
90e814c
·
verified ·
1 Parent(s): 84d0923

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +313 -306
app.py CHANGED
@@ -1,35 +1,73 @@
1
- from fastapi import FastAPI, Request
2
- from fastapi.responses import JSONResponse
3
  from fastapi.middleware.cors import CORSMiddleware
 
4
  import json
5
  import os
 
6
  from datetime import datetime, date
7
  import requests
8
  import logging
 
9
 
10
  # Logging ayarı
11
- logging.basicConfig(level=logging.INFO)
 
 
 
12
  logger = logging.getLogger(__name__)
13
 
14
- app = FastAPI(title="AI Chat API", version="1.0.0")
 
 
 
 
 
15
 
16
- # CORS ayarları
17
  app.add_middleware(
18
  CORSMiddleware,
19
- allow_origins=["*"],
 
20
  allow_methods=["*"],
21
  allow_headers=["*"],
 
22
  )
23
 
24
- # Dosya yolları ve konfigürasyon
25
  DB_PATH = "users.json"
26
  HF_TOKEN = os.getenv("HF_TOKEN", "")
27
  MODEL_NAME = "mistralai/Mistral-7B-Instruct-v0.2"
28
  API_URL = f"https://api-inference.huggingface.co/models/{MODEL_NAME}"
29
 
30
- # Varsayılan limitler
31
  DAILY_LIMIT = 100
32
- MAX_TOKENS = 200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  def load_db():
35
  """Kullanıcı veritabanını yükle"""
@@ -52,15 +90,14 @@ def save_db(data):
52
  logger.error(f"Veritabanı kaydetme hatası: {e}")
53
  return False
54
 
55
- def get_model_response_v1(message):
56
- """Model yanıtı - V1 (Daha basit format)"""
57
  if not HF_TOKEN:
58
- logger.warning("HF_TOKEN bulunamadı")
59
- return "API token bulunamadı. Lütfen HF_TOKEN ortam değişkenini ayarlayın."
60
 
61
  try:
62
- # Mistral için uygun prompt formatı
63
- formatted_prompt = f"<s>[INST] {message} [/INST]"
64
 
65
  response = requests.post(
66
  API_URL,
@@ -69,216 +106,214 @@ def get_model_response_v1(message):
69
  "Content-Type": "application/json"
70
  },
71
  json={
72
- "inputs": formatted_prompt,
73
  "parameters": {
74
  "max_new_tokens": MAX_TOKENS,
75
  "temperature": 0.7,
76
- "top_p": 0.95,
77
  "do_sample": True,
78
  "return_full_text": False
79
  }
80
  },
81
- timeout=30
82
  )
83
 
84
- logger.info(f"API Yanıt Kodu: {response.status_code}")
85
 
86
  if response.status_code == 200:
87
  result = response.json()
88
- logger.info(f"API Yanıtı: {result}")
89
 
90
- # Farklı response formatlarını işle
91
  if isinstance(result, list):
92
- if len(result) > 0:
93
- if isinstance(result[0], dict):
94
- # Format 1: [{'generated_text': '...'}]
95
- if 'generated_text' in result[0]:
96
- text = result[0]['generated_text']
97
- # Prompt'u temizle
98
  if isinstance(text, str):
99
- text = text.replace(formatted_prompt, "").strip()
100
- return text
 
 
101
 
102
- # Format 2: [{'generated_text': [{'content': '...'}]}]
103
- for key in result[0]:
104
- if isinstance(result[0][key], str):
105
- text = result[0][key]
106
- text = text.replace(formatted_prompt, "").strip()
107
- return text
108
 
109
- # Direk string dönerse
110
- if isinstance(result, str):
111
- return result.replace(formatted_prompt, "").strip()
112
-
113
- return "Yanıt alındı ancak format beklenmiyor."
114
 
115
  elif response.status_code == 503:
116
- logger.warning("Model yükleniyor...")
117
- return "Model şu anda yükleniyor, lütfen 10-20 saniye sonra tekrar deneyin."
118
 
119
  elif response.status_code == 429:
120
- return "Çok fazla istek gönderildi. Lütfen bir süre bekleyin."
121
-
122
- elif response.status_code == 401:
123
- return "API token geçersiz. Lütfen token'ı kontrol edin."
124
 
125
  else:
126
- logger.error(f"API Hatası: {response.status_code} - {response.text[:200]}")
127
- return f"API hatası: {response.status_code}"
128
-
129
- except requests.exceptions.Timeout:
130
- logger.error("API timeout hatası")
131
- return "Model yanıt verme süresi aşıldı. Lütfen daha sonra tekrar deneyin."
132
 
133
- except requests.exceptions.ConnectionError:
134
- logger.error("API bağlantı hatası")
135
- return "API'ye bağlanılamadı. Lütfen internet bağlantınızı kontrol edin."
136
 
137
  except Exception as e:
138
- logger.error(f"Model iletişim hatası: {str(e)}")
139
- return f"Beklenmeyen hata: {str(e)}"
140
 
141
- def get_model_response_v2(message):
142
- """Model yanıtı - V2 (Alternatif yaklaşım)"""
143
- if not HF_TOKEN:
144
- return "API token bulunamadı."
145
-
146
- try:
147
- # Daha basit prompt formatı
148
- formatted_prompt = f"Kullanıcı: {message}\nAsistan:"
149
-
150
- response = requests.post(
151
- API_URL,
152
- headers={"Authorization": f"Bearer {HF_TOKEN}"},
153
- json={
154
- "inputs": formatted_prompt,
155
- "parameters": {
156
- "max_new_tokens": 150,
157
- "temperature": 0.8,
158
- "top_k": 50,
159
- "return_full_text": False
160
- }
161
- },
162
- timeout=25
163
- )
164
-
165
- if response.status_code == 200:
166
- result = response.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- # Basit format çözümleme
169
- if isinstance(result, list):
170
- for item in result:
171
- if isinstance(item, dict):
172
- for key, value in item.items():
173
- if isinstance(value, str):
174
- # Prompt'u temizle
175
- cleaned = value.replace(formatted_prompt, "").strip()
176
- if cleaned:
177
- return cleaned
178
- elif isinstance(value, list):
179
- for sub_item in value:
180
- if isinstance(sub_item, dict) and 'content' in sub_item:
181
- return sub_item['content']
182
 
183
- return "Anlamlı bir yanıt alınamadı."
184
-
185
- return "Model geçici olarak kullanılamıyor."
186
-
187
- except Exception:
188
- return "Bağlantı hatası oluştu."
189
-
190
- def get_model_response_v3(message):
191
- """Model yanıtı - V3 (En basit)"""
192
- if not HF_TOKEN:
193
- return "Sistem hazır değil. Lütfen daha sonra tekrar deneyin."
194
-
195
- try:
196
- # En basit yaklaşım
197
- response = requests.post(
198
- API_URL,
199
- headers={"Authorization": f"Bearer {HF_TOKEN}"},
200
- json={"inputs": message},
201
- timeout=20
202
- )
203
-
204
- if response.status_code == 200:
205
- result = response.json()
206
 
207
- # Çok basit parsing
208
- if isinstance(result, list):
209
- return str(result[0]) if result else "Boş yanıt"
210
- elif isinstance(result, dict):
211
- for value in result.values():
212
- if isinstance(value, str) and value.strip():
213
- return value.strip()
214
 
215
- return "Yanıt işlenemedi"
216
-
217
- return f"Hata kodu: {response.status_code}"
218
-
219
- except Exception:
220
- return "Servis geçici olarak kullanılamıyor."
221
-
222
- def get_model_response(message):
223
- """Ana model yanıt fonksiyonu - Tüm versiyonları dener"""
224
- logger.info(f"Gelen mesaj: {message}")
225
-
226
- # Versiyonları sırayla dene
227
- responses = []
228
-
229
- # V1'i dene
230
- response_v1 = get_model_response_v1(message)
231
- if response_v1 and len(response_v1) > 10 and "token" not in response_v1.lower() and "hata" not in response_v1.lower():
232
- return response_v1
233
- responses.append(response_v1)
234
-
235
- # V2'yi dene
236
- response_v2 = get_model_response_v2(message)
237
- if response_v2 and len(response_v2) > 10 and "token" not in response_v2.lower() and "hata" not in response_v2.lower():
238
- return response_v2
239
- responses.append(response_v2)
240
-
241
- # V3'ü dene
242
- response_v3 = get_model_response_v3(message)
243
- if response_v3 and len(response_v3) > 10:
244
- return response_v3
245
-
246
- # Hiçbiri çalışmazsa en iyi yanıtı seç
247
- for resp in responses:
248
- if resp and len(resp) > 5:
249
- return resp
250
-
251
- return "Üzgünüm, şu anda yanıt veremiyorum. Lütfen daha sonra tekrar deneyin."
252
-
253
- @app.get("/")
254
- def home():
255
- """Ana sayfa"""
256
- return {
257
- "app": "AI Chat API",
258
- "version": "1.0.0",
259
- "status": "active",
260
- "endpoints": {
261
- "health": "/health",
262
- "chat": "/api/chat (POST)",
263
- "stats": "/api/stats/{email} (GET)"
264
- }
265
- }
266
 
267
  @app.get("/health")
268
- def health():
269
- """Sağlık kontrolü"""
270
- token_status = "valid" if HF_TOKEN else "missing"
271
  db_status = "exists" if os.path.exists(DB_PATH) else "missing"
 
272
 
273
  return {
274
- "status": "healthy",
275
  "timestamp": datetime.now().isoformat(),
276
- "token": token_status,
277
- "database": db_status,
278
  "model": MODEL_NAME,
279
- "daily_limit": DAILY_LIMIT
 
 
 
 
280
  }
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  @app.post("/api/chat")
283
  async def chat(request: Request):
284
  """Chat endpoint'i"""
@@ -287,28 +322,19 @@ async def chat(request: Request):
287
  email = data.get("email", "").strip().lower()
288
  message = data.get("message", "").strip()
289
 
290
- logger.info(f"Chat isteği - Email: {email}, Mesaj: {message[:50]}...")
291
 
292
  # Validasyon
293
  if not email or "@" not in email:
294
- return JSONResponse(
295
- status_code=400,
296
- content={"error": "Geçerli bir email adresi giriniz."}
297
- )
298
 
299
  if not message:
300
- return JSONResponse(
301
- status_code=400,
302
- content={"error": "Mesaj boş olamaz."}
303
- )
304
 
305
- if len(message) > 1000:
306
- return JSONResponse(
307
- status_code=400,
308
- content={"error": "Mesaj çok uzun. Maksimum 1000 karakter."}
309
- )
310
 
311
- # Veritabanı işlemleri
312
  db = load_db()
313
  today = date.today().isoformat()
314
 
@@ -317,145 +343,126 @@ async def chat(request: Request):
317
  "count": 0,
318
  "total": 0,
319
  "last_reset": today,
320
- "created_at": datetime.now().isoformat(),
321
- "last_used": datetime.now().isoformat()
322
  }
323
 
324
  user = db[email]
325
 
326
- # Günlük limit kontrolü
327
  if user["last_reset"] != today:
328
  user["count"] = 0
329
  user["last_reset"] = today
330
 
331
  if user["count"] >= DAILY_LIMIT:
332
- return JSONResponse(
333
- status_code=429,
334
- content={
335
- "error": "Günlük limit doldu",
336
- "limit": DAILY_LIMIT,
337
- "reset_date": today
338
- }
339
- )
340
-
341
- # Model yanıtını al
342
- start_time = datetime.now()
343
- ai_response = get_model_response(message)
344
- response_time = (datetime.now() - start_time).total_seconds()
345
-
346
- logger.info(f"Yanıt süresi: {response_time:.2f}s")
347
 
348
- # Kullanıcı istatistiklerini güncelle
 
349
  user["count"] += 1
350
  user["total"] += 1
351
- user["last_used"] = datetime.now().isoformat()
352
 
353
- # Veritabanını kaydet
354
  save_db(db)
355
 
356
- # Yanıt
357
  return {
358
  "response": ai_response,
359
  "status": "success",
360
  "remaining": DAILY_LIMIT - user["count"],
361
  "used_today": user["count"],
362
  "total_used": user["total"],
363
- "response_time": f"{response_time:.2f}s"
364
  }
365
 
366
- except json.JSONDecodeError:
367
- return JSONResponse(
368
- status_code=400,
369
- content={"error": "Geçersiz JSON formatı"}
370
- )
371
-
372
  except Exception as e:
373
- logger.error(f"Chat hatası: {str(e)}")
374
- return JSONResponse(
375
- status_code=500,
376
- content={"error": f"Sunucu hatası: {str(e)}"}
377
- )
378
 
379
  @app.get("/api/stats/{email}")
380
- def get_stats(email: str):
381
- """Kullanıcı istatistiklerini getir"""
382
- try:
383
- email = email.strip().lower()
384
- db = load_db()
385
-
386
- if email not in db:
387
- return JSONResponse(
388
- status_code=404,
389
- content={"error": "Kullanıcı bulunamadı"}
390
- )
391
-
392
- user = db[email]
393
- today = date.today().isoformat()
394
-
395
- # Günlük limit sıfırlama kontrolü
396
- if user["last_reset"] != today:
397
- user["count"] = 0
398
- user["last_reset"] = today
399
- save_db(db)
400
-
401
- return {
402
- "email": email,
403
- "used_today": user["count"],
404
- "remaining_today": DAILY_LIMIT - user["count"],
405
- "total_used": user["total"],
406
- "last_reset": user["last_reset"],
407
- "last_used": user.get("last_used", "never"),
408
- "created_at": user.get("created_at", "unknown")
409
- }
410
-
411
- except Exception as e:
412
- return JSONResponse(
413
- status_code=500,
414
- content={"error": str(e)}
415
- )
416
 
417
- @app.get("/api/reset-test/{email}")
418
- def reset_test(email: str):
419
- """Test için kullanıcı limitini sıfırla"""
420
- try:
421
- email = email.strip().lower()
422
- db = load_db()
 
 
 
 
423
 
424
- if email in db:
425
- db[email]["count"] = 0
426
- db[email]["last_reset"] = date.today().isoformat()
427
- save_db(db)
428
-
429
- return {
430
- "status": "success",
431
- "message": f"{email} limiti sıfırlandı"
432
- }
433
- else:
434
- return JSONResponse(
435
- status_code=404,
436
- content={"error": "Kullanıcı bulunamadı"}
437
- )
438
-
439
- except Exception as e:
440
- return JSONResponse(
441
- status_code=500,
442
- content={"error": str(e)}
443
- )
 
 
 
 
444
 
445
  if __name__ == "__main__":
446
  import uvicorn
447
 
448
- logger.info("=" * 50)
449
- logger.info("AI Chat API Başlatılıyor...")
450
- logger.info(f"Model: {MODEL_NAME}")
451
- logger.info(f"Token Durumu: {'Var' if HF_TOKEN else 'Yok'}")
452
- logger.info(f"Günlük Limit: {DAILY_LIMIT}")
453
- logger.info("=" * 50)
 
 
 
 
 
 
 
454
 
 
455
  uvicorn.run(
456
- "app:app",
457
- host="0.0.0.0",
458
- port=8000,
459
  reload=True,
460
- log_level="info"
 
461
  )
 
1
+ from fastapi import FastAPI, Request, HTTPException
2
+ from fastapi.responses import JSONResponse, HTMLResponse
3
  from fastapi.middleware.cors import CORSMiddleware
4
+ from fastapi.staticfiles import StaticFiles
5
  import json
6
  import os
7
+ import socket
8
  from datetime import datetime, date
9
  import requests
10
  import logging
11
+ import threading
12
 
13
  # Logging ayarı
14
+ logging.basicConfig(
15
+ level=logging.INFO,
16
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
17
+ )
18
  logger = logging.getLogger(__name__)
19
 
20
+ app = FastAPI(
21
+ title="AI Chat API",
22
+ version="2.0.0",
23
+ docs_url="/docs",
24
+ redoc_url="/redoc"
25
+ )
26
 
27
+ # TÜM CORS izinleri - Telefondan erişim için
28
  app.add_middleware(
29
  CORSMiddleware,
30
+ allow_origins=["*"], # Tüm domain'lere izin ver
31
+ allow_credentials=True,
32
  allow_methods=["*"],
33
  allow_headers=["*"],
34
+ expose_headers=["*"]
35
  )
36
 
37
+ # Dosya yolları
38
  DB_PATH = "users.json"
39
  HF_TOKEN = os.getenv("HF_TOKEN", "")
40
  MODEL_NAME = "mistralai/Mistral-7B-Instruct-v0.2"
41
  API_URL = f"https://api-inference.huggingface.co/models/{MODEL_NAME}"
42
 
43
+ # Limitler
44
  DAILY_LIMIT = 100
45
+ MAX_TOKENS = 150
46
+
47
+ def get_local_ip():
48
+ """Bilgisayarın IP adresini bul"""
49
+ try:
50
+ # İnternet bağlantısı olan bir socket oluştur
51
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
52
+ s.connect(("8.8.8.8", 80)) # Google DNS
53
+ ip = s.getsockname()[0]
54
+ s.close()
55
+ return ip
56
+ except:
57
+ return "127.0.0.1"
58
+
59
+ # Sunucu bilgileri
60
+ SERVER_IP = get_local_ip()
61
+ SERVER_PORT = 8000
62
+ BASE_URL = f"http://{SERVER_IP}:{SERVER_PORT}"
63
+
64
+ # QR kodu oluşturmak için
65
+ def generate_qr_code_url():
66
+ """Telefonda açmak için QR kodu URL'si"""
67
+ import urllib.parse
68
+ html_url = f"{BASE_URL}/test"
69
+ qr_url = f"https://api.qrserver.com/v1/create-qr-code/?size=200x200&data={urllib.parse.quote(html_url)}"
70
+ return qr_url
71
 
72
  def load_db():
73
  """Kullanıcı veritabanını yükle"""
 
90
  logger.error(f"Veritabanı kaydetme hatası: {e}")
91
  return False
92
 
93
+ def get_model_response_simple(message):
94
+ """Basit model yanıtı - Hata toleranslı"""
95
  if not HF_TOKEN:
96
+ return "🔑 API token bulunamadı. Lütfen HF_TOKEN ayarlayın."
 
97
 
98
  try:
99
+ # Daha kısa ve basit prompt
100
+ prompt = f"Kullanıcı soruyor: {message}\nYanıt:"
101
 
102
  response = requests.post(
103
  API_URL,
 
106
  "Content-Type": "application/json"
107
  },
108
  json={
109
+ "inputs": prompt,
110
  "parameters": {
111
  "max_new_tokens": MAX_TOKENS,
112
  "temperature": 0.7,
113
+ "top_p": 0.9,
114
  "do_sample": True,
115
  "return_full_text": False
116
  }
117
  },
118
+ timeout=15
119
  )
120
 
121
+ logger.info(f"API Status: {response.status_code}")
122
 
123
  if response.status_code == 200:
124
  result = response.json()
 
125
 
126
+ # Farklı formatları işle
127
  if isinstance(result, list):
128
+ for item in result:
129
+ if isinstance(item, dict):
130
+ # Format: [{'generated_text': '...'}]
131
+ if 'generated_text' in item:
132
+ text = item['generated_text']
 
133
  if isinstance(text, str):
134
+ # Prompt'u temizle
135
+ text = text.replace(prompt, "").strip()
136
+ if text:
137
+ return text
138
 
139
+ # Diğer formatlar
140
+ for key, value in item.items():
141
+ if isinstance(value, str) and len(value) > 10:
142
+ cleaned = value.replace(prompt, "").strip()
143
+ if cleaned:
144
+ return cleaned
145
 
146
+ return "🤖 Yanıt alındı ancak işlenemedi."
 
 
 
 
147
 
148
  elif response.status_code == 503:
149
+ return "Model yükleniyor, lütfen 15 saniye bekleyin..."
 
150
 
151
  elif response.status_code == 429:
152
+ return "🚫 Çok fazla istek, lütfen bekleyin."
 
 
 
153
 
154
  else:
155
+ return f"API hatası: {response.status_code}"
 
 
 
 
 
156
 
157
+ except requests.exceptions.Timeout:
158
+ return "⏱️ Zaman aşımı, lütfen daha kısa soru sorun."
 
159
 
160
  except Exception as e:
161
+ logger.error(f"Model hatası: {e}")
162
+ return f"⚠️ Teknik hata: {str(e)[:50]}"
163
 
164
+ @app.get("/", response_class=HTMLResponse)
165
+ async def home():
166
+ """Ana sayfa - QR kodu ve bağlantılar"""
167
+ html_content = f"""
168
+ <!DOCTYPE html>
169
+ <html>
170
+ <head>
171
+ <meta charset="UTF-8">
172
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
173
+ <title>AI Chat API - Telefon Erişimi</title>
174
+ <style>
175
+ body {{
176
+ font-family: Arial, sans-serif;
177
+ max-width: 800px;
178
+ margin: 0 auto;
179
+ padding: 20px;
180
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
181
+ min-height: 100vh;
182
+ color: white;
183
+ }}
184
+ .container {{
185
+ background: rgba(255,255,255,0.95);
186
+ border-radius: 20px;
187
+ padding: 30px;
188
+ color: #333;
189
+ box-shadow: 0 10px 40px rgba(0,0,0,0.3);
190
+ }}
191
+ h1 {{ color: #4f46e5; }}
192
+ .qr-container {{
193
+ text-align: center;
194
+ margin: 30px 0;
195
+ padding: 20px;
196
+ background: #f8fafc;
197
+ border-radius: 15px;
198
+ }}
199
+ .qr-code {{
200
+ width: 200px;
201
+ height: 200px;
202
+ margin: 0 auto;
203
+ background: white;
204
+ padding: 10px;
205
+ border-radius: 10px;
206
+ }}
207
+ .link-box {{
208
+ background: #e0f2fe;
209
+ padding: 15px;
210
+ border-radius: 10px;
211
+ margin: 10px 0;
212
+ word-break: break-all;
213
+ }}
214
+ .btn {{
215
+ display: inline-block;
216
+ background: #4f46e5;
217
+ color: white;
218
+ padding: 12px 24px;
219
+ text-decoration: none;
220
+ border-radius: 10px;
221
+ margin: 5px;
222
+ font-weight: bold;
223
+ }}
224
+ .status {{
225
+ padding: 10px;
226
+ border-radius: 8px;
227
+ margin: 10px 0;
228
+ }}
229
+ .success {{ background: #d1fae5; color: #065f46; }}
230
+ .warning {{ background: #fef3c7; color: #92400e; }}
231
+ .error {{ background: #fee2e2; color: #dc2626; }}
232
+ </style>
233
+ </head>
234
+ <body>
235
+ <div class="container">
236
+ <h1>🤖 AI Chat API</h1>
237
+ <p>Telefonunuzdan bağlanmak için:</p>
238
 
239
+ <div class="status {'success' if HF_TOKEN else 'warning'}">
240
+ <strong>Model Durumu:</strong> {'✅ Hazır' if HF_TOKEN else '⚠️ Token Eksik'}
241
+ </div>
 
 
 
 
 
 
 
 
 
 
 
242
 
243
+ <div class="qr-container">
244
+ <h3>📱 Telefon ile Bağlan</h3>
245
+ <p>Telefon kameranızla bu QR kodu tarayın:</p>
246
+ <div class="qr-code">
247
+ <img src="{generate_qr_code_url()}" width="200" height="200">
248
+ </div>
249
+ <p style="font-size: 14px; color: #666;">veya bağlantıya tıklayın</p>
250
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
 
252
+ <h3>🔗 Bağlantılar:</h3>
253
+ <div class="link-box">
254
+ <strong>Test Arayüzü:</strong><br>
255
+ <a href="/test" class="btn">📲 Aç</a>
256
+ <a href="{BASE_URL}/test" target="_blank">{BASE_URL}/test</a>
257
+ </div>
 
258
 
259
+ <div class="link-box">
260
+ <strong>API Dokümantasyon:</strong><br>
261
+ <a href="/docs" class="btn">📚 Aç</a>
262
+ <a href="{BASE_URL}/docs" target="_blank">{BASE_URL}/docs</a>
263
+ </div>
264
+
265
+ <div class="link-box">
266
+ <strong>Health Check:</strong><br>
267
+ <a href="/health" class="btn">🩺 Aç</a>
268
+ <a href="{BASE_URL}/health" target="_blank">{BASE_URL}/health</a>
269
+ </div>
270
+
271
+ <div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #e5e7eb;">
272
+ <h4>📋 Bilgiler:</h4>
273
+ <p><strong>IP Adresi:</strong> {SERVER_IP}</p>
274
+ <p><strong>Port:</strong> {SERVER_PORT}</p>
275
+ <p><strong>Model:</strong> {MODEL_NAME}</p>
276
+ <p><strong>Günlük Limit:</strong> {DAILY_LIMIT} sorgu/kullanıcı</p>
277
+ </div>
278
+ </div>
279
+ </body>
280
+ </html>
281
+ """
282
+ return HTMLResponse(content=html_content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
  @app.get("/health")
285
+ async def health():
286
+ """Sağlık kontrolü - JSON formatında"""
 
287
  db_status = "exists" if os.path.exists(DB_PATH) else "missing"
288
+ token_exists = bool(HF_TOKEN)
289
 
290
  return {
291
+ "status": "healthy" if token_exists else "no_token",
292
  "timestamp": datetime.now().isoformat(),
293
+ "server_ip": SERVER_IP,
294
+ "port": SERVER_PORT,
295
  "model": MODEL_NAME,
296
+ "token": "valid" if token_exists else "missing",
297
+ "database": db_status,
298
+ "daily_limit": DAILY_LIMIT,
299
+ "api_url": f"http://{SERVER_IP}:{SERVER_PORT}",
300
+ "test_url": f"http://{SERVER_IP}:{SERVER_PORT}/test"
301
  }
302
 
303
+ @app.get("/test", response_class=HTMLResponse)
304
+ async def test_page():
305
+ """Test arayüzü sayfası"""
306
+ with open("test.html", "r", encoding="utf-8") as f:
307
+ html_content = f.read()
308
+
309
+ # API URL'sini dinamik olarak ayarla
310
+ html_content = html_content.replace(
311
+ 'const API_BASE_URL = \'http://localhost:8000\';',
312
+ f'const API_BASE_URL = \'http://{SERVER_IP}:{SERVER_PORT}\';'
313
+ )
314
+
315
+ return HTMLResponse(content=html_content)
316
+
317
  @app.post("/api/chat")
318
  async def chat(request: Request):
319
  """Chat endpoint'i"""
 
322
  email = data.get("email", "").strip().lower()
323
  message = data.get("message", "").strip()
324
 
325
+ logger.info(f"Chat isteği: {email} - {message[:30]}...")
326
 
327
  # Validasyon
328
  if not email or "@" not in email:
329
+ raise HTTPException(400, "Geçerli email gerekli")
 
 
 
330
 
331
  if not message:
332
+ raise HTTPException(400, "Mesaj boş olamaz")
 
 
 
333
 
334
+ if len(message) > 500:
335
+ raise HTTPException(400, "Mesaj çok uzun (max 500 karakter)")
 
 
 
336
 
337
+ # Veritabanı
338
  db = load_db()
339
  today = date.today().isoformat()
340
 
 
343
  "count": 0,
344
  "total": 0,
345
  "last_reset": today,
346
+ "created": datetime.now().isoformat()
 
347
  }
348
 
349
  user = db[email]
350
 
351
+ # Limit kontrol
352
  if user["last_reset"] != today:
353
  user["count"] = 0
354
  user["last_reset"] = today
355
 
356
  if user["count"] >= DAILY_LIMIT:
357
+ raise HTTPException(429, f"Günlük limit ({DAILY_LIMIT}) doldu")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
+ # Model yanıtı
360
+ ai_response = get_model_response_simple(message)
361
  user["count"] += 1
362
  user["total"] += 1
 
363
 
 
364
  save_db(db)
365
 
 
366
  return {
367
  "response": ai_response,
368
  "status": "success",
369
  "remaining": DAILY_LIMIT - user["count"],
370
  "used_today": user["count"],
371
  "total_used": user["total"],
372
+ "timestamp": datetime.now().isoformat()
373
  }
374
 
375
+ except HTTPException:
376
+ raise
 
 
 
 
377
  except Exception as e:
378
+ logger.error(f"Chat hatası: {e}")
379
+ raise HTTPException(500, f"Sunucu hatası: {str(e)}")
 
 
 
380
 
381
  @app.get("/api/stats/{email}")
382
+ async def get_stats(email: str):
383
+ """İstatistikler"""
384
+ email = email.strip().lower()
385
+ db = load_db()
386
+
387
+ if email not in db:
388
+ raise HTTPException(404, "Kullanıcı bulunamadı")
389
+
390
+ user = db[email]
391
+ today = date.today().isoformat()
392
+
393
+ if user["last_reset"] != today:
394
+ user["count"] = 0
395
+ user["last_reset"] = today
396
+ save_db(db)
397
+
398
+ return {
399
+ "email": email,
400
+ "used_today": user["count"],
401
+ "remaining_today": DAILY_LIMIT - user["count"],
402
+ "total_used": user["total"],
403
+ "last_reset": user["last_reset"],
404
+ "created": user.get("created", "unknown")
405
+ }
 
 
 
 
 
 
 
 
 
 
 
 
406
 
407
+ @app.get("/api/reset/{email}")
408
+ async def reset_limit(email: str):
409
+ """Limit sıfırlama (test için)"""
410
+ email = email.strip().lower()
411
+ db = load_db()
412
+
413
+ if email in db:
414
+ db[email]["count"] = 0
415
+ db[email]["last_reset"] = date.today().isoformat()
416
+ save_db(db)
417
 
418
+ return {"status": "success", "message": f"{email} limiti sıfırlandı"}
419
+ else:
420
+ raise HTTPException(404, "Kullanıcı bulunamadı")
421
+
422
+ @app.get("/api/info")
423
+ async def api_info():
424
+ """API bilgileri"""
425
+ return {
426
+ "api_name": "AI Chat API",
427
+ "version": "2.0.0",
428
+ "model": MODEL_NAME,
429
+ "server_ip": SERVER_IP,
430
+ "port": SERVER_PORT,
431
+ "base_url": f"http://{SERVER_IP}:{SERVER_PORT}",
432
+ "endpoints": {
433
+ "home": "/",
434
+ "test_ui": "/test",
435
+ "chat": "POST /api/chat",
436
+ "health": "GET /health",
437
+ "stats": "GET /api/stats/{email}",
438
+ "reset": "GET /api/reset/{email}",
439
+ "docs": "/docs"
440
+ }
441
+ }
442
 
443
  if __name__ == "__main__":
444
  import uvicorn
445
 
446
+ logger.info("=" * 60)
447
+ logger.info("🤖 AI Chat API Başlatılıyor...")
448
+ logger.info(f"📡 Sunucu IP: {SERVER_IP}")
449
+ logger.info(f"🔌 Port: {SERVER_PORT}")
450
+ logger.info(f"🧠 Model: {MODEL_NAME}")
451
+ logger.info(f"🔑 Token: {'✅ Var' if HF_TOKEN else '❌ Yok'}")
452
+ logger.info(f"📊 Günlük Limit: {DAILY_LIMIT}")
453
+ logger.info("=" * 60)
454
+ logger.info("📱 Telefon bağlantıları:")
455
+ logger.info(f" • Test Arayüzü: http://{SERVER_IP}:{SERVER_PORT}/test")
456
+ logger.info(f" • API Doküman: http://{SERVER_IP}:{SERVER_PORT}/docs")
457
+ logger.info(f" • Health Check: http://{SERVER_IP}:{SERVER_PORT}/health")
458
+ logger.info("=" * 60)
459
 
460
+ # Uvicorn'u başlat
461
  uvicorn.run(
462
+ app,
463
+ host="0.0.0.0", # Tüm ağlardan erişime izin ver
464
+ port=SERVER_PORT,
465
  reload=True,
466
+ log_level="info",
467
+ access_log=True
468
  )