دانلود مدل های هوش مصنوعی با Background Fetch API

تاریخ انتشار: 20 فوریه 2025

دانلود مطمئن مدل های بزرگ هوش مصنوعی یک کار چالش برانگیز است. اگر کاربران اتصال اینترنتی خود را قطع کنند یا وب سایت یا برنامه وب شما را ببندند، فایل های مدل نیمه دانلود شده را از دست می دهند و پس از بازگشت به صفحه شما باید دوباره شروع به کار کنند. با استفاده از Background Fetch API به عنوان یک پیشرفت پیشرونده، می توانید تجربه کاربر را به میزان قابل توجهی بهبود بخشید.

Browser Support

  • کروم: 74.
  • لبه: 79.
  • فایرفاکس: پشتیبانی نمی شود.
  • سافاری: پشتیبانی نمی شود.

Source

ثبت نام کارگر خدماتی

API واکشی پس‌زمینه به برنامه شما نیاز دارد تا یک سرویس‌کار ثبت کند .

if ('serviceWorker' in navigator) {
  window.addEventListener('load', async () => {
    const registration = await navigator.serviceWorker.register('sw.js');
    console.log('Service worker registered for scope', registration.scope);
  });
}

واکشی پس‌زمینه را فعال کنید

همانطور که مرورگر واکشی می کند، پیشرفت را به کاربر نشان می دهد و روشی برای لغو دانلود به آنها ارائه می دهد. پس از تکمیل دانلود، مرورگر سرویس کارگر را راه اندازی می کند و برنامه می تواند با پاسخ اقدام کند.

Background Fetch API حتی می تواند واکشی را برای شروع در حالت آفلاین آماده کند. به محض اتصال مجدد کاربر، دانلود شروع می شود. اگر کاربر آفلاین شود، فرآیند متوقف می شود تا زمانی که کاربر دوباره آنلاین شود.

در مثال زیر، کاربر روی دکمه ای کلیک می کند تا Gemma 2B را دانلود کند. قبل از واکشی، بررسی می‌کنیم که آیا مدل قبلاً دانلود و ذخیره شده است یا خیر، بنابراین از منابع غیرضروری استفاده نمی‌کنیم. اگر کش نیست، واکشی پس‌زمینه را شروع می‌کنیم.

const FETCH_ID = 'gemma-2b';
const MODEL_URL =
  'https://storage.googleapis.com/jmstore/kaggleweb/grader/g-2b-it-gpu-int4.bin';

downloadButton.addEventListener('click', async (event) => {
  // If the model is already downloaded, return it from the cache.
  const modelAlreadyDownloaded = await caches.match(MODEL_URL);
  if (modelAlreadyDownloaded) {
    const modelBlob = await modelAlreadyDownloaded.blob();
    // Do something with the model.
    console.log(modelBlob);
    return;
  }

  // The model still needs to be downloaded.
  // Feature detection and fallback to classic `fetch()`.
  if (!('BackgroundFetchManager' in self)) {
    try {
      const response = await fetch(MODEL_URL);
      if (!response.ok || response.status !== 200) {
        throw new Error(`Download failed ${MODEL_URL}`);
      }
      const modelBlob = await response.blob();
      // Do something with the model.
      console.log(modelBlob);
      return;
    } catch (err) {
      console.error(err);
    }
  }

  // The service worker registration.
  const registration = await navigator.serviceWorker.ready;

  // Check if there's already a background fetch running for the `FETCH_ID`.
  let bgFetch = await registration.backgroundFetch.get(FETCH_ID);

  // If not, start a background fetch.
  if (!bgFetch) {
    bgFetch = await registration.backgroundFetch.fetch(FETCH_ID, MODEL_URL, {
      title: 'Gemma 2B model',
      icons: [
        {
          src: 'icon.png',
          size: '128x128',
          type: 'image/png',
        },
      ],
      downloadTotal: await getResourceSize(MODEL_URL),
    });
  }
});

تابع getResourceSize() اندازه بایت دانلود را برمی گرداند. شما می توانید این را با درخواست HEAD پیاده سازی کنید.

const getResourceSize = async (url) => {
  try {
    const response = await fetch(url, { method: 'HEAD' });
    if (response.ok) {
      return response.headers.get('Content-Length');
    }
    console.error(`HTTP error: ${response.status}`);
    return 0;
  } catch (error) {
    console.error('Error fetching content size:', error);
    return 0;
  }
};

گزارش پیشرفت دانلود

پس از شروع واکشی پس‌زمینه، مرورگر یک BackgroundFetchRegistration را برمی‌گرداند. شما می توانید از این برای اطلاع کاربر از پیشرفت دانلود، با رویداد progress استفاده کنید.

