Gateway: Kontext-Limit-Warnung ignoriert Warm-Pings (max_tokens<=16)
Lucys Augen-Waermer (alle 10 min, max_tokens=1 an "vision"), warmup.sh und models/load enden konstruktionsbedingt mit finish_reason=length — die Warnung vom 15.07. hielt jeden Ping fuer einen abgerissenen Worker und spammte den Briefkasten (~alle 20 min, Serie 16.07. abends). Wer freiwillig auf <=16 Tokens deckelt, will keine echte Antwort -> keine Warnung; echte Abrisse melden weiter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -239,7 +239,7 @@ async def _proxy(path: str, request: Request):
|
||||
async def gen():
|
||||
try:
|
||||
async for chunk in r.aiter_raw():
|
||||
record_stream_chunk(chunk, alias)
|
||||
record_stream_chunk(chunk, alias, body.get("max_tokens"))
|
||||
yield chunk
|
||||
finally:
|
||||
await r.aclose()
|
||||
@@ -251,7 +251,7 @@ async def _proxy(path: str, request: Request):
|
||||
record_usage(resp_json.get("usage"), alias)
|
||||
if any(isinstance(c, dict) and c.get("finish_reason") == "length"
|
||||
for c in resp_json.get("choices") or []):
|
||||
warn_truncation(alias)
|
||||
warn_truncation(alias, body.get("max_tokens"))
|
||||
return JSONResponse(resp_json, status_code=r.status_code, headers=routed)
|
||||
|
||||
|
||||
|
||||
@@ -22,8 +22,16 @@ log = logging.getLogger(__name__)
|
||||
_trunc_last: dict[str, float] = {}
|
||||
_TRUNC_EVERY = 600.0 # s
|
||||
|
||||
# Warm-Pings (Lucys Augen-Wärmer alle 10 min, warmup.sh, models/load) halten Modelle
|
||||
# ABSICHTLICH mit max_tokens=1 warm — deren finish_reason=length ist konstruktionsbedingt
|
||||
# und kein abgerissener Worker (Fehlalarm-Serie 16.07. abends, ~alle 20 min im Briefkasten).
|
||||
# Wer freiwillig so knapp deckelt, will keine echte Antwort → keine Warnung.
|
||||
_PING_MAXTOK = 16
|
||||
|
||||
def warn_truncation(model: str) -> None:
|
||||
|
||||
def warn_truncation(model: str, max_tokens: int | None = None) -> None:
|
||||
if isinstance(max_tokens, int) and max_tokens <= _PING_MAXTOK:
|
||||
return
|
||||
now = time.time()
|
||||
if now - _trunc_last.get(model, 0.0) < _TRUNC_EVERY:
|
||||
return
|
||||
@@ -50,11 +58,11 @@ def record_usage(usage: dict | None, model: str) -> None:
|
||||
increment_tokens(prompt, completion, model=model)
|
||||
|
||||
|
||||
def record_stream_chunk(chunk: bytes, model: str) -> None:
|
||||
def record_stream_chunk(chunk: bytes, model: str, max_tokens: int | None = None) -> None:
|
||||
"""Rohen SSE-Chunk auf `usage` prüfen und Tokens verbuchen. Fehler werden
|
||||
geloggt (debug) statt verschluckt — ein defekter Chunk bricht den Stream nicht."""
|
||||
if b'"finish_reason":"length"' in chunk or b'"finish_reason": "length"' in chunk:
|
||||
warn_truncation(model)
|
||||
warn_truncation(model, max_tokens)
|
||||
if b'"usage"' not in chunk:
|
||||
return
|
||||
text = chunk.decode("utf-8", errors="ignore")
|
||||
|
||||
Reference in New Issue
Block a user