Çoğu yapay zeka modelinin en az bir ortak noktası vardır: Bunlar internet üzerinden aktarılan bir kaynak için oldukça büyüktür. En küçük MediaPipe nesne algılama modelinin (SSD MobileNetV2 float16
) ağırlığı 5,6 MB, en büyüğünün ağırlığı ise 25 MB'tır.
gemma-2b-it-gpu-int4.bin
adlı açık kaynak LLM'nin saati 1,35 GB'tır.Bu boyut, LLM için çok küçük olarak kabul edilir.
Üretken yapay zeka modelleri çok büyük önem taşıyor. Günümüzde yapay zeka kullanımının
çoğunlukla bulutta gerçekleşmesinin nedeni budur. Uygulamalar giderek doğrudan cihaz üzerinde son derece optimize edilmiş modeller çalıştırıyor. Tarayıcıda çalışan LLM'lerin demoları mevcut olsa da, aşağıda çalışan diğer modellere ilişkin bazı üretim düzeyinde örnekler verilmiştir:
- Adobe Photoshop, akıllı nesne seçim aracı için cihaz üzerinde
Conv2D
modelinin bir varyantını çalıştırır. - Google Meet, arka plan bulanıklaştırma özelliği için kişi segmentasyonu için
MobileNetV3-small
modelinin optimize edilmiş bir sürümünü çalıştırır. - Tokopedia, hizmetine geçersiz kayıtları önlemek amacıyla gerçek zamanlı yüz algılama için
MediaPipeFaceDetector-TFJS
modelini çalıştırır. - Google Colab, kullanıcıların Colab not defterlerinde sabit disklerindeki modelleri kullanmalarına olanak tanır.
Uygulamalarınızın gelecekte daha hızlı kullanıma sunulmasını sağlamak için örtülü HTTP tarayıcı önbelleğine güvenmek yerine, model verilerini cihaz üzerinde açık bir şekilde önbelleğe almalısınız.
Bu kılavuzda chatbot oluşturmak için gemma-2b-it-gpu-int4.bin model
kullanılsa da bu yaklaşım, diğer modellere ve cihazdaki diğer kullanım alanlarına uyacak şekilde genelleştirilebilir. Bir uygulamayı bir modele bağlamanın en yaygın yolu, modeli geri kalan uygulama kaynaklarıyla birlikte sunmaktır. Yayını optimize etmek
kritik önemdedir.
Doğru önbellek üstbilgilerini yapılandırma
Sunucunuzdan yapay zeka modelleri sunuyorsanız doğru Cache-Control
üstbilgisinin yapılandırılması önemlidir. Aşağıdaki örnekte, uygulamanızın ihtiyaçlarına göre geliştirebileceğiniz sağlam bir varsayılan ayar gösterilmektedir.
Cache-Control: public, max-age=31536000, immutable
Bir AI modelinin yayınlanan her sürümü statik bir kaynaktır. Hiç değişmeyen içeriğe, istek URL'sinde önbellek bozma ile birlikte uzun bir max-age
değeri verilmelidir. Modeli güncellemeniz gerekiyorsa yeni bir URL vermeniz gerekir.
Kullanıcı sayfayı yeniden yüklediğinde, sunucu içeriğin kararlı olduğunu bilse bile istemci bir yeniden doğrulama isteği gönderir. immutable
yönergesinde, içerik değişmeyeceğinden yeniden doğrulamanın gerekli olmadığı açıkça belirtilir. immutable
yönergesi, tarayıcılar ve ara önbellek veya proxy sunucuları tarafından geniş ölçüde desteklenmemektedir. Ancak bunu, evrensel olarak anlaşılan max-age
yönergesiyle birleştirdiğinizde maksimum uyumluluk sağlayabilirsiniz. public
yanıt yönergesi, yanıtın paylaşılan bir önbellekte depolanabileceğini belirtir.
![](https://developer.chrome.com/static/docs/ai/cache-models/images/cache-control.png?authuser=6&hl=tr)
Cache-Control
üretim başlıklarını gösterir.
(Kaynak)
İstemci tarafında AI modellerini önbelleğe al
Bir yapay zeka modeli sunarken modeli tarayıcıda açık bir şekilde önbelleğe almanız önemlidir. Böylece, kullanıcı uygulamayı yeniden yükledikten sonra model verileri kullanılabilir hale gelir.
Bunu başarmak için kullanabileceğiniz birkaç teknik vardır. Aşağıdaki kod örnekleri için her model dosyasının bellekte blob
adlı bir Blob
nesnesinde depolandığını varsayın.
Performansı anlamak için her kod örneğine performance.mark()
ve performance.measure()
yöntemleriyle ek açıklama eklenir. Bu ölçümler cihaza bağlı olup genelleştirilemez.
![](https://developer.chrome.com/static/docs/ai/cache-models/images/usage-graph.jpg?authuser=6&hl=tr)
Tarayıcıda AI modellerini önbelleğe almak için şu API'lerden birini kullanmayı seçebilirsiniz: Cache API, Origin Private File System API ve IndexedDB API. Genel öneri, Cache API'nin kullanılmasıdır, ancak bu kılavuzda tüm seçeneklerin avantajları ve dezavantajları ele alınmaktadır.
Önbellek API'si
Cache API, uzun ömürlü bellekte önbelleğe alınan Request
ve Response
nesne çiftleri için kalıcı depolama alanı sağlar. Hizmet Çalışanları spesifikasyonunda tanımlanmış olsa da bu API'yi ana iş parçacığından veya normal bir çalışandan kullanabilirsiniz. Hizmet çalışanı bağlamı dışında kullanmak için Request
nesnesi yerine sentetik URL ile eşlenmiş sentetik Response
nesnesiyle Cache.put()
yöntemini çağırın.
Bu kılavuzda, bellek içi blob
olduğu varsayılmıştır. Önbellek anahtarı olarak sahte bir URL ve blob
temelinde sentetik bir Response
kullanın. Modeli doğrudan indirirseniz fetch()
isteği göndererek elde edeceğiniz Response
değerini kullanırsınız.
Örneğin, bir model dosyasının Cache API ile nasıl depolanacağı ve geri yükleneceği aşağıda açıklanmıştır.
const storeFileInSWCache = async (blob) => {
try {
performance.mark('start-sw-cache-cache');
const modelCache = await caches.open('models');
await modelCache.put('model.bin', new Response(blob));
performance.mark('end-sw-cache-cache');
const mark = performance.measure(
'sw-cache-cache',
'start-sw-cache-cache',
'end-sw-cache-cache'
);
console.log('Model file cached in sw-cache.', mark.name, mark.duration.toFixed(2));
} catch (err) {
console.error(err.name, err.message);
}
};
const restoreFileFromSWCache = async () => {
try {
performance.mark('start-sw-cache-restore');
const modelCache = await caches.open('models');
const response = await modelCache.match('model.bin');
if (!response) {
throw new Error(`File model.bin not found in sw-cache.`);
}
const file = await response.blob();
performance.mark('end-sw-cache-restore');
const mark = performance.measure(
'sw-cache-restore',
'start-sw-cache-restore',
'end-sw-cache-restore'
);
console.log(mark.name, mark.duration.toFixed(2));
console.log('Cached model file found in sw-cache.');
return file;
} catch (err) {
throw err;
}
};
Kaynak Gizli Dosya Sistemi API'sı
Kaynak Gizli Dosya Sistemi (OPFS), depolama uç noktası için nispeten yeni bir standarttır. Bu, sayfanın kaynağına özeldir ve normal dosya sisteminin aksine kullanıcı tarafından görülmez. Performans açısından son derece optimize edilmiş özel bir dosyaya erişim sağlar ve içeriğine yazma erişimi sunar.
Örneğin, bir model dosyasının OPFS'de nasıl depolanacağı ve geri yükleneceği aşağıda açıklanmıştır.
const storeFileInOPFS = async (blob) => {
try {
performance.mark('start-opfs-cache');
const root = await navigator.storage.getDirectory();
const handle = await root.getFileHandle('model.bin', { create: true });
const writable = await handle.createWritable();
await blob.stream().pipeTo(writable);
performance.mark('end-opfs-cache');
const mark = performance.measure(
'opfs-cache',
'start-opfs-cache',
'end-opfs-cache'
);
console.log('Model file cached in OPFS.', mark.name, mark.duration.toFixed(2));
} catch (err) {
console.error(err.name, err.message);
}
};
const restoreFileFromOPFS = async () => {
try {
performance.mark('start-opfs-restore');
const root = await navigator.storage.getDirectory();
const handle = await root.getFileHandle('model.bin');
const file = await handle.getFile();
performance.mark('end-opfs-restore');
const mark = performance.measure(
'opfs-restore',
'start-opfs-restore',
'end-opfs-restore'
);
console.log('Cached model file found in OPFS.', mark.name, mark.duration.toFixed(2));
return file;
} catch (err) {
throw err;
}
};
IndexedDB API'sı
IndexedDB, rastgele verilerin tarayıcıda kalıcı şekilde depolanması için iyi bilinen bir standarttır. Karmaşık API'siyle bilinse de idb-keyval gibi bir sarmalayıcı kitaplığı kullanarak IndexedDB'yi klasik bir anahtar/değer deposu gibi kullanabilirsiniz.
Örneğin:
import { get, set } from 'https://cdn.jsdelivr.net/npm/idb-keyval@latest/+esm';
const storeFileInIDB = async (blob) => {
try {
performance.mark('start-idb-cache');
await set('model.bin', blob);
performance.mark('end-idb-cache');
const mark = performance.measure(
'idb-cache',
'start-idb-cache',
'end-idb-cache'
);
console.log('Model file cached in IDB.', mark.name, mark.duration.toFixed(2));
} catch (err) {
console.error(err.name, err.message);
}
};
const restoreFileFromIDB = async () => {
try {
performance.mark('start-idb-restore');
const file = await get('model.bin');
if (!file) {
throw new Error('File model.bin not found in IDB.');
}
performance.mark('end-idb-restore');
const mark = performance.measure(
'idb-restore',
'start-idb-restore',
'end-idb-restore'
);
console.log('Cached model file found in IDB.', mark.name, mark.duration.toFixed(2));
return file;
} catch (err) {
throw err;
}
};
Depolama alanını kalıcı olarak işaretle
Kalıcı depolama alanını kullanma izni istemek için bu önbelleğe alma yöntemlerinden herhangi birinin sonunda navigator.storage.persist()
çağrısı yapın. Bu yöntem, izin verilirse true
, aksi takdirde false
olarak çözümlenen bir taahhüt döndürür. Tarayıcı, tarayıcıya özgü kurallara bağlı olarak isteği yerine getirebilir veya etmeyebilir.
if ('storage' in navigator && 'persist' in navigator.storage) {
try {
const persistent = await navigator.storage.persist();
if (persistent) {
console.log("Storage will not be cleared except by explicit user action.");
return;
}
console.log("Storage may be cleared under storage pressure.");
} catch (err) {
console.error(err.name, err.message);
}
}
Özel durum: Sabit diskte model kullanma
Tarayıcı depolama alanına alternatif olarak AI modellerine doğrudan kullanıcının sabit diskinden referans verebilirsiniz. Bu teknik, araştırma odaklı uygulamaların belirli modelleri tarayıcıda çalıştırmanın uygulanabilirliğini sergilemesine veya sanatçıların uzman yaratıcılık uygulamalarında kendi kendine eğitilen modelleri kullanmalarına yardımcı olabilir.
File System Access API
File System Access API ile sabit diskteki dosyaları açabilir ve IndexedDB'ye devam edebileceğiniz bir FileSystemFileHandle elde edebilirsiniz.
Bu kalıpta, kullanıcının model dosyasına yalnızca bir kez erişim izni vermesi gerekir. Kalıcı izinler sayesinde kullanıcı, dosyaya kalıcı olarak erişim izni verebilir. Uygulama yeniden yüklendikten ve fare tıklaması gibi gerekli bir kullanıcı hareketinin ardından FileSystemFileHandle
, sabit diskteki dosyaya erişim sağlayarak IndexedDB'den geri yüklenebilir.
Dosya erişim izinleri sorgulanır ve gerekirse istenir. Bu sayede, gelecekteki yeniden yükleme işlemleri için bu sorunsuz bir süreç sunulur. Aşağıdaki örnekte, sabit diskten bir dosya için herkese açık kullanıcı adının nasıl alınacağı ve ardından bu tutma yerinin nasıl depolanıp geri yükleneceği gösterilmektedir.
import { fileOpen } from 'https://cdn.jsdelivr.net/npm/browser-fs-access@latest/dist/index.modern.js';
import { get, set } from 'https://cdn.jsdelivr.net/npm/idb-keyval@latest/+esm';
button.addEventListener('click', async () => {
try {
const file = await fileOpen({
extensions: ['.bin'],
mimeTypes: ['application/octet-stream'],
description: 'AI model files',
});
if (file.handle) {
// It's an asynchronous method, but no need to await it.
storeFileHandleInIDB(file.handle);
}
return file;
} catch (err) {
if (err.name !== 'AbortError') {
console.error(err.name, err.message);
}
}
});
const storeFileHandleInIDB = async (handle) => {
try {
performance.mark('start-file-handle-cache');
await set('model.bin.handle', handle);
performance.mark('end-file-handle-cache');
const mark = performance.measure(
'file-handle-cache',
'start-file-handle-cache',
'end-file-handle-cache'
);
console.log('Model file handle cached in IDB.', mark.name, mark.duration.toFixed(2));
} catch (err) {
console.error(err.name, err.message);
}
};
const restoreFileFromFileHandle = async () => {
try {
performance.mark('start-file-handle-restore');
const handle = await get('model.bin.handle');
if (!handle) {
throw new Error('File handle model.bin.handle not found in IDB.');
}
if ((await handle.queryPermission()) !== 'granted') {
const decision = await handle.requestPermission();
if (decision === 'denied' || decision === 'prompt') {
throw new Error(Access to file model.bin.handle not granted.');
}
}
const file = await handle.getFile();
performance.mark('end-file-handle-restore');
const mark = performance.measure(
'file-handle-restore',
'start-file-handle-restore',
'end-file-handle-restore'
);
console.log('Cached model file handle found in IDB.', mark.name, mark.duration.toFixed(2));
return file;
} catch (err) {
throw err;
}
};
Bu yöntemler birlikte kullanılabilir. İkiniz de tarayıcıdaki bir modeli açık bir şekilde önbelleğe aldığınız ve kullanıcının sabit diskindeki bir modeli kullandığınız bir durum söz konusu olabilir.
Demo
MediaPipe LLM demosunda üç normal kılıf depolama yöntemini ve uygulanan sabit disk yöntemini de görebilirsiniz.
Bonus: Büyük dosyaları parçalar halinde indirin
İnternetten büyük bir yapay zeka modeli indirmeniz gerekiyorsa indirmeyi farklı parçalara paralel hale getirin ve ardından istemcide tekrar birleştirin.
Aşağıda, kodunuzda kullanabileceğiniz bir yardımcı işlev verilmiştir. Bunu yalnızca url
geçirmeniz gerekir. chunkSize
(varsayılan: 5 MB), maxParallelRequests
(varsayılan: 6), progressCallback
işlevi (downloadedBytes
ve toplam fileSize
değerini raporlar) ve AbortSignal
sinyali için signal
isteğe bağlıdır.
Aşağıdaki işlevi projenize kopyalayabilir veya npm paketinden fetch-in-chunks
paketini yükleyebilirsiniz.
async function fetchInChunks(
url,
chunkSize = 5 * 1024 * 1024,
maxParallelRequests = 6,
progressCallback = null,
signal = null
) {
// Helper function to get the size of the remote file using a HEAD request
async function getFileSize(url, signal) {
const response = await fetch(url, { method: 'HEAD', signal });
if (!response.ok) {
throw new Error('Failed to fetch the file size');
}
const contentLength = response.headers.get('content-length');
if (!contentLength) {
throw new Error('Content-Length header is missing');
}
return parseInt(contentLength, 10);
}
// Helper function to fetch a chunk of the file
async function fetchChunk(url, start, end, signal) {
const response = await fetch(url, {
headers: { Range: `bytes=${start}-${end}` },
signal,
});
if (!response.ok && response.status !== 206) {
throw new Error('Failed to fetch chunk');
}
return await response.arrayBuffer();
}
// Helper function to download chunks with parallelism
async function downloadChunks(
url,
fileSize,
chunkSize,
maxParallelRequests,
progressCallback,
signal
) {
let chunks = [];
let queue = [];
let start = 0;
let downloadedBytes = 0;
// Function to process the queue
async function processQueue() {
while (start < fileSize) {
if (queue.length < maxParallelRequests) {
let end = Math.min(start + chunkSize - 1, fileSize - 1);
let promise = fetchChunk(url, start, end, signal)
.then((chunk) => {
chunks.push({ start, chunk });
downloadedBytes += chunk.byteLength;
// Update progress if callback is provided
if (progressCallback) {
progressCallback(downloadedBytes, fileSize);
}
// Remove this promise from the queue when it resolves
queue = queue.filter((p) => p !== promise);
})
.catch((err) => {
throw err;
});
queue.push(promise);
start += chunkSize;
}
// Wait for at least one promise to resolve before continuing
if (queue.length >= maxParallelRequests) {
await Promise.race(queue);
}
}
// Wait for all remaining promises to resolve
await Promise.all(queue);
}
await processQueue();
return chunks.sort((a, b) => a.start - b.start).map((chunk) => chunk.chunk);
}
// Get the file size
const fileSize = await getFileSize(url, signal);
// Download the file in chunks
const chunks = await downloadChunks(
url,
fileSize,
chunkSize,
maxParallelRequests,
progressCallback,
signal
);
// Stitch the chunks together
const blob = new Blob(chunks);
return blob;
}
export default fetchInChunks;
Sizin için doğru yöntemi seçin
Bu rehberde, yapay zeka modellerini tarayıcıda etkili bir şekilde önbelleğe almayla ilgili çeşitli yöntemler ele alınmıştır. Bu yöntem, kullanıcının deneyimini ve uygulamanızın performansını iyileştirmek açısından çok önemlidir. Chrome depolama ekibi, yapay zeka modellerine hızlı erişim sağlamak, yükleme sürelerini kısaltmak ve yanıt verme süresini iyileştirmek amacıyla optimum performans için Cache API'yi önerir.
OPFS ve IndexedDB daha az kullanılabilir seçeneklerdir. Verilerin depolanabilmesi için OPFS ve IndexedDB API'lerinin verileri serileştirmesi gerekir. IndexedDB'nin veriler alındığında verilerde seri durumdan çıkarması da gerekir. Bu, bu verileri büyük modelleri depolamak için en kötü yer haline getirir.
File System Access API, niş uygulamalar için kullanıcının cihazındaki dosyalara doğrudan erişim imkanı sunar. Bu özellik, kendi AI modellerini yöneten kullanıcılar için idealdir.
Yapay zeka modelinizin güvenliğini sağlamanız gerekiyorsa modelinizi sunucuda tutun. İstemcide depolandıktan sonra, Geliştirici Araçları veya OFPS DevTools uzantısı ile hem Cache hem de IndexedDB'den veri ayıklamak çok basittir. Bu depolama API'lerinin güvenlikleri doğası gereği eşittir. Modelin şifrelenmiş bir sürümünü depolamak isteyebilirsiniz. Ancak daha sonra, müdahale edilmesi mümkün olabilecek şifre çözme anahtarını istemciye aktarmanız gerekir. Bu, kötü bir oyuncunun modelini çalmanın biraz daha zor olduğu, ancak imkansız olmadığı anlamına gelir.
Uygulamanızın şartlarına, hedef kitle davranışına ve kullanılan yapay zeka modellerinin özelliklerine uygun bir önbelleğe alma stratejisi seçmenizi öneririz. Bu, uygulamalarınızın çeşitli ağ koşulları ve sistem kısıtlamaları altında duyarlı ve sağlam olmasını sağlar.
Teşekkür
Bu inceleme; Joshua Bell, Reilly Grant, Evan Stade, Nathan Memmott, Austin Sullivan, Etienne Noël, André Bandarra, Alexandra Klepper, François Beaufort, Paul Kinlan ve Rachel Andrew tarafından incelenmiştir.