تخطَّ إلى المحتوى
معالجة الأخطاء

معالجة الأخطاء

الطلب الذي يفشل يعيد رمز حالة HTTP ونص JSON فيه نوع الخطأ ورسالة. تسرد هذه الصفحة كل حالة، وتعرض نص الخطأ في كل صيغة API، وتبيّن أي الأخطاء تستحق إعادة الإرسال.

ترفع الحزم كائن خطأ يحمل رمز الحالة وحقول النص. يسمّي هذا الطلب نموذجاً غير موجود:

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

يعيد الحالة 400 وهذا النص:

400 JSON
{
  "error": {
    "type": "invalid_request_error",
    "message": "unknown model: no-such-model"
  }
}

نص الخطأ

هناك نصّان. يجيب /v1/messages بصيغة Anthropic؛ وتجيب كل نقطة نهاية أخرى بصيغة OpenAI. في الاثنين تكون التفاصيل في error.type وerror.message، فيخدم قارئ واحد كل نقاط النهاية.

401 صيغة OpenAI
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key",
    "code": "invalid_api_key",
    "param": null
  }
}
401 صيغة Anthropic
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key"
  }
}
الحقل النوع الوصف
error.type string نوع الخطأ. انظر أنواع الأخطاء أدناه.
error.message string جملة موجهة إلى إنسان. النصوص في الجداول أدناه ثابتة باستثناء أجزائها المتغيرة، الظاهرة بالشكل <id> أو <n> أو ….
error.code string | null موجود في بعض أخطاء صيغة OpenAI: invalid_api_key مع 401، وrequest_too_large مع 413، وcontext_length_exceeded عندما تكون المحادثة طويلة جداً، وفيما عدا ذلك null أو غائب. قرّر أولاً بحسب الحالة وerror.type وعامل code كمعلومة إضافية.
error.param null موجود في الأخطاء نفسها التي فيها code. دائماً null.
type string في صيغة Anthropic فقط. دائماً error.

أنواع الأخطاء

النوع الحالات الوصف
invalid_request_error 400, 413, 415, 422 الطلب نفسه خاطئ: حقل أو النص أو معرّف النموذج أو مدخل لا يقبله النموذج. غيّر الطلب قبل أن ترسله من جديد.
authentication_error 401 مفتاح API مفقود أو غير معروف أو مُبطَل.
not_found_error 404 المسار غير موجود.
rate_limit_error 429 الرصيد لا يغطي الطلب، أو أوقفته الحماية من الإغراق، أو أن النموذج مشغول. وتبيّن الرسالة أيّها.
api_error 500, 502, 503, 504 كان الطلب سليماً والفشل من جهتنا. أعد إرساله.
server_error 500 كان الطلب سليماً والفشل من جهتنا. أعد إرساله.

رموز الحالة

