تطوير الويب

ورشة تطبيقية: بناء PWA أوفلاين لتحويل اللهجات العربية إلى فصحى باستخدام WASM

ورشة عملية لبناء PWA يعمل أوفلاين لتحويل اللهجات العربية إلى فصحى داخل المتصفح باستخدام WebAssembly وWebGPU، مع أمثلة وشفرة تشغيل.

Detailed view of a red printed circuit board (PCB) highlighting a designated area for PWA labeling.

مقدمة سريعة: لماذا PWA + WASM لتحويل اللهجات إلى فصحى؟

في هذه الورشة سنبني تطبيق Progressive Web App (PWA) قادر على العمل دون اتصال ويحوّل النصوص المكتوبة باللهجات العربية المحلية (مصرية، شامية، خليجية...) إلى العربية الفصحى. الفكرة الأساسية هي تحميل نموذج صغير مُكمَّش إلى جهاز المستخدم وتشغيله داخل المتصفح باستخدام WebAssembly (WASM) مع الاستفادة من WebGPU/WebNN عندما تكون متاحة لتسريع الاستدلال. هذا النهج يُحافظ على خصوصية المستخدم (لا تُرسل البيانات للسيرفر) ويُحسّن زمن الاستجابة وموثوقية العمل في بيئات اتصال متقطّع.

التقنيات الأساسية التي سنغطيها: Service Worker لعمل التطبيق أوفلاين، نظام تخزين وإدارة أوزان النماذج (CacheStorage / IndexedDB)، واجهة WASM أو محرك استدلال خفيف مثل نسخة WASM من llama.cpp أو محركات ONNX/WASM، وواجهة مستخدم بسيطة لإدخال النص والحصول على الفصحى المحوّلة.

لمعرفة أن WebGPU/WebNN تُعدان عامل تسريع رئيسي للاستدلال داخل المتصفح، اطلع على جهود تشغيل ONNX وTransformer.js عبر WebGPU، بالإضافة إلى وثائق WebGPU.

معمارية الحل ومكوّناته

سنبني التطبيق على المكوّنات التالية:

  • واجهة الويب (Frontend): صفحة HTML/JS (يمكن استخدام إطار مثل Svelte/React) مسؤولة عن إدخال النص، عرض النتائج، وإدارة حالة التحميل/التخزين.
  • Service Worker: يعالج التخزين المؤقت للملفات الثابتة وملف النموذج (model weights) ويُمكّن التطبيق من العمل أوفلاين وفق استراتيجيات caching مناسبة. يُرجى اتباع ممارسات PWA القياسية عند كتابة Service Worker.
  • محرك استدلال داخل المتصفح (WASM / WebGPU): مكوّن WASM مُجمَّع من مكتبة مثل llama.cpp / wllama أو محرك ONNX Runtime Web. هذا المحرك يستدعي الوزنات المحمّلة ويُنفّذ عمليات tokenization وinference. يُمكن الاستفادة من WebGPU أو WebNN عند توافرها لتسريع العمليات الحسابية.
  • تخزين النماذج والوزنات: تحميل ملف نموذج بصيغة مدمجة (GGUF/ONNX/quantized) ثم تخزينه في CacheStorage أو IndexedDB بعد التحميل الأول، مع استراتيجيات تحقق وإصدار (ETag / checksum) لتحديثه عند الحاجة.
  • Web Worker: تشغيل WASM بعيدًا عن الـmain thread لمنع تجميد واجهة المستخدم، والتواصل عبر postMessage.

هناك مشاريع وتجارب عملية تُظهر كيف يمكن تشغيل نسخ مصغّرة من LLMs في المتصفح باستخدام WASM وواجهات WebGPU، بما في ذلك ربطات WASM لـ llama.cpp (wllama) ومحركات WebLLM وONNX Runtime Web. هذه الموارد مفيدة كنقطة انطلاق.

PWA service worker offline code browser
صورة: AS Photography — Pexels

خطوات تنفيذية مختصرة مع أمثلة للشفرة

