Zenkad commited on
Commit
5e66fcd
·
verified ·
1 Parent(s): 2185257

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +366 -85
app.py CHANGED
@@ -2,25 +2,43 @@ import os
2
  import time
3
  from typing import List, Optional, Dict, Any
4
  import re
 
 
5
 
6
  from fastapi import FastAPI, Request
7
  from fastapi.middleware.cors import CORSMiddleware
8
- from fastapi.responses import JSONResponse
9
  from pydantic import BaseModel
10
  from huggingface_hub import InferenceClient
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # ===============================
13
  # MODEL
14
  # ===============================
15
  MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
16
  HF_TOKEN = os.getenv("HF_TOKEN", os.getenv("HUGGINGFACE_TOKEN"))
17
 
18
- client = InferenceClient(model=MODEL_ID, token=HF_TOKEN)
19
-
20
  # ===============================
21
  # APP
22
  # ===============================
23
- app = FastAPI(title="ZenkaMind API", version="2.0")
 
 
 
 
 
24
 
25
  app.add_middleware(
26
  CORSMiddleware,
@@ -30,6 +48,16 @@ app.add_middleware(
30
  allow_headers=["*"],
31
  )
32
 
 
 
 
 
 
 
 
 
 
 
33
  # ===============================
34
  # AYARLAR
35
  # ===============================
@@ -44,11 +72,8 @@ def clean_response(text: str) -> str:
44
  """Cevabı temizle"""
45
  if not text:
46
  return ""
47
- # Fazla boşlukları temizle
48
  text = re.sub(r'\s+', ' ', text)
49
- # Çin karakterlerini temizle
50
  text = re.sub(r'[\u3400-\u9FFF\uF900-\uFAFF]', '', text)
51
- # Tekrar eden noktaları temizle
52
  text = re.sub(r'\.{3,}', '...', text)
53
  return text.strip()
54
 
@@ -145,11 +170,8 @@ class ChatRequest(BaseModel):
145
  # ===============================
146
  # FREELANCE ÖZEL FONKSİYONLAR
147
  # ===============================
148
-
149
  def enhance_freelance_response(message: str, response: str) -> str:
150
- """Freelance modu için cevabı geliştir"""
151
  message_lower = message.lower()
152
-
153
  enhancements = []
154
 
155
  if any(word in message_lower for word in ["fiyat", "ücret", "price", "fee", "ne kadar"]):
@@ -178,41 +200,313 @@ def enhance_freelance_response(message: str, response: str) -> str:
178
 
179
  return response
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  # ===============================
182
  # ENDPOINTLER
183
  # ===============================
184
- @app.get("/")
185
  async def root():
 
 
 
 
 
 
186
  return {
187
- "status": "ok",
 
188
  "service": "ZenkaMind API",
189
- "model": MODEL_ID,
190
- "free_limit": FREE_MESSAGE_LIMIT,
191
- "modes": list(PROMPTS.keys()),
192
  "version": "2.0",
193
- "docs": "/docs",
194
  "environment": os.getenv("SPACE_ID", "development")
195
  }
196
 
197
- @app.get("/health")
198
- async def health_check():
199
- """Sağlık kontrol endpoint'i"""
200
- return {"status": "healthy", "timestamp": time.time()}
201
-
202
  @app.get("/modes")
203
  async def get_modes():
204
  """Mevcut modları listele"""
205
  modes_info = {
206
- "agir_abi": "Ağır abi tavrı - Hayat dersi veren, otoriter",
207
- "kurumsal": "Kurumsal - Profesyonel, iş odaklı",
208
- "esnaf": "Esnaf - Samimi, pratik çözümlü",
209
- "tech": "Teknik - Kod odaklı, detaylı",
210
- "freelance": "Freelance - Serbest çalışan, proje bazlı"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  }
212
  return {"modes": modes_info}
213
 
214
  @app.post("/api/chat")
215
  async def chat(body: ChatRequest):
 
 
 
 
 
 
 
 
 
 
216
  user_key = body.user_id or "anon"
217
  count = usage_counts.get(user_key, 0)
218
 
@@ -239,6 +533,8 @@ async def chat(body: ChatRequest):
239
  messages.append({"role": "user", "content": body.message.strip()})
240
 
241
  try:
 
 
242
  result = client.chat_completion(
243
  messages=messages,
244
  max_tokens=400,
@@ -255,35 +551,42 @@ async def chat(body: ChatRequest):
255
  usage_counts[user_key] = count + 1
256
  remaining = FREE_MESSAGE_LIMIT - usage_counts[user_key]
257
 
 
 
258
  return {
259
  "response": answer,
260
  "used": usage_counts[user_key],
261
  "remaining": remaining,
262
  "mode": mode,
263
  "premium": False if remaining > 0 else True,
264
- "user_id": user_key
 
265
  }
266
 
267
  except Exception as e:
268
  error_msg = str(e)
 
 
269
  if "rate limit" in error_msg.lower():
270
  fallback_response = "Şu anda yoğunluk var. Lütfen 1 dakika sonra tekrar deneyin."
271
  elif "token" in error_msg.lower():
272
- fallback_response = "Sistem ayarlarında geçici bir sorun var."
 
 
273
  else:
274
  fallback_response = "Teknik bir sorun oluştu. Lütfen tekrar deneyin."
275
 
276
  return {
277
  "response": fallback_response,
278
- "error": error_msg[:100] if len(error_msg) > 100 else error_msg,
279
  "used": count,
280
  "remaining": FREE_MESSAGE_LIMIT - count,
281
- "mode": mode
 
282
  }
283
 
284
  @app.get("/api/usage/{user_id}")
285
  async def get_usage(user_id: str):
286
- """Kullanım bilgilerini getir"""
287
  count = usage_counts.get(user_id, 0)
288
  remaining = FREE_MESSAGE_LIMIT - count
289
 
@@ -292,12 +595,12 @@ async def get_usage(user_id: str):
292
  "used": count,
293
  "remaining": remaining,
294
  "limit": FREE_MESSAGE_LIMIT,
295
- "percentage": (count / FREE_MESSAGE_LIMIT) * 100 if FREE_MESSAGE_LIMIT > 0 else 0
 
296
  }
297
 
298
  @app.get("/api/stats")
299
  async def get_stats():
300
- """Genel istatistikler"""
301
  total_users = len(usage_counts)
302
  total_messages = sum(usage_counts.values())
303
 
@@ -305,65 +608,43 @@ async def get_stats():
305
  "total_users": total_users,
306
  "total_messages": total_messages,
307
  "active_users": sum(1 for v in usage_counts.values() if v > 0),
308
- "average_messages": total_messages / total_users if total_users > 0 else 0
 
309
  }
