@huggingface/transformers
Version:
State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server!
170 lines (152 loc) • 7.64 kB
JavaScript
import { getCache } from '../cache.js';
import { buildResourcePaths, checkCachedResource } from '../hub.js';
import { get_files } from './get_files.js';
import { get_pipeline_files } from './get_pipeline_files.js';
/**
* @typedef {Object} FileCacheStatus
* @property {string} file - The file path
* @property {boolean} cached - Whether the file is cached
*/
/**
* @typedef {Object} CacheCheckResult
* @property {boolean} allCached - Whether all files are cached
* @property {FileCacheStatus[]} files - Array of files with their cache status
*/
/**
* Internal helper to check cache status for a list of files
* @private
* @param {string} modelId - The model id
* @param {string[]} files - List of file paths to check
* @param {Object} options - Options including cache_dir
* @returns {Promise<CacheCheckResult>}
*/
async function check_files_cache(modelId, files, options = {}) {
const cache = await getCache(options?.cache_dir);
if (!cache) {
const fileStatuses = files.map((filename) => ({ file: filename, cached: false }));
// No cache available, all files considered not cached
return { allCached: false, files: fileStatuses };
}
const fileStatuses = await Promise.all(
files.map(async (filename) => {
const { localPath, proposedCacheKey } = buildResourcePaths(modelId, filename, options, cache);
const cached = await checkCachedResource(cache, localPath, proposedCacheKey);
return { file: filename, cached: !!cached };
}),
);
return { allCached: fileStatuses.every((f) => f.cached), files: fileStatuses };
}
/**
* Internal helper to check whether a single file is cached.
* @private
* @param {string} modelId - The model id
* @param {string} filename - The file path to check
* @param {Object} options - Options including cache_dir
* @returns {Promise<boolean>}
*/
async function is_file_cached(modelId, filename, options = {}) {
const cache = await getCache(options?.cache_dir);
if (!cache) return false;
const { localPath, proposedCacheKey } = buildResourcePaths(modelId, filename, options, cache);
return !!(await checkCachedResource(cache, localPath, proposedCacheKey));
}
/**
* Quickly checks if a model is cached by verifying that `config.json` is present,
* then confirming all required files are cached.
* Returns a plain boolean — use `is_cached_files` if you need per-file detail.
*
* @param {string} modelId The model id (e.g., "Xenova/gpt2")
* @param {Object} [options] Optional parameters
* @param {string} [options.cache_dir] Custom cache directory
* @param {string} [options.revision] Model revision (default: 'main')
* @param {import('../../configs.js').PretrainedConfig} [options.config] Pre-loaded config
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype] Override dtype
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device] Override device
* @returns {Promise<boolean>} Whether all required files are cached
*/
export async function is_cached(modelId, options = {}) {
if (!modelId) {
throw new Error('modelId is required');
}
// Fast early-exit: if config.json is missing we can expect the rest not to be cached too.
if (!(await is_file_cached(modelId, 'config.json', options))) {
return false;
}
const files = await get_files(modelId, options);
const result = await check_files_cache(modelId, files, options);
return result.allCached;
}
/**
* Checks if all files for a given model are already cached, with per-file detail.
* Automatically determines which files are needed using get_files().
*
* @param {string} modelId The model id (e.g., "Xenova/gpt2")
* @param {Object} [options] Optional parameters
* @param {string} [options.cache_dir] Custom cache directory
* @param {string} [options.revision] Model revision (default: 'main')
* @param {import('../../configs.js').PretrainedConfig} [options.config] Pre-loaded config
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype] Override dtype
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device] Override device
* @returns {Promise<CacheCheckResult>} Object with allCached boolean and files array with cache status
*/
export async function is_cached_files(modelId, options = {}) {
if (!modelId) {
throw new Error('modelId is required');
}
const files = await get_files(modelId, options);
return await check_files_cache(modelId, files, options);
}
/**
* Quickly checks if all files for a specific pipeline task are cached by verifying
* that `config.json` is present, then confirming all required files are cached.
* Returns a plain boolean — use `is_pipeline_cached_files` if you need per-file detail.
*
* @param {string} task - The pipeline task (e.g., "text-generation", "image-classification")
* @param {string} modelId - The model id (e.g., "Xenova/gpt2")
* @param {Object} [options] - Optional parameters
* @param {string} [options.cache_dir] - Custom cache directory
* @param {string} [options.revision] - Model revision (default: 'main')
* @param {import('../../configs.js').PretrainedConfig} [options.config] - Pre-loaded config
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype] - Override dtype
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device] - Override device
* @returns {Promise<boolean>} Whether all required files are cached
*/
export async function is_pipeline_cached(task, modelId, options = {}) {
if (!task) {
throw new Error('task is required');
}
if (!modelId) {
throw new Error('modelId is required');
}
// Fast early-exit: if config.json is missing we can expect the rest not to be cached too.
if (!(await is_file_cached(modelId, 'config.json', options))) {
return false;
}
const files = await get_pipeline_files(task, modelId, options);
const result = await check_files_cache(modelId, files, options);
return result.allCached;
}
/**
* Checks if all files for a specific pipeline task are already cached, with per-file detail.
* Automatically determines which components are needed based on the task.
*
* @param {string} task - The pipeline task (e.g., "text-generation", "image-classification")
* @param {string} modelId - The model id (e.g., "Xenova/gpt2")
* @param {Object} [options] - Optional parameters
* @param {string} [options.cache_dir] - Custom cache directory
* @param {string} [options.revision] - Model revision (default: 'main')
* @param {import('../../configs.js').PretrainedConfig} [options.config] - Pre-loaded config
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype] - Override dtype
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device] - Override device
* @returns {Promise<CacheCheckResult>} Object with allCached boolean and files array with cache status
*/
export async function is_pipeline_cached_files(task, modelId, options = {}) {
if (!task) {
throw new Error('task is required');
}
if (!modelId) {
throw new Error('modelId is required');
}
const files = await get_pipeline_files(task, modelId, options);
return await check_files_cache(modelId, files, options);
}