إنشاء برنامج دردشة آلي متوافق مع الأجهزة المحلية وغير المتصلة بالإنترنت باستخدام WebLLM

تاريخ النشر: 13 كانون الثاني (يناير) 2024

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

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

‫WebLLM هو منصّة تشغيل مستندة إلى الويب للنماذج اللغوية الكبيرة (LLM) تقدّمها ميزة "تجميع تعلُّم الآلة". يمكنك تجربة WebLLM كتطبيق مستقل. استُوحي التطبيق من تطبيقات المحادثة المستندة إلى السحابة الإلكترونية، مثل Gemini، ولكن يتم تنفيذ الاستنتاج باستخدام نموذج اللغة الكبيرة على جهازك بدلاً من السحابة الإلكترونية. لا تغادر طلباتك وبياناتك جهازك أبدًا، ويمكنك التأكّد من أنّه لا يتم استخدامها لتدريب النماذج.

لتنفيذ الاستنتاج من النماذج على الجهاز، يجمع WebLLM بين WebAssembly وWebGPU. في حين أنّ WebAssembly يتيح إجراء عمليات حسابية فعّالة على وحدة المعالجة المركزية (CPU)، يمنح WebGPU للمطوّرين إمكانية الوصول إلى وظائف المستوى الأدنى في وحدة معالجة الرسومات (GPU) للجهاز.

Browser Support

  • Chrome: 113.
  • Edge: 113.
  • Firefox Technology Preview: supported.
  • Safari Technology Preview: supported.

Source

تثبيت WebLLM

تتوفّر WebLLM كـ حزمة npm. يمكنك إضافة هذه الحزمة إلى تطبيق قائمة المهام من خلال تشغيل npm install @mlc-ai/web-llm.

اختيار نموذج

بعد ذلك، عليك اختيار نموذج معالجة لغوية كبيرة (LLM) لتنفيذه على الجهاز. تتوفّر نماذج مختلفة.

اتّبِع الخطوات التالية لمعرفة ما إذا كان عليك استخدام ميزة "الإعلانات المتجاوبة على شبكة البحث":

  • العنصر: أصغر وحدة نصية يمكن لنموذج لغوي كبير معالجتها.
  • إطار السياق: الحد الأقصى لعدد الرموز التي يمكن للنموذج معالجتها.
  • المَعلمات أو الأوزان: المتغيّرات الداخلية التي يتم تعلّمها أثناء التدريب، ويُحتسَب عددها بالمليارات.
  • التكمية: عدد وحدات البت التي تمثّل الأوزان كلما زاد عدد البتات، زادت الدقة، ولكن زاد أيضًا استخدام الذاكرة.
  • تنسيقات الأرقام ذات النقطة العائمة: توفّر الأرقام ذات النقطة العائمة بسعة 32 بت (دقة كاملة، F32) دقة أفضل، في حين تتمتع الأرقام ذات النقطة العائمة بسعة 16 بت (دقة جزئية، F16) بسرعات أعلى واستخدام أقل للذاكرة، ولكنها تتطلّب أجهزة متوافقة.

وغالبًا ما تكون هذه العبارات الرئيسية جزءًا من اسم النموذج. على سبيل المثال، يحتوي العنوان Llama-3.2-3B-Instruct-q4f32_1-MLC على المعلومات التالية:

  • الطراز هو LLaMa 3.2.
  • يتضمّن النموذج 3 مليارات مَعلمة.
  • تم تحسينه ليعمل مع المساعدين الذين يقدّمون التعليمات والطلبات (Instruct).
  • ويستخدم تقسيمًا موحّدًا (_1) بسعة 4 بت (q4).
  • وهي تتضمّن أعدادًا عشرية بدقة كاملة و32 بت.
  • وهو إصدار خاص تم إنشاؤه من خلال ميزة "تجميع التعلم الآلي".

قد تحتاج إلى اختبار نماذج مختلفة لتحديد النموذج الذي يناسب حالة الاستخدام.

يمكن أن يصل حجم ملف النموذج الذي يتضمّن 3 مليارات مَعلمة و4 بت لكل مَعلمة إلى 1.4 غيغابايت في وقت كتابة هذه المقالة، ويجب أن ينزِّله التطبيق على جهاز المستخدم قبل الاستخدام الأول. من الممكن استخدام نماذج 3B، ولكن عندما يتعلق الأمر بقدرات الترجمة أو معرفة معلومات عامة، تحقّق نماذج 7B نتائج أفضل. ومع ذلك، تزداد هذه المساحة بشكلٍ ملحوظ عند استخدام 3.3 غيغابايت أو أكثر.

لإنشاء محرك WebLLM وبدء تنزيل النموذج لقائمة المهام الدردشة الآلية، أضِف الرمز التالي إلى تطبيقك:

import {CreateMLCEngine} from '@mlc-ai/web-llm';
const engine = await CreateMLCEngine('Llama-3.2-3B-Instruct-q4f32_1-MLC', {
  initProgressCallback: ({progress}) =>  console.log(progress);
});

تأخذ طريقة CreateMLCEngine سلسلة النموذج وكائن ملف تكوين اختياري. باستخدام الطريقة initProgressCallback، يمكنك الاستعلام عن مستوى تقدّم تنزيل النموذج لتقديمه للمستخدمين أثناء انتظارهم.

Cache API: تشغيل نموذج اللغة الكبير بلا إنترنت

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

بعد تنزيلها، يقرأ WebLLM ملفات النماذج من Cache API بدلاً من طلبها عبر الشبكة، ما يجعل WebLLM متوافقًا تمامًا مع وضع عدم الاتّصال بالإنترنت.

كما هو الحال مع جميع مساحات التخزين الخاصة بالمواقع الإلكترونية، يتم عزل ذاكرة التخزين المؤقت لكل مصدر. وهذا يعني أنّه لا يمكن لمصدرَين، example.com وexample.net، مشاركة مساحة التخزين نفسها. إذا أردت هذين الموقعَين الإلكترونيَين استخدام النموذج نفسه، عليهما تنزيل النموذج بشكل منفصل.

يمكنك فحص ذاكرة التخزين المؤقت باستخدام "أدوات المطوّر" من خلال الانتقال إلى التطبيق > مساحة التخزين وفتح مساحة تخزين ذاكرة التخزين المؤقت.

إعداد المحادثة

يمكن إعداد النموذج باستخدام مجموعة من الطلبات الأولية. عادةً ما يكون هناك ثلاثة أدوار للرسائل:

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

يمكن استخدام طلبات المستخدم والمساعد لطلبات N-shot من خلال تقديم أمثلة على لغة طبيعية للنموذج اللغوي الكبير (LLM) حول كيفية تصرفه أو ردّه.

في ما يلي مثال بسيط لإعداد المحادثة في تطبيق قائمة المهام:

const messages = [
  { role: "system",
    content: `You are a helpful assistant. You will answer questions related to
    the user's to-do list. Decline all other requests not related to the user's
    todos. This is the to-do list in JSON: ${JSON.stringify(todos)}`
  },
  {role: "user", content: "How many open todos do I have?"}
];

الإجابة عن سؤالك الأول

يتم عرض ميزة إكمال المحادثة كخاصية في محرّك WebLLM الذي تم إنشاؤه من قبل (engine.chat.completions). بعد تنزيل النموذج، يمكنك تنفيذ الاستنتاج من النموذج من خلال استدعاء طريقة create() في هذه السمة. في حالة الاستخدام التي تتعامل معها، تريد بث الردود حتى يتمكّن المستخدم من بدء القراءة أثناء إنشائها، ما يقلل من وقت الانتظار المُتوقّع:

const chunks = await engine.chat.completions.create({  messages,  stream: true, });

تُرجع هذه الطريقة AsyncGenerator، وهي فئة فرعية من فئة hidden AsyncIterator المخفية. استخدِم حلقة for await...of للانتظار إلى أن يتم إرسال الشرائح. ومع ذلك، لا يحتوي الردّ إلا على الرموز المميزة الجديدة (delta)، لذا عليك تجميع الردّ الكامل بنفسك.

let reply = '';

for await (const chunk of chunks) {
  reply += chunk.choices[0]?.delta.content ?? '';
  console.log(reply);
}

تبيّن أنّ شبكة الويب كانت تتعامل دائمًا مع الردود التي يتم بثّها. يمكنك استخدام واجهات برمجة التطبيقات، مثل DOMImplementation للعمل مع هذه الردود المتعلقة بالبث وتعديل ملف HTML بكفاءة.

تستند النتائج إلى السلسلة فقط. يجب تحليلها أولاً إذا كنت تريد تفسيرها على أنّها ملف JSON أو تنسيقات ملفات أخرى.

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

عرض توضيحي

يتم معالجة هذه العيوب من خلال Prompt API، وهي واجهة برمجة تطبيقات استكشافية اقترحتها Google ويتم تشغيلها أيضًا من جهة العميل، ولكنها تستخدِم نموذجًا مركزيًا يتم تنزيله إلى Chrome. وهذا يعني أنّه يمكن لعدة تطبيقات استخدام النموذج نفسه بسرعته الكاملة في التنفيذ.

يمكنك الاطّلاع على مزيد من المعلومات حول إضافة إمكانات chatbot باستخدام Prompt API في المقالة التالية.