310
 
311
  @app.post("/api/reset/{user_id}")
312
  async def reset_usage(user_id: str):
313
- """Kullanıcı kullanımını sıfırla"""
314
  if user_id in usage_counts:
 
315
  usage_counts[user_id] = 0
316
- return {"status": "success", "message": f"{user_id} kullanımı sıfırlandı"}
317
- return {"status": "error", "message": "Kullanıcı bulunamadı"}
318
-
319
- # ===============================
320
- # FREELANCE ÖZEL ENDPOINTLER
321
- # ===============================
322
- @app.get("/freelance/tips")
323
- async def freelance_tips():
324
- """Freelance için hızlı ipuçları"""
325
- tips = [
326
- "1. Her proje için net sözleşme imzala",
327
- "2. %50 peşinat, %50 teslimatta ödeme al",
328
- "3. Revizyon sayısını sınırla (max 3)",
329
- "4. Günlük zaman takibi yap (Toggl, Clockify)",
330
- "5. Aylık gelirinin %30'unu vergi için ayır",
331
- "6. Her müşteriden referans al",
332
- "7. Portföyünü sürekli güncelle",
333
- "8. Networking'e zaman ayır (LinkedIn, etkinlikler)",
334
- "9. Fiyatlarını yılda bir gözden geçir",
335
- "10. Sağlık sigortanı ihmal etme"
336
- ]
337
- return {"tips": tips}
338
-
339
- @app.get("/freelance/checklist")
340
- async def freelance_checklist():
341
- """Yeni proje başlangıç checklist"""
342
- checklist = {
343
- "öncesi": [
344
- "Müşteri ihtiyaç analizi yap",
345
- "Net scope belirle",
346
- "Fiyat teklifi hazırla",
347
- "Teslim tarihlerini netleştir",
348
- "Sözleşme hazırla"
349
- ],
350
- "sırası": [
351
- "Günlük ilerleme raporu tut",
352
- "Müşteriyle düzenli iletişimde kal",
353
- "Kaynak dosyalarını düzenli sakla",
354
- "Ara teslimatlar yap"
355
- ],
356
- "sonrası": [
357
- "Son ödemeyi al",
358
- "Referans iste",
359
- "Portföye ekle",
360
- "Projeyi değerlendir (ne öğrendin?)",
361
- "Müşteriyi takip listene ekle"
362
- ]
363
  }
