infinityonline commited on
Commit
86a6197
·
verified ·
1 Parent(s): c73fb17

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +31 -20
main.py CHANGED
@@ -6,8 +6,9 @@ import asyncio
6
  import threading
7
  import json
8
  import re
 
9
  from fastapi import FastAPI, Request
10
- from fastapi.responses import JSONResponse
11
 
12
  # ====================================================================
13
  # Configuration
@@ -15,7 +16,7 @@ from fastapi.responses import JSONResponse
15
  API_SECRET_KEY = os.getenv("API_SECRET_KEY", "change-me-secret")
16
  POOL_SIZE = int(os.getenv("POOL_SIZE", "5"))
17
  MAX_REQUESTS = int(os.getenv("MAX_REQUESTS", "30"))
18
- QUEUE_TIMEOUT = int(os.getenv("QUEUE_TIMEOUT", "300")) # ثواني انتظار Queue
19
 
20
  DUCK_MODELS = {
21
  "gpt-5-mini": "GPT-5 mini",
@@ -136,10 +137,8 @@ class BrowserWorker:
136
  self.busy = False
137
 
138
  async def _do_chat(self, model_label: str, prompt: str) -> str:
139
- # تأخير عشوائي لتبدو الطلبات طبيعية
140
  await asyncio.sleep(random.uniform(0.5, 2.0))
141
 
142
- # تجديد context دورياً
143
  self._request_count += 1
144
  self._total_count += 1
145
  if self._request_count >= MAX_REQUESTS:
@@ -324,7 +323,7 @@ class BrowserPool:
324
  self._thread = threading.Thread(target=self._run, daemon=True)
325
  self._queue: asyncio.Queue | None = None
326
  self._total_requests = 0
327
- self._rejected = 0 # عدد الطلبات المرفوضة بسبب timeout
328
 
329
  def start(self):
330
  self._thread.start()
@@ -350,8 +349,6 @@ class BrowserPool:
350
 
351
  async def _process(self, model_label: str, prompt: str) -> str:
352
  self._total_requests += 1
353
-
354
- # انتظر worker حر — بحد أقصى QUEUE_TIMEOUT ثانية
355
  try:
356
  worker: BrowserWorker = await asyncio.wait_for(
357
  self._queue.get(), timeout=QUEUE_TIMEOUT
@@ -365,8 +362,7 @@ class BrowserPool:
365
  f"Please retry in a moment. (rejected total: {self._rejected})"
366
  )
367
 
368
- print(f"[POOL] Assigned W{worker.id} "
369
- f"(total req: {self._total_requests}) ✓")
370
  try:
371
  return await worker.chat(model_label, prompt)
372
  finally:
@@ -598,27 +594,42 @@ async def health():
598
  busy = sum(1 for w in pool.workers if w.busy)
599
  stats = [
600
  {
601
- "id": w.id,
602
- "busy": w.busy,
603
- "total_requests": w._total_count,
604
  "requests_until_rotation": MAX_REQUESTS - w._request_count,
605
  }
606
  for w in pool.workers
607
  ]
 
608
  return {
609
- "status": "running",
610
- "message": "Duck.ai API Pool Server is active!",
611
- "models": ALL_MODELS,
612
- "pool_size": POOL_SIZE,
613
- "workers_busy": busy,
614
- "workers_free": POOL_SIZE - busy,
615
- "total_requests": pool._total_requests,
616
  "rejected_requests": pool._rejected,
617
  "queue_timeout_sec": QUEUE_TIMEOUT,
618
- "workers": stats,
 
 
 
 
 
 
619
  }
620
 
621
 
 
 
 
 
 
 
 
 
622
  if __name__ == "__main__":
623
  import uvicorn
624
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
6
  import threading
7
  import json
8
  import re
9
+ import psutil
10
  from fastapi import FastAPI, Request
11
+ from fastapi.responses import JSONResponse, HTMLResponse
12
 
13
  # ====================================================================
14
  # Configuration
 
16
  API_SECRET_KEY = os.getenv("API_SECRET_KEY", "change-me-secret")
17
  POOL_SIZE = int(os.getenv("POOL_SIZE", "5"))
18
  MAX_REQUESTS = int(os.getenv("MAX_REQUESTS", "30"))
19
+ QUEUE_TIMEOUT = int(os.getenv("QUEUE_TIMEOUT", "300"))
20
 
21
  DUCK_MODELS = {
22
  "gpt-5-mini": "GPT-5 mini",
 
137
  self.busy = False
138
 
139
  async def _do_chat(self, model_label: str, prompt: str) -> str:
 
140
  await asyncio.sleep(random.uniform(0.5, 2.0))
141
 
 
142
  self._request_count += 1
143
  self._total_count += 1
144
  if self._request_count >= MAX_REQUESTS:
 
323
  self._thread = threading.Thread(target=self._run, daemon=True)
324
  self._queue: asyncio.Queue | None = None
325
  self._total_requests = 0
326
+ self._rejected = 0
327
 
328
  def start(self):
329
  self._thread.start()
 
349
 
350
  async def _process(self, model_label: str, prompt: str) -> str:
351
  self._total_requests += 1
 
 
352
  try:
353
  worker: BrowserWorker = await asyncio.wait_for(
354
  self._queue.get(), timeout=QUEUE_TIMEOUT
 
362
  f"Please retry in a moment. (rejected total: {self._rejected})"
363
  )
364
 
365
+ print(f"[POOL] Assigned W{worker.id} (total req: {self._total_requests}) ✓")
 
366
  try:
367
  return await worker.chat(model_label, prompt)
368
  finally:
 
594
  busy = sum(1 for w in pool.workers if w.busy)
595
  stats = [
596
  {
597
+ "id": w.id,
598
+ "busy": w.busy,
599
+ "total_requests": w._total_count,
600
  "requests_until_rotation": MAX_REQUESTS - w._request_count,
601
  }
602
  for w in pool.workers
603
  ]
604
+ mem = psutil.virtual_memory()
605
  return {
606
+ "status": "running",
607
+ "message": "Duck.ai API Pool Server is active!",
608
+ "models": ALL_MODELS,
609
+ "pool_size": POOL_SIZE,
610
+ "workers_busy": busy,
611
+ "workers_free": POOL_SIZE - busy,
612
+ "total_requests": pool._total_requests,
613
  "rejected_requests": pool._rejected,
614
  "queue_timeout_sec": QUEUE_TIMEOUT,
615
+ "workers": stats,
616
+ "ram": {
617
+ "used_gb": round(mem.used / 1024**3, 2),
618
+ "total_gb": round(mem.total / 1024**3, 2),
619
+ "percent": mem.percent,
620
+ },
621
+ "cpu": psutil.cpu_percent(interval=None),
622
  }
623
 
624
 
625
+ @app.get("/dashboard", response_class=HTMLResponse)
626
+ async def dashboard(request: Request):
627
+ if not _auth(request):
628
+ return HTMLResponse("<h1>401 Unauthorized</h1>", status_code=401)
629
+ with open("dashboard.html", "r", encoding="utf-8") as f:
630
+ return HTMLResponse(f.read())
631
+
632
+
633
  if __name__ == "__main__":
634
  import uvicorn
635
  uvicorn.run(app, host="0.0.0.0", port=7860)