fix(openai-wrapper): Kontext-Ueberlauf als OpenAI-400 context_length_exceeded
Bisher kam context_exceeded als 502 an — OpenAI-Clients (litellm/OpenHands) hielten das fuer einen Serverfehler statt zu kuerzen/verdichten. Jetzt 400 mit code context_length_exceeded und dem OpenAI-ueblichen Text inkl. Zahlen. Doku: Abschnitt "Den Verlauf verwaltet das Programm" (Kuerzen, Verdichten, Gedaechtnis) fuer Drittprogramme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -296,7 +296,10 @@ steht und welche Modelle es gibt. Im Programm eintragen:
|
|||||||
- `POST /v1/chat/completions` — auch `stream: true` (kommt derzeit in einem
|
- `POST /v1/chat/completions` — auch `stream: true` (kommt derzeit in einem
|
||||||
Rutsch) und `tools`
|
Rutsch) und `tools`
|
||||||
- Fehler als HTTP-Fehler mit OpenAI-Fehlerobjekt: nicht geladenes Modell →
|
- Fehler als HTTP-Fehler mit OpenAI-Fehlerobjekt: nicht geladenes Modell →
|
||||||
404 `model_not_found`, Cluster nicht erreichbar → 503, Zeitüberschreitung → 504
|
404 `model_not_found`, Cluster nicht erreichbar → 503, Zeitüberschreitung → 504,
|
||||||
|
Verlauf zu lang → **400 `context_length_exceeded`** mit dem OpenAI-üblichen Text
|
||||||
|
(„maximum context length is N tokens …") — daran erkennen OpenAI-Clients
|
||||||
|
(litellm, OpenHands …) den Überlauf und kürzen/verdichten selbst
|
||||||
- Antwort-Header `X-Aria-Node` / `X-Aria-Gpu` sagen, wer geantwortet hat
|
- Antwort-Header `X-Aria-Node` / `X-Aria-Gpu` sagen, wer geantwortet hat
|
||||||
- **Läuft das Programm selbst in Docker**, ist `127.0.0.1` dort der eigene
|
- **Läuft das Programm selbst in Docker**, ist `127.0.0.1` dort der eigene
|
||||||
Container. Dann das Docker-Netz `aria-llm` anhängen und
|
Container. Dann das Docker-Netz `aria-llm` anhängen und
|
||||||
@@ -333,6 +336,25 @@ Boxen den Wrapper (B) nehmen.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Den Verlauf verwaltet das Programm
|
||||||
|
|
||||||
|
Die Box merkt sich **nichts** zwischen zwei Anfragen. Jede Anfrage muss alles
|
||||||
|
mitbringen, was das Modell sehen soll (Systemprompt, Werkzeuge, Verlauf). Das
|
||||||
|
Kontextfenster (`ctx`) ist die Obergrenze für **eine** Anfrage inklusive
|
||||||
|
Antwort. Wächst der Verlauf darüber hinaus, muss das Programm ihn kleiner
|
||||||
|
machen — drei übliche Wege, auch kombiniert:
|
||||||
|
|
||||||
|
| Weg | Was passiert | Gut für |
|
||||||
|
|---|---|---|
|
||||||
|
| **Kürzen** | älteste Nachrichten weglassen (Systemprompt behalten) | einfache Chats, Werkzeug-Schleifen |
|
||||||
|
| **Verdichten** („Compacting") | alte Teile vom Modell zusammenfassen lassen, Zusammenfassung statt Original mitsenden | lange Arbeitssitzungen |
|
||||||
|
| **Gedächtnis** (RAG) | Wichtiges als Fakten in einer Datenbank ablegen, pro Anfrage nur Passendes dazuholen | dauerhaftes Wissen über Sitzungen hinweg |
|
||||||
|
|
||||||
|
Wichtig dabei: Systemprompt **und** Werkzeug-Definitionen zählen mit, Platz
|
||||||
|
für die Antwort (`max_tokens`) einplanen, Token grob schätzen (Deutsch/Code:
|
||||||
|
eher 2,5–3 Zeichen pro Token) — und `context_exceeded` trotzdem abfangen:
|
||||||
|
kürzen, einmal neu senden.
|
||||||
|
|
||||||
## Was Programme nicht senden
|
## Was Programme nicht senden
|
||||||
|
|
||||||
`llm_provision_model`, `llm_unload_model` und `llm_remove_model` sind der
|
`llm_provision_model`, `llm_unload_model` und `llm_remove_model` sind der
|
||||||
|
|||||||
@@ -228,6 +228,15 @@ async def handle(reader: asyncio.StreamReader, writer: asyncio.StreamWriter) ->
|
|||||||
return await reply(writer, 503, oai_error(_unreachable(e), "cluster_unreachable", "server_error"))
|
return await reply(writer, 503, oai_error(_unreachable(e), "cluster_unreachable", "server_error"))
|
||||||
if not res.get("ok"):
|
if not res.get("ok"):
|
||||||
code = res.get("errorCode") or "model_error"
|
code = res.get("errorCode") or "model_error"
|
||||||
|
if code == "context_exceeded":
|
||||||
|
# Wie OpenAI: 400 + context_length_exceeded und die Zahlen im
|
||||||
|
# Text — daran erkennen OpenAI-Clients (litellm/OpenHands & Co.)
|
||||||
|
# einen Kontext-Ueberlauf und kuerzen/verdichten selbst.
|
||||||
|
n_ctx, n_req = res.get("ctx"), res.get("promptTokens")
|
||||||
|
msg = (f"This model's maximum context length is {n_ctx} tokens. However, your "
|
||||||
|
f"messages resulted in {n_req} tokens. Please reduce the length of the messages."
|
||||||
|
if n_ctx and n_req else (res.get("error") or "context length exceeded"))
|
||||||
|
return await reply(writer, 400, oai_error(msg, "context_length_exceeded"))
|
||||||
status = {"bad_request": 400, "model_unavailable": 404, "timeout": 504}.get(code, 502)
|
status = {"bad_request": 400, "model_unavailable": 404, "timeout": 504}.get(code, 502)
|
||||||
return await reply(writer, status, oai_error(
|
return await reply(writer, status, oai_error(
|
||||||
res.get("error") or "Fehler", "model_not_found" if code == "model_unavailable" else code,
|
res.get("error") or "Fehler", "model_not_found" if code == "model_unavailable" else code,
|
||||||
|
|||||||
Reference in New Issue
Block a user