364
- return checklist
365
 
366
  # ===============================
367
- # HUGGING FACE SPACES İÇİN ÖZEL AYAR
368
  # ===============================
369
- # Bu kısmı olduğu gibi bırakın, HF Spaces bunu otomatik yönetecek
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import time
3
  from typing import List, Optional, Dict, Any
4
  import re
5
+ import asyncio
6
+ from contextlib import asynccontextmanager
7
 
8
  from fastapi import FastAPI, Request
9
  from fastapi.middleware.cors import CORSMiddleware
10
+ from fastapi.responses import JSONResponse, HTMLResponse
11
  from pydantic import BaseModel
12
  from huggingface_hub import InferenceClient
13
 
14
+ # ===============================
15
+ # LIFECYCLE MANAGEMENT
16
+ # ===============================
17
+ @asynccontextmanager
18
+ async def lifespan(app: FastAPI):
19
+ # Startup
20
+ print("🚀 ZenkaMind API başlatılıyor...")
21
+ print(f"📊 Model: Qwen/Qwen2.5-0.5B-Instruct")
22
+ print(f"🔧 Ortam: {os.getenv('SPACE_ID', 'development')}")
23
+ yield
24
+ # Shutdown
25
+ print("👋 ZenkaMind API kapatılıyor...")
26
+
27
  # ===============================
28
  # MODEL
29
  # ===============================
30
  MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
31
  HF_TOKEN = os.getenv("HF_TOKEN", os.getenv("HUGGINGFACE_TOKEN"))
32
 
 
 
33
  # ===============================
34
  # APP
35
  # ===============================
36
+ app = FastAPI(
37
+ title="ZenkaMind API",
38
+ version="2.0",
39
+ description="Türkçe AI Asistan - Çeşitli modlarla sohbet",
40
+ lifespan=lifespan
41
+ )
42
 
43
  app.add_middleware(
44
  CORSMiddleware,
 
48
  allow_headers=["*"],
49
  )
50
 
51
+ # ===============================
52
+ # INITIALIZE CLIENT
53
+ # ===============================
54
+ try:
55
+ client = InferenceClient(model=MODEL_ID, token=HF_TOKEN)
56
+ print(f"✅ Model client başarıyla oluşturuldu")
57
+ except Exception as e:
58
+ print(f"⚠️ Model client oluşturulamadı: {e}")
59
+ client = None
60
+
61
  # ===============================
62
  # AYARLAR
63
  # ===============================
 
72
  """Cevabı temizle"""
73
  if not text:
74
  return ""
 
75
  text = re.sub(r'\s+', ' ', text)
 
76
  text = re.sub(r'[\u3400-\u9FFF\uF900-\uFAFF]', '', text)
 
