SiCore TokenWorks
LLM APIAPI Gateway

مهندس token8341 في الميدان: بناء نموذج أولي لخدمة العملاء الذكية في أسبوع واحد، وسجل المشاكل في مقارنة واجهات برمجة التطبيقات متعددة النماذج

SiCore TokenWorks Team·2026-10-05

الأسبوع الماضي تسلمت مهمة، وهي بناء نموذج أولي لخدمة العملاء الذكية لفريق يعمل على نظام تذاكر SaaS، بشرط أن يعمل خلال أسبوع، مع إجراء مقارنة أفقية لجودة استجابات أربعة نماذج: GPT-4o وDeepSeek-V3 وQwen-Max وDoubao. يبدو الأمر غير صعب، لكن عند التنفيذ الفعلي اكتشفت أن توحيد الوصول إلى نماذج متعددة يخفي كل مشاكله في التفاصيل. أسجل هذه المقالة العملية لأساعد الزملاء الذين سيقومون بمقارنة متعددة النماذج على توفير بعض الوقت.

إدارة مفاتيح Key: 5 منصات و5 لوحات تحكم خلفية، رتّب الحسابات أولاً

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

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

توافق SDK: واجهات كل جهة تبدو مختلفة

خطوة تثبيت SDK قضت على نصف الصبر. منظومة OpenAI SDK هي الأكثر نضجاً، وكثير من الشركات تدّعي التوافق، لكن عند الدمج الفعلي تكتشف أن أسماء المعاملات غير متطابقة. مثلاً في بعض المنصات يسمى temperature بـ temperature، وفي أخرى يخلطون top_p معه، وهناك من غيّر max_tokens إلى max_output_tokens. كما أن مفتاح البث غير موحد، فبعضها يستخدم stream=True، وبعضها يتطلب تمرير stream_options بشكل منفصل.

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

الإخراج المتدفق: تنفيذ بروتوكول SSE يختلف بين الجهات

خدمة العملاء الذكية يجب أن تستخدم البث، وإلا سينتظر المستخدم ثلاث ثوانٍ قبل رؤية النص، وستنهار التجربة مباشرة. المشكلة أن تفاصيل تنفيذ بروتوكول SSE تختلف بين الجهات. بعض المنصات ترسل بنية event كاملة مع كل chunk، وبعضها يرسل حقل data فقط؛ وعلامة النهاية قد تكون [DONE]، أو تعيين حقل finish_reason؛ وبعضها يدرج حزم نبضات heartbeat في المنتصف، مما يسهل على الواجهة الأمامية تفسيرها خطأً كمحتوى.

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

معالجة الاستثناءات: عندما تنتهي مهلة إحدى الجهات، كيف نبدّلها تلقائياً

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

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

مراقبة التكلفة: كيف نجمع استهلاك Token

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

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

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

المؤلف: Zhou Mingzhe

تاريخ النشر: 6 أكتوبر 2026