إن واجهة برمجة تطبيقات ChatGPT (API) تتطور بسرعة، وتخرق العقود في كثير من الأحيان، وتُحاسبك على كل رمز مميز حتى لو كانت اختباراتك خاطئة. تفشل الاستجابات المتدفقة (Streaming responses) بشكل مختلف عن الاستجابات غير المتدفقة. تضيف استدعاءات الوظائف (Function calling) طبقة JSON-schema لا تتطابق دائمًا مع ما يُرجعه النموذج. تظهر قيود المعدل (Rate limits) بصمت في الإنتاج وليس في لوحة تحكم المطور لديك. إذا قمت بتصحيح كل هذا في Python REPL أو حلقة curl، فإنك تهدر المال والوقت.
يشرح هذا الدليل سير عمل اختبار واجهة برمجة تطبيقات ChatGPT بالكامل داخل Apidog: المصادقة، وإكمال الدردشة الأول، وتدفق SSE، واستدعاء الوظائف، ومعالجة الأخطاء، وفحص قيود المعدل، والاستجابات الوهمية للعمل المتوازي للواجهة الأمامية. بحلول النهاية، سيكون لديك مشروع Apidog قابل لإعادة الاستخدام يكتشف انحرافات عقود OpenAI قبل أن تصل إلى الإنتاج.
ملخص
- أضف عنوان URL الأساسي لـ ChatGPT
https://api.openai.com/v1كبيئة في Apidog، وقم بتخزين مفتاح API كمتغير سري، وطبق مصادقة Bearer على مستوى المجلد. - قم ببناء طلب
/chat/completionsمرة واحدة، واحفظه، وأعد استخدامه لكل نموذج (GPT-5.5، GPT-5.5 Pro، GPT-4o، o3). - يتعامل Apidog مع تدفق SSE بشكل أصلي، لذا سترى المخرجات رمزًا تلو الآخر في لوحة الاستجابة دون أي أدوات إضافية.
- استدعاء الوظائف هو مجرد مصفوفة
toolsفي نص الطلب؛ يتحقق Apidog من صحة JSON لـtool_callsالمُرجع مقابل المخطط الخاص بك. - قم بإنشاء نموذج وهمي (Mock) لـ ChatGPT داخل Apidog عندما تكون واجهتك الأمامية جاهزة وقبل استنفاذ ميزانية مفتاح OpenAI الخاص بك.
- احفظ الطلب العامل كسيناريو اختبار مع تأكيدات على رمز الحالة، و
choices[0].message.content، وusage.total_tokens. قم بتشغيله في CI قبل كل تغيير في المطالبة (prompt).
لماذا يجب اختبار واجهة برمجة تطبيقات ChatGPT على الإطلاق؟
تبدو واجهة برمجة تطبيقات OpenAI مستقرة. لكنها ليست كذلك. بين يناير 2024 والآن، قام الفريق بإطلاق أو تغيير ما يلي:
- من
function_callإلىtool_calls(لا يزال شكلان متنافسان موجودين في الواقع) - الوضع الصارم لمخططات الأدوات (Strict mode for tool schemas)
- نماذج الاستدلال (
o1,o3) التي تتخلى عن مفاتيحtemperatureوtop_p response_format: { type: "json_schema" }مع إصدارات- سلوك التدفق لاستدعاءات الأدوات (تأتي التغييرات الجزئية (deltas) على أجزاء، وعليك تجميعها)
- نقطة نهاية جديدة
/v1/responsesتتداخل مع/v1/chat/completions
إذا قمت بربط أي من هذا مباشرة بتطبيقك وتجاوزت طبقة الاختبار، فإن طلب سحب (PR) تغيير المطالبة التالي سيؤدي إلى تراجع (regression) لن تراه إلا عندما يشتكي المستخدمون. مجموعة طلبات في Apidog تمنحك عقدًا تتحكم فيه. يمكنك إعادة تشغيل الطلب بالضبط، ومقارنة الاستجابة، والفشل بصوت عالٍ عندما يتغير الشكل.
الخطوة 1: إضافة OpenAI كبيئة في Apidog
افتح Apidog وأنشئ مشروعًا جديدًا. داخل المشروع، افتح إدارة البيئات (القائمة المنسدلة في أعلى اليمين) وأضف بيئة تسمى OpenAI Prod:
| المتغير (Variable) | القيمة (Value) |
|---|---|
baseUrl |
https://api.openai.com/v1 |
OPENAI_API_KEY |
sk-proj-... (احفظه كسرّ) |
defaultModel |
gpt-5.5 |
اجعل OPENAI_API_KEY سريًا حتى يتم إخفاؤه في مساحات العمل المشتركة ولا تتم كتابته أبدًا في المجموعات المُصدّرة. يخزن Apidog الأسرار لكل مستخدم، لذلك سيرى زميل في الفريق يسحب المشروع اسم المتغير ولكنه سيوفر مفتاحه الخاص.
الخطوة 2: تعيين مصادقة Bearer على مستوى المجلد
أنشئ مجلدًا يسمى ChatGPT داخل المشروع. افتح إعدادات المجلد، اذهب إلى المصادقة (Auth)، اختر Bearer Token، والصق {{OPENAI_API_KEY}}. يرث كل طلب داخل المجلد هذا الرأس. تتوقف عن لصق Authorization: Bearer sk-... في كل طلب، ويصبح تدوير المفتاح تعديلًا واحدًا.
هذه هي التفاصيل الصغيرة التي تجعل Apidog أسرع من سير عمل curl الخام: المصادقة موجودة في مكان واحد، وتبقى نصوص الطلبات نظيفة.
الخطوة 3: بناء أول طلب إكمال دردشة
داخل مجلد ChatGPT، أنشئ طلبًا جديدًا:
- الطريقة (Method):
POST - الرابط (URL):
{{baseUrl}}/chat/completions - النص (Body) (JSON):
{
"model": "{{defaultModel}}",
"messages": [
{ "role": "system", "content": "You are a senior backend engineer. Answer in under 100 words." },
{ "role": "user", "content": "What's the difference between idempotent and safe HTTP methods?" }
],
"temperature": 0.2
}
اضغط على إرسال (Send). يجب أن تحصل على 200 مع حقل choices[0].message.content يحمل الإجابة وكتلة usage تحتوي على عدد الرموز. احفظ الطلب باسم chat-completion-basic.
إذا حصلت على 401، فإن مفتاحك لم يتم تحميله. تحقق من أن القائمة المنسدلة للبيئة في أعلى اليمين مضبوطة على OpenAI Prod. إذا حصلت على 429، فقد وصلت إلى حد المعدل، وهو ما تغطيه الخطوة التالية.
الخطوة 4: اختبار الاستجابات المتدفقة (SSE)
التدفق هو المكان الذي تفشل فيه معظم عمليات دمج ChatGPT. الاستجابة هي text/event-stream، وليست JSON، وكل جزء هو سطر data: {...} مع delta جزئي. يتحدث Apidog SSE بشكل أصلي.
انسخ chat-completion-basic، وأعد تسميته إلى chat-completion-stream، وأضف "stream": true إلى النص:
{
"model": "{{defaultModel}}",
"stream": true,
"messages": [
{ "role": "user", "content": "Stream the first 100 prime numbers, comma-separated." }
]
}
اضغط على إرسال. ستتحول لوحة الاستجابة إلى عرض التدفق وستعرض كل جزء data: فور وصوله. سترى إطارات SSE الفعلية، وليس فقط النص المجمع. هذا هو العرض الذي تحتاجه عند تصحيح خطأ في دلتا مشوهة أو Terminator [DONE] مفقود.
ما يجب الانتباه إليه:
- الإطار الأخير هو السلسلة الحرفية
data: [DONE]. إذا لم يتعامل عميلك مع ذلك، فسيؤدي إلى خطأ في تحليل JSON. - لا توجد
usageفي الاستجابات المتدفقة إلا إذا مررت"stream_options": { "include_usage": true }. أضفها إذا كانت خطة الفوترة الخاصة بك تعتمد على عدد الرموز لكل مكالمة. - تصل دلتا استدعاء الأدوات (Tool-call deltas) على أجزاء:
index، ثمid، ثمfunction.name، ثمfunction.argumentsمجمعة حرفًا بحرف. اختبر هذا بشكل صريح.
الخطوة 5: اختبار استدعاء الوظائف واستخدام الأدوات
يعد استدعاء الوظائف (Function calling) هو المكان الأكثر شيوعًا حيث تؤدي تغييرات المطالبات إلى كسر الكود السفلي (downstream code) بصمت. يُرجع النموذج مصفوفة tool_calls؛ وظيفتك هي التحقق من صحة تحليل الوسائط وفقًا لمخطط JSON الذي قمت بتسجيله.
أنشئ طلبًا chat-completion-tools بهذا النص:
{
"model": "{{defaultModel}}",
"messages": [
{ "role": "user", "content": "What is the weather in Singapore right now?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string" },
"unit": { "type": "string", "enum": ["c", "f"] }
},
"required": ["city"]
},
"strict": true
}
}
],
"tool_choice": "auto"
}
الاستجابة الصحيحة تحتوي على choices[0].message.tool_calls[0].function.name === "get_weather" و function.arguments هي سلسلة JSON يتم تحليلها إلى { "city": "Singapore", "unit": "c" } (أو ما شابه).
في علامة تبويب الاختبارات (Tests) الخاصة بالطلب، أضف:
pm.test("Tool was called", () => {
const body = pm.response.json();
const call = body.choices[0].message.tool_calls?.[0];
pm.expect(call?.function?.name).to.eql("get_weather");
});
pm.test("Arguments parse as valid JSON", () => {
const body = pm.response.json();
const args = JSON.parse(body.choices[0].message.tool_calls[0].function.arguments);
pm.expect(args.city).to.be.a("string");
});
قم بتشغيله. أصبحت الاختبارات الخضراء هي عقدك الآن. عندما تغير OpenAI الشكل، سيتحول الاختبار إلى اللون الأحمر قبل أن يحدث ذلك في حركة المرور الإنتاجية.
الخطوة 6: التعامل مع الأخطاء وقيود المعدل بشكل صريح
تفشل تكاملات ChatGPT في الإنتاج بخمس طرق متوقعة. قم ببناء طلب لكل منها وتحقق من السلوك المتوقع:
| السيناريو (Scenario) | كيفية التفعيل (How to trigger) | المتوقع (Expected) |
|---|---|---|
| مفتاح غير صالح | اضبط OPENAI_API_KEY على sk-bad في بيئة Sandbox |
401 مع error.code = "invalid_api_key" |
| حد المعدل (Rate limit) | كرر الطلب 200 مرة في مشغل مجموعات Apidog | 429 مع رأس Retry-After |
| تجاوز سقف الرموز (Token cap exceeded) | أرسل مطالبة 200 ألف رمز إلى نموذج سياقي 128 ألف رمز | 400 مع error.code = "context_length_exceeded" |
| اسم نموذج خاطئ | "model": "gpt-99" |
404 |
| انتهاك المخطط (Schema violation) | استدعاء أداة بـ strict: true ومدخلات مشوهة |
يرفض النموذج الأداة، ويعيد نصًا عاديًا |
أضف تأكيدات في علامة تبويب "الاختبارات" (Tests) بحيث يظهر التراجع (regression) كاختبار أحمر، وليس عاصفة إعادة محاولة صامتة. رأس Retry-After هو الذي تخطئ فيه معظم الأكواد الإنتاجية. إنه بالثواني، وأحيانًا قيمة كسرية، ويجب عليك قراءته بدلاً من ترميز التراجع (backoff) بشكل ثابت.
الخطوة 7: إنشاء نموذج وهمي لـ ChatGPT من أجل تطوير الواجهة الأمامية المتوازي
لدى مفتاح OpenAI الخاص بك سقف شهري. فريق الواجهة الأمامية الخاص بك ليس لديه ذلك. عندما تحتاج واجهة المستخدم إلى عرض الرموز المتدفقة، والمتابعات المقترحة، وبطاقات استدعاء الأدوات قبل الانتهاء من مطالبة الواجهة الخلفية، قدم لهم نموذج Apidog وهميًا.
في مجلد ChatGPT، انقر بزر الماوس الأيمن على طلب chat-completion-basic، اختر Smart Mock، وقم بتمكينه. سيعيد Apidog استجابة اصطناعية تتطابق مع مخطط OpenAI: id، object، created، model، choices، usage. سيبدو عنوان URL الوهمي مثل https://mock.apidog.com/m1/<projectId>/chat/completions ويقبل نفس النص.
بالنسبة للنماذج الوهمية المتدفقة (streaming mocks)، حدد نصًا برمجيًا في علامة تبويب Advanced Mock يكتب أجزاء data: { ... }\n\n بفواصل زمنية قدرها 50 مللي ثانية. تحصل الواجهة الأمامية على تدفق SSE واقعي دون أي حركة مرور لـ OpenAI.
عندما تصل المطالبة الحقيقية، قم بإعادة تعيين عنوان URL الأساسي للواجهة الأمامية إلى https://api.openai.com/v1. لا يتغير أي شيء آخر.
الخطوة 8: حفظ المجموعة كسيناريو اختبار CI
تتيح لك سيناريوهات الاختبار في Apidog ربط الطلبات مع التأكيدات وتشغيلها بدون واجهة مستخدم. أنشئ سيناريو يقوم بما يلي:
- يستدعي
chat-completion-basic، ويؤكد أنstatus === 200وusage.total_tokens > 0. - يستدعي
chat-completion-stream، ويؤكد أن SSE انتهت بـ[DONE]. - يستدعي
chat-completion-tools، ويؤكد أن مخطط استدعاء الأداة صالح. - يستدعي كل سيناريو خطأ من الخطوة 6، ويؤكد رمز الحالة الصحيح.
صدر السيناريو وقم بتشغيله في CI عبر apidog-cli run scenario.json --env OpenAI Prod. قم بربطه بخط أنابيب PR للملف الذي يحتوي على مطالباتك. الآن، يتم تشغيل كل تغيير في المطالبة مقابل واجهة برمجة تطبيقات OpenAI الحية كفحص قبل الدمج. التكلفة: بضعة سنتات لكل تشغيل CI. القيمة: تتوقف عن إرسال تراجعات المطالبة.
الأسئلة الشائعة
هل يعمل هذا مع Azure OpenAI؟ نعم. قم بتبديل baseUrl إلى عنوان URL لمورد Azure الخاص بك، وأضف معلمة استعلام api-version، وغيّر المصادقة من Bearer إلى رأس api-key. نصوص الطلبات متطابقة.
هل يمكنني استخدام هذا لنماذج الاستدلال o1 و o3؟ نعم، لكن هذه النماذج ترفض temperature، top_p، presence_penalty، و frequency_penalty. أنشئ مجلدًا منفصلاً باسم Reasoning بقالب نص مجرد.
كيف أقوم بإصدار المطالبات داخل Apidog؟ يدعم Apidog الفروع. أنشئ فرعًا لكل تجربة مطالبة، وقم بتشغيل سيناريو الاختبار مقابل واجهة برمجة التطبيقات الحية، وقارن استخدام الرمز وجودة الاستجابة، ثم ادمج. إنه نفس سير العمل للكود، مطبقًا على المطالبات.
ماذا عن نقطة النهاية الجديدة /v1/responses؟ قم بإعداد مجلد منفصل لها. المصادقة وعنوان URL الأساسي متطابقان؛ يختلف شكل النص فقط. احتفظ بكلا المجلدين حتى تتمكن من إجراء اختبار A/B لهما مقابل نفس المطالبات.
هل يفرض Apidog رسومًا على كل استدعاء API؟ لا. عميل Apidog مجاني للاستخدام الفردي ومعظم استخدامات الفريق. تفرض OpenAI رسومًا على كل رمز؛ Apidog لا يتدخل بينك وبين OpenAI.
الخلاصة
ستستمر واجهة برمجة تطبيقات ChatGPT في التغيير. سيتعطل التدفق بطرق جديدة، وستصبح مخططات الأدوات أكثر صرامة، وستستمر نماذج الاستدلال في التخلي عن المعلمات التي اعتقدت أنها مستقرة. الدفاع هو مجموعة طلبات تتحكم فيها، وخادم وهمي يمكن أن تعتمد عليه واجهتك الأمامية، وسيناريو اختبار يقوم CI بتشغيله قبل كل PR مطالبة.
قم بتنزيل Apidog وقم باستيراد مكالمات OpenAI الحالية. مجموعات Postman وأوامر curl كلاهما يتحول بنقرة واحدة. قم ببناء الطلبات الثمانية المذكورة أعلاه مرة واحدة، وسيصبح كل تحديث مستقبلي لـ ChatGPT تشغيل اختبار متحكمًا فيه بدلاً من حادث إنتاجي.