77
  text = re.sub(r'\.{3,}', '...', text)
78
  return text.strip()
79
 
 
170
  # ===============================
171
  # FREELANCE ÖZEL FONKSİYONLAR
172
  # ===============================
 
173
  def enhance_freelance_response(message: str, response: str) -> str:
 
174
  message_lower = message.lower()
 
175
  enhancements = []
176
 
177
  if any(word in message_lower for word in ["fiyat", "ücret", "price", "fee", "ne kadar"]):
 
200
 
201
  return response
202
 
203
+ # ===============================
204
+ # HTML ARAYÜZ
205
+ # ===============================
206
+ HTML_TEMPLATE = """
207
+ <!DOCTYPE html>
208
+ <html>
209
+ <head>
210
+ <title>ZenkaMind API</title>
211
+ <meta charset="UTF-8">
212
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
213
+ <style>
214
+ * { margin: 0; padding: 0; box-sizing: border-box; }
215
+ body {
216
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
217
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
218
+ min-height: 100vh;
219
+ padding: 20px;
220
+ color: #333;
221
+ }
222
+ .container {
223
+ max-width: 1200px;
224
+ margin: 0 auto;
225
+ }
226
+ .header {
227
+ text-align: center;
228
+ margin-bottom: 40px;
229
+ color: white;
230
+ }
231
+ .header h1 {
232
+ font-size: 3em;
233
+ margin-bottom: 10px;
234
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
235
+ }
236
+ .header p {
237
+ font-size: 1.2em;
238
+ opacity: 0.9;
239
+ }
240
+ .card {
241
+ background: white;
242
+ border-radius: 20px;
243
+ padding: 30px;
244
+ margin-bottom: 30px;
245
+ box-shadow: 0 20px 60px rgba(0,0,0,0.1);
246
+ }
247
+ .card h2 {
248
+ color: #667eea;
249
+ margin-bottom: 20px;
250
+ font-size: 1.8em;
251
+ }
252
+ .api-info {
253
+ display: grid;
254
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
255
+ gap: 20px;
256
+ margin-top: 20px;
257
+ }
258
+ .info-box {
259
+ background: #f8f9fa;
260
+ padding: 20px;
261
+ border-radius: 15px;
262
+ border-left: 5px solid #667eea;
263
+ }
264
+ .info-box h3 {
265
+ color: #555;
266
+ margin-bottom: 10px;
267
+ font-size: 1.1em;
268
+ }
269
+ .info-box p {
270
+ font-size: 1.4em;
271
+ font-weight: bold;
272
+ color: #333;
273
+ }
274
+ .endpoints {
275
+ margin-top: 30px;
276
+ }
277
+ .endpoint {
278
+ background: #f8f9fa;
279
+ padding: 15px;
280
+ border-radius: 10px;
281
+ margin-bottom: 15px;
282
+ border-left: 5px solid #764ba2;
283
+ }
284
+ .method {
285
+ display: inline-block;
286
+ background: #667eea;
287
+ color: white;
288
+ padding: 5px 15px;
289
+ border-radius: 20px;
290
+ font-weight: bold;
291
+ margin-right: 10px;
292
+ }
293
+ .url {
294
+ font-family: monospace;
295
+ color: #555;
296
+ font-size: 1.1em;
297
+ }
298
+ .modes {
299
+ display: flex;
300
+ flex-wrap: wrap;
301
+ gap: 15px;
302
+ margin-top: 20px;
303
+ }
304
+ .mode-tag {
305
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
306
+ color: white;
307
+ padding: 10px 20px;
308
+ border-radius: 25px;
309
+ font-weight: bold;
310
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
311
+ }
312
+ .footer {
313
+ text-align: center;
314
+ margin-top: 40px;
315
+ color: white;
316
+ opacity: 0.8;
317
+ }
318
+ .status-badge {
319
+ display: inline-block;
320
+ padding: 8px 16px;
321
+ background: #4CAF50;
322
+ color: white;
323
+ border-radius: 20px;
324
+ font-weight: bold;
325
+ margin-left: 10px;
326
+ }
327
+ @media (max-width: 768px) {
328
+ .container {
329
+ padding: 10px;
330
+ }
331
+ .header h1 {
332
+ font-size: 2em;
333
+ }
334
+ .card {
335
+ padding: 20px;
336
+ }
337
+ }
338
+ </style>
339
+ </head>
340
+ <body>
341
+ <div class="container">
342
+ <div class="header">
343
+ <h1>🤖 ZenkaMind API</h1>
344
+ <p>Türkçe Yapay Zeka Asistanı • Çoklu Mod Desteği</p>
345
+ <div style="margin-top: 20px;">
346
+ <span class="status-badge">🚀 Çalışıyor</span>
347
+ <span class="status-badge">🔧 v2.0</span>
348
+ </div>
349
+ </div>
350
+
351
+ <div class="card">
352
+ <h2>📊 API Bilgileri</h2>
353
+ <div class="api-info">
354
+ <div class="info-box">
355
+ <h3>Model</h3>
356
+ <p>Qwen2.5-0.5B-Instruct</p>
357
+ </div>
358
+ <div class="info-box">
359
+ <h3>Ücretsiz Mesaj</h3>
360
+ <p>50 mesaj / kullanıcı</p>
361
+ </div>
362
+ <div class="info-box">
363
+ <h3>Mevcut Modlar</h3>
364
+ <p>5 farklı kişilik</p>
365
+ </div>
366
+ <div class="info-box">
367
+ <h3>Çalışma Ortamı</h3>
368
+ <p>Hugging Face Spaces</p>
369
+ </div>
370
+ </div>
371
+ </div>
372
+
373
+ <div class="card">
374
+ <h2>🎭 Kullanılabilir Modlar</h2>
375
+ <div class="modes">
376
+ <div class="mode-tag">Ağır Abi</div>
377
+ <div class="mode-tag">Kurumsal</div>
378
+ <div class="mode-tag">Esnaf</div>
379
+ <div class="mode-tag">Teknik</div>
380
+ <div class="mode-tag">Freelance</div>
381
+ </div>
382
+ </div>
383
+
384
+ <div class="card">
385
+ <h2>🔌 API Endpoint'leri</h2>
386
+ <div class="endpoints">
387
+ <div class="endpoint">
388
+ <span class="method">GET</span>
389
+ <span class="url">/docs</span>
390
+ <p style="margin-top: 10px; color: #666;">Interactive API Documentation</p>
391
+ </div>
392
+ <div class="endpoint">
393
+ <span class="method">POST</span>
394
+ <span class="url">/api/chat</span>
395
+ <p style="margin-top: 10px; color: #666;">Ana sohbet endpoint'i</p>
396
+ </div>
397
+ <div class="endpoint">
398
+ <span class="method">GET</span>
399
+ <span class="url">/modes</span>
400
+ <p style="margin-top: 10px; color: #666;">Mevcut modları listele</p>
401
+ </div>
402
+ <div class="endpoint">
403
+ <span class="method">GET</span>
404
+ <span class="url">/health</span>
405
+ <p style="margin-top: 10px; color: #666;">Sağlık kontrolü</p>
406
+ </div>
407
+ </div>
408
+ </div>
409
+
410
+ <div class="card">
411
+ <h2>🚀 Hızlı Başlangıç</h2>
412
+ <pre style="background: #f8f9fa; padding: 20px; border-radius: 10px; overflow-x: auto; margin-top: 20px; font-family: monospace;">
413
+ # Örnek cURL isteği
414
+ curl -X POST "https://your-space.hf.space/api/chat" \\
415
+ -H "Content-Type: application/json" \\
416
+ -d '{
417
+ "message": "Merhaba, nasılsın?",
418
+ "mode": "agir_abi",
419
+ "user_id": "test-123"
420
+ }'
421
+
422
+ # Python örneği
423
+ import requests
424
+
425
+ response = requests.post("https://your-space.hf.space/api/chat", json={
426
+ "message": "Freelance iş nasıl bulunur?",
427
+ "mode": "freelance",
428
+ "user_id": "user-456"
429
+ })
430
+ print(response.json())</pre>
431
+ </div>
432
+
433
+ <div class="footer">
434
+ <p>© 2024 ZenkaMind API • Hugging Face Spaces • FastAPI</p>
435
+ <p style="margin-top: 10px; font-size: 0.9em;">
436
+ Model: Qwen/Qwen2.5-0.5B-Instruct •
437
+ <a href="/docs" style="color: white; text-decoration: underline;">API Docs</a> •
438
+ <a href="https://huggingface.co/spaces" style="color: white; text-decoration: underline;">Hugging Face</a>
439
+ </p>
440
+ </div>
441
+ </div>
442
+ </body>
443
+ </html>
444
+ """
445
+
446
  # ===============================