فيما يلي الخطوات الرئيسية مع مقتطفات توضيحية. الهدف أن يكون التطبيق بسيطًا وقابلًا للتوسع.

1) هيكل المشروع

  • /index.html — واجهة المستخدم
  • /app.js — منطق الواجهة وتحميل النموذج وتشغيل الاستدلال
  • /sw.js — Service Worker لإدارة الكاش والعمل أوفلاين
  • /wasm/engine.wasm — محرك الاستدلال المجمّع (مثلاً wllama أو ONNX Runtime Web)
  • /models/arabic_transformer.gguf — ملف النموذج المصغَّر (quantized)

2) Service Worker — استراتيجية تحميل النموذج وتخزينه

const CACHE_NAME = 'app-v1';
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll(['/','/index.html','/app.js','/wasm/engine.wasm']);
    })
  );
});
self.addEventListener('fetch', event => {
  // cache-first for app shell, network-first for model updates with fallback to cache
});

راجع أفضل ممارسات PWA لتجنب مشكلات cache-busting عند نشر تحديثات.

3) تحميل النموذج وتشغيل WASM في Web Worker

// main thread (app.js)
const worker = new Worker('inference-worker.js');
worker.postMessage({ type: 'load-model', url: '/models/arabic_transformer.gguf' });
worker.onmessage = e => {
  if (e.data.type === 'result') showResult(e.data.text);
};

// inference-worker.js
self.onmessage = async (e) => {
  if (e.data.type === 'load-model') {
    const resp = await fetch(e.data.url);
    const blob = await resp.arrayBuffer();
    // تحميل إلى الذاكرة وإرسالها إلى WASM engine
    // initWasmEngine(blob)...
  }
  if (e.data.type === 'infer') {
    const output = await runInference(e.data.input);
    postMessage({ type: 'result', text: output });
  }
};

تأكد من تشغيل محرك WASM خارج الـmain thread لأن عمليات الاستدلال قد تكون كثيفة CPU. إذا توفَّر WebGPU أو WebNN فابدأ بالسعي لاستخدامهما كخيار تسريع عبر ONNX Runtime Web أو محركات WebLLM.

نصائح أداء، حدود وحجم النموذج المأمول

نقاط يجب مراعاتها:

  • حجم النموذج: المتصفحات محدودة بالذاكرة، لذا اعمل على نماذج صغيرة جداً (عشرات إلى مئات ميغابايت بعد الـquantization) أو استخدم تقنيات distillation/quantization قبل النشر.
  • الكمّيّات (Quantization): تحويل النموذج إلى دقّة منخفضة (مثل int8 أو مخططات مخصصة) يقلّل الحجم ويُسرّع الاستدلال لكنه قد يؤثر على جودة التحويل بين اللهجات والفصحى.
  • WebGPU/WebNN كخيار تسريع: عند توافرها تقدّم WebGPU/WebNN تسريعاً كبيراً مقارنة بتشغيل كل شيء على CPU عبر WASM؛ لكن لا يعتمد التطبيق عليها كخيار وحيد—وفر مسارًا احتياطياً عبر WASM.
  • تحميل كسيناريو تدريجي: ضع تجربة مبنية على النصوص الصغيرة أولًا، وحمّل النموذج الكامل عند الحاجة، مع progress UI ووضعيات "خفيف/مُحسّن للبيانات المحمولة".
  • أمان وخصوصية: تشغيل النموذج محليًا يبقي البيانات على جهاز المستخدم، لكن تأكد من توقيع النموذج والتحقق من سلامته قبل التنفيذ لمنع استغلال ملفات WASM خبيثة.

ملحوظة عملية: المجتمع فتح مداخل عديدة لتشغيل LLMs خفيفة في المتصفح—مشروعات مثل wllama تُظهر كيفية ربط llama.cpp بـWASM لتشغيل نماذج مصغّرة محليًا. اطلع على أمثلة جاهزة قبل إعادة بناء كل شيء من الصفر.

خاتمة وخطوات قادمة

