تخطّي إلى المحتوى
Geb AI
للمطوّرين

ابنِ على جْبْ. العربية أولًا، ومتوافق مع OpenAI.

عنوان أساسي واحد ومفتاح واحد. وجّه مكتبة OpenAI إلى جْبْ لتحصل على ردود عربية ومتعددة اللغات قوية، وبثٍّ مباشر، ودوالّ من تطبيقك، وأدوات مدمجة.

العنوان الأساسيhttps://api.gebai.ca/v2

يلزم تسجيل الدخول. تحصل الحسابات المجانية على 500 استدعاء شهريًا. لا رسوم على الرموز.

متوافق مع مكتبات OpenAI

غيّر العنوان الأساسي والمفتاح فقط. تعمل واجهة إكمال المحادثة والبثّ واستدعاء الدوال كما تتوقع.

العربية أولًا

تتبع الردود لغة مستخدمك، بالعربية الفصحى الحديثة أو بالعامية المصرية عندما تطلب ذلك.

مصمَّم لإعادة المحاولة

مفاتيح عدم التكرار، ورموز أخطاء واضحة، وردّ على كل استدعاء حتى عندما يُقطع التوليد قبل اكتماله.

1.ما تقدمه الواجهة البرمجية وما لا تقدمه

تمنح الواجهة البرمجية لجْبْ تطبيقك النموذج نفسه الذي يردّ داخل تطبيق جْبْ، عبر واجهة إكمال المحادثة التي تتحدث بها مكتبات عملاء OpenAI أصلًا. وجّه حزمة OpenAI SDK إلى https://api.gebai.ca/v2، واستخدم مفتاح جْبْ، وستعمل مباشرة.

تسمّي جْبْ هذه الواجهة API v2، وتبدأ مسارات عناوين URL فيها بـ /v2. ويستمر العملاء الحاليون الذين ما زالوا يستدعون /v1 في العمل: إذ إن /v1/... اسم بديل يصل إلى المعالجات نفسها تمامًا، بالسلوك والترويسات والأخطاء والحصص نفسها، ويُحتسب الاستدعاء مرة واحدة أيًّا كانت البادئة المستخدمة. وينبغي للشيفرة الجديدة أن تستخدم /v2.

ما تحصل عليه

  • إكمال المحادثة عند POST /v2/chat/completions، بشكل مكتمل أو مبثوث عبر أحداث يرسلها الخادم.
  • ردود قوية بالعربية وبلغات متعددة. تردّ جْبْ بلغة آخر رسالة من مستخدمك، في 23 لغة. العربية لغة من الدرجة الأولى، وليست طبقة ترجمة.
  • دوالّك الخاصة عبر الحقل القياسي tools (استدعاء الدوال).
  • الأدوات المدمجة في جْبْ، مثل البحث في الويب والطقس ومنشئات المستندات وجداول البيانات، عندما تفعّلها بالاسم.
  • مخرجات منظَّمة عبر response_format (json_object وjson_schema).
  • إدخال الصور في رسائل المستخدم.
  • التحكم في الاستدلال بمستويات الجهد.
  • محادثات مخزَّنة يمكنك متابعتها بالمعرّف، وتبقى منفصلة عن أي ذاكرة للحساب.
  • قواعد الرد (geb_acceptance): صرّح بنطاقات الكلمات والعبارات المحظورة ومتطلبات الإسناد، وتتحقق جْبْ من الرد وتحسّنه قبل إعادته.
  • لا رسوم لكل رمز. تتضمن باقتك عددًا من الاستدعاءات في كل فترة فوترة (انظر القسم 10). لا تُحتسب الرموز.

ما لا تقدمه

  • ليست وسيطًا لـ OpenAI. كل رد يأتي من نموذج جْبْ نفسه. ولا يُسلَّم طلبك أبدًا إلى نموذج تابع لمورّد آخر.
  • لا تدرك الذاكرة. لا تقرأ استدعاءات API ذاكرة حساب جْبْ الخاص بك ولا تكتب إليها. يُبنى الاستدعاء من طلبك وحده (إضافة إلى سلسلة محادثة مخزَّنة إذا طلبتها، انظر القسم 5.5).
  • إكمال المحادثة فقط. لا توجد نقاط نهاية للتضمينات أو الصوت أو توليد الصور أو الملفات أو المعالجة الدفعية أو الضبط الدقيق، ولا لواجهتي Assistants وResponses.
  • اختيار واحد فقط. يُرفض كل من n وlogprobs والحقل القديم functions.
  • بعض حقول أخذ العينات مقبولة ومتجاهلة. لا تتسبب stop وuser وseed وtemperature وtop_p وpresence_penalty وfrequency_penalty وlogit_bias وmin_p وtop_k وrepetition_penalty في أي خطأ، وليس لها أي أثر اليوم.
  • لا يمكن استدعاؤها من متصفح على موقع شخص آخر. تردّ الواجهة على طلبات التحقق المسبق عبر الأصول المختلفة لمواقع جْبْ فقط. استدعِها من خادمك، لا من JavaScript في جهة العميل. ولا تضع مفتاحًا أبدًا في صفحة ويب أو تطبيق جوال.

2.البدء السريع

أول استدعاء لك في خمس دقائق. اختر لغتك؛ يُحفظ اختيارك في كل الأمثلة في الصفحة.

  1. احصل على مفتاح (القسم 3). يبدو بالشكل geb_live_ متبوعًا بـ 43 حرفًا.
  2. ضعه في متغير بيئة. ولا تلصقه أبدًا في الشيفرة المصدرية.
  3. أجرِ استدعاءً.
export GEB_API_KEY="geb_live_..."   # paste your key here, in your shell only

curl https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "geb",
    "messages": [
      {"role": "user", "content": "Greet me in Arabic and in English, one line each."}
    ]
  }'

الحصول على مفتاح

  1. سجّل الدخول إلى gebai.ca.
  2. افتح الملف الشخصي، ثم مفاتيح API.
  3. أنشئ مفتاحًا، وانسخه مرة واحدة، واحتفظ به على خادمك.
احصل على مفتاح API

ما تحصل عليه في الرد

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1790000000,
  "model": "<model-id>",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "..." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 }
}

model هو معرّف النموذج الذي ردّ، كما يرد في GET /v2/models. ويشمل usage.prompt_tokens تعليمات جْبْ الأساسية، التي تتصدر كل موجّه.

إذا حصلت على 401 فتحقق من المفتاح ومن ترويسة Authorization (القسم 4). وإذا حصلت على 429 فاقرأ القسم 10.

3.الحصول على مفتاح