447
  # ENDPOINTLER
448
  # ===============================
449
+ @app.get("/", response_class=HTMLResponse)
450
  async def root():
451
+ """Ana sayfa - HTML arayüz"""
452
+ return HTML_TEMPLATE
453
+
454
+ @app.get("/health")
455
+ async def health_check():
456
+ """Sağlık kontrol endpoint'i"""
457
  return {
458
+ "status": "healthy",
459
+ "timestamp": time.time(),
460
  "service": "ZenkaMind API",
 
 
 
461
  "version": "2.0",
462
+ "model": MODEL_ID if client else None,
463
  "environment": os.getenv("SPACE_ID", "development")
464
  }
465
 
 
 
 
 
 
466
  @app.get("/modes")
467
  async def get_modes():
468
  """Mevcut modları listele"""
469
  modes_info = {
470
+ "agir_abi": {
471
+ "name": "Ağır Abi",
472
+ "description": "Hayat tecrübesi olan, otoriter ama dostane tavır",
473
+ "icon": "👨‍🏫"
474
+ },
475
+ "kurumsal": {
476
+ "name": "Kurumsal",
477
+ "description": "Profesyonel, iş dünyasına uygun, maddeli açıklamalar",
478
+ "icon": "💼"
479
+ },
480
+ "esnaf": {
481
+ "name": "Esnaf",
482
+ "description": "Samimi, pratik çözümlü, mahalle esnafı tavrı",
483
+ "icon": "👨‍🍳"
484
+ },
485
+ "tech": {
486
+ "name": "Teknik",
487
+ "description": "Kod odaklı, teknik detaylı, öğretici yaklaşım",
488
+ "icon": "💻"
489
+ },
490
+ "freelance": {
491
+ "name": "Freelance",
492
+ "description": "Serbest çalışan, proje bazlı, pazarlıkçı tavır",
493
+ "icon": "🚀"
494
+ }
495
  }
