Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -71,7 +71,7 @@ RAM_WARN_GB = float(os.getenv("RAM_WARN_GB", "0")) # 0 = auto 82% of total
|
|
| 71 |
RAM_REJECT_GB = float(os.getenv("RAM_REJECT_GB", "0")) # 0 = auto 90% of total RAM
|
| 72 |
RAM_FLUSH_GB = float(os.getenv("RAM_FLUSH_GB", "0")) # 0 = auto 95% of total RAM
|
| 73 |
REQUEST_TIMEOUT = float(os.getenv("REQUEST_TIMEOUT","90.0"))
|
| 74 |
-
THINKING_TIMEOUT = float(os.getenv("THINKING_TIMEOUT","
|
| 75 |
GENERATE_TIMEOUT = float(os.getenv("GENERATE_TIMEOUT","600.0")) # file generation (big code files)
|
| 76 |
QUEUE_TIMEOUT = float(os.getenv("QUEUE_TIMEOUT", "30.0"))
|
| 77 |
ENRICH_TIMEOUT = float(os.getenv("ENRICH_TIMEOUT", "12.0"))
|
|
@@ -1211,11 +1211,11 @@ async def chat(request: Request) -> Response | StreamingResponse:
|
|
| 1211 |
"chat_template_kwargs": {"enable_thinking": bool(thinking_requested)},
|
| 1212 |
}
|
| 1213 |
if thinking_requested:
|
| 1214 |
-
_think_budget = int(body.get("thinking_budget",
|
| 1215 |
payload["reasoning_budget"] = _think_budget
|
| 1216 |
# CRITICAL: max_tokens must cover thinking budget + actual answer
|
| 1217 |
# Without this, the <think> block eats all tokens and content is empty
|
| 1218 |
-
max_tok = max(max_tok, _think_budget +
|
| 1219 |
payload["max_tokens"] = max_tok
|
| 1220 |
if body.get("tools"):
|
| 1221 |
payload["tools"] = body["tools"]
|
|
@@ -1284,6 +1284,7 @@ async def chat(request: Request) -> Response | StreamingResponse:
|
|
| 1284 |
resp, deduped = await dedup.run_once(cache_key or rid, _do)
|
| 1285 |
if deduped: logger.info(f"[{rid}] DEDUP HIT")
|
| 1286 |
except asyncio.TimeoutError:
|
|
|
|
| 1287 |
return E(f"Inference timeout {_req_timeout:.0f}s", 504, "timeout", rid)
|
| 1288 |
except httpx.RequestError as e:
|
| 1289 |
return E(f"Upstream error: {e}",502,"server_error",rid)
|
|
@@ -1387,16 +1388,21 @@ async def file_upload(
|
|
| 1387 |
"temperature": 0.6,
|
| 1388 |
"cache_prompt": False,
|
| 1389 |
"stream": False,
|
|
|
|
|
|
|
| 1390 |
}
|
| 1391 |
if thinking.lower() == "true":
|
| 1392 |
-
|
| 1393 |
-
pl["reasoning_budget"]
|
|
|
|
| 1394 |
|
| 1395 |
_file_timeout = THINKING_TIMEOUT if thinking.lower() == "true" else REQUEST_TIMEOUT
|
| 1396 |
resp = await asyncio.wait_for(
|
| 1397 |
llama.req("POST","/v1/chat/completions",
|
| 1398 |
content=orjson.dumps(pl),
|
| 1399 |
-
headers={"Content-Type":"application/json"}
|
|
|
|
|
|
|
| 1400 |
timeout=_file_timeout)
|
| 1401 |
|
| 1402 |
return Response(resp.content, resp.status_code,
|
|
@@ -1404,6 +1410,7 @@ async def file_upload(
|
|
| 1404 |
headers={"X-File":fname,"X-Bytes":str(len(data))})
|
| 1405 |
|
| 1406 |
except asyncio.TimeoutError:
|
|
|
|
| 1407 |
return E("File processing timed out", 504, "timeout")
|
| 1408 |
except Exception as e:
|
| 1409 |
logger.error(f"[files] {e}", exc_info=True)
|
|
@@ -1459,13 +1466,14 @@ async def generate_file(request: Request) -> Response:
|
|
| 1459 |
"temperature": 0.3,
|
| 1460 |
"cache_prompt":False,
|
| 1461 |
"stream": False,
|
|
|
|
|
|
|
|
|
|
| 1462 |
}
|
| 1463 |
if thinking:
|
| 1464 |
-
pl["
|
| 1465 |
-
pl["reasoning_budget"] = 4096
|
| 1466 |
|
| 1467 |
try:
|
| 1468 |
-
# generate can produce long files — use GENERATE_TIMEOUT (600s default)
|
| 1469 |
resp = await asyncio.wait_for(
|
| 1470 |
llama.req("POST","/v1/chat/completions",
|
| 1471 |
content=orjson.dumps(pl),
|
|
@@ -1489,6 +1497,14 @@ async def generate_file(request: Request) -> Response:
|
|
| 1489 |
file_content = "\n".join(lines).strip()
|
| 1490 |
|
| 1491 |
tokens_used = data.get("usage",{}).get("completion_tokens","?")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1492 |
return Response(
|
| 1493 |
content=file_content.encode("utf-8"),
|
| 1494 |
media_type="application/octet-stream",
|
|
@@ -1499,6 +1515,7 @@ async def generate_file(request: Request) -> Response:
|
|
| 1499 |
"X-Lines": str(len(file_content.splitlines())),
|
| 1500 |
})
|
| 1501 |
except asyncio.TimeoutError:
|
|
|
|
| 1502 |
return E("Generation timed out",504)
|
| 1503 |
except Exception as e:
|
| 1504 |
logger.error(f"[generate] {e}",exc_info=True)
|
|
|
|
| 71 |
RAM_REJECT_GB = float(os.getenv("RAM_REJECT_GB", "0")) # 0 = auto 90% of total RAM
|
| 72 |
RAM_FLUSH_GB = float(os.getenv("RAM_FLUSH_GB", "0")) # 0 = auto 95% of total RAM
|
| 73 |
REQUEST_TIMEOUT = float(os.getenv("REQUEST_TIMEOUT","90.0"))
|
| 74 |
+
THINKING_TIMEOUT = float(os.getenv("THINKING_TIMEOUT","600.0")) # thinking mode — CPU needs time
|
| 75 |
GENERATE_TIMEOUT = float(os.getenv("GENERATE_TIMEOUT","600.0")) # file generation (big code files)
|
| 76 |
QUEUE_TIMEOUT = float(os.getenv("QUEUE_TIMEOUT", "30.0"))
|
| 77 |
ENRICH_TIMEOUT = float(os.getenv("ENRICH_TIMEOUT", "12.0"))
|
|
|
|
| 1211 |
"chat_template_kwargs": {"enable_thinking": bool(thinking_requested)},
|
| 1212 |
}
|
| 1213 |
if thinking_requested:
|
| 1214 |
+
_think_budget = int(body.get("thinking_budget", 512)) # 512 default — 4096 is too slow on CPU
|
| 1215 |
payload["reasoning_budget"] = _think_budget
|
| 1216 |
# CRITICAL: max_tokens must cover thinking budget + actual answer
|
| 1217 |
# Without this, the <think> block eats all tokens and content is empty
|
| 1218 |
+
max_tok = max(max_tok, _think_budget + 256)
|
| 1219 |
payload["max_tokens"] = max_tok
|
| 1220 |
if body.get("tools"):
|
| 1221 |
payload["tools"] = body["tools"]
|
|
|
|
| 1284 |
resp, deduped = await dedup.run_once(cache_key or rid, _do)
|
| 1285 |
if deduped: logger.info(f"[{rid}] DEDUP HIT")
|
| 1286 |
except asyncio.TimeoutError:
|
| 1287 |
+
await llama._reset() # close broken connection before next request uses it
|
| 1288 |
return E(f"Inference timeout {_req_timeout:.0f}s", 504, "timeout", rid)
|
| 1289 |
except httpx.RequestError as e:
|
| 1290 |
return E(f"Upstream error: {e}",502,"server_error",rid)
|
|
|
|
| 1388 |
"temperature": 0.6,
|
| 1389 |
"cache_prompt": False,
|
| 1390 |
"stream": False,
|
| 1391 |
+
# Always set explicitly — without this Qwen3 may silently enter thinking mode
|
| 1392 |
+
"chat_template_kwargs": {"enable_thinking": thinking.lower() == "true"},
|
| 1393 |
}
|
| 1394 |
if thinking.lower() == "true":
|
| 1395 |
+
_think_budget = 512 # same conservative default as chat endpoint
|
| 1396 |
+
pl["reasoning_budget"] = _think_budget
|
| 1397 |
+
pl["max_tokens"] = max(MAX_NEW_TOKENS, _think_budget + 256)
|
| 1398 |
|
| 1399 |
_file_timeout = THINKING_TIMEOUT if thinking.lower() == "true" else REQUEST_TIMEOUT
|
| 1400 |
resp = await asyncio.wait_for(
|
| 1401 |
llama.req("POST","/v1/chat/completions",
|
| 1402 |
content=orjson.dumps(pl),
|
| 1403 |
+
headers={"Content-Type":"application/json"},
|
| 1404 |
+
timeout=httpx.Timeout(connect=10.0, read=_file_timeout + 30.0,
|
| 1405 |
+
write=10.0, pool=5.0)),
|
| 1406 |
timeout=_file_timeout)
|
| 1407 |
|
| 1408 |
return Response(resp.content, resp.status_code,
|
|
|
|
| 1410 |
headers={"X-File":fname,"X-Bytes":str(len(data))})
|
| 1411 |
|
| 1412 |
except asyncio.TimeoutError:
|
| 1413 |
+
await llama._reset()
|
| 1414 |
return E("File processing timed out", 504, "timeout")
|
| 1415 |
except Exception as e:
|
| 1416 |
logger.error(f"[files] {e}", exc_info=True)
|
|
|
|
| 1466 |
"temperature": 0.3,
|
| 1467 |
"cache_prompt":False,
|
| 1468 |
"stream": False,
|
| 1469 |
+
# CRITICAL: always set thinking explicitly — without this Qwen3 may enter thinking
|
| 1470 |
+
# mode silently, consuming all tokens in <think> blocks and producing empty files
|
| 1471 |
+
"chat_template_kwargs": {"enable_thinking": bool(thinking)},
|
| 1472 |
}
|
| 1473 |
if thinking:
|
| 1474 |
+
pl["reasoning_budget"] = 4096
|
|
|
|
| 1475 |
|
| 1476 |
try:
|
|
|
|
| 1477 |
resp = await asyncio.wait_for(
|
| 1478 |
llama.req("POST","/v1/chat/completions",
|
| 1479 |
content=orjson.dumps(pl),
|
|
|
|
| 1497 |
file_content = "\n".join(lines).strip()
|
| 1498 |
|
| 1499 |
tokens_used = data.get("usage",{}).get("completion_tokens","?")
|
| 1500 |
+
|
| 1501 |
+
# Guard: if content is empty the model likely entered thinking mode silently
|
| 1502 |
+
if not file_content:
|
| 1503 |
+
logger.warning(f"[generate] model returned empty content (tokens={tokens_used}) — "
|
| 1504 |
+
"possible silent thinking mode. Check enable_thinking=False is applied.")
|
| 1505 |
+
return E("Model returned empty file content — the generation produced no output. "
|
| 1506 |
+
"Try rephrasing the prompt.", 500)
|
| 1507 |
+
|
| 1508 |
return Response(
|
| 1509 |
content=file_content.encode("utf-8"),
|
| 1510 |
media_type="application/octet-stream",
|
|
|
|
| 1515 |
"X-Lines": str(len(file_content.splitlines())),
|
| 1516 |
})
|
| 1517 |
except asyncio.TimeoutError:
|
| 1518 |
+
await llama._reset() # prevent broken connection on next request
|
| 1519 |
return E("Generation timed out",504)
|
| 1520 |
except Exception as e:
|
| 1521 |
logger.error(f"[generate] {e}",exc_info=True)
|