Feelerbehandlung
Eng Ufro, déi feelschléit, gëtt en HTTP-Status-Code an e JSON-Body mat engem Feelertyp an enger Message zréck. Dës Säit lëscht all Status op, weist de Feeler-Body vun all API-Format a seet, bei wéi enge Feeler et sech lount, nach eng Kéier ze schécken.
D'SDKs werfen en Feeler-Objet, dat de Status-Code an d'Felder vum Body enthält. Dës Ufro nennt e Modell, deen et net gëtt:
import openai
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
try:
client.chat.completions.create(
model="no-such-model",
messages=[{"role": "user", "content": "Hello"}],
)
except openai.APIStatusError as error:
print(error.status_code) # 400
print(error.type) # invalid_request_error
print(error.body["message"]) # unknown model: no-such-model
print(error.response.headers.get("x-request-id")) # the id of this request import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
try {
await client.chat.completions.create({
model: "no-such-model",
messages: [{ role: "user", content: "Hello" }],
});
} catch (error) {
if (!(error instanceof OpenAI.APIError)) throw error;
console.log(error.status); // 400
console.log(error.type); // invalid_request_error
console.log(error.error.message); // unknown model: no-such-model
} curl -i https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "no-such-model",
"messages": [{"role": "user", "content": "Hello"}]
}' Si gëtt de Status 400 an dëse Body zréck:
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} Feeler-Body
Et ginn zwee Bodys. /v1/messages äntwert am Anthropic-Format; all aner Endpoint äntwert am OpenAI-Format. A béiden stinn d'Detailer an error.type an error.message, sou datt ee Reader fir all Endpoints geet.
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "invalid_api_key",
"param": null
}
} {
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key"
}
} | Feld | Typ | Beschreiwung |
|---|---|---|
error.type | string | D'Zort vum Feeler. Kuckt Feelertypen ënnen. |
error.message | string | E Saz fir e Mënsch. D'Texter an den Tabellen ënnendrënner sinn stabil, ausser hire variabelen Deeler, déi als <id>, <n> oder … gewise ginn. |
error.code | string | null | Bei e puer Feeler vum OpenAI-Format präsent: invalid_api_key mat 401, request_too_large mat 413, context_length_exceeded, wann eng Konversatioun ze laang ass, soss null oder net do. Entscheet fir d'éischt no dem Status an error.type a behandelt code als Zousaz. |
error.param | null | Bei deene selwechte Feeler präsent wéi code. Ëmmer null. |
type | string | Nëmmen am Anthropic-Format. Ëmmer error. |
Feelertypen
| Typ | Statussen | Beschreiwung |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | D'Ufro selwer ass falsch: e Feld, de Body, d'Modell-ID oder en Input, deen de Modell net hëlt. Ännert d'Ufro, ier Dir se nach eng Kéier schéckt. |
authentication_error | 401 | Den API-Schlëssel feelt, ass onbekannt oder gouf widderruff. |
not_found_error | 404 | De Pfad gëtt et net. |
rate_limit_error | 429 | Den Solde deckt d'Ufro net of, de Flood-Schutz huet se gestoppt, oder de Modell ass beschäftegt. D'Message seet, wat et ass. |
api_error | 500, 502, 503, 504 | D'Ufro war a Rei an de Feeler läit bei eis. Schéckt se nach eng Kéier. |
server_error | 500 | D'Ufro war a Rei an de Feeler läit bei eis. Schéckt se nach eng Kéier. |
Status-Coden
| Status | Typ | Message | Wéini |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | De Body ass kee gültegt JSON. |
400 | invalid_request_error | unknown model: <id> | model ass keng publizéiert ID. Op /v1/responses och dann, wann model feelt. |
400 | invalid_request_error | No user message provided | Shannon-Stufen: d'Ufro enthält keen Text vum Benotzer. |
400 | invalid_request_error | <id> does not accept image input | E Bild gouf un en Hosted Open-Weight-Modell ouni Bild-Input geschéckt. |
400 | invalid_request_error | audio and video input are not supported by any hosted model | En Audio- oder Video-Deel gouf un en Hosted Open-Weight-Modell geschéckt. |
400 | invalid_request_error | <id> does not accept response_format | Strukturéiert Output gouf vun engem Hosted Open-Weight-Modell ugefrot, deen dat net huet. |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | E JSON-Schema gouf un en Hosted Open-Weight-Modell geschéckt, dee just json_object hëlt. |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | De Reasoning-Effort ass kee vun den opgelëschte Wäerter. Hosted Open-Weight-Modeller. |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | D'Tokenzielen gouf fir e Modell ugefrot, deen net zu den Hosted Open-Weight-Modeller gehéiert. |
401 | authentication_error | Missing authentication | Et gouf kee API-Schlëssel geschéckt. |
401 | authentication_error | Invalid API key | De Schlëssel ass onbekannt, gouf duerch e méi neie ersat oder widderruff. |
404 | not_found_error | Not Found | De Pfad gëtt et net, zum Beispill /v1/embeddings. |
405 | api_error | Method Not Allowed | De Pfad gëtt et, awer net mat dëser HTTP-Method. |
413 | invalid_request_error | Failed to buffer the request body: … | De Body vun der Ufro ass méi grouss wéi 32 MiB. |
415 | invalid_request_error | Expected request with `Content-Type: application/json` | De Content-Type-Header feelt oder ass net application/json. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | E noutwendegt Feld feelt, zum Beispill messages, oder e Feld huet de falsche JSON-Typ. |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | D'Output-Limit vun der Ufro ass méi grouss wéi dat, wat vun Ärem Solde iwwereg ass. |
429 | rate_limit_error | Too many requests. Retry in <n>s. | Flood-Schutz: méi wéi 120 Ufroen an enger Minutt op Ärem Kont. <n> ass d'Zuel vu Sekonnen, bis d'Minutt eriwwer ass. |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | shannon-coder-1 op /v1/chat/completions an /v1/messages: d'Shannon-Coder-Ruffer vun Ärem Plan fir dat aktuellt 4-Stonne-Fënster sinn opgebraucht. |
429 | rate_limit_error | Shannon routes are temporarily busy. Please retry. | De Modell ass an dësem Moment beschäftegt. |
500 | server_error | The model backend failed to answer. Please retry. | De Modell huet keng Äntwert produzéiert. |
500 | server_error | An internal error occurred. Please retry. | En internen Ausfall, wärend d'Ufro virbereet gouf. |
502 | api_error | The model backend failed to answer. Please retry. | De Modell huet keng Äntwert produzéiert. Shannon-3-Famill an Hosted Open-Weight-Modeller. |
503 | api_error | Could not verify your quota right now. Please retry. | Äre Solde konnt an dësem Moment net gelies ginn. |
503 | api_error | token counting is temporarily unavailable for this model | D'Tokenzielen ass fir dëse Modell an dësem Moment net verfügbar. |
504 | api_error | upstream timed out | En Hosted Open-Weight-Modell huet méi laang gebraucht wéi d'Zäitlimit vun enger Ufro, déi net gestreamt gëtt. |
D'Kontrolle lafen an dëser Reiefolleg: API-Schlëssel, Ufro-Body, Modell-ID, Flood-Schutz, Solde. Eng Ufro mat engem falsche Schlëssel an engem falsche Body gëtt dofir 401 zréck. Eng Ufro, déi mat engem 4xx-Status refuséiert gëtt, gëtt net berechent.
Solde a Flood-Schutz
All Ufro gëtt gläich behandelt: et gëtt keng Rate-Stufen a keng separat API-Quota. Zwee Saache kënnen trotzdem 429 äntweren, béid mam Typ rate_limit_error. D'Message seet, wat wat ass.
Solde
Äre Solde ass d'Plan-Zuelung vun haut, déi um 00:00 UTC nei geet, an duerno Äre gekaafte Crédit. De Chat an d'API huelen aus deemselwechte Solde.
All Ufro leet fir d'éischt hir Output-Limit apaart: max_tokens, oder max_output_tokens op /v1/responses, 4,096, wann Dir kee vun deenen zwee schéckt. Wann d'Äntwert komplett ass, gëtt dat Apaartgeluechten duerch dat ersat, wat d'Ufro benotzt huet. Wann de Betrag net méi an de Rescht vum Solde passt, gëtt d'Ufro Quota exceeded zréck, ier de Modell ufänkt.
Ufroen, déi zur selwechter Zäit lafen, leeë jeweils hire Betrag apaart. Vill parallel Ufroen mat engem héije max_tokens kënnen den Solde dofir fir en Ament opbrauchen, och wann all Äntwert kuerz ass. E méi nidderegt max_tokens leet manner apaart.
Flood-Schutz
De Flood-Schutz erlaabt 120 Ufroen pro Minutt pro Kont. Hie zielt de Kont, net de Schlëssel, iwwer /v1/chat/completions, /v1/responses an /v1/messages zesummen. D'Minutt fänkt mat Ärer éischter Ufro un.
D'Ufro Nummer 121 an där Minutt gëtt Too many requests. Retry in <n>s. zréck a kascht näischt. Refuséiert Ufroen zielen och mat, dofir bleift e Client, deen ouni Waarden nach eng Kéier schéckt, refuséiert, bis d'Minutt eriwwer ass. Waart déi <n> Sekonne vun der Message.
Ufroen, déi parallel geschéckt ginn, ginn net refuséiert, well se parallel sinn. Si waarde an der Schlaang a ginn nodeneen beäntwert.
GET /v1/models an d'Endpoints fir d'Tokenzielen ginn net matgezielt.
Méi zu Limiten a Solde, a wou Dir Äre Solde a Är Notzung gesitt: Limiten a Solde Schlësselen & Notzung
Wat nach eng Kéier probéiert gëtt
Schéckt eng Ufro nëmme nach eng Kéier, wann déiselwecht Ufro gelénge kann. D'OpenAI- an d'Anthropic-SDKs probéieren 429- an 5xx-Äntwerten schonn zweemol vu selwer erëm; setzt max_retries (maxRetries a JavaScript), fir dat z'änneren.
| Feeler | Nach eng Kéier schécken? | Wéi |
|---|---|---|
400, 404, 405, 413, 415, 422 | Neen. Korrigéiert d'Ufro fir d'éischt. | D'Message nennt d'Feld, de Modell oder den Input, deen net stëmmt. |
401 | Neen. Benotzt e gültege Schlëssel. | Erstellt oder ersetzt de Schlëssel op der Säit Schlësselen & Notzung. |
429 Too many requests | Jo, no der Waardezäit. | Waart d'Zuel vu Sekonnen aus der Message, schéckt dann déiselwecht Ufro. |
429 Quota exceeded | Net sou wéi se ass. | Reduzéiert max_tokens, waart op de Reset vum Dag um 00:00 UTC, oder fügt Crédit derbäi. |
429 Shannon Coder call quota reached | Jo, am nächste Fënster. | D'Fënstere fänken all 4 Stonnen ab 00:00 UTC un. E aner Modell äntwert direkt. |
429 … temporarily busy | Jo. | Waart e puer Sekonnen, bei all weiderem Versuch méi laang. |
500, 502, 503 | Jo. | Waart 1 Sekonn, dann 2, 4 an 8. Héiert no e puer Versich op a mellt d'Ufro-ID. |
504 | Jo. | Schéckt se mat stream op true: d'Zäitlimit gëllt fir Äntwerten, déi net gestreamt ginn. |
Eng Retry-Loop no dëser Tabell:
import re
import time
import openai
from openai import OpenAI
# max_retries=0: this loop does the retrying, the SDK does not add its own.
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1", max_retries=0)
def create_with_retry(attempts=5, **request):
for attempt in range(attempts):
try:
return client.chat.completions.create(**request)
except openai.RateLimitError as error:
text = str(error)
flood = re.search(r"Retry in (\d+)s", text)
if flood:
time.sleep(int(flood.group(1))) # flood protection: wait out the minute
elif "temporarily busy" in text:
time.sleep(2 ** attempt)
else:
raise # balance: a wait of seconds does not help
except (openai.InternalServerError, openai.APIConnectionError):
time.sleep(2 ** attempt) # 1, 2, 4, 8 seconds
raise RuntimeError("the request failed after all attempts")
response = create_with_retry(
model="shannon-3",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content) import OpenAI from "openai";
// maxRetries: 0 — this loop does the retrying, the SDK does not add its own.
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1", maxRetries: 0 });
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
async function createWithRetry(request, attempts = 5) {
for (let attempt = 0; attempt < attempts; attempt++) {
try {
return await client.chat.completions.create(request);
} catch (error) {
const text = String(error.message);
const flood = text.match(/Retry in (\d+)s/);
if (error.status === 429 && flood) {
await sleep(Number(flood[1])); // flood protection: wait out the minute
} else if (error.status === 429 && text.includes("temporarily busy")) {
await sleep(2 ** attempt);
} else if (error.status >= 500 || error instanceof OpenAI.APIConnectionError) {
await sleep(2 ** attempt); // 1, 2, 4, 8 seconds
} else {
throw error; // wrong request, wrong key or balance
}
}
}
throw new Error("the request failed after all attempts");
}
const response = await createWithRetry({
model: "shannon-3",
messages: [{ role: "user", content: "Hello" }],
});
console.log(response.choices[0].message.content); Feeler an engem Stream
E Stream huet vum éischte Byte un de Status 200. E Feeler dono kënnt als Event am Stream: e Chunk mat engem error-Member op /v1/chat/completions, en error-Event op /v1/messages, e response.failed- oder error-Event op /v1/responses. Déi ofschléissend Events vum Stream folgen trotzdem. Behandelt eng sou Äntwert als gescheitert a schéckt d'Ufro nach eng Kéier, wéi bei engem 5xx-Status.
Eng Konversatioun, déi méi laang ass wéi d'Kontextfënster vum Modell, gëtt sou gemellt, mam Typ invalid_request_error an dem Code context_length_exceeded. Kierzt d'Konversatioun, ier Dir se nach eng Kéier schéckt.
Déi exakt Frames si bei Streaming beschriwwen. Streaming
Ufro-IDen
All Äntwert, och Feeler, huet en x-request-id-Header. Et ass de Wäert, dee Dir an Ärem eegenen x-request-id-Header geschéckt hutt, oder 12 hexadezimal Zeechen, wann Dir keen geschéckt hutt. Loggt en, a gitt en un, wann Dir Hëllef bei enger Ufro frot.