496
  return {"modes": modes_info}
497
 
498
  @app.post("/api/chat")
499
  async def chat(body: ChatRequest):
500
+ """Ana sohbet endpoint'i"""
501
+ if not client:
502
+ return JSONResponse({
503
+ "response": "Model şu anda kullanılamıyor. Lütfen daha sonra tekrar deneyin.",
504
+ "error": "Model client not initialized",
505
+ "used": 0,
506
+ "remaining": FREE_MESSAGE_LIMIT,
507
+ "mode": body.mode
508
+ }, status_code=503)
509
+
510
  user_key = body.user_id or "anon"
511
  count = usage_counts.get(user_key, 0)
512
 
 
533
  messages.append({"role": "user", "content": body.message.strip()})
534
 
535
  try:
536
+ print(f"📨 İstek alındı: {user_key}, mod: {mode}, mesaj: {body.message[:50]}...")
537
+
538
  result = client.chat_completion(
539
  messages=messages,
540
  max_tokens=400,
 
551
  usage_counts[user_key] = count + 1
552
  remaining = FREE_MESSAGE_LIMIT - usage_counts[user_key]
553
 
554
+ print(f"✅ Cevap gönderildi: {user_key}, kalan: {remaining}")
555
+
556
  return {
557
  "response": answer,
558
  "used": usage_counts[user_key],
559
  "remaining": remaining,
560
  "mode": mode,
561
  "premium": False if remaining > 0 else True,
562
+ "user_id": user_key,
563
+ "timestamp": time.time()
564
  }
565
 
566
  except Exception as e:
567
  error_msg = str(e)
568
+ print(f"❌ Hata: {error_msg}")
569
+
570
  if "rate limit" in error_msg.lower():
571
  fallback_response = "Şu anda yoğunluk var. Lütfen 1 dakika sonra tekrar deneyin."
572
  elif "token" in error_msg.lower():
573
+ fallback_response = "API token hatası. Lütfen yönetici ile iletişime geçin."
574
+ elif "timeout" in error_msg.lower():
575
+ fallback_response = "İstek zaman aşımına uğradı. Lütfen tekrar deneyin."
576
  else:
577
  fallback_response = "Teknik bir sorun oluştu. Lütfen tekrar deneyin."
578
 
579
  return {
580
  "response": fallback_response,
581
+ "error": error_msg[:100],
582
  "used": count,
583
  "remaining": FREE_MESSAGE_LIMIT - count,
584
+ "mode": mode,
585
+ "timestamp": time.time()
586
  }
587
 
588
  @app.get("/api/usage/{user_id}")
589
  async def get_usage(user_id: str):
 
590
  count = usage_counts.get(user_id, 0)
591
  remaining = FREE_MESSAGE_LIMIT - count
592
 
 
595
  "used": count,
596
  "remaining": remaining,
597
  "limit": FREE_MESSAGE_LIMIT,
598
+ "percentage": (count / FREE_MESSAGE_LIMIT) * 100 if FREE_MESSAGE_LIMIT > 0 else 0,
599
+ "timestamp": time.time()
600
  }
