Download src/cache.js from ProCreations/minicpm5-2b-webgpu: direct link, hf CLI and curl.
- Browser
- Download file 3.72 kB
-
https://huggingface.co/spaces/ProCreations/minicpm5-2b-webgpu/resolve/main/src/cache.js
- Command line
-
hf download hf://spaces/ProCreations/minicpm5-2b-webgpu/src/cache.js
-
curl -L -o cache.js https://huggingface.co/spaces/ProCreations/minicpm5-2b-webgpu/resolve/main/src/cache.js
3.72 kB
| // Wllama-compatible OPFS storage with bounded 4 MiB writes instead of one | |
| // main-thread/worker round trip per network packet. Metadata format and keys | |
| // remain Wllama's, so complete existing cache entries continue to work. | |
| // Let session-only inference run even when this browser has no OPFS support. | |
| export class UnavailableStorage { | |
| isSupported(){return true;} | |
| async read(){return null;} | |
| async getSize(){return -1;} | |
| async list(){return [];} | |
| async delete(){} | |
| async write(){throw new Error('Model storage is unavailable in this browser. Turn off Save model in browser and try again.');} | |
| } | |
| export class BufferedOPFS { | |
| isSupported(){return !!navigator.storage?.getDirectory;} | |
| async directory(){return (await navigator.storage.getDirectory()).getDirectoryHandle('cache',{create:true});} | |
| async read(key){try{return await(await(await this.directory()).getFileHandle(key)).getFile();}catch(e){if(e.name==='NotFoundError')return null;throw e;}} | |
| async getSize(key){return (await this.read(key))?.size??-1;} | |
| async list(){const entries=[];for await(const [key,h]of(await this.directory()).entries())if(h.kind==='file')entries.push({key,size:(await h.getFile()).size});return entries;} | |
| async delete(key){try{await(await this.directory()).removeEntry(key);}catch(e){if(e.name!=='NotFoundError')throw e;}} | |
| async write(key,stream){ | |
| const worker=new Worker(new URL('./cache-worker.js',import.meta.url),{type:'module'}); | |
| const call=(data,transfer=[])=>new Promise((resolve,reject)=>{worker.onmessage=({data})=>data.error?reject(new Error(data.error)):resolve();worker.onerror=e=>reject(new Error(e.message));worker.postMessage(data,transfer);}); | |
| const reader=stream.getReader();let slab=new Uint8Array(4*1024*1024),used=0,closed=false; | |
| try{ | |
| await call({action:'open',key}); | |
| while(true){ | |
| const {done,value}=await reader.read();if(done)break; | |
| let offset=0;while(offset<value.byteLength){const n=Math.min(slab.byteLength-used,value.byteLength-offset);slab.set(value.subarray(offset,offset+n),used);used+=n;offset+=n; | |
| if(used===slab.byteLength){await call({action:'write',buffer:slab.buffer},[slab.buffer]);slab=new Uint8Array(4*1024*1024);used=0;} | |
| } | |
| } | |
| if(used){const tail=slab.slice(0,used);await call({action:'write',buffer:tail.buffer},[tail.buffer]);} | |
| await call({action:'close'});closed=true; | |
| }finally{if(!closed){await reader.cancel().catch(()=>{});await call({action:'close'}).catch(()=>{});}reader.releaseLock();worker.terminate();} | |
| } | |
| } | |
| // Retain the existing weight-cache keys so earlier opt-in downloads still work. | |
| export class WeightCache { | |
| constructor(){const storage=new BufferedOPFS();this.storage=storage.isSupported()?storage:new UnavailableStorage();} | |
| async getNameFromURL(url){const hash=await crypto.subtle.digest('SHA-1',new TextEncoder().encode(url));return [...new Uint8Array(hash)].map(b=>b.toString(16).padStart(2,'0')).join('')+'_'+url.split('/').pop();} | |
| open(name){return this.storage.read(name);} | |
| async list(){ | |
| const files=await this.storage.list(),metadata=new Map(); | |
| for(const file of files){if(file.key.startsWith('__metadata__')){const blob=await this.storage.read(file.key);try{metadata.set(file.key.slice(12),JSON.parse(await blob.text()));}catch{}}} | |
| return files.filter(f=>!f.key.startsWith('__metadata__')).map(f=>({name:f.key,size:f.size,metadata:metadata.get(f.key)||{}})); | |
| } | |
| async write(name,stream,metadata){await this.storage.write(name,stream);await this.storage.write('__metadata__'+name,new Blob([JSON.stringify(metadata)]).stream());} | |
| async deleteMany(predicate){for(const entry of await this.list())if(predicate(entry)){await this.storage.delete(entry.name);await this.storage.delete('__metadata__'+entry.name);}} | |
| } | |