بهذه الورشة قُدمت خارطة طريق عملية لبناء PWA يعمل أوفلاين ويحوّل اللهجات العربية إلى فصحى داخل المتصفح باستخدام WASM، مع إمكانية تسريع عبر WebGPU/WebNN حيثما توفرت. التحديات الرئيسية تبقى حجم النماذج وجودة التحويل مقابل قيود الذاكرة والأداء على الأجهزة المحمولة.

خطوات مقترحة للتطوير المستقبلي:

  • تحضير مجموعة بيانات موازنة للهجات مختلفة لإعادة تدريب/تقطير نموذج صغير (distillation).
  • تجربة تنسيقات النماذج (GGUF/ONNX/MLC) وطرق quantization متعددة لقياس توازن الحجم/الدقة.
  • دمج آلية تحديث آمنة للنموذج (signed updates) وواجهة لإدارة الإصدارات من داخل PWA.

مصادر للقراءة والتطبيق العملي: وثائق ONNX Runtime Web وملفات عرض WebGPU بالإضافة إلى مستودعات wllama وllama.cpp لتجارب تشغيل LLM داخل المتصفح.

ملاحظة: تواريخ ودعم واجهات الويب (WebGPU/WebNN) تتقدّم بسرعة—راجع روابط المشاريع الرسمية للنسخ والمزودين المدعومين قبل اختيار الاعتماد على تسريع GPU داخل المتصفح.

إعلان

مقالات ذات صلة

Engineers in protective suits work on telescopic mirrors in a high-tech lab.

Wasm في المتصفح لمعالجة النص العربي والصور: تجارب أداء وأدوات عملية

دليل عملي لمطوري الويب: مقارنة أداء Rust/Wasm، Pyodide وWasmEdge لمعالجة النص العربي والصور داخل المتصفح دون خ…

An extreme close-up of colorful programming code on a computer screen, showcasing development and software debugging.

بناء مكونات RTL متقدّمة وأداء عالٍ في React وSvelte: دليل عملي للمطورين العرب

إرشادات عملية لبناء مكونات RTL عربية في React وSvelte: من توجيه HTML وCSS المنطقي إلى تحسين الخطوط، SSR، والاخ…

Laptop displaying source code with dual screens for software development.

قياس تجربة المستخدم لمواقع عربية: مقارنة أداء React وSvelte وSolid مع ممارسات RTL وخطوط الويب

مقارنة عملية لأداء مواقع عربية (LCP/INP/CLS) بين React وSvelte وSolid، مع أفضل ممارسات RTL وتحميل خطوط الويب ل…

Detailed close-up of a hand-drawn wireframe design on paper for a UX project.

WebAssembly لمعالجة النص العربي داخل المتصفّح: حالات استخدام متقدّمة وأداء WASI مقابل Wasm

دليل عملي لـWebAssembly لمعالجة النص العربي في المتصفّح: حالات استخدام، أدوات (ICU4X, ONNX, Pyodide)، مقارنة أ…

تشغيل نماذج تعلم الآلة في المتصفح باستخدام Pyodide وWASM: أمثلة على تحليل نص عربي دون سيرفر [Web Development > WebAssembly & Edge]

تشغيل نماذج تعلم الآلة في المتصفح باستخدام Pyodide وWASM: أمثلة عملية لتحليل نص عربي دون سيرفر

دليل لتشغيل معالجة النص العربي داخل المتصفح باستخدام Pyodide وWASM وONNX/WebNN — أمثلة عملية، تعليمات تحميل، و…

اختيار إطار العمل الأمامي لعام 2025 لمواقع عربية: React vs Svelte vs Solid — مقارنة أداء وتجربة المطور [Web Development > Frontend Frameworks]

اختيار إطار العمل الأمامي لمواقع عربية 2025: React أم Svelte أم Solid؟

مقارنة عملية بين React وSvelte وSolid لعام 2025 تركز على الأداء، SSR، دعم RTL، وتجربة المطور لتسريع مواقع عربي…