601
 
602
  @app.get("/api/stats")
603
  async def get_stats():
 
604
  total_users = len(usage_counts)
605
  total_messages = sum(usage_counts.values())
606
 
 
608
  "total_users": total_users,
609
  "total_messages": total_messages,
610
  "active_users": sum(1 for v in usage_counts.values() if v > 0),
611
+ "average_messages": total_messages / total_users if total_users > 0 else 0,
612
+ "timestamp": time.time()
613
  }
614
 
615
  @app.post("/api/reset/{user_id}")
616
  async def reset_usage(user_id: str):
 
617
  if user_id in usage_counts:
618
+ old_count = usage_counts[user_id]
619
  usage_counts[user_id] = 0
620
+ return {
621
+ "status": "success",
622
+ "message": f"{user_id} kullanımı sıfırlandı (eski: {old_count})",
623
+ "timestamp": time.time()
624
+ }
625
+ return {
626
+ "status": "error",
627
+ "message": "Kullanıcı bulunamadı",
628
+ "timestamp": time.time()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
629
  }
 
630
 
631
  # ===============================
632
+ # SERVER STARTUP
633
  # ===============================
634
+ if __name__ == "__main__":
635
+ import uvicorn
636
+
637
+ # Hugging Face Spaces genellikle 7860 portunu kullanır
638
+ port = int(os.getenv("PORT", 7860))
639
+
640
+ print(f"🚀 ZenkaMind API {port} portunda başlatılıyor...")
641
+ print(f"📊 Model: {MODEL_ID}")
642
+ print(f"🔗 Docs: http://localhost:{port}/docs")
643
+ print(f"🏠 Ana sayfa: http://localhost:{port}/")
644
+
645
+ uvicorn.run(
646
+ "app:app",
647
+ host="0.0.0.0",
648
+ port=port,
649
+ reload=False # Production'da reload kapalı
650
+ )