@huggingface/transformers
Version:
State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server!
91 lines (81 loc) • 4.07 kB
JavaScript
import { apis, env } from '../env.js';
import { FileCache } from './cache/FileCache.js';
import { logger } from './logger.js';
import { CrossOriginStorage } from './cache/CrossOriginStorageCache.js';
/**
* @typedef {Object} CacheInterface
* @property {(request: string) => Promise<Response|import('./hub/FileResponse.js').FileResponse|undefined|string>} match
* Checks if a request is in the cache and returns the cached response if found.
* @property {(request: string, response: Response, progress_callback?: (data: {progress: number, loaded: number, total: number}) => void) => Promise<void>} put
* Adds a response to the cache.
* @property {(request: string) => Promise<boolean>} [delete]
* Deletes a request from the cache. Returns true if deleted, false otherwise.
*/
/**
* Retrieves an appropriate caching backend based on the environment configuration.
* Attempts to use custom cache, browser cache, or file system cache in that order of priority.
* @returns {Promise<CacheInterface | null>}
* @param file_cache_dir {string|null} Path to a directory in which a downloaded pretrained model configuration should be cached if using the file system cache.
*/
export async function getCache(file_cache_dir = null) {
// First, check if the a caching backend is available
// If no caching mechanism available, will download the file every time
let cache = null;
if (env.useCustomCache) {
// Allow the user to specify a custom cache system.
if (!env.customCache) {
throw Error('`env.useCustomCache=true`, but `env.customCache` is not defined.');
}
// Check that the required methods are defined:
if (!env.customCache.match || !env.customCache.put) {
throw new Error(
'`env.customCache` must be an object which implements the `match` and `put` functions of the Web Cache API. ' +
'For more information, see https://developer.mozilla.org/en-US/docs/Web/API/Cache',
);
}
cache = env.customCache;
}
if (!cache && env.experimental_useCrossOriginStorage && CrossOriginStorage.isAvailable()) {
cache = new CrossOriginStorage();
}
if (!cache && env.useBrowserCache) {
if (typeof caches === 'undefined') {
throw Error('Browser cache is not available in this environment.');
}
try {
// In some cases, the browser cache may be visible, but not accessible due to security restrictions.
// For example, when running an application in an iframe, if a user attempts to load the page in
// incognito mode, the following error is thrown: `DOMException: Failed to execute 'open' on 'CacheStorage':
// An attempt was made to break through the security policy of the user agent.`
// So, instead of crashing, we just ignore the error and continue without using the cache.
cache = await caches.open(env.cacheKey);
} catch (e) {
logger.warn('An error occurred while opening the browser cache:', e);
}
}
if (!cache && env.useFSCache) {
if (!apis.IS_FS_AVAILABLE) {
throw Error('File System Cache is not available in this environment.');
}
// If `cache_dir` is not specified, use the default cache directory
cache = new FileCache(file_cache_dir ?? env.cacheDir);
}
return cache;
}
/**
* Searches the cache for any of the provided names and returns the first match found.
* @param {CacheInterface} cache The cache to search
* @param {...string} names The names of the items to search for
* @returns {Promise<import('./hub/FileResponse.js').FileResponse|Response|undefined|string>} The item from the cache, or undefined if not found.
*/
export async function tryCache(cache, ...names) {
for (let name of names) {
try {
let result = await cache.match(name);
if (result) return result;
} catch (e) {
continue;
}
}
return undefined;
}