تُنشأ المفاتيح بواسطة حساب جْبْ مسجَّل الدخول، في تطبيق ويب جْبْ.

  1. أنشئ حسابك أو سجّل الدخول إليه على https://gebai.ca.
  2. افتح الملف الشخصي، ثم مفاتيح API (https://gebai.ca/profile/api-keys).
  3. اختر إنشاء مفتاح API. أعطه اسمًا، واختياريًا مدة صلاحية بالأيام (من 1 إلى 365).
  4. انسخ المفتاح فورًا. يُعرض مرة واحدة ولا يمكن استرجاعه لاحقًا. وتخزّن جْبْ قيمة تجزئة فقط.

احصل على مفتاح API

أمور ينبغي معرفتها:

  • يمكن للحساب أن يحمل حتى 10 مفاتيح نشطة. ألغِ أحدها لتحرير خانة.
  • ألغِ أي مفتاح من الصفحة نفسها في أي وقت. المفتاح الملغى أو المنتهي يردّ بـ 401 منذ الطلب التالي.
  • كل مفتاح يتبع الحساب الذي أنشأه. وتُحتسب الاستدعاءات والحصة وحدود المعدّل لكل حساب، عبر جميع مفاتيحه.
  • نطاق المفتاح الوحيد هو chat:write، وهو يغطي كل نقطة نهاية في هذا الدليل.
  • كل باقة تستطيع استخدام الواجهة، ومنها المجانية: يمكن للحساب المجاني إنشاء مفاتيح وإجراء 500 استدعاء في كل فترة فوترة. وعدد الاستدعاءات التي تتضمنها كل باقة مذكور في القسم 10.

أبقِ المفاتيح على خادمك. استخدم مفتاحًا واحدًا لكل تطبيق أو بيئة، لتتمكن من إلغاء أحدها دون المساس بالبقية.

4.المصادقة

أرسل المفتاح كرمز حامل (bearer token) في كل طلب.

Authorization: Bearer geb_live_...
curl https://api.gebai.ca/v2/models -H "Authorization: Bearer $GEB_API_KEY"

الطلب بلا مفتاح، أو بترويسة مشوَّهة، أو بنظام مصادقة مختلف (مثل Basic)، أو بمفتاح مجهول أو ملغى أو منتهي، كلها تعيد الرد نفسه:

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
x-request-id: 0f658b6d9742d46fec9ce4b984f99667

{"error":{"message":"A valid developer API key is required.","type":"invalid_api_key","param":null,"code":null,"request_id":"0f658b6d9742d46fec9ce4b984f99667"}}

يعني 403 permission_error أن المفتاح صالح لكن الحساب غير مسموح له باستخدام الواجهة (مثلًا الحساب معلّق).

5.نقاط النهاية

جميع نقاط النهاية تحت https://api.gebai.ca، وتستخدم JSON، وتتطلب مفتاح الحامل. والبادئة المعتمدة هي /v2. أما المسارات نفسها بالبادئة /v1 فهي اسم بديل للعملاء الحاليين وتسلك السلوك نفسه. وعندما يذكر رد أو خطأ مسارًا فإنه يذكر البادئة التي استخدمتها.

الطريقة والمسارالغرض
GET /v2/modelsيعرض النموذج الذي يمكنك استدعاؤه، مع قدراته الحية.
GET /v2/models/{id}يسترجع ذلك النموذج. المعرّف المجهول يعطي 404.
POST /v2/chat/completionsينشئ إكمال محادثة، مكتملًا أو مبثوثًا.
GET /v2/conversationsيعرض محادثاتك المخزَّنة.
GET /v2/conversations/{id}يقرأ محادثة مخزَّنة واحدة.
DELETE /v2/conversations/{id}يحذف محادثة مخزَّنة واحدة.

يمكن ضغط أجسام الطلبات بـ gzip أو deflate (Content-Encoding: gzip). والحد الأقصى لجسم الطلب 32 MiB بعد فك الضغط.

5.1 قائمة النماذج

curl https://api.gebai.ca/v2/models -H "Authorization: Bearer $GEB_API_KEY"

الرد قائمة بصيغة OpenAI. ويحمل كل نموذج معلومات حية عما تستطيع الواجهة فعله الآن:

{
  "object": "list",
  "data": [
    {
      "id": "<model-id>",
      "object": "model",
      "created": 1755475200,
      "owned_by": "geb-ai",
      "context_window": 0,
      "modalities": { "input": ["text", "image"], "output": ["text"] },
      "capabilities": { "streaming": true, "tools": true, "vision": true, "reasoning": true },
      "reasoning": {
        "always_on": true,
        "efforts": ["low", "medium", "high", "ultra"],
        "default_effort": "<level>",
        "parameters": ["reasoning", "reasoning_effort", "thinking", "enable_thinking", "..."]
      },
      "limits": {
        "max_tokens": "answer_ceiling",
        "max_tokens_default": "derived_from_context_window",
        "long_non_streamed": "keepalive"
      },
      "geb_tools": ["web_search", "weather_forecast", "..."],
      "status": { "healthy": true, "state": "<state>" }
    }
  ]
}
  • context_window هو عدد الرموز التي يستطيع النموذج استيعابها في طلب واحد. وقيمته null عندما لا تستطيع جْبْ قياسه حاليًا.
  • capabilities.vision و"image" في modalities.input حيّان: لا تكونان true إلا ما دام طلب يحتوي صورة سيُقبل في هذه اللحظة.
  • geb_tools هي القائمة الدقيقة لأسماء الأدوات المدمجة التي يجوز للطلب تسميتها (القسم 7.2).
  • القيم أعلاه توضيحية. اقرأ القيم الفعلية من استدعائك أنت.

تخدم الواجهة اليوم نموذجًا واحدًا من جْبْ. الحقل model في الإكمال مقبول لأغراض التوافق مع OpenAI (أي نص مقبول) ولا يختار بين النماذج. ويذكر الرد المعرّف الذي ردّ فعلًا.

5.2 إنشاء إكمال محادثة

POST /v2/chat/completions

المعاملالنوعملاحظات
modelنصاختياري. مقبول للتوافق، انظر أعلاه.
messagesمصفوفةمطلوب. الأدوار system وuser وassistant وtool. وcontent نص، أو في رسائل user مصفوفة من أجزاء text وimage_url.
streamقيمة منطقيةtrue يبثّ أحداثًا يرسلها الخادم (القسم 6).
max_tokensعدد صحيحسقف للإجابة المرئية. وتُحتسب ميزانية التفكير بشكل منفصل (القسم 8).
tools, tool_choice, parallel_tool_callsدوالّك الخاصة (القسم 7.1).
response_formatكائن{"type":"json_object"} أو {"type":"json_schema", ...}.
stream_optionsكائن{"include_usage": true} يضيف مقطع استخدام أخيرًا إلى البثّ.
reasoning, reasoning_effort, thinking, enable_thinkingالتحكم في الاستدلال (القسم 8).
geb_toolsقيمة منطقية أو مصفوفةالأدوات المدمجة في جْبْ، معطّلة افتراضيًا (القسم 7.2).
geb_acceptanceكائنقواعد الرد (القسم 5.6).
conversation_idنص"new" يبدأ محادثة مخزَّنة، ومعرّف يتابع محادثة (القسم 5.5).
locale"en", "ar", "fr"اختياري. تلميح للغة الرد عندما لا تحددها الرسالة نفسها.

مقبولة لكن متجاهلة (بلا خطأ وبلا أثر): stop وuser وseed وtemperature وtop_p وpresence_penalty وfrequency_penalty وlogit_bias وmin_p وtop_k وrepetition_penalty.

مرفوضة بـ 400: n وlogprobs وfunctions. كما يُرفض geb_memory: true (memory_unavailable)، لأن استدعاءات API لا ذاكرة لها.

الحقول المجهولة أخطاء. الخاصية التي لا تعرفها جْبْ، مثل max_completion_tokens أو store، تعيد 400 برسالة مثل property store should not exist. استخدم max_tokens. وإذا كانت مكتبة العميل لديك تضيف حقولًا من تلقاء نفسها، فأزِلها.

ينبغي أن يكون جسم الطلب JSON صالحًا. تُرفض الفواصل الزائدة في النهاية والتعليقات وNaN وسائر أخطاء الصياغة بالرمز 400 invalid_json_body. أما الحقل الذي يظهر مرتين في كائن واحد فليس خطأً: كما في أي محلّل JSON قياسي، تفوز القيمة الأخيرة. لا ترسل حقولًا مكررة عمدًا.

تعليمات جْبْ نفسها تتصدر كل موجّه. تردّ جْبْ بصفتها جْبْ، ولا يمكن تجاوز قواعد السلامة الخاصة بها. وتأتي رسالة system الخاصة بك بعدها وتؤطّر المحادثة. وتُحتسب هذه التعليمات ضمن usage.prompt_tokens.

لغة الرد. تردّ جْبْ بلغة آخر رسالة من مستخدمك وتتبع أي تحوّل في منتصف المحادثة. والتعليمة الصريحة مثل «رُدَّ بالفرنسية» لها الأولوية. والرسالة التي لا تحسم اللغة («ok»، أو شيفرة) تُبقي لغة آخر رسالة واضحة. وتبقى الشيفرة والأوامر ووسائط الأدوات بلغتها الطبيعية. وبالنسبة للعربية، تحدد رسالة system الخاصة بك المستوى اللغوي: اطلب «العربية الفصحى» أو «العربية المصرية». وفي غياب ذلك تكون المخرجات المكتوبة والترجمات بالعربية الفصحى، وتكون المحادثة بالعربية المصرية. وطلب الترجمة يعيد الترجمة وحدها.

الرد. يشبه الإكمال العادي رد البدء السريع. وتكون finish_reason هي stop (اكتمل)، أو length (قُطع عند max_tokens الخاص بك، أو قُطع مبكرًا، انظر القسم 6.4)، أو tool_calls (يجري استدعاء دالتك)، أو content_filter. تحقق منها دائمًا قبل أن تستخرج JSON من أي رد.

r = client.chat.completions.create(
    model="geb",
    messages=[
        {"role": "system", "content": "You are a concise assistant for a travel app."},
        {"role": "user", "content": "اقترح لي خطة ليوم واحد في القاهرة"},
    ],
    max_tokens=800,
)
print(r.choices[0].message.content, r.choices[0].finish_reason, r.usage.total_tokens)

5.3 المخرجات المنظَّمة

curl https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role":"user","content":"Extract: Layla, 34, lives in Giza."}],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "person",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {"name":{"type":"string"},"age":{"type":"integer"},"city":{"type":"string"}},
          "required": ["name","age","city"],
          "additionalProperties": false
        }
      }
    }
  }'
  • ردود json_schema صالحة وفق المخطط. أرسل "strict": true لتتحقق جْبْ من مخططك أولًا: عندئذ يحتاج كل كائن إلى additionalProperties: false ولا بد من إدراج كل خاصية في required، ويُرفض المخطط الذي لا يستطيع تحقيق ذلك بـ 400 مع تسمية المسار المخالف. وبدون الحقل strict تستخدم جْبْ مخططك كما أُرسل ولا ترفضه، فالمخطط الذي يخالف القواعد الصارمة ليس خطأً، لكن ردوده لا تكون مقيّدة إلا بقدر ما يقيّدها المخطط.
  • تحقق من finish_reason. إذا كانت length فإن JSON ناقص. ولا يُبلَّغ أبدًا عن جسم JSON مقطوع على أنه stop.
  • يُحتجز البثّ في استدعاء response_format إلى أن تتحقق جْبْ من الرد، ثم يُسلَّم (القسم 6.3). وتُبقي نبضات الاتصال الاتصال مفتوحًا في أثناء ذلك.
  • لا تعمل الأدوات المدمجة في جْبْ في استدعاء response_format.

