abedgemma commited on
Commit
d174a15
·
verified ·
1 Parent(s): b866073

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -9
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","300.0")) # thinking mode gets longer budget
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", 4096))
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 + 512)
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
- pl["chat_template_kwargs"] = {"enable_thinking": True}
1393
- pl["reasoning_budget"] = 4096
 
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["chat_template_kwargs"] = {"enable_thinking": True}
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)