تخطي إلى المحتوى الرئيسي
OpenAI

22 أبريل 2026

الهندسة

تسريع مسارات العمل الوكيلية باستخدام WebSockets في Responses API

بقلم براين يو وأشوين ناثان، عضوي الطاقم التقني

جاري التحميل...

عندما تطلب من Codex إصلاح خطأ برمجي، فإنه يفحص قاعدة الشيفرة لديك بحثًا عن الملفات ذات الصلة، ويقرأها لبناء السياق، ويجري التعديلات، ثم يشغّل الاختبارات للتحقق من نجاح الإصلاح. وفي الخلفية، يعني ذلك عشرات الطلبات المتبادلة ذهابًا وإيابًا إلى Responses API: تحديد الخطوة التالية للنموذج، وتشغيل أداة على جهازك، ثم إرسال مخرجات الأداة إلى واجهة API، وتكرار ذلك.

وقد تتراكم هذه الطلبات كلها لتتحول إلى دقائق يقضيها المستخدمون في انتظار Codex حتى يُكمل المهام المعقدة. ومن منظور زمن الاستجابة، يقضي تكرار عمل وكيل Codex معظم وقته في ثلاث مراحل رئيسية: العمل داخل خدمات API لمعالجة الطلبات والتحقق منها، والاستدلال بالنموذج، والوقت على جانب العميل، مثل تشغيل الأدوات وبناء سياق النموذج. ويُقصد بالاستدلال المرحلة التي يعمل فيها النموذج على وحدات GPU لتوليد رموز جديدة. وفي السابق، كان تشغيل الاستدلال للنماذج اللغوية الكبيرة على وحدات GPU هو أبطأ جزء في دورة عمل الوكيل، لذلك كان من السهل إخفاء أثر التأخير الناتج عن خدمات API. أما الآن، ومع تسارع الاستدلال، فقد أصبح الأثر التراكمي لعبء API في عمليات الطرح الوكيلية أكثر وضوحًا بكثير.

وفي هذا المقال، نشرح كيف جعلنا دورات عمل الوكلاء التي تستخدم API أسرع بنسبة 40% من البداية إلى النهاية، بما أتاح للمستخدمين ملاحظة قفزة في سرعة الاستدلال من 65 إلى ما يقارب 1,000 رمز في الثانية. وقد حققنا ذلك عبر التخزين المؤقت، وإزالة القفزات غير الضرورية على مستوى الشبكة، وتحسين منظومة السلامة لدينا لرصد المشكلات بسرعة، والأهم من ذلك كله، بناء وسيلة لإنشاء اتصال دائم مع Responses API، بدلًا من الاضطرار إلى تنفيذ سلسلة من استدعاءات API المتزامنة.

مخطط بعنوان A Codex agent loop in practice "حلقة عمل وكيل Codex في الممارسة"، يوضّح تدفّقًا تكراريًا بين Codex وواجهة Responses API، مع استدعاءات للأدوات (rg وsed وapply_patch وpytest) وتبادل النتائج إلى أن تظهر الرسالة النهائية: The bug has been fixed"تم إصلاح الخطأ."

عندما أصبحت واجهة API هي عنق الزجاجة

في Responses API، كانت النماذج الرائدة السابقة مثل GPT‑5 وGPT‑5.2 تعمل بسرعة تقارب 65 رمزًا في الثانية (TPS). أما عند إطلاق GPT‑5.3‑Codex‑Spark، وهو نموذج سريع للبرمجة، فقد كان هدفنا أسرع بعشرات المرات: أكثر من 1,000 رمز في الثانية، بفضل عتاد Cerebras المتخصص والمهيأ لاستدلال النماذج اللغوية الكبيرة. ولكي نتيح للمستخدمين اختبار السرعة الحقيقية لهذا النموذج الجديد، كان علينا تقليل العبء الناتج عن API.

وفي نحو نوفمبر 2025، أطلقنا دفعة تحسينات للأداء على Responses API، وركزنا فيها على تحسين زمن الاستجابة على المسار الحرج للطلب الواحد، وذلك عبر مجموعة من التحسينات، منها:

  • تخزين الرموز المولدة وإعدادات النموذج مؤقتًا في الذاكرة لتجاوز عمليات تقسيم النص إلى رموز والاتصالات الشبكية المكلفة في الاستجابات متعددة الجولات
  • تقليل زمن القفزات الشبكية عبر إلغاء الاستدعاءات الموجهة إلى الخدمات الوسيطة، مثل خدمات معالجة الصور، والاتصال مباشرة بخدمة الاستدلال نفسها
  • تحسين منظومة السلامة لدينا حتى نتمكن من تشغيل بعض المصنفات لرصد المحادثات بسرعة أكبر