bgFetch.addEventListener('progress', (e) => {
  // There's no download progress yet.
  if (!bgFetch.downloadTotal) {
    return;
  }
  // Something went wrong.
  if (bgFetch.failureReason) {
    console.error(bgFetch.failureReason);
  }
  if (bgFetch.result === 'success') {
    return;
  }
  // Update the user about progress.
  console.log(`${bgFetch.downloaded} / ${bgFetch.downloadTotal}`);
});

کاربران و مشتری را از تکمیل واکشی مطلع کنید

وقتی واکشی پس‌زمینه با موفقیت انجام شد، سرویس‌کار برنامه‌تان یک رویداد backgroundfetchsuccess دریافت می‌کند.

کد زیر در سرویس کارگر قرار داده شده است. فراخوانی updateUI() نزدیک به پایان به شما امکان می‌دهد رابط مرورگر را به‌روزرسانی کنید تا کاربر را از واکشی موفق پس‌زمینه مطلع کنید. در نهایت، برای مثال با استفاده از postMessage() در مورد دانلود تمام شده به مشتری اطلاع دهید.

self.addEventListener('backgroundfetchsuccess', (event) => {
  // Get the background fetch registration.
  const bgFetch = event.registration;

  event.waitUntil(
    (async () => {
      // Open a cache named 'downloads'.
      const cache = await caches.open('downloads');
      // Go over all records in the background fetch registration.
      // (In the running example, there's just one record, but this way
      // the code is future-proof.)
      const records = await bgFetch.matchAll();
      // Wait for the response(s) to be ready, then cache it/them.
      const promises = records.map(async (record) => {
        const response = await record.responseReady;
        await cache.put(record.request, response);
      });
      await Promise.all(promises);

      // Update the browser UI.
      event.updateUI({ title: 'Model downloaded' });

      // Inform the clients that the model was downloaded.
      self.clients.matchAll().then((clientList) => {
        for (const client of clientList) {
          client.postMessage({
            message: 'download-complete',
            id: bgFetch.id,
          });
        }
      });
    })(),
  );
});

دریافت پیام از کارگر خدمات

برای دریافت پیام موفقیت آمیز ارسال شده در مورد دانلود کامل شده در مشتری، به رویدادهای message گوش دهید. پس از دریافت پیام از طرف سرویس دهنده، می توانید با مدل هوش مصنوعی کار کنید و آن را با Cache API ذخیره کنید.

navigator.serviceWorker.addEventListener('message', async (event) => {
  const cache = await caches.open('downloads');
  const keys = await cache.keys();
  for (const key of keys) {
    const modelBlob = await cache
      .match(key)
      .then((response) => response.blob());
    // Do something with the model.
    console.log(modelBlob);
  }
});

لغو واکشی پس‌زمینه

برای اینکه کاربر بتواند دانلود در حال انجام را لغو کند، از روش abort() BackgroundFetchRegistration استفاده کنید.

const registration = await navigator.serviceWorker.ready;
const bgFetch = await registration.backgroundFetch.get(FETCH_ID);
if (!bgFetch) {
  return;
}
await bgFetch.abort();

مدل را کش کنید

مدل های دانلود شده را در حافظه پنهان ذخیره کنید ، بنابراین کاربران شما فقط یک بار مدل را دانلود می کنند. در حالی که Background Fetch API تجربه دانلود را بهبود می‌بخشد، شما باید همیشه سعی کنید از کوچک‌ترین مدل ممکن در هوش مصنوعی سمت مشتری استفاده کنید.

این APIها با هم به شما کمک می کنند تا تجربه هوش مصنوعی بهتری را برای کاربران خود ایجاد کنید.

نسخه ی نمایشی

شما می توانید اجرای کامل این رویکرد را در دمو و کد منبع آن مشاهده کنید.

پانل برنامه Chrome DevTools برای دانلود Background Fetch باز می شود.
با Chrome DevTools، می‌توانید رویدادهای مربوط به واکشی پس‌زمینه در حال انجام را پیش‌نمایش کنید. نسخه آزمایشی یک بارگیری در حال انجام را نشان می دهد که 17.54 میلیون مگابایت انجام شده است، در مجموع 1.26 گیگابایت. نشانگر دانلود مرورگر نیز دانلود در حال انجام را نشان می دهد.

قدردانی

این راهنما توسط فرانسوا بوفور ، آندره باندارا ، سباستین بنز ، مود نالپاس و الکساندرا کلپر بررسی شده است.