5.4 إدخال الصور

يمكن أن تحمل رسائل المستخدم صورًا على هيئة أجزاء محتوى OpenAI. وتذهب الصور إلى نموذج الرؤية الخاص بجْبْ.

r = client.chat.completions.create(
    model="geb",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What is in this picture?"},
            {"type": "image_url", "image_url": {"url": "https://example.com/cat.jpg"}},
        ],
    }],
)
  • المصادر: عناوين https:// (تجلبها جْبْ) أو معرّفات data:image/{png,jpeg,webp,gif};base64,.... وتُرفض http:// والأنظمة الأخرى.
  • الصيغ: PNG وJPEG وWebP وGIF (الإطار الأول). ولا بد أن تطابق البايتات النوع المعلن.
  • الحدود: 16 صورة كحد أقصى لكل طلب، و20 MB لكل صورة، و64 MB من بيانات الصور المفكوكة لكل طلب. أرسل الصور الكبيرة كعناوين URL: فجسم الطلب كاملًا محدود بـ 32 MiB.
  • تُرفض العناوين التي تُحلّ إلى عناوين خاصة أو داخلية (image_url_forbidden).
  • تُعرض الصور في الطلب مع آخر رسالة للمستخدم، بالترتيب. والرسالة التي تحتوي صورة فقط صالحة. وتُرفض الأجزاء غير text وimage_url (الصوت، الملفات).
  • إذا كان نموذج الرؤية غير متاح في تلك اللحظة تحصل على 503 vision_unavailable، ولا تحصل أبدًا على تخمين نصي فقط. ويُبلغ GET /v2/models عن capabilities.vision: false في الحالة نفسها.

5.5 المحادثات

يمكنك إرسال السجل كاملًا مع كل طلب، كما في أي واجهة محادثة. ويمكن لجْبْ أيضًا تخزين السلسلة نيابةً عنك.

  • أرسل "conversation_id": "new". يعود المعرّف في الرد (conversation_id) وفي مقطع البثّ الأخير.
  • أرسل ذلك المعرّف في الاستدعاءات اللاحقة للمتابعة.
  • إذا كان طلبك يحتوي أي رسالة assistant أو tool فقد أرسلت السجل: تُستخدم رسائلك كما أُرسلت تمامًا. وإذا كان يحتوي رسائل system وuser فقط، تضيف جْبْ السلسلة المخزَّنة إلى الموجّه، بدءًا بأحدث الأدوار، بقدر ما يتسع في نافذة السياق. ويُخزَّن الدور الجديد في الحالتين.
  • السلسلة المخزَّنة ليست ذاكرة حساب. لا تقرؤها المحادثة أبدًا، ولا يستطيع أي حساب آخر قراءتها.
المسارالنتيجة
GET /v2/conversations?limit=50&after=<cursor>{"object":"list","data":[{"id","object":"conversation","created_at","last_message_at","title"}],"has_more","next_cursor"}، الأحدث أولًا.
GET /v2/conversations/{id}?limit=100&after=<cursor>المحادثة مع messages: [{"role","content","created_at"}] الأقدم أولًا، إضافة إلى message_count وhas_more وnext_cursor.
DELETE /v2/conversations/{id}{"id","object":"conversation.deleted","deleted":true}.

المعرّف الذي لا يخصك يردّ بـ 404. وتُحتسب هذه المسارات الثلاثة استدعاءات API على حصتك، مثل الإكمال؛ والاستدعاء الذي يفشل لا يستهلك استدعاءً.

curl https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" -H "Content-Type: application/json" \
  -d '{"conversation_id":"new","messages":[{"role":"user","content":"Remember: my shop sells dates."}]}'

5.6 قواعد الرد (`geb_acceptance`)

للأعمال التي ينبغي أن يستوفي فيها الرد قائمة تحقق، صرّح بالقواعد. تكتب جْبْ مسودة، وتتحقق، وتحسّن ما يفشل، وتعيد أفضل نسخة مع تقرير. ولا تُحتسب فحوص القواعد في الفوترة: يبقى الاستدعاء استدعاءً واحدًا.