الحالة النوع الرسالة متى
400 invalid_request_error Failed to parse the request body as JSON: … النص ليس JSON صالحاً.
400 invalid_request_error unknown model: <id> model ليس معرّفاً منشوراً. وعلى /v1/responses أيضاً عندما يكون model مفقوداً.
400 invalid_request_error No user message provided مستويات Shannon: الطلب لا يحتوي على نص من المستخدم.
400 invalid_request_error <id> does not accept image input أُرسلت صورة إلى نموذج مفتوح الأوزان مستضاف لا يدعم إدخال الصور.
400 invalid_request_error audio and video input are not supported by any hosted model أُرسل جزء صوت أو فيديو إلى نموذج مفتوح الأوزان مستضاف.
400 invalid_request_error <id> does not accept response_format طُلبت مخرجات منظمة من نموذج مفتوح الأوزان مستضاف لا يدعمها.
400 invalid_request_error <id> does not accept response_format json_schema; use json_object أُرسل مخطط JSON إلى نموذج مفتوح الأوزان مستضاف لا يقبل سوى json_object.
400 invalid_request_error unknown reasoning effort '<value>'; expected off, low, medium or high جهد الاستدلال ليس إحدى القيم المذكورة. النماذج المفتوحة الأوزان المستضافة.
400 invalid_request_error count_tokens is available for the hosted open models; unknown model: <id> طُلب عدّ tokens لنموذج من خارج النماذج المفتوحة الأوزان المستضافة.
401 authentication_error Missing authentication لم يُرسل مفتاح API.
401 authentication_error Invalid API key المفتاح غير معروف، أو استُبدل بمفتاح أحدث، أو أُبطل.
404 not_found_error Not Found المسار غير موجود، مثل /v1/embeddings.
405 api_error Method Not Allowed المسار موجود لكن ليس بطريقة HTTP هذه.
413 invalid_request_error Failed to buffer the request body: … نص الطلب أكبر من 32 MiB.
415 invalid_request_error Expected request with `Content-Type: application/json` ترويسة Content-Type مفقودة أو ليست application/json.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … حقل مطلوب مفقود، مثل messages، أو أن نوع JSON لأحد الحقول خاطئ.
429 rate_limit_error Quota exceeded. Upgrade your plan at shannon-ai.com/plan حد مخرجات الطلب أكبر من المتبقي من رصيدك.
429 rate_limit_error Too many requests. Retry in <n>s. الحماية من الإغراق: أكثر من 120 طلباً في الدقيقة الواحدة على حسابك. و<n> هو عدد الثواني حتى تنتهي الدقيقة.
429 rate_limit_error Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan shannon-coder-1 على /v1/chat/completions و/v1/messages: استُنفدت استدعاءات Shannon Coder في خطتك لنافذة الـ 4 ساعات الحالية.
429 rate_limit_error Shannon routes are temporarily busy. Please retry. النموذج مشغول في هذه اللحظة.
500 server_error The model backend failed to answer. Please retry. لم ينتج النموذج رداً.
500 server_error An internal error occurred. Please retry. فشل داخلي أثناء تجهيز الطلب.
502 api_error The model backend failed to answer. Please retry. لم ينتج النموذج رداً. عائلة Shannon 3 والنماذج المفتوحة الأوزان المستضافة.
503 api_error Could not verify your quota right now. Please retry. تعذرت قراءة رصيدك في هذه اللحظة.
503 api_error token counting is temporarily unavailable for this model عدّ tokens غير متاح لهذا النموذج في هذه اللحظة.
504 api_error upstream timed out استغرق نموذج مفتوح الأوزان مستضاف وقتاً أطول من الحد الزمني لطلب غير مبثوث.

تجري الفحوص بهذا الترتيب: مفتاح API، ثم نص الطلب، ثم معرّف النموذج، ثم الحماية من الإغراق، ثم الرصيد. لذا يعيد الطلب ذو المفتاح الخاطئ والنص الخاطئ 401. والطلب الذي يُرفض بحالة 4xx لا يُحاسَب.

الرصيد والحماية من الإغراق

كل طلب يُخدَم بالتساوي: لا توجد مستويات للمعدل ولا حصة API منفصلة. ومع ذلك يمكن لأمرين أن يجيبا بـ 429، كلاهما بالنوع rate_limit_error. وتفرّق الرسالة بينهما.

الرصيد

رصيدك هو مخصصات الخطة لليوم، التي تُعاد ضبطها عند 00:00 UTC، ثم رصيدك المشتري بعدها. الدردشة وAPI تسحبان من الرصيد نفسه.

كل طلب يحجز أولاً حد مخرجاته: max_tokens، أو max_output_tokens على /v1/responses، وهو 4,096 إذا لم ترسل أياً منهما. وعند اكتمال الرد يُستبدل المقدار المحجوز بما استخدمه الطلب. وإذا لم يتسع المقدار في الرصيد المتبقي، يعيد الطلب Quota exceeded قبل أن يبدأ النموذج.

الطلبات التي تعمل في الوقت نفسه يحجز كل منها مقداره الخاص. لذا قد تستنفد طلبات متوازية كثيرة ذات max_tokens مرتفع الرصيد للحظة، حتى لو كان كل رد قصيراً. وmax_tokens أقل يحجز مقداراً أقل.

