Yayınlanma tarihi: 20 Şubat 2025
Büyük yapay zeka modellerini güvenilir bir şekilde indirmek zorlu bir görevdir. Kullanıcılar internet bağlantılarını kaybederse veya web sitenizi ya da web uygulamanızı kapatırsa kısmen indirilmiş model dosyalarını kaybeder ve sayfanıza döndüklerinde baştan başlamaları gerekir. Background Fetch API'yi aşamalı geliştirme olarak kullanarak kullanıcı deneyimini önemli ölçüde iyileştirebilirsiniz.
Hizmet çalışanı kaydetme
Arka planda getirme API'si, uygulamanızın bir hizmet çalışanı kaydetmesini gerektirir.
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);
});
}
Arka planda getirme işlemini tetikleme
Tarayıcı, getirme işlemi sırasında kullanıcıya ilerleme durumunu gösterir ve indirmeyi iptal etme yöntemi sunar. İndirme işlemi tamamlandığında tarayıcı, hizmet çalışanını başlatır ve uygulama, yanıtla ilgili işlem yapabilir.
Background Fetch API, getirme işlemini çevrimdışıyken başlayacak şekilde bile hazırlayabilir. Kullanıcı yeniden bağlandığında indirme işlemi başlar. Kullanıcı çevrimdışı olursa işlem, kullanıcı tekrar çevrimiçi olana kadar duraklatılır.
Aşağıdaki örnekte, kullanıcı Gemma 2B'yi indirmek için bir düğmeyi tıklıyor. Getirme işleminden önce modelin daha önce indirilip önbelleğe alınıp alınmadığını kontrol ederiz. Böylece gereksiz kaynakları kullanmayız. Önbelleğe alınmamışsa arka planda getirme işlemi başlatılır.
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() işlevi, indirmenin bayt boyutunu döndürür. Bunu HEAD isteği göndererek uygulayabilirsiniz.
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;
}
};
Rapor indirme işleminin ilerleme durumu
Arka planda getirme işlemi başladığında tarayıcı BackgroundFetchRegistration döndürür.
Kullanıcıyı indirme işlemiyle ilgili bilgilendirmek için progress etkinliğini kullanabilirsiniz.
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}`);
});
Kullanıcıları ve istemciyi getirme işleminin tamamlanması konusunda bilgilendirme
Arka planda getirme işlemi başarılı olduğunda uygulamanızın hizmet çalışanı bir backgroundfetchsuccess etkinliği alır.
Aşağıdaki kod, hizmet çalışanına dahil edilir. Sona yakın olan updateUI() çağrısı, tarayıcının arayüzünü güncelleyerek kullanıcıyı başarılı arka plan getirme işlemi hakkında bilgilendirmenize olanak tanır. Son olarak, postMessage() gibi bir yöntem kullanarak müşteriyi tamamlanan indirme işlemi hakkında bilgilendirin.
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,
});
}
});
})(),
);
});
Service worker'dan mesaj alma
İstemcide tamamlanan indirme işlemiyle ilgili gönderilen başarı mesajını almak için message etkinliklerini dinleyin. Service worker'dan mesajı aldıktan sonra yapay zeka modeliyle çalışabilir ve modeli Cache API ile saklayabilirsiniz.
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);
}
});
Arka planda getirme işlemini iptal etme
Kullanıcının devam eden bir indirme işlemini iptal etmesine izin vermek için BackgroundFetchRegistration sınıfının abort() yöntemini kullanın.
const registration = await navigator.serviceWorker.ready;
const bgFetch = await registration.backgroundFetch.get(FETCH_ID);
if (!bgFetch) {
return;
}
await bgFetch.abort();
Modeli önbelleğe alma
İndirilen modelleri önbelleğe alın. Böylece kullanıcılarınız modeli yalnızca bir kez indirir. Arka planda getirme API'si indirme deneyimini iyileştirse de istemci taraflı yapay zekada her zaman mümkün olan en küçük modeli kullanmayı hedeflemelisiniz.
Bu API'ler, kullanıcılarınız için daha iyi bir istemci tarafı yapay zeka deneyimi oluşturmanıza yardımcı olur.
Demo
Bu yaklaşımın eksiksiz bir uygulamasını demoda ve kaynak kodunda görebilirsiniz.
Teşekkür
Bu kılavuz; François Beaufort, Andre Bandarra, Sebastian Benz, Maud Nalpas ve Alexandra Klepper tarafından incelenmiştir.