Yayınlanma tarihi: 20 Şubat 2025
Büyük yapay zeka modellerini güvenilir bir şekilde indirmek zor bir iştir. Kullanıcılar internet bağlantılarını kaybederse veya web sitenizi ya da web uygulamanızı kapatırsa kısmen indirilen model dosyalarını kaybeder ve sayfanıza geri döndüklerinde baştan başlamak zorunda kalırlar. Background Fetch API'yi aşamalı bir iyileştirme olarak kullanarak kullanıcı deneyimini önemli ölçüde iyileştirebilirsiniz.
Hizmet çalışanı kaydetme
Arka Planda Getirme API'si, uygulamanızın bir Service Worker kaydettirmesini 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 getirmeyi tetikleme
Tarayıcı, verileri getirirken kullanıcıya ilerleme durumunu gösterir ve indirme işlemini iptal etmeleri için bir yöntem sunar. İndirme işlemi tamamlandığında tarayıcı servis çalışanını başlatır ve uygulama, yanıtla işlem yapabilir.
Arka Planda Getirme API'si, getirme işlemini çevrimdışıyken başlatılacak şekilde bile hazırlayabilir. Kullanıcı yeniden bağlanır bağlanmaz indirme işlemi başlar. Kullanıcı çevrimdışı olursa işlem, kullanıcı tekrar çevrimdışı olana kadar duraklatılır.
Aşağıdaki örnekte, kullanıcı Gemma 2B'yi indirmek için bir düğmeyi tıklar. Göndermeden ö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şlemini başlatırız.
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, indirme işleminin 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ı bir BackgroundFetchRegistration
döndürür.
progress
etkinliğini kullanarak kullanıcıyı indirme işleminin ilerleme durumu hakkında bilgilendirebilirsiniz.
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 tamamlandığı konusunda bilgilendirme
Arka planda getirme işlemi başarılı olduğunda uygulamanızın servis çalışanı bir backgroundfetchsuccess
etkinliği alır.
Aşağıdaki kod, hizmet işleyiciye dahil edilmiştir. Sonlara doğru yapılan updateUI()
çağrısı, kullanıcıyı arka planda başarılı bir şekilde getirilen veri hakkında bilgilendirmek için tarayıcının arayüzünü güncellemenize olanak tanır. Son olarak, indirme işleminin tamamlandığı hakkında müşteriyi bilgilendirin (ör. postMessage()
kullanarak).
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,
});
}
});
})(),
);
});
Hizmet çalışanından mesaj alma
İndirme işleminin tamamlanmasıyla ilgili gönderilen başarı mesajını istemcide almak için message
etkinliklerini dinleyin. Hizmet çalışanından mesajı aldıktan sonra yapay zeka modeliyle çalışabilir ve 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
Kullanıcılarınızın modeli yalnızca bir kez indirmesi için indirilen modelleri önbelleğe alın. Arka Planda Getirme API'si indirme deneyimini iyileştirse de istemci tarafı yapay zekada her zaman mümkün olan en küçük modeli kullanmayı hedeflemeniz gerekir.
Bu API'ler birlikte, kullanıcılarınıza daha iyi bir istemci tarafı yapay zeka deneyimi sunmanıza yardımcı olur.
Demo
Bu yaklaşımın tam bir uygulamasını demo ve kaynak kodunda görebilirsiniz.

Teşekkür ederiz
Bu kılavuz, François Beaufort, Andre Bandarra, Sebastian Benz, Maud Nalpas ve Alexandra Klepper tarafından incelendi.