{
  "messages": [{"role": "user", "content": "Write a 300 word product summary from the sources below. ..."}],
  "geb_acceptance": {
    "version": 1,
    "rules": [
      {"type": "word_range", "path": "", "min": 250, "max": 350},
      {"type": "forbidden_phrases", "paths": ["/**"], "phrases": ["world-class", "cutting-edge"]},
      {"type": "claims_grounded", "paths": ["/**"]}
    ],
    "on_fail": "return_best_with_report"
  }
}
  • أنواع القواعد: word_range وforbidden_phrases وno_repeated_paragraphs وcited_ids_named وmin_named_sources وclaims_grounded وno_copy_from وphrases_require_source. والمسار path هو JSON Pointer إلى الرد؛ وفي الرد النصي العادي استخدم "" أو /**.
  • يحمل الرد x_geb_acceptance: {"passed": true, "rounds": 1}، أو passed: false مع قائمة failures.
  • on_fail: "error_422" يحوّل الفشل النهائي إلى 422 geb_acceptance_failed بدلًا من ذلك.
  • العقد غير الصالح هو 400 invalid_geb_acceptance، حيث يسمّي param القاعدة ويبيّن rule_index موضعها.
  • يُحتجز البثّ الذي يحمل geb_acceptance حتى تنتهي الفحوص (القسم 6.3).

5.7 الترويسات في كل استجابة

الترويسةالمعنى
x-request-idمعرّف هذا الاستدعاء، في كل استجابة، ناجحة أو غير ناجحة. ويساوي error.request_id عند الخطأ. اذكره عند التواصل مع الدعم.
x-geb-api-version2 على البادئة /v2 وعلى البادئة /v1 معًا.
X-RateLimit-Limitحد الدقيقة، وهو 120 في كل باقة (القسم 10.2).
X-Quota-Limit-Month, X-Quota-Remaining-Month, X-Quota-Resetموقعك من حصة الاستدعاءات الشهرية (القسم 10.1).
x-geb-reasoning-effort, x-geb-reasoning-adjustedمستوى الاستدلال المستخدم (القسم 8.4).

6.البثّ

اضبط "stream": true. الرد من النوع text/event-stream: أحداث يرسلها الخادم، كل منها سطر data: <json> يليه سطر فارغ.

curl -N https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" -H "Content-Type: application/json" \
  -d '{"stream":true,"stream_options":{"include_usage":true},
       "messages":[{"role":"user","content":"Count to five in Arabic."}]}'

6.1 ترتيب الإطارات

  1. سطر تعليق من الحشو في البداية (تبدأ التعليقات بـ :)، وهو يفرّغ ما تحتجزه الوسطاء. تجاهله.
  2. أول chat.completion.chunk يحمل delta فيه role: "assistant".
  3. مقاطع المحتوى، يحمل كل منها نص delta.content.
  4. مقطع أخير فيه delta: {} وfinish_reason. ويحمل أيضًا conversation_id عند استخدامك المحادثات.
  5. إذا ضبطت stream_options.include_usage: مقطع واحد إضافي فيه "choices": [] وكائن usage.
  6. data: [DONE].
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"<model-id>","choices":[{"index":0,"delta":{"role":"assistant","content":"One"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"<model-id>","choices":[{"index":0,"delta":{"content":", two"},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"<model-id>","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"<model-id>","choices":[],"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}

data: [DONE]

المقاطع ذات المصفوفة choices الفارغة بيانات وصفية (الاستخدام، وامتدادات جْبْ مثل x_geb_acceptance وx_geb_partial). وعلى المحلّل الصارم أن يتخطاها عند قراءة النص. ولا تبثّ جْبْ نص استدلالها أبدًا.

6.2 نبضات الإبقاء

في أثناء تفكير جْبْ أو فحصها للرد يبقى الاتصال مفتوحًا وتكتب جْبْ سطر تعليق، : heartbeat، كل 15 ثانية تقريبًا. وكل محلّل SSE يتجاهل التعليقات. وإذا كتبت محلّلًا خاصًا بك فتخطَّ أي سطر يبدأ بـ :.

تتضمن ترويسات الرد في البثّ x-request-id وترويسات X-Quota-* الخاصة بك (القسم 10) وترويسات الاستدلال (القسم 8). وإذا أغلقت الاتصال تتوقف جْبْ عن التوليد.

6.3 البثّ المحتجز

مع response_format أو geb_acceptance تتحقق جْبْ من الرد قبل إرساله. يُفتح البثّ بالتعليق : geb is checking the reply before sending it، ثم أسطر : heartbeat فقط، ثم المحتوى بعد التحقق. وإذا احتجت إلى الرموز لحظة توليدها فلا ترسل أيًّا من الحقلين.

6.4 كيف ينتهي البثّ

ينتهي البثّ دائمًا بـ data: [DONE]، بإحدى ثلاث طرق.

  1. مكتمل. مقطع أخير فيه finish_reason هو stop (أو tool_calls)، ثم [DONE].
  2. رد جزئي. إذا توقف التوليد أو فشل بعد إرسال نص بالفعل، تنهي جْبْ البثّ بما أرسلته: مقطع وصفي {"choices":[],"x_geb_partial":{"reason":"stalled","code":"geb_dispatch_stalled","complete":false,"chars":123}}، ثم مقطع أخير فيه finish_reason: "length"، ثم [DONE]. اعتبره إجابة ناقصة. وتكون reason إحدى القيم stalled أو edge_deadline أو deadline أو upstream_error. ولا تُعرض الردود الجزئية إلا في الاستدعاءات النصية العادية؛ أما الاستدعاء الذي يحمل tools أو response_format فيحصل على إطار الخطأ أدناه بدلًا من ذلك.
  3. خطأ ضمن البثّ. إذا لم يُنتج شيء صالح للاستخدام، يأتي إطار data: {"error": {...}} يليه data: [DONE]. وكانت حالة HTTP قد أُرسلت 200 بالفعل، فلا يمكن أن يكون الخطأ حالة HTTP. وتُطلق حزم OpenAI SDK الرسمية خطأً عند رؤية هذا الإطار.

البثّ الذي يُغلق من دون [DONE] يعني أن الاتصال فُقد. اعتبره فشلًا وأعد المحاولة (استخدم Idempotency-Key، القسم 9.3).

المشكلات التي تستطيع جْبْ رؤيتها قبل أن تبدأ، مثل مفتاح خاطئ أو خطأ تحقق أو حصة مستنفدة، تعود بحالات خطأ HTTP حقيقية، لا بالحالة 200.

6.5 تحليل البثّ من دون SDK

import json, os, requests

r = requests.post(
    "https://api.gebai.ca/v2/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['GEB_API_KEY']}"},
    json={"stream": True, "messages": [{"role": "user", "content": "Hello"}]},
    stream=True,
)
r.raise_for_status()
done = False
for raw in r.iter_lines(decode_unicode=True):
    if not raw or raw.startswith(":"):
        continue                      # blank line or keepalive comment
    payload = raw[len("data:"):].strip()
    if payload == "[DONE]":
        done = True
        break
    frame = json.loads(payload)
    if "error" in frame:
        raise RuntimeError(frame["error"])
    for choice in frame.get("choices", []):
        print(choice["delta"].get("content") or "", end="")
if not done:
    raise RuntimeError("stream ended without [DONE]; retry")

6.6 الاستدعاءات المكتملة الطويلة

الاستدعاء غير المبثوث الذي ما زال يعمل بعد نحو 70 ثانية يتلقى ترويسات 200 مبكرًا، يتبعها حرف مسافة واحد كل 25 ثانية تقريبًا إلى أن يصل جسم JSON. والمسافة في البداية صالحة في JSON، فيقرأ JSON.parse وfetch().json() وPython requests وحزم OpenAI SDK الجسم دون تغيير. ويحمل الرد x-geb-keepalive: on عند حدوث ذلك.

إذا فشل الاستدعاء بعد إرسال تلك الترويسات تبقى الحالة 200 ويكون الجسم كائن الخطأ، لذا عند وجود x-geb-keepalive: on تحقق من وجود مفتاح error في المستوى الأعلى. أرسل ترويسة الطلب x-geb-keepalive: off لتعطيل ذلك وتحصل بدلًا منه على 504 geb_edge_deadline عند نحو 95 ثانية.

للتوليدات الطويلة، استخدم البثّ. فالرد المبثوث لا حد زمنيًا إجماليًا له ما دام يحرز تقدمًا.

7.استدعاءات الأدوات واستدعاء الدوال

هناك نوعان مختلفان من الأدوات. وهما مستقلان ويمكن إرسالهما معًا.

tools (دوالّك)geb_tools (الأدوات المدمجة في جْبْ)
دوالّ مندوالّك أنتدوالّ جْبْ: البحث في الويب والطقس والمستندات والشيفرة
من يشغّلهاأنتجْبْ
الآثار الجانبيةلا شيء من جهة جْبْحقيقية (مثل ملف مولَّد)
الافتراضيتُستخدم عند إرسالهامعطّلة

إذا أرسلت النوعين معًا، يُعرض على النموذج دوالّك، وأي استدعاءات يعيدها تتولى أنت تنفيذها، ولا يعمل مشغّل الأدوات الخاص بجْبْ في ذلك الدور.

7.1 دوالّك (`tools`)

تصف أنت دوالّك، وتقرر جْبْ متى تستدعي إحداها، وتشغّلها أنت وترسل النتيجة. هذا بروتوكول OpenAI القياسي، فتعمل حزم SDK دون تغيير.

curl https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "parallel_tool_calls": false,
    "messages": [{"role":"user","content":"What is the weather in Alexandria?"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Current weather for a city.",
        "parameters": {
          "type": "object",
          "properties": {"city": {"type": "string"}},
          "required": ["city"]
        }
      }
    }]
  }'

يردّ النموذج بـ finish_reason: "tool_calls" مع ضبط message.content على null:

{
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [{
        "id": "chatcmpl-tool-9d22d13b24ef97ed",
        "type": "function",
        "function": { "name": "get_weather", "arguments": "{\"city\": \"Alexandria\"}" }
      }]
    },
    "finish_reason": "tool_calls"
  }]
}

شغّل الدالة، ثم أرسل طلبًا ثانيًا يحتوي سجلّك، ودور المساعد كما استلمته تمامًا، ورسالة tool واحدة لكل استدعاء:

import json

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Current weather for a city.",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]
messages = [{"role": "user", "content": "What is the weather in Alexandria?"}]

first = client.chat.completions.create(
    model="geb", messages=messages, tools=tools, parallel_tool_calls=False
)
call = first.choices[0].message.tool_calls[0]
result = {"city": "Alexandria", "temp_c": 27, "sky": "clear"}   # your code runs here

messages.append(first.choices[0].message)
messages.append({
    "role": "tool",
    "tool_call_id": call.id,
    "name": call.function.name,
    "content": json.dumps(result),
})
final = client.chat.completions.create(model="geb", messages=messages, tools=tools)
print(final.choices[0].message.content)

القواعد:

  • ينبغي أن يكون tools[].type هو "function". ويطابق function.name النمط ^[a-zA-Z0-9_-]{1,64}$ ولا بد أن يكون فريدًا. وfunction.parameters كائن JSON Schema. بحد أقصى 128 أداة، و128 KiB بعد التسلسل.
  • function.arguments نص مرمَّز بـ JSON، في الاتجاهين. ولا بد أن تكون رسالة tool ذات content نصًا: سلسل نتيجتك بنفسك.
  • ردّ على كل استدعاء. إذا أصدر دور المساعد ثلاثة استدعاءات فأرسل ثلاث رسائل tool قبل الإكمال التالي. وإلا تحصل على 400 unanswered_tool_call يسمّي المعرّفات الناقصة. وهذا مقصود: فعند ترك الاستدعاء بلا نتيجة قد يختلق النموذج النتائج الناقصة.
  • tool_choice: عند عدم إرساله أو "auto" يقرر النموذج، و"none" يمنع الاستدعاءات، و"required" يفرض استدعاءً واحدًا على الأقل، و{"type":"function","function":{"name":"..."}} يسمح بتلك الدالة وحدها. ومع "required" أو دالة مسمّاة، إذا ردّ النموذج بنص عادي بدلًا من الاستدعاء، تطلب منه جْبْ مرة أخرى قبل الرد. وهذا يكلّف مرور نموذج إضافيًا من زمن الاستجابة، لا استدعاءً ثانيًا على حصتك. وإذا ظل النموذج يردّ بنص عادي، فتتلقى ذلك النص مع finish_reason: "stop"، لذا تحقق من finish_reason قبل أن تقرأ tool_calls. ومع الاختيار المسمّى تصفّي جْبْ الرد أيضًا على تلك الدالة. وإذا احتجت إلى أقوى ضمان فاستخدم "required" مع فهرس يحتوي دالة واحدة. وفي البثّ مع "required" أو دالة مسمّاة يُحتجز النص حتى ينتهي الدور ثم يُرسل، فيصل الرد النصي العادي معًا في النهاية.
  • أرسل "parallel_tool_calls": false ما لم تكن تريد عدة استدعاءات في الدور الواحد. فهو يعطي استدعاءً واحدًا نظيفًا بالضبط في كل دور.
  • تزيل جْبْ الاستدعاءات المكررة المتطابقة بايتًا ببايت، وتُسقط الاستدعاء الأخير إذا قُطع بسبب length. وتُمرَّر الوسائط فيما عدا ذلك كما هي حرفيًا، بما فيها الوسائط غير الصالحة بصفتها JSON، فتحقق منها قبل الاستخدام.
  • البثّ مدعوم. تصل استدعاءات الأدوات بإطارات delta.tool_calls القياسية (إطار افتتاحي فيه id وname، ثم أجزاء arguments، تُجمَّع حسب index). وتصل معًا في نهاية الدور، لا متداخلة مع التوليد. والناتج المجمَّع مطابق لبثّ OpenAI.
  • رحلة الأداة ذهابًا وإيابًا طلبان، ويُحتسب كل منهما استدعاءً.

7.2 الأدوات المدمجة في جْبْ (`geb_tools`)

افتراضيًا يكون استدعاء API استدعاءً عاديًا للنموذج: توليد واحد، بلا أدوات، وبلا آثار جانبية. وفعّل الأدوات عبر geb_tools.

القيمةالسلوك
غائبة، false، []لا أدوات من جْبْ. هذا هو الافتراضي.
trueكل أداة من جْبْ متاحة الآن. ويقرر النموذج متى يستخدمها.
["web_search", "weather_forecast"]الأدوات المسمّاة فقط. يُعرض على النموذج هذه الأدوات بالضبط، ويُرفض استدعاء أي أداة أخرى.
curl https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role":"user","content":"What did the ECB decide at its last meeting?"}],
    "geb_tools": ["web_search"]
  }'

أسماء الأدوات العامة (القائمة الحية لاستدعائك هي geb_tools في GET /v2/models):

الاسمما تفعله
web_searchبحث في الويب: عناوين وروابط ومقتطفات.
web_grounded_searchبحث في الويب يقرأ أيضًا أهم الصفحات، لإجابات موثَّقة بمراجع.
url_fetchيجلب عنوان URL واحدًا ويقرؤه.
polinex_newsأخبار حديثة من تغذية Polinex للدول التي تغطيها.
weather_forecastالأحوال الحالية والتوقعات لمكان ما.
currency_convertتحويل العملات الحي.
wikipedia_summaryملخص مقالة من Wikipedia.
places_searchالأماكن والأعمال التجارية قرب موقع.
geocodeمن العنوان إلى الإحداثيات والعكس.
directionsمسار بين أماكن.
distance_matrixالمسافة وزمن السفر بين عدة نقاط.
static_mapصورة خريطة لموقع.
code_executeيشغّل Python في بيئة معزولة. وتُعاد الملفات التي يكتبها كروابط.
generate_text_fileينتج ملفًا نصيًا (md وcsv وjson وhtml وغيرها) ويعيد رابط تنزيل.
build_documentينشئ مستند Word (.docx) ويعيد رابط تنزيل.
build_workbookينشئ مصنّف Excel (.xlsx) ويعيد رابط تنزيل.
build_slidesينشئ عرض PowerPoint (.pptx) ويعيد رابط تنزيل.
  • الاسم الذي لا تعرفه جْبْ، أو المعطّل، يعيد 400 invalid_geb_tools مع قائمة الأسماء الصالحة في error.valid_geb_tools. بحد أقصى 32 اسمًا.
  • مع القائمة يُفرض التقييد مرتين: لا يرى النموذج إلا الأدوات المسمّاة، ولا يُنفَّذ أي استدعاء لأداة أخرى (يتلقى النموذج خطأ أداة ويكمل رده دونها).
  • الأدوات الثلاث build_* منفصلة عمدًا. فتسمية build_document تسمح بملف Word فقط.
  • يبدأ بناء المستندات من نص تعليمتك أنت، لا من كلمات صيغ الملفات داخل محتوى لصقته. فإذا كان الذكر الوحيد لـ «xlsx» أو «slides» داخل كتلة شيفرة أو نص ملصوق طويل، فإن جْبْ تردّ نصًا.
  • قد تستغرق الأدوات وقتًا أطول من الإكمال العادي. وتُخزَّن الملفات التي تنتجها الأدوات تحت حسابك وتُعاد كروابط محدودة المدة.
  • ذاكرة حسابك وسجل محادثاتك والموصّلات (Google وMicrosoft وDropbox وغيرها) وأدوات الحساب الأخرى غير متاحة على الواجهة.

8.الاستدلال

تفكر جْبْ دائمًا قبل أن تردّ. وأنت تختار مقدار الجهد. لا تعيد جْبْ نص استدلالها؛ تتلقى الإجابة، وتُحتسب رموز التفكير ضمن usage.completion_tokens.

8.1 المستويات

المستوىالمعنى
lowأقصر تفكير.
mediumالافتراضي للأسئلة الأصعب.
highتفكير طويل. يقابل أعلى إعداد في النموذج.
ultraأعلى إعداد في النموذج.

يعرض GET /v2/models المستويات (reasoning.efforts) وافتراضي الخادم (reasoning.default_effort).

8.2 معنى «إيقاف الاستدلال»

لا يُوقَف التفكير أبدًا. كل صيغ «الإيقاف» ("off" و"none" وfalse و"disabled" و0) تُبقي التفكير مفعّلًا مع ميزانية تفكير قدرها صفر رمز: يغلق النموذج استدلاله فورًا ويبدأ الإجابة. فتحصل على إجابة عادية بلا خطوة استدلال. استخدمه للطلبات البسيطة الحساسة لزمن الاستجابة. وللمسائل الصعبة فضّل medium أو high.

8.3 كيف تطلب

استخدم أي صيغة يرسلها عميلك أصلًا. لا يُرفض أي منها أبدًا.

المعاملأمثلة
reasoning"high", "off", "on", {"effort": "medium"}
reasoning_effort"low", "medium", "high", "ultra", "minimal", "none", "xhigh"
thinking{"type": "enabled", "budget_tokens": 3000}, {"type": "disabled"}, true
enable_thinkingtrue, false
chat_template_kwargs{"enable_thinking": false}, {"reasoning_effort": "high"}
extra_body{"reasoning_effort": "medium"}، للعملاء الذين يرسلون extra_body حرفيًا

التحويلات: minimal تصبح low. وxhigh وmax وmaximum تصبح ultra. وقيمة budget_tokens تُحوَّل إلى أقرب مستوى (حتى 1024 هي low، وحتى 2048 هي medium، وحتى 4096 هي high، وما فوق ذلك ultra). والمستوى المجهول (مثل "turbo") يستخدم افتراضي الخادم.

إذا أرسلت عدة صيغ متعارضة، فتفوز أول صيغة في هذه القائمة تسمّي مستوى: reasoning وreasoning_effort وthinking وenable_thinking وchat_template_kwargs وextra_body. والصيغة التي تفعّل التفكير فقط لا تتجاوز أبدًا مستوى مسمًّى في موضع آخر.

curl https://api.gebai.ca/v2/chat/completions \
  -H "Authorization: Bearer $GEB_API_KEY" -H "Content-Type: application/json" \
  -d '{"reasoning_effort":"high","messages":[{"role":"user","content":"Plan a 3-city sales route to minimise travel."}]}' -i

8.4 ما يعود إليك

ترويسة الردالقيمة
x-geb-reasoning-effortالمستوى المستخدم، أو default عندما لا ترسل شيئًا.
x-geb-reasoning-adjustedتظهر عندما حُوّلت قيمة أو تُجوهلت، مثل enable_thinking=false->budget 0 (thinking stays on; think block closed).

8.5 max_tokens والتفكير

max_tokens هو السقف على الإجابة المرئية. وتُحتسب ميزانية التفكير بشكل منفصل فوقه، فلا يُضعف max_tokens الصغير الاستدلال، ولا تضرب جْبْ رقمك أبدًا. وإذا بلغت الإجابة السقف قُطعت عنده وكانت finish_reason هي length. وإذا لم تضبط max_tokens اشتُقّت ميزانية الإجابة من نافذة السياق. ويشمل usage.completion_tokens رموز التفكير.

9.الأخطاء وإعادة المحاولة

9.1 الغلاف

كل رد خطأ من مسار /v2 (ومن اسمه البديل /v1) هو JSON بشكل واحد:

{
  "error": {
    "message": "A human-readable explanation.",
    "type": "invalid_request_error",
    "param": "messages",
    "code": "invalid_json_body",
    "request_id": "0f658b6d9742d46fec9ce4b984f99667"
  }
}
  • type هو فئة الخطأ. تفرّع على type وcode، لا على صياغة message أبدًا.
  • param يسمّي الحقل المخالف عندما يكون هناك حقل مسؤول، وإلا فهو null.
  • code سبب أكثر تحديدًا مقروء آليًا، أو null.
  • request_id موجود دائمًا ويُرسل أيضًا كترويسة الرد x-request-id. ويحمل كل رد x-request-id، ومنها الردود الناجحة. اذكره عند التواصل مع الدعم. يمكنك إرسال x-request-id خاص بك إن شئت؛ وقد تعيد جْبْ مع ذلك معرّف التتبع الخاص بها.
  • تضيف بعض الأخطاء retry_after_ms في المستوى الأعلى بجانب error، وRetry-After كترويسة (بالثواني).
  • الإخفاقات بعد بدء البثّ تصل ضمن البثّ (القسم 6.4). والإخفاقات بعد بدء استدعاء مكتمل طويل تصل كجسم 200 فيه مفتاح error (القسم 6.6).
  • الطلب إلى مسار غير موجود يعيد 404 عاديًا بصيغة {"message", "error", "statusCode"}، لا هذا الغلاف. وإذا رأيته فتحقق من العنوان.

9.2 الفهرس

HTTPtypecodeالمعنى وما ينبغي فعله
400invalid_request_errornullفشل تحقق: خاصية مجهولة، أو نوع خاطئ، أو messages فارغة، أو حقل غير مدعوم (n وlogprobs وfunctions)، أو رسالة أكبر من اللازم. أصلح الطلب.
400invalid_request_errorinvalid_json_bodyالجسم ليس JSON صارمًا.
400invalid_request_errorinvalid_content_encodingالجسم ليس gzip أو deflate صالحًا بالنسبة إلى Content-Encoding.
400invalid_request_errorinvalid_geb_toolsقيمة geb_tools خاطئة. يسرد error.valid_geb_tools الأسماء المقبولة.
400invalid_request_errorinvalid_geb_acceptanceقيمة geb_acceptance خاطئة. يحدد param وrule_index موضع القاعدة.
400invalid_request_errormemory_unavailable, invalid_geb_memorygeb_memory: true، أو قيمة غير منطقية. لا ذاكرة في استدعاءات API.
400invalid_request_errorunsupported_tool_choice_mode, unknown_tool, duplicate_tool_name, too_many_tools, tools_too_large, invalid_type, invalid_value, missing_required_parameterمشكلة في tools أو tool_choice. يشير param إلى المسار، مثل tools[2].function.name.
400invalid_request_errorunknown_tool_call_id, unanswered_tool_callرسالة tool لا تطابق استدعاءً سابقًا، أو استدعاء بلا نتيجة.
400invalid_request_errorinvalid_content, unsupported_content_part, invalid_image_url, unsupported_image_type, invalid_image, too_many_images, image_too_large, images_too_large, image_url_forbidden, image_fetch_failed, image_fetch_timeoutمشكلة في صورة أو جزء محتوى (القسم 5.4).
401invalid_api_keynullمفتاح مفقود أو مشوَّه أو مجهول أو ملغى أو منتهي. لا تعد المحاولة.
403permission_errornullالمفتاح صالح لكن الحساب غير مسموح له باستخدام الواجهة. لا تعد المحاولة.
404not_found_errornullمعرّف نموذج مجهول عند الاسترجاع، أو محادثة لا تخصك.
409idempotency_key_reuse, idempotent_request_in_progressالاسم نفسه الذي في typeIdempotency-Key نفسه مع جسم مختلف، أو أن الاستدعاء الأول ما زال يعمل (القسم 9.3).
413invalid_request_errorrequest_too_largeالجسم بعد فك الضغط يتجاوز حد 32 MiB.
415invalid_request_errorunsupported_content_encodingContent-Encoding غير gzip أو deflate.
422invalid_request_errorgeb_acceptance_failedon_fail: "error_422" وما زال الرد يخالف قواعدك. لا يُحتسب على حصتك.
429rate_limit_exceedednullحد الاندفاع في الدقيقة. انتظر Retry-After ثانية.
429rate_limit_errorgeb_concurrency_limitعدد كبير من الطلبات الجارية في وقت واحد لحسابك. انتظر Retry-After، أو انتظر انتهاء أحدها.
429quota_exceedednullاستُنفدت حصة الاستدعاءات الشهرية. الحل الوحيد هو انتظار إعادة الضبط، أو تغيير الباقة.
502server_errorempty_answerأنهى النموذج دون إجابة. أعد المحاولة فورًا، فالطلب نفسه ينجح عادة. وقيمة retry_after_ms هي 0.
503server_busynull أو maintenanceجْبْ مشغولة أو غير متاحة لوقت قصير. انتظر Retry-After (نحو 5 ثوانٍ عند الانشغال، وحتى 120 عند الصيانة).
503server_errorvision_unavailableنموذج الرؤية غير متاح الآن. أعد المحاولة لاحقًا أو أرسل بلا صور.
503server_errordegenerate_outputقُطع الرد لأسباب تتعلق بالجودة ولم تتوفر إعادة محاولة نظيفة. أعد المحاولة.
503server_errorgeb_instance_shutdownنسخة الخادم قيد إعادة التشغيل. أعد المحاولة فورًا.
504server_errorgeb_edge_deadline, geb_dispatch_stalled, geb_dispatch_deadlineاستغرق الطلب وقتًا طويلًا أو لم يحرز تقدمًا. أعد المحاولة مع "stream": true.
5xxserver_errornullأي حالة أخرى. الرسالة عامة عمدًا. أعد المحاولة مع تراجع تدريجي، واذكر request_id إذا استمرت المشكلة.

في البثّ تصل الأخطاء نفسها كإطار الخطأ ضمن البثّ، إضافة إلى geb_incomplete_stream (انتهى التوليد قبل اكتماله؛ أعد المحاولة).

9.3 إرشادات إعادة المحاولة

  • لا تعد المحاولة أبدًا مع 400 و401 و403 و404 و409 idempotency_key_reuse و413 و415 و422. فلا بد من تغيير الطلب.
  • أعد المحاولة بعد الانتظار مع 429 rate_limit_exceeded وgeb_concurrency_limit (استخدم Retry-After)، و503 server_busy.
  • لا تُلحّ على 429 quota_exceeded. اقرأ reset_at في الجسم أو X-Quota-Reset، وتوقف حتى ذلك الحين.
  • أعد المحاولة فورًا، مرة أو مرتين مع 502 empty_answer و503 geb_instance_shutdown.
  • انتقل إلى البثّ ثم أعد المحاولة مع 504.
  • أضف تراجعًا أسيًّا مع تشويش عشوائي لسائر حالات 5xx، بحد أقصى بضع محاولات.
  • أرسل دائمًا Idempotency-Key في الاستدعاءات التي قد تعيد محاولتها. وهو أي نص حتى 255 حرفًا، فريد لكل طلب منطقي. يعمل الاستدعاء الأول عادةً. والتكرار بالمفتاح نفسه والجسم نفسه يعيد الإجابة المخزَّنة (Idempotency-Replayed: true)، دون توليد جديد ودون استهلاك حصة، لمدة 24 ساعة. وللإعادة المحتوى والحقول والقيم نفسها كما في الإجابة الأولى؛ وقد يختلف ترتيب الحقول داخل كائن JSON، لذا قارن JSON بعد تحليله، لا البايتات. والمفتاح نفسه مع جسم مختلف هو 409 idempotency_key_reuse. والتكرار والاستدعاء الأول ما زال يعمل هو 409 idempotent_request_in_progress: انتظر ولا تدُر في حلقة. والبثّ الذي فشل في منتصفه لا يُخزَّن، فتعمل إعادة المحاولة من جديد. وتذكر ترويسة Idempotency-Status إحدى القيم stored أو replayed أو disabled.
  • اضبط مهلة عميلك بسخاء، أو استخدم البثّ. ترسل حزم OpenAI SDK مهلتها كترويسة، وتعيد جْبْ أفضل إجابة جزئية (finish_reason: "length"، x_geb_partial) بدلًا من لا شيء عندما تقترب مهلتك أنت.

ينتهي كل استدعاء بواحد من ثلاثة أشياء: الإجابة، أو إجابة جزئية موسومة بـ finish_reason: "length" مع x_geb_partial، أو خطأ منظَّم. وهكذا تبدو الإجابة الجزئية غير المبثوثة:

{
  "choices": [{"index": 0, "message": {"role": "assistant", "content": "..."}, "finish_reason": "length"}],
  "x_geb_partial": {"reason": "stalled", "code": "geb_dispatch_stalled", "complete": false, "chars": 812}
}

9.4 مساعد إعادة المحاولة

import os, random, time, uuid, requests

URL = "https://api.gebai.ca/v2/chat/completions"
HEADERS = {"Authorization": f"Bearer {os.environ['GEB_API_KEY']}"}

def complete(body, attempts=5):
    key = str(uuid.uuid4())                       # same key on every attempt
    for n in range(attempts):
        r = requests.post(URL, json=body, headers={**HEADERS, "Idempotency-Key": key}, timeout=620)
        if r.ok:
            data = r.json()
            if "error" in data:                   # error after a keepalive commit
                raise RuntimeError(data["error"])
            return data
        err = r.json().get("error", {})
        code, kind = err.get("code"), err.get("type")
        if r.status_code in (400, 401, 403, 404, 413, 415, 422) or kind == "quota_exceeded":
            raise RuntimeError(f"{r.status_code} {kind}/{code}: {err.get('message')} ({err.get('request_id')})")
        if code in ("empty_answer", "geb_instance_shutdown"):
            wait = 0
        elif r.status_code == 504:
            raise RuntimeError("timed out: retry with stream=True")
        else:
            wait = float(r.headers.get("Retry-After", 2 ** n)) + random.random()
        time.sleep(wait)
    raise RuntimeError("gave up after retries")

10.الحدود والحصص

10.1 الحصة الشهرية للاستدعاءات

كل باقة تتضمن الواجهة، ومنها المجانية، بعدد من استدعاءات API في كل فترة فوترة. لا تُحتسب الرموز ولا توجد رسوم لكل رمز.

الباقةالاستدعاءات في الفترة
المجانية500
الأساسية1,500
المحترف10,000
الأستاذ100,000
المطوّرغير محدودة
  • الفترة هي فترة فوترة اشتراكك، أو الشهر التقويمي (UTC) إن لم يكن لديك اشتراك.
  • الاستدعاءات الناجحة فقط تُحتسب. والاستدعاء الذي يفشل لا يستهلك حصة. وإعادة الرد المخزَّن من Idempotency-Key لا تستهلك حصة. وتُحتسب مسارات المحادثات استدعاءات. ورحلة الأداة ذهابًا وإيابًا استدعاءان.
  • عند تجاوز الحصة تردّ الواجهة بـ 429 quota_exceeded مع التفاصيل:
{
  "error": {
    "type": "quota_exceeded",
    "message": "Monthly API request quota reached: your Free plan includes 500 calls per billing period and 500 have been used. The quota resets at 2026-11-01T00:00:00.000Z.",
    "tier": "free",
    "limit": 500,
    "used": 500,
    "remaining": 0,
    "reset_at": "2026-11-01T00:00:00.000Z",
    "request_id": "..."
  }
}

يحمل كل رد ناجح موقعك في الترويسات: X-Quota-Limit-Month وX-Quota-Remaining-Month وX-Quota-Reset. ويحملها أيضًا 429 الخاص بالحصة، مع ضبط Retry-After على الثواني حتى إعادة الضبط.

curl -s -D - -o /dev/null https://api.gebai.ca/v2/models -H "Authorization: Bearer $GEB_API_KEY" | grep -i "x-quota\|x-ratelimit"

10.2 حدود المعدّل

الحدالقيمة
الطلبات في الدقيقة (اندفاع)، لكل حساب120 في كل باقة: المجانية والأساسية والمحترف والأستاذ والمطوّر. تُحتسب عبر جميع مفاتيح الحساب.
الطلبات المتزامنة، لكل حسابحصة عادلة من السعة المتاحة في تلك اللحظة. وعند تجاوزها: 429 geb_concurrency_limit.

يُقاس استخدام API بعدد الاستدعاءات الشهري (القسم 10.1). وحد الدقيقة موجود فقط لمنع الاندفاعات وإساءة الاستخدام، لذلك هو نفسه في كل باقة. ويُرسل كـ X-RateLimit-Limit. ويحمل 429 الخاص بالاندفاع Retry-After. وزّع الاندفاعات، أو استخدم البثّ بطلبات أقل وأطول.

10.3 حدود الطلب

الحدالقيمة
جسم الطلب32 MiB بعد فك الضغط. gzip وdeflate مقبولان.
الرسائل وحجم الرسالةمحدودة بنافذة سياق النموذج (context_window في GET /v2/models). وتجاوز الحد هو 400 يسمّيه.
الصور16 لكل طلب، و20 MB لكل صورة، و64 MB مفكوكة في المجموع.
أدواتك (tools)128 دالة، و128 KiB بعد التسلسل.
geb_tools32 اسمًا.
Idempotency-Key255 حرفًا، تُحفظ 24 ساعة.
المفاتيح النشطة لكل حساب10.
المحادثات المخزَّنةبلا حد، وتُحفظ حتى تحذفها.

10.4 الزمن

لا حد زمنيًا إجماليًا للبثّ ما دام النموذج يحرز تقدمًا. والاستدعاء غير المبثوث يُبقى حيًّا بعد مهلة الحافة (القسم 6.6). والاستدعاء الذي لا يحرز تقدمًا لوقت طويل جدًا ينتهي بإجابة جزئية أو 504 بدلًا من أن يعلق.

11.التوافق مع OpenAI SDK

تعمل حزمتا OpenAI لـ Python وJavaScript بتغييرين: عنوان الأساس والمفتاح.

from openai import OpenAI
client = OpenAI(base_url="https://api.gebai.ca/v2", api_key="geb_live_...")
# Anything that reads the standard environment variables also works:
export OPENAI_BASE_URL="https://api.gebai.ca/v2"
export OPENAI_API_KEY="geb_live_..."

ما يعمل بالطريقة نفسها: chat.completions.create (مكتملًا ومبثوثًا) وmodels.list وmodels.retrieve واستدعاء الدوال وresponse_format وstream_options.include_usage وأجزاء محتوى الصور وأخطاء بصيغة OpenAI مع Retry-After.

فروق ينبغي التخطيط لها:

  • إكمال المحادثة فقط. الاستدعاءات إلى التضمينات أو الصوت أو الصور أو الملفات أو الدُّفعات أو واجهة Responses غير موجودة.
  • الحقول المجهولة تعيد 400. مرّر فقط الحقول المذكورة في القسم 5.2. وعلى وجه الخصوص استخدم max_tokens لا max_completion_tokens، ولا ترسل store أو metadata.
  • حقول جْبْ الخاصة (geb_tools وgeb_acceptance وconversation_id وlocale) تمرّ عبر extra_body في Python (تدمجه الحزمة في جسم الطلب). وفي JavaScript مرّرها كخصائص إضافية.
  • حقول أخذ العينات متجاهلة. temperature وtop_p وstop وseed والعقوبات مقبولة وبلا أثر.
  • نموذج واحد. لا يختار model شيئًا. استخدم client.models.list() لترى ما يُقدَّم.
  • مستويات الاستدلال. يقبل reasoning_effort القيم low وmedium وhigh، وكذلك ultra (أرسله عبر extra_body إذا كانت نسخة الحزمة لديك تحدد نوع الحقل).
  • الاستخدام من جهة الخادم. لا تستدعِ الواجهة من متصفح على نطاقك الخاص.
  • حقول إضافية في الرد. قد تحمل الردود حقول جْبْ مثل conversation_id وx_geb_*. وهي إضافية فقط.
  • إعادة المحاولة. تعيد الحزم المحاولة تلقائيًا عند 429 و5xx. أضف Idempotency-Key عبر extra_headers حتى لا يُشغَّل الاستدعاء المعاد ولا يُحتسب مرتين:
client.chat.completions.create(
    model="geb",
    messages=[{"role": "user", "content": "Hello"}],
    extra_headers={"Idempotency-Key": "order-7421-reply-1"},
)

12.التعامل مع البيانات

  • لا ذاكرة حساب. لا تقرأ استدعاءات API من ذاكرة حساب جْبْ الخاص بك ولا تكتب إليها. وهذا يسري على كل مفتاح وكل باقة.
  • المحادثات المخزَّنة لا توجد إلا إذا استخدمت conversation_id. وهي منفصلة عن الذاكرة، ولا يقرؤها إلا حسابك، وتُحذف عند حذفك المحادثة.
  • سجلات API. يُسجَّل كل استدعاء لأغراض التشغيل والدعم ومنع إساءة الاستخدام: محتوى الطلب والرد، والنموذج، والمعاملات، وأعداد الرموز، وزمن الاستجابة، والحالة، ووكيل المستخدم، ومعرّف المفتاح، وبلد المتصل. وتُحجب بيانات الاعتماد والأسرار الموجودة في المحتوى (المفاتيح والرموز وكلمات المرور والروابط الموقَّعة) قبل التخزين. وتُخزَّن الصور المضمَّنة بحجمها وبصمتها فقط. كما تظهر نسخة من كل استدعاء لك، ويمكنك حذفها، ضمن بياناتك في تطبيق جْبْ. ويُحتفظ بالسجل التشغيلي طوال عمر الحساب ويُحذف عند حذف الحساب. ولا تُستخدم سجلات API أبدًا كذاكرة.
  • الأدوات والملفات المولَّدة تُخزَّن تحت حسابك وتُعاد كروابط محدودة المدة.

لا ترسل بيانات لا يُسمح لك بإرسالها إلى خدمة طرف ثالث. وإذا احتجت إلى اتفاقية معالجة بيانات فتواصل مع جْبْ قبل الإطلاق.

13.الإصدار والدعم

واجهة جْبْ API v2. تُقدَّم على https://api.gebai.ca/v2، مع بقاء /v1 اسمًا بديلًا للعملاء الحاليين. مراجعة الدليل 1.1، 28 أكتوبر 2026.

يصف هذا الدليل سلوك الواجهة الحية في ذلك التاريخ. وقد تُعتمد الحقول المعلَّمة بأنها متجاهلة لاحقًا؛ وقد تظهر حقول اختيارية جديدة في الردود. عامل الحقول المجهولة في الرد على أنها إضافية.

عندما تحتاج إلى مساعدة فأرفق request_id من جسم الخطأ (أو ترويسة x-request-id)، ووقت الاستدعاء، وشكل الطلب دون المفتاح. وتواصل مع جْبْ عبر https://gebai.ca/contact.