الحماية من الإغراق

تسمح الحماية من الإغراق بـ 120 طلباً في الدقيقة لكل حساب. وهي تحسب الحساب لا المفتاح، عبر /v1/chat/completions و/v1/responses و/v1/messages معاً. وتبدأ الدقيقة مع أول طلب منك.

الطلب رقم 121 ضمن تلك الدقيقة يعيد Too many requests. Retry in <n>s. ولا يكلف شيئاً. والطلبات المرفوضة تُحتسب أيضاً، لذا يبقى العميل الذي يعيد الإرسال دون انتظار مرفوضاً حتى تنتهي الدقيقة. انتظر <n> ثانية المذكورة في الرسالة.

الطلبات المرسلة بالتوازي لا تُرفض لكونها متوازية. إنما تنتظر في الطابور ويُجاب عنها بالدور.

لا يُحتسب GET /v1/models ولا نقاط نهاية عدّ tokens.

المزيد عن الحدود والرصيد، وأين ترى رصيدك واستخدامك: الحدود والرصيد المفاتيح والاستخدام

ما الذي تُعاد محاولته

أعد إرسال الطلب فقط عندما يمكن للطلب نفسه أن ينجح. تعيد حزم OpenAI وAnthropic SDK محاولة ردود 429 و5xx مرتين من تلقاء نفسها؛ اضبط max_retries (maxRetries في JavaScript) لتغيير ذلك.

الخطأ هل تُعاد المحاولة؟ كيف
400, 404, 405, 413, 415, 422 لا. صحّح الطلب أولاً. تسمّي الرسالة الحقل أو النموذج أو المدخل الخاطئ.
401 لا. استخدم مفتاحاً صالحاً. أنشئ المفتاح أو استبدله في صفحة المفاتيح والاستخدام.
429 Too many requests نعم، بعد الانتظار. انتظر عدد الثواني المذكور في الرسالة، ثم أرسل الطلب نفسه.
429 Quota exceeded ليس كما هو. خفّض max_tokens، أو انتظر إعادة الضبط اليومية عند 00:00 UTC، أو أضف رصيداً.
429 Shannon Coder call quota reached نعم، في النافذة التالية. تبدأ النوافذ كل 4 ساعات من 00:00 UTC. ويجيب نموذج آخر فوراً.
429 … temporarily busy نعم. انتظر بضع ثوانٍ، ثم مدة أطول في كل محاولة لاحقة.
500, 502, 503 نعم. انتظر 1 ثانية، ثم 2 ثم 4 ثم 8. توقف بعد بضع محاولات وأبلغ عن معرّف الطلب.
504 نعم. أرسله مع ضبط stream على true: فالحد الزمني يسري على الردود غير المبثوثة.

حلقة إعادة محاولة تتبع هذا الجدول:

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)

الأخطاء داخل البث

للبث الحالة 200 منذ أول بايت. والفشل بعد ذلك يصل كحدث داخل البث: جزء فيه عضو error على /v1/chat/completions، أو حدث error على /v1/messages، أو حدث response.failed أو error على /v1/responses. وتتبعه أحداث إغلاق البث. اعتبر ردّاً كهذا فاشلاً وأعد إرسال الطلب، كما في حالة 5xx.

المحادثة الأطول من نافذة سياق النموذج يُبلَّغ عنها بهذه الطريقة، بالنوع invalid_request_error والرمز context_length_exceeded. قصّر المحادثة قبل أن ترسلها من جديد.

الإطارات بالتفصيل موصوفة مع البث. البث

معرّفات الطلبات

كل رد، بما فيه الأخطاء، يحمل ترويسة x-request-id. وهي القيمة التي أرسلتها في ترويستك x-request-id، أو 12 رمزاً سداسياً عشرياً إن لم ترسل شيئاً. سجّلها، واذكرها عند طلب المساعدة بشأن طلب.