الخلاصة

  • يضيف pai-auth-ws-client 1.6.0 نداءً لحل إعداد حالة استخدام الذكاء الاصطناعي ونداءً منفصلاً للمحادثة، ويعيد كلا النوعين بيانات المزوّد والنموذج.
  • لا يتضمن العقد العام بلغة Java معرّف حل أو إصدار إعداد مشتركاً، لذلك يستطيع المستدعي مقارنة صفات متشابهة ولا يستطيع ربط الجواب قطعاً بالحالة التي فحصها قبل التنفيذ.

يستحق التصميم الجديد أن يبدأ عرضه من عناصر قوته. يشترط ملف README عند الوسم 1.6.0 رمز Bearer من PAI يحمل دور portal-ai-gateway، كما يجب أن يكون عنوان IP للجهة المستدعية ضمن AI_LLM_WS_IP_WHITELIST. يستخدم العميل التحقق القياسي من TLS واسم المضيف، ويشفّر use كمقطع واحد من المسار، ويحدد خمس ثوان للاتصال و90 ثانية للجواب. ويحوّل انتهاء المهلة إلى gateway_timeout برمز 504. أما نتيجة المحادثة فتسجل الاستخدام والمزوّد والنموذج وزمن الاستجابة. هذه ضوابط عملية وليست مجرد غلاف مبهم فوق نموذج.

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

الملاحظة الأضيق تتعلق بما يمكن للعميل نفسه إثباته. يقدم الإصدار عمليتين مستقلتين. تستدعي الأولى resolve(token, use) لمعرفة الإعداد المرتبط بالاستخدام. ثم ترسل الثانية chat(token, use, messages) الاستخدام والرسائل إلى البوابة. ويوضح README أن التطبيق هو الذي يختار قيمة use، بينما يكتفي العميل بتمريرها.

تعيد فئة AiResolveData صورة غنية نسبياً: الاستخدام، المزوّد، معرّف النموذج واسمه، حالة التفعيل، المهلة واسم مرجع بيانات الاعتماد، فضلاً عن النجاح ورمز HTTP والخطأ. وتعطي AiChatData النص والاستخدام والمزوّد ومعرّف النموذج وزمن الاستجابة. لذلك لا يكون الجواب المحفوظ بلا مصدر تماماً؛ فهو يقول أي مزوّد وأي نموذج تنسب إليهما البوابة النتيجة.

لكن عملية الحل نفسها بلا هوية مشتركة. لا تحتوي الفئتان على resolutionId أو configurationId أو إصدار للإعداد أو معرّف طلب أو أثر أو ارتباط موحد. كما أن أسلوب المحادثة لا يستقبل كائن الحل السابق ولا بطاقة مبهمة صدرت عنه؛ بل يعيد إرسال use والرسائل.

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

لنفترض أن تطبيقاً فحص استخداماً عند الساعة العاشرة، وسجل المزوّد أ والنموذج ب ومهلة 60 ثانية. وبعد دقيقة أعادت المحادثة أ وب. هذا توافق مطمئن للصفات. لكنه لا يثبت إن كان الإصدار 17 الذي فُحص هو الذي أنتج الجواب، أم الإصدار 18 الذي أبقى المزوّد والنموذج وغيّر ضابطاً آخر. توجد صورتان متوافقتان، لا إيصال واحد يربط الحدثين.

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

الوظيفة حديثة العهد. يسجل GitHub الإصدار 1.6.0 في 12 سبتمبر 2026. وتقول ملاحظته إن مجموعة Maven الكاملة اجتازت 59 اختباراً على Java 17 وإن الفحص البنيوي نجح. وتبين المقارنة مع 1.5.1 أن الوسم الجديد يتقدم بثمانية إيداعات، أضاف ما قبل الأخير منها عميل البوابة ثم حصّن الأخير النداءات. هذا فحص لعقد جديد عند ظهوره، لا نبش في كود مهجور.

وتوضح اختبارات PortalAiClient ما أراد المطورون تثبيته: إرسال Bearer، قراءة ربط الكتالوج، تشفير الرموز المحجوزة في use، تسلسل الرسائل ذات الأدوار، رفض الاستخدام الفارغ، تحويل انتهاء المهلة إلى 504، والتفويض عبر PortalWSClient. هذه خصائص تكامل مفيدة. ولا يوجد اختبار ينقل هوية الحل إلى المحادثة لأن الواجهة لا تقدم تلك الهوية بعد.

أصغر تحسين ليس دمج العمليتين قسراً ولا نشر الإعداد الداخلي. يمكن لـresolve أن يعيد resolutionId مبهمًا أو إصدار الإعداد. في النمط الصارم تستقبل المحادثة هذه القيمة وترفض بوضوح حلاً انتهت صلاحيته أو استُبدل. وفي النمط المرن تستطيع البوابة تبديل المسار لحماية الاستمرارية، لكنها تعيد هوية الحالة التي نفذتها فعلياً. كلا النمطين مشروع؛ المهم أن يعرف التطبيق أيهما استعمل.

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

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

كما أن الإيصال يحمي LACNIC. من دونه قد ينسب المستدعي نتيجة غريبة إلى تغيير صامت في البوابة حتى لو لم يحدث أي تغيير. وبوجوده تستطيع الجهة المشغلة إثبات استمرارية الأثر أو تحديد موضع الاختلاف. زيادة الدليل هنا تضيق المسؤولية ولا توسعها بلا حدود.

ولا يعيد هذا المقال موضوع التحقيق السابق في ذكر Java 8 في وثائق العميل بينما يتطلب البناء والـbytecode الحديثان Java 17. كان ذلك سؤال قابلية التشغيل. أما هنا فنفترض أن المكتبة تعمل ونسأل ما الدليل الذي تبقيه عن قرار البوابة. البرنامج واحد، لكن سطح التحكم مختلف.

المصادر