ومع هذه التحسينات، لاحظنا تحسنًا يقارب 45% في زمن الوصول إلى أول رمز (TTFT)، وهو مؤشر يعكس مدى سرعة استجابة API. لكن رغم ذلك، لم تكن هذه التحسينات كافية بالسرعة المطلوبة لـ GPT‑5.3‑Codex‑Spark. فحتى بعد هذا التقدم، ظل العبء الناتج عن Responses API كبيرًا مقارنة بسرعة النموذج؛ أي إن المستخدمين كانوا لا يزالون ينتظرون وحدات CPU التي تشغّل واجهة API قبل أن يتمكنوا من الاستفادة من وحدات GPU التي تقدّم النموذج.

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

بناء اتصال دائم

ولتحسين التصميم، أعدنا التفكير في بروتوكول النقل: هل يمكننا الحفاظ على اتصال دائم وتخزين الحالة مؤقتًا، بدلًا من إنشاء اتصال جديد عبر HTTP وإرسال السجل الكامل للمحادثة مع كل طلب متابعة؟ كانت الفكرة تقوم على إرسال المعلومات الجديدة فقط، أي تلك التي تحتاج إلى تحقق ومعالجة، مع الاحتفاظ بالحالة القابلة لإعادة الاستخدام في الذاكرة طوال مدة الاتصال. وهذا من شأنه أن يقلل العبء الناتج عن العمل المتكرر.

ودرَسنا عدة خيارات مختلفة، من بينها WebSockets والبث الثنائي الاتجاه عبر gRPC. وفي النهاية اخترنا WebSockets، لأنه بروتوكول بسيط لنقل الرسائل، ولن يضطر المستخدمون معه إلى تغيير أشكال الإدخال والإخراج في Responses API. كما أنه مناسب للمطورين وينسجم مع بنيتنا الحالية بأقل قدر من الاضطراب.

وقد غيّر أول نموذج أولي قائم على WebSocket تصورنا لما هو ممكن من حيث زمن الاستجابة في Responses API. إذ تمكّن أحد مهندسي فريق Codex، ممن يملكون خبرة عميقة عبر طبقات API المختلفة، من إعداد نموذج أولي من خلال تشغيل وكيل Codex طوال الليل.

وفي ذلك النموذج الأولي، جرى تمثيل عمليات الطرح الوكيلية على أنها Response واحدة طويلة التشغيل. وباستخدام ميزات asyncio ، ستدخل واجهة Responses API في حالة انتظار غير متزامن داخل حلقة أخذ العينات بعد أخذ عينة لاستدعاء أداة، ثم سترسل واجهة Responses API حدث response.done مرة أخرى إلى العميل. وبعد تنفيذ استدعاء الأداة، كان العميل يعيد إرسال حدث response.append مرفقًا بنتيجة الأداة، مما يرفع التوقف عن حلقة أخذ العينات ويتيح للنموذج متابعة العمل.

ويمكن تشبيه ذلك بالتعامل مع استدعاء الأداة المحلية كما لو كان استدعاءً لأداة مستضافة. فعندما يستدعي النموذج البحث على الويب، تتوقف حلقة الاستدلال، وتستدعي خدمة بحث ويب، ثم تضع استجابة تلك الخدمة في سياق النموذج. وفي تصميمنا فعلنا الشيء نفسه، لكن بدلًا من استدعاء خدمة بعيدة، أرسلنا استدعاء الأداة الخاص بالنموذج إلى العميل عبر WebSocket. وعندما ردّ العميل، أدرجنا استجابة استدعاء الأداة ضمن السياق، ثم واصلنا أخذ العينات.

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

لكن هذا جاء على حساب شكل أكثر تعقيدًا وأقل ألفة لواجهة API. وكنا نريد أن يتمكن المطورون من إضافة دعم WebSocket بسهولة، من دون الحاجة إلى إعادة كتابة تكاملهم مع API حول نمط تفاعل جديد.

الحفاظ على API مألوفة مع جعل البنية تراكمية

بالنسبة إلى الإصدار الذي أطلقناه، عدنا إلى صيغة مألوفة: الاستمرار في استخدام response.create مع نفس نص الطلب، واستخدام previous_response_id لمتابعة سياق المحادثة انطلاقًا من حالة الاستجابة السابقة.

وعبر اتصال WebSocket، يحتفظ الخادم بذاكرة تخزين مؤقتة داخلية خاصة بنطاق الاتصال لحالة الاستجابات السابقة. وعندما يتضمن طلب متابعة من نوع response.create القيمة previous_response_id، فإننا نسترجع تلك الحالة من الذاكرة المؤقتة بدلًا من إعادة بناء المحادثة الكاملة من الصفر.

وتشمل هذه الحالة المخزنة مؤقتًا ما يلي:

  • عنصر response السابق
  • عناصر المدخلات والمخرجات السابقة
  • تعريفات الأدوات ومساحات الأسماء
  • مخرجات أخذ عينات قابلة لإعادة الاستخدام، مثل الرموز التي جرى توليدها سابقًا
مخطط بعنوان From sequential requests to overlapped execution "من الطلبات المتسلسلة إلى التنفيذ المتداخل"، يقارن بين مسار طلبات متسلسل ونهج قائم على WebSocket تتداخل فيه عدة طلبات عبر مراحل التحقق، وما قبل الاستدلال، وأخذ العينات، وما بعد الاستدلال.

ومن خلال إعادة استخدام حالة الاستجابة السابقة المخزنة في الذاكرة، تمكّنا من تحقيق عدة تحسينات رئيسية:

  • جعل بعض مصنفات السلامة وأدوات التحقق من الطلبات لدينا تعالج المدخلات الجديدة فقط، بدلًا من معالجة السجل الكامل في كل مرة
  • الاحتفاظ بذاكرة تخزين مؤقت داخلية للرموز المولدة، نضيف إليها باستمرار، حتى نتمكن من تجاوز عمليات تقسيم النص إلى رموز غير الضرورية
  • إعادة استخدام منطق اختيار النموذج/توجيهه الذي أثبت نجاحه عبر الطلبات المختلفة 
  • تنفيذ الأعمال اللاحقة للاستدلال غير المعطِّلة، مثل الفوترة، بالتوازي مع الطلبات اللاحقة

وكان الهدف هو الاقتراب قدر الإمكان من النموذج الأولي منخفض العبء، ولكن بصيغة API يفهمها المطورون مسبقًا وقد بنوا تكاملاتهم على أساسها.

نرسي معيارًا جديدًا للسرعة

بعد سباق تطوير استمر شهرين لبناء وضع WebSocket، أطلقنا نسخة ألفا بالتعاون مع شركات ناشئة رئيسية تعمل في مجال وكلاء البرمجة، حتى تتمكن من دمجه في بنيتها التحتية وزيادة حركة المرور عليه بصورة آمنة. وقد أعجب بها المستخدمون الأوائل، الذين أفادوا بتحسن وصل إلى 40%(يفتح في نافذة جديدة) في مسارات عملهم الوكيلية. ومع هذا التفاعل الإيجابي، أصبحنا جاهزين للإطلاق.

وجاءت نتائج الإطلاق فورية. فقد نقل Codex سريعًا معظم حركة المرور الخاصة به على Responses API إلى وضع WebSocket، مع تحسن واضح في زمن الاستجابة. وبالنسبة إلى GPT‑5.3‑Codex‑Spark، وصلنا إلى هدفنا البالغ 1,000 رمز في الثانية، ورصدنا قفزات بلغت حتى 4,000 رمز في الثانية، وهو ما أظهر أن Responses API قادرة على مجاراة الاستدلال الأسرع بكثير في حركة الإنتاج الفعلية. وسرعان ما ظهر هذا الأثر أيضًا في مجتمع المطورين:

ويُعد وضع WebSocket واحدًا من أهم القدرات الجديدة التي أضيفت إلى Responses API منذ إطلاقها في مارس 2025. فقد انتقلنا من الفكرة إلى التشغيل في بيئة الإنتاج خلال بضعة أسابيع فقط، بفضل التعاون الوثيق بين فريقي API وCodex في OpenAI. وهو لا يحسن زمن الاستجابة في عمليات الطرح الوكيلية بشكل كبير فحسب، بل يلبي أيضًا حاجة متزايدة لدى البنّائين: فكلما أصبح استدلال النماذج أسرع، كان على الخدمات والأنظمة المحيطة به أن تتسارع هي الأخرى حتى تنتقل هذه المكاسب إلى المستخدمين. 

الكاتبان

Brian Yu وAshwin Nathan

الشكر والتقدير

شكر خاص لفرقي Responses API وCodex، اللذين عملا على تطوير وضع WebSocket.