Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -69,11 +69,10 @@ RATE_LIMIT_RPM = int(os.getenv("RATE_LIMIT_RPM", "60"))
|
|
| 69 |
RATE_BURST = int(os.getenv("RATE_LIMIT_BURST", "10"))
|
| 70 |
RATE_VIP_IPS = set(os.getenv("RATE_VIP_IPS", "127.0.0.1").split(","))
|
| 71 |
# RAM thresholds — auto-calculated as % of total RAM if not set explicitly
|
| 72 |
-
|
| 73 |
-
#
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
RAM_FLUSH_GB = float(os.getenv("RAM_FLUSH_GB", str(round(_total_ram_gb * 0.98, 1))))
|
| 77 |
REQUEST_TIMEOUT = float(os.getenv("REQUEST_TIMEOUT","90.0"))
|
| 78 |
QUEUE_TIMEOUT = float(os.getenv("QUEUE_TIMEOUT", "30.0"))
|
| 79 |
ENRICH_TIMEOUT = float(os.getenv("ENRICH_TIMEOUT", "12.0"))
|
|
@@ -523,7 +522,12 @@ async def _flush_kv() -> bool:
|
|
| 523 |
return False
|
| 524 |
|
| 525 |
async def watchdog_task():
|
| 526 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 527 |
while True:
|
| 528 |
try:
|
| 529 |
await asyncio.sleep(2.0)
|
|
@@ -531,9 +535,9 @@ async def watchdog_task():
|
|
| 531 |
used = mem.used / (1024**3)
|
| 532 |
wd.ram_gb = used
|
| 533 |
|
| 534 |
-
if used >=
|
| 535 |
if wd.level != "flush":
|
| 536 |
-
logger.warning(f"[wd] 🚨 FLUSH {used:.1f}GB")
|
| 537 |
wd.level = "flush"; wd.flushes += 1
|
| 538 |
gc.collect(2)
|
| 539 |
exact_cache.cleanup()
|
|
@@ -543,13 +547,13 @@ async def watchdog_task():
|
|
| 543 |
await _flush_kv()
|
| 544 |
after = psutil.virtual_memory().used / (1024**3)
|
| 545 |
logger.info(f"[wd] post-flush {after:.1f}GB (freed {used-after:.1f}GB)")
|
| 546 |
-
if after <
|
| 547 |
-
elif used >=
|
| 548 |
if wd.level not in ("reject", "flush"):
|
| 549 |
-
logger.warning(f"[wd] ⚠ REJECT {used:.1f}GB")
|
| 550 |
wd.level = "reject"; wd.rejects += 1; gc.collect(1)
|
| 551 |
-
elif used >=
|
| 552 |
-
if wd.level == "ok": logger.info(f"[wd] ⚡ WARN {used:.1f}GB")
|
| 553 |
wd.level = "warn"
|
| 554 |
else:
|
| 555 |
if wd.level != "ok": logger.info(f"[wd] ✅ OK {used:.1f}GB")
|
|
@@ -1099,6 +1103,10 @@ async def chat(request: Request) -> Response | StreamingResponse:
|
|
| 1099 |
headers={"X-Request-ID":rid,"X-Cache":"SEMANTIC-HIT"})
|
| 1100 |
|
| 1101 |
# Build payload
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1102 |
payload: dict = {
|
| 1103 |
"messages": messages,
|
| 1104 |
"cache_prompt": True,
|
|
@@ -1109,12 +1117,11 @@ async def chat(request: Request) -> Response | StreamingResponse:
|
|
| 1109 |
"top_k": int(body.get("top_k", 20)),
|
| 1110 |
"min_p": float(body.get("min_p", 0.0)),
|
| 1111 |
"stream": is_stream,
|
|
|
|
|
|
|
| 1112 |
}
|
| 1113 |
-
if
|
| 1114 |
-
payload["chat_template_kwargs"] = {"enable_thinking": True}
|
| 1115 |
payload["reasoning_budget"] = int(body.get("thinking_budget", 4096))
|
| 1116 |
-
elif body.get("thinking") is False:
|
| 1117 |
-
payload["chat_template_kwargs"] = {"enable_thinking": False}
|
| 1118 |
if body.get("tools"):
|
| 1119 |
payload["tools"] = body["tools"]
|
| 1120 |
payload["tool_choice"] = body.get("tool_choice", "auto")
|
|
@@ -1592,4 +1599,4 @@ if __name__ == "__main__":
|
|
| 1592 |
import uvicorn
|
| 1593 |
uvicorn.run("app:app", host="0.0.0.0",
|
| 1594 |
port=int(os.getenv("API_PORT","7860")),
|
| 1595 |
-
loop="uvloop", http="h11", workers=1)
|
|
|
|
| 69 |
RATE_BURST = int(os.getenv("RATE_LIMIT_BURST", "10"))
|
| 70 |
RATE_VIP_IPS = set(os.getenv("RATE_VIP_IPS", "127.0.0.1").split(","))
|
| 71 |
# RAM thresholds — auto-calculated as % of total RAM if not set explicitly
|
| 72 |
+
# RAM thresholds — computed dynamically in watchdog_task() based on actual machine RAM
|
| 73 |
+
RAM_WARN_GB = float(os.getenv("RAM_WARN_GB", "0")) # 0 = auto 82% of total RAM
|
| 74 |
+
RAM_REJECT_GB = float(os.getenv("RAM_REJECT_GB", "0")) # 0 = auto 90% of total RAM
|
| 75 |
+
RAM_FLUSH_GB = float(os.getenv("RAM_FLUSH_GB", "0")) # 0 = auto 95% of total RAM
|
|
|
|
| 76 |
REQUEST_TIMEOUT = float(os.getenv("REQUEST_TIMEOUT","90.0"))
|
| 77 |
QUEUE_TIMEOUT = float(os.getenv("QUEUE_TIMEOUT", "30.0"))
|
| 78 |
ENRICH_TIMEOUT = float(os.getenv("ENRICH_TIMEOUT", "12.0"))
|
|
|
|
| 522 |
return False
|
| 523 |
|
| 524 |
async def watchdog_task():
|
| 525 |
+
# Compute dynamic thresholds based on actual machine RAM
|
| 526 |
+
_total = psutil.virtual_memory().total / (1024**3)
|
| 527 |
+
_warn = RAM_WARN_GB if RAM_WARN_GB > 0 else round(_total * 0.82, 1)
|
| 528 |
+
_reject = RAM_REJECT_GB if RAM_REJECT_GB > 0 else round(_total * 0.90, 1)
|
| 529 |
+
_flush = RAM_FLUSH_GB if RAM_FLUSH_GB > 0 else round(_total * 0.95, 1)
|
| 530 |
+
logger.info(f"[wd] total={_total:.1f}G warn={_warn}G reject={_reject}G flush={_flush}G")
|
| 531 |
while True:
|
| 532 |
try:
|
| 533 |
await asyncio.sleep(2.0)
|
|
|
|
| 535 |
used = mem.used / (1024**3)
|
| 536 |
wd.ram_gb = used
|
| 537 |
|
| 538 |
+
if used >= _flush:
|
| 539 |
if wd.level != "flush":
|
| 540 |
+
logger.warning(f"[wd] 🚨 FLUSH {used:.1f}/{_total:.0f}GB")
|
| 541 |
wd.level = "flush"; wd.flushes += 1
|
| 542 |
gc.collect(2)
|
| 543 |
exact_cache.cleanup()
|
|
|
|
| 547 |
await _flush_kv()
|
| 548 |
after = psutil.virtual_memory().used / (1024**3)
|
| 549 |
logger.info(f"[wd] post-flush {after:.1f}GB (freed {used-after:.1f}GB)")
|
| 550 |
+
if after < _reject: wd.level = "ok"
|
| 551 |
+
elif used >= _reject:
|
| 552 |
if wd.level not in ("reject", "flush"):
|
| 553 |
+
logger.warning(f"[wd] ⚠ REJECT {used:.1f}/{_total:.0f}GB")
|
| 554 |
wd.level = "reject"; wd.rejects += 1; gc.collect(1)
|
| 555 |
+
elif used >= _warn:
|
| 556 |
+
if wd.level == "ok": logger.info(f"[wd] ⚡ WARN {used:.1f}/{_total:.0f}GB")
|
| 557 |
wd.level = "warn"
|
| 558 |
else:
|
| 559 |
if wd.level != "ok": logger.info(f"[wd] ✅ OK {used:.1f}GB")
|
|
|
|
| 1103 |
headers={"X-Request-ID":rid,"X-Cache":"SEMANTIC-HIT"})
|
| 1104 |
|
| 1105 |
# Build payload
|
| 1106 |
+
# Thinking mode OFF by default — Qwen3 thinks for EVERY request otherwise
|
| 1107 |
+
# User must explicitly pass "thinking": true to enable reasoning
|
| 1108 |
+
thinking_requested = body.get("thinking", False)
|
| 1109 |
+
|
| 1110 |
payload: dict = {
|
| 1111 |
"messages": messages,
|
| 1112 |
"cache_prompt": True,
|
|
|
|
| 1117 |
"top_k": int(body.get("top_k", 20)),
|
| 1118 |
"min_p": float(body.get("min_p", 0.0)),
|
| 1119 |
"stream": is_stream,
|
| 1120 |
+
# Always set thinking explicitly to avoid Qwen3 auto-enabling it
|
| 1121 |
+
"chat_template_kwargs": {"enable_thinking": bool(thinking_requested)},
|
| 1122 |
}
|
| 1123 |
+
if thinking_requested:
|
|
|
|
| 1124 |
payload["reasoning_budget"] = int(body.get("thinking_budget", 4096))
|
|
|
|
|
|
|
| 1125 |
if body.get("tools"):
|
| 1126 |
payload["tools"] = body["tools"]
|
| 1127 |
payload["tool_choice"] = body.get("tool_choice", "auto")
|
|
|
|
| 1599 |
import uvicorn
|
| 1600 |
uvicorn.run("app:app", host="0.0.0.0",
|
| 1601 |
port=int(os.getenv("API_PORT","7860")),
|
| 1602 |
+
loop="uvloop", http="h11", workers=1)
|