@huggingface/transformers 4.0.0-next.5 → 4.0.0-next.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/dist/ort-wasm-simd-threaded.jsep.mjs +24 -24
- package/dist/transformers.js +2189 -1015
- package/dist/transformers.min.js +16 -16
- package/dist/transformers.node.cjs +2234 -1029
- package/dist/transformers.node.min.cjs +20 -20
- package/dist/transformers.node.min.mjs +20 -20
- package/dist/transformers.node.mjs +2194 -1017
- package/dist/transformers.web.js +2175 -1001
- package/dist/transformers.web.min.js +18 -18
- package/package.json +4 -4
- package/src/backends/onnx.js +77 -58
- package/src/backends/utils/cacheWasm.js +22 -43
- package/src/cache_utils.js +62 -0
- package/src/configs.js +32 -5
- package/src/env.js +36 -6
- package/src/image_processors_utils.js +3 -3
- package/src/models/auto/modeling_auto.js +14 -1
- package/src/models/chatterbox/modeling_chatterbox.js +1 -1
- package/src/models/detr/image_processing_detr.js +1 -1
- package/src/models/feature_extractors.js +2 -0
- package/src/models/gemma3n/modeling_gemma3n.js +2 -0
- package/src/models/granite_speech/feature_extraction_granite_speech.js +58 -0
- package/src/models/granite_speech/modeling_granite_speech.js +5 -0
- package/src/models/granite_speech/processing_granite_speech.js +62 -0
- package/src/models/grounding_dino/image_processing_grounding_dino.js +1 -1
- package/src/models/idefics3/modeling_idefics3.js +5 -32
- package/src/models/image_processors.js +1 -0
- package/src/models/lfm2_vl/image_processing_lfm2_vl.js +305 -0
- package/src/models/lfm2_vl/modeling_lfm2_vl.js +13 -0
- package/src/models/lfm2_vl/processing_lfm2_vl.js +77 -0
- package/src/models/llava/modeling_llava.js +1 -1
- package/src/models/mistral3/modeling_mistral3.js +2 -2
- package/src/models/modeling_utils.js +234 -292
- package/src/models/models.js +9 -0
- package/src/models/olmo_hybrid/modeling_olmo_hybrid.js +5 -0
- package/src/models/paligemma/modeling_paligemma.js +2 -25
- package/src/models/processors.js +3 -0
- package/src/models/qwen2_5_vl/modeling_qwen2_5_vl.js +5 -1
- package/src/models/qwen2_moe/modeling_qwen2_moe.js +5 -0
- package/src/models/qwen2_vl/image_processing_qwen2_vl.js +1 -41
- package/src/models/qwen2_vl/modeling_qwen2_vl.js +36 -3
- package/src/models/qwen3_5/modeling_qwen3_5.js +1 -0
- package/src/models/qwen3_5_moe/modeling_qwen3_5_moe.js +2 -1
- package/src/models/qwen3_moe/modeling_qwen3_moe.js +5 -0
- package/src/models/qwen3_next/modeling_qwen3_next.js +5 -0
- package/src/models/qwen3_vl/modeling_qwen3_vl.js +2 -1
- package/src/models/qwen3_vl_moe/modeling_qwen3_vl_moe.js +4 -0
- package/src/models/registry.js +39 -4
- package/src/models/sam/image_processing_sam.js +1 -1
- package/src/models/session.js +17 -6
- package/src/models/smolvlm/modeling_smolvlm.js +7 -0
- package/src/models/ultravox/modeling_ultravox.js +1 -3
- package/src/models/voxtral/modeling_voxtral.js +3 -0
- package/src/models/voxtral_realtime/feature_extraction_voxtral_realtime.js +71 -0
- package/src/models/voxtral_realtime/modeling_voxtral_realtime.js +239 -0
- package/src/models/voxtral_realtime/processing_voxtral_realtime.js +113 -0
- package/src/models/whisper/feature_extraction_whisper.js +2 -12
- package/src/pipelines/index.js +2 -84
- package/src/pipelines.js +40 -77
- package/src/transformers.js +2 -0
- package/src/utils/audio.js +18 -2
- package/src/utils/cache/CrossOriginStorageCache.js +251 -0
- package/src/utils/cache/FileCache.js +128 -0
- package/src/utils/cache/cross-origin-storage.d.ts +38 -0
- package/src/utils/cache.js +8 -3
- package/src/utils/hub/{files.js → FileResponse.js} +0 -105
- package/src/utils/hub/utils.js +35 -1
- package/src/utils/hub.js +6 -5
- package/src/utils/image.js +12 -13
- package/src/utils/lru_cache.js +67 -0
- package/src/utils/memoize_promise.js +45 -0
- package/src/utils/model_registry/ModelRegistry.js +70 -23
- package/src/utils/model_registry/get_file_metadata.js +14 -2
- package/src/utils/model_registry/get_model_files.js +63 -78
- package/src/utils/model_registry/get_pipeline_files.js +15 -24
- package/src/utils/model_registry/is_cached.js +81 -4
- package/src/utils/tensor.js +18 -2
- package/types/backends/onnx.d.ts.map +1 -1
- package/types/backends/utils/cacheWasm.d.ts +3 -17
- package/types/backends/utils/cacheWasm.d.ts.map +1 -1
- package/types/cache_utils.d.ts +29 -0
- package/types/cache_utils.d.ts.map +1 -0
- package/types/configs.d.ts.map +1 -1
- package/types/env.d.ts +18 -3
- package/types/env.d.ts.map +1 -1
- package/types/image_processors_utils.d.ts +17 -1
- package/types/image_processors_utils.d.ts.map +1 -1
- package/types/models/auto/modeling_auto.d.ts +6 -0
- package/types/models/auto/modeling_auto.d.ts.map +1 -1
- package/types/models/detr/image_processing_detr.d.ts +1 -1
- package/types/models/feature_extractors.d.ts +2 -0
- package/types/models/gemma3n/modeling_gemma3n.d.ts +2 -0
- package/types/models/gemma3n/modeling_gemma3n.d.ts.map +1 -1
- package/types/models/granite_speech/feature_extraction_granite_speech.d.ts +16 -0
- package/types/models/granite_speech/feature_extraction_granite_speech.d.ts.map +1 -0
- package/types/models/granite_speech/modeling_granite_speech.d.ts +4 -0
- package/types/models/granite_speech/modeling_granite_speech.d.ts.map +1 -0
- package/types/models/granite_speech/processing_granite_speech.d.ts +19 -0
- package/types/models/granite_speech/processing_granite_speech.d.ts.map +1 -0
- package/types/models/grounding_dino/image_processing_grounding_dino.d.ts +1 -1
- package/types/models/idefics3/modeling_idefics3.d.ts +2 -18
- package/types/models/idefics3/modeling_idefics3.d.ts.map +1 -1
- package/types/models/image_processors.d.ts +1 -0
- package/types/models/lfm2_vl/image_processing_lfm2_vl.d.ts +41 -0
- package/types/models/lfm2_vl/image_processing_lfm2_vl.d.ts.map +1 -0
- package/types/models/lfm2_vl/modeling_lfm2_vl.d.ts +4 -0
- package/types/models/lfm2_vl/modeling_lfm2_vl.d.ts.map +1 -0
- package/types/models/lfm2_vl/processing_lfm2_vl.d.ts +18 -0
- package/types/models/lfm2_vl/processing_lfm2_vl.d.ts.map +1 -0
- package/types/models/mistral3/modeling_mistral3.d.ts +2 -2
- package/types/models/mistral3/modeling_mistral3.d.ts.map +1 -1
- package/types/models/modeling_utils.d.ts +44 -24
- package/types/models/modeling_utils.d.ts.map +1 -1
- package/types/models/models.d.ts +9 -0
- package/types/models/olmo_hybrid/modeling_olmo_hybrid.d.ts +8 -0
- package/types/models/olmo_hybrid/modeling_olmo_hybrid.d.ts.map +1 -0
- package/types/models/paligemma/modeling_paligemma.d.ts +2 -8
- package/types/models/paligemma/modeling_paligemma.d.ts.map +1 -1
- package/types/models/processors.d.ts +3 -0
- package/types/models/qwen2_5_vl/modeling_qwen2_5_vl.d.ts +3 -0
- package/types/models/qwen2_5_vl/modeling_qwen2_5_vl.d.ts.map +1 -1
- package/types/models/qwen2_moe/modeling_qwen2_moe.d.ts +8 -0
- package/types/models/qwen2_moe/modeling_qwen2_moe.d.ts.map +1 -0
- package/types/models/qwen2_vl/image_processing_qwen2_vl.d.ts.map +1 -1
- package/types/models/qwen2_vl/modeling_qwen2_vl.d.ts +2 -0
- package/types/models/qwen2_vl/modeling_qwen2_vl.d.ts.map +1 -1
- package/types/models/qwen3_5/modeling_qwen3_5.d.ts +2 -0
- package/types/models/qwen3_5/modeling_qwen3_5.d.ts.map +1 -1
- package/types/models/qwen3_5_moe/modeling_qwen3_5_moe.d.ts +3 -0
- package/types/models/qwen3_5_moe/modeling_qwen3_5_moe.d.ts.map +1 -1
- package/types/models/qwen3_moe/modeling_qwen3_moe.d.ts +8 -0
- package/types/models/qwen3_moe/modeling_qwen3_moe.d.ts.map +1 -0
- package/types/models/qwen3_next/modeling_qwen3_next.d.ts +8 -0
- package/types/models/qwen3_next/modeling_qwen3_next.d.ts.map +1 -0
- package/types/models/qwen3_vl/modeling_qwen3_vl.d.ts +3 -0
- package/types/models/qwen3_vl/modeling_qwen3_vl.d.ts.map +1 -1
- package/types/models/qwen3_vl_moe/modeling_qwen3_vl_moe.d.ts +7 -0
- package/types/models/qwen3_vl_moe/modeling_qwen3_vl_moe.d.ts.map +1 -0
- package/types/models/registry.d.ts +2 -1
- package/types/models/registry.d.ts.map +1 -1
- package/types/models/sam/image_processing_sam.d.ts +1 -1
- package/types/models/session.d.ts +3 -2
- package/types/models/session.d.ts.map +1 -1
- package/types/models/smolvlm/modeling_smolvlm.d.ts +8 -0
- package/types/models/smolvlm/modeling_smolvlm.d.ts.map +1 -0
- package/types/models/ultravox/modeling_ultravox.d.ts +0 -2
- package/types/models/ultravox/modeling_ultravox.d.ts.map +1 -1
- package/types/models/voxtral/modeling_voxtral.d.ts +4 -0
- package/types/models/voxtral/modeling_voxtral.d.ts.map +1 -0
- package/types/models/voxtral_realtime/feature_extraction_voxtral_realtime.d.ts +28 -0
- package/types/models/voxtral_realtime/feature_extraction_voxtral_realtime.d.ts.map +1 -0
- package/types/models/voxtral_realtime/modeling_voxtral_realtime.d.ts +17 -0
- package/types/models/voxtral_realtime/modeling_voxtral_realtime.d.ts.map +1 -0
- package/types/models/voxtral_realtime/processing_voxtral_realtime.d.ts +44 -0
- package/types/models/voxtral_realtime/processing_voxtral_realtime.d.ts.map +1 -0
- package/types/models/whisper/feature_extraction_whisper.d.ts.map +1 -1
- package/types/pipelines/index.d.ts +0 -34
- package/types/pipelines/index.d.ts.map +1 -1
- package/types/pipelines.d.ts.map +1 -1
- package/types/transformers.d.ts +1 -0
- package/types/transformers.d.ts.map +1 -1
- package/types/utils/audio.d.ts +5 -2
- package/types/utils/audio.d.ts.map +1 -1
- package/types/utils/cache/CrossOriginStorageCache.d.ts +120 -0
- package/types/utils/cache/CrossOriginStorageCache.d.ts.map +1 -0
- package/types/utils/cache/FileCache.d.ts +39 -0
- package/types/utils/cache/FileCache.d.ts.map +1 -0
- package/types/utils/cache.d.ts +4 -4
- package/types/utils/cache.d.ts.map +1 -1
- package/types/utils/dtypes.d.ts +1 -1
- package/types/utils/hub/{files.d.ts → FileResponse.d.ts} +1 -38
- package/types/utils/hub/FileResponse.d.ts.map +1 -0
- package/types/utils/hub/utils.d.ts +17 -2
- package/types/utils/hub/utils.d.ts.map +1 -1
- package/types/utils/hub.d.ts +7 -7
- package/types/utils/hub.d.ts.map +1 -1
- package/types/utils/image.d.ts +1 -1
- package/types/utils/image.d.ts.map +1 -1
- package/types/utils/lru_cache.d.ts +38 -0
- package/types/utils/lru_cache.d.ts.map +1 -0
- package/types/utils/memoize_promise.d.ts +14 -0
- package/types/utils/memoize_promise.d.ts.map +1 -0
- package/types/utils/model_registry/ModelRegistry.d.ts +66 -6
- package/types/utils/model_registry/ModelRegistry.d.ts.map +1 -1
- package/types/utils/model_registry/get_file_metadata.d.ts.map +1 -1
- package/types/utils/model_registry/get_model_files.d.ts +1 -0
- package/types/utils/model_registry/get_model_files.d.ts.map +1 -1
- package/types/utils/model_registry/get_pipeline_files.d.ts +2 -1
- package/types/utils/model_registry/get_pipeline_files.d.ts.map +1 -1
- package/types/utils/model_registry/is_cached.d.ts +47 -4
- package/types/utils/model_registry/is_cached.d.ts.map +1 -1
- package/types/utils/tensor.d.ts.map +1 -1
- package/src/utils/data-structures.js +0 -572
- package/types/utils/data-structures.d.ts +0 -294
- package/types/utils/data-structures.d.ts.map +0 -1
- package/types/utils/hub/files.d.ts.map +0 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Mapping from file extensions to MIME types.
|
|
@@ -120,107 +119,3 @@ export class FileResponse {
|
|
|
120
119
|
return JSON.parse(await this.text());
|
|
121
120
|
}
|
|
122
121
|
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* File system cache implementation that implements the CacheInterface.
|
|
126
|
-
* Provides `match` and `put` methods compatible with the Web Cache API.
|
|
127
|
-
*/
|
|
128
|
-
export class FileCache {
|
|
129
|
-
/**
|
|
130
|
-
* Instantiate a `FileCache` object.
|
|
131
|
-
* @param {string} path
|
|
132
|
-
*/
|
|
133
|
-
constructor(path) {
|
|
134
|
-
this.path = path;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Checks whether the given request is in the cache.
|
|
139
|
-
* @param {string} request
|
|
140
|
-
* @returns {Promise<FileResponse | undefined>}
|
|
141
|
-
*/
|
|
142
|
-
async match(request) {
|
|
143
|
-
let filePath = path.join(this.path, request);
|
|
144
|
-
let file = new FileResponse(filePath);
|
|
145
|
-
|
|
146
|
-
if (file.exists) {
|
|
147
|
-
return file;
|
|
148
|
-
} else {
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Adds the given response to the cache.
|
|
155
|
-
* @param {string} request
|
|
156
|
-
* @param {Response} response
|
|
157
|
-
* @param {(data: {progress: number, loaded: number, total: number}) => void} [progress_callback] Optional.
|
|
158
|
-
* The function to call with progress updates
|
|
159
|
-
* @returns {Promise<void>}
|
|
160
|
-
*/
|
|
161
|
-
async put(request, response, progress_callback = undefined) {
|
|
162
|
-
let filePath = path.join(this.path, request);
|
|
163
|
-
|
|
164
|
-
try {
|
|
165
|
-
const contentLength = response.headers.get('Content-Length');
|
|
166
|
-
const total = parseInt(contentLength ?? '0');
|
|
167
|
-
let loaded = 0;
|
|
168
|
-
|
|
169
|
-
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
|
|
170
|
-
const fileStream = fs.createWriteStream(filePath);
|
|
171
|
-
const reader = response.body.getReader();
|
|
172
|
-
|
|
173
|
-
while (true) {
|
|
174
|
-
const { done, value } = await reader.read();
|
|
175
|
-
if (done) {
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
await new Promise((resolve, reject) => {
|
|
180
|
-
fileStream.write(value, (err) => {
|
|
181
|
-
if (err) {
|
|
182
|
-
reject(err);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
resolve();
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
loaded += value.length;
|
|
190
|
-
const progress = total ? (loaded / total) * 100 : 0;
|
|
191
|
-
|
|
192
|
-
progress_callback?.({ progress, loaded, total });
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
fileStream.close();
|
|
196
|
-
} catch (error) {
|
|
197
|
-
// Clean up the file if an error occurred during download
|
|
198
|
-
try {
|
|
199
|
-
await fs.promises.unlink(filePath);
|
|
200
|
-
} catch {}
|
|
201
|
-
throw error;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Deletes the cache entry for the given request.
|
|
207
|
-
* @param {string} request
|
|
208
|
-
* @returns {Promise<boolean>} A Promise that resolves to `true` if the cache entry was deleted, `false` otherwise.
|
|
209
|
-
*/
|
|
210
|
-
async delete(request) {
|
|
211
|
-
let filePath = path.join(this.path, request);
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
await fs.promises.unlink(filePath);
|
|
215
|
-
return true;
|
|
216
|
-
} catch (error) {
|
|
217
|
-
// File doesn't exist or couldn't be deleted
|
|
218
|
-
return false;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// TODO add the rest?
|
|
223
|
-
// addAll(requests: RequestInfo[]): Promise<void>;
|
|
224
|
-
// keys(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<ReadonlyArray<Request>>;
|
|
225
|
-
// matchAll(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<ReadonlyArray<Response>>;
|
|
226
|
-
}
|
package/src/utils/hub/utils.js
CHANGED
|
@@ -80,7 +80,7 @@ export function handleError(status, remoteURL, fatal) {
|
|
|
80
80
|
/**
|
|
81
81
|
* Read and track progress when reading a Response object
|
|
82
82
|
*
|
|
83
|
-
* @param {Response|import('./
|
|
83
|
+
* @param {Response|import('./FileResponse.js').FileResponse} response The Response object to read
|
|
84
84
|
* @param {(data: {progress: number, loaded: number, total: number}) => void} progress_callback The function to call with progress updates
|
|
85
85
|
* @param {number} [expectedSize] The expected size of the file (used when content-length header is missing)
|
|
86
86
|
* @returns {Promise<Uint8Array>} A Promise that resolves with the Uint8Array buffer
|
|
@@ -132,3 +132,37 @@ export async function readResponse(response, progress_callback, expectedSize) {
|
|
|
132
132
|
|
|
133
133
|
return buffer;
|
|
134
134
|
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Checks if the given URL is a blob URL (created via URL.createObjectURL).
|
|
138
|
+
* Blob URLs should not be cached as they are temporary in-memory references.
|
|
139
|
+
* @param {string} url - The URL to check.
|
|
140
|
+
* @returns {boolean} True if the URL is a blob URL, false otherwise.
|
|
141
|
+
*/
|
|
142
|
+
export function isBlobURL(url) {
|
|
143
|
+
return isValidUrl(url, ['blob:']);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Converts any URL to an absolute URL if needed.
|
|
148
|
+
* If the URL is already absolute (http://, https://, or blob:), returns it unchanged (handled by new URL(...)).
|
|
149
|
+
* Otherwise, resolves it relative to the current page location (browser) or module location (Node/Bun/Deno).
|
|
150
|
+
* @param {string} url - The URL to convert (can be relative or absolute).
|
|
151
|
+
* @returns {string} The absolute URL.
|
|
152
|
+
*/
|
|
153
|
+
export function toAbsoluteURL(url) {
|
|
154
|
+
let baseURL;
|
|
155
|
+
|
|
156
|
+
if (typeof location !== 'undefined' && location.href) {
|
|
157
|
+
// Browser environment: use location.href
|
|
158
|
+
baseURL = location.href;
|
|
159
|
+
} else if (typeof import.meta !== 'undefined' && import.meta.url) {
|
|
160
|
+
// Node.js/Bun/Deno module environment: use import.meta.url
|
|
161
|
+
baseURL = import.meta.url;
|
|
162
|
+
} else {
|
|
163
|
+
// Fallback: if no base is available, return the URL unchanged
|
|
164
|
+
return url;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return new URL(url, baseURL).href;
|
|
168
|
+
}
|
package/src/utils/hub.js
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import { apis, env } from '../env.js';
|
|
8
8
|
import { dispatchCallback } from './core.js';
|
|
9
|
-
import { FileResponse
|
|
9
|
+
import { FileResponse } from './hub/FileResponse.js';
|
|
10
|
+
import { FileCache } from './cache/FileCache.js';
|
|
10
11
|
import { handleError, isValidUrl, pathJoin, isValidHfModelId, readResponse } from './hub/utils.js';
|
|
11
12
|
import { getCache, tryCache } from './cache.js';
|
|
12
13
|
import { get_file_metadata } from './model_registry/get_file_metadata.js';
|
|
@@ -39,7 +40,7 @@ export { MAX_EXTERNAL_DATA_CHUNKS } from './hub/constants.js';
|
|
|
39
40
|
* @typedef {Object} ModelSpecificPretrainedOptions Options for loading a pretrained model.
|
|
40
41
|
* @property {string} [subfolder='onnx'] In case the relevant files are located inside a subfolder of the model repo on huggingface.co,
|
|
41
42
|
* you can specify the folder name here.
|
|
42
|
-
* @property {string} [model_file_name=null] If specified, load the model with this name (excluding the .onnx
|
|
43
|
+
* @property {string} [model_file_name=null] If specified, load the model with this name (excluding the dtype and .onnx suffixes). Currently only valid for encoder- or decoder-only models.
|
|
43
44
|
* @property {import("./devices.js").DeviceType|Record<string, import("./devices.js").DeviceType>} [device=null] The device to run the model on. If not specified, the device will be chosen from the environment settings.
|
|
44
45
|
* @property {import("./dtypes.js").DataType|Record<string, import("./dtypes.js").DataType>} [dtype=null] The data type to use for the model. If not specified, the data type will be chosen from the environment settings.
|
|
45
46
|
* @property {ExternalData|Record<string, ExternalData>} [use_external_data_format=false] Whether to load the model using the external data format (used for models >= 2GB in size).
|
|
@@ -160,7 +161,7 @@ export function buildResourcePaths(path_or_repo_id, filename, options = {}, cach
|
|
|
160
161
|
* @param {import('./cache.js').CacheInterface | null} cache The cache instance to check.
|
|
161
162
|
* @param {string} localPath The local path to try first.
|
|
162
163
|
* @param {string} proposedCacheKey The proposed cache key to try second.
|
|
163
|
-
* @returns {Promise<Response|import('./hub/
|
|
164
|
+
* @returns {Promise<Response|import('./hub/FileResponse.js').FileResponse|undefined|string>}
|
|
164
165
|
* The cached response if found, undefined otherwise.
|
|
165
166
|
*/
|
|
166
167
|
export async function checkCachedResource(cache, localPath, proposedCacheKey) {
|
|
@@ -182,7 +183,7 @@ export async function checkCachedResource(cache, localPath, proposedCacheKey) {
|
|
|
182
183
|
* @param {string} filename The name of the file to cache.
|
|
183
184
|
* @param {import('./cache.js').CacheInterface} cache The cache instance to store in.
|
|
184
185
|
* @param {string} cacheKey The cache key to use.
|
|
185
|
-
* @param {Response|import('./hub/
|
|
186
|
+
* @param {Response|import('./hub/FileResponse.js').FileResponse} response The response to cache.
|
|
186
187
|
* @param {Uint8Array} [result] The result buffer if already read.
|
|
187
188
|
* @param {PretrainedOptions} [options] Options containing progress callback and context for progress updates.
|
|
188
189
|
* @returns {Promise<void>}
|
|
@@ -259,7 +260,7 @@ export async function loadResourceFile(
|
|
|
259
260
|
// Whether to cache the final response in the end.
|
|
260
261
|
let toCacheResponse = false;
|
|
261
262
|
|
|
262
|
-
/** @type {Response|import('./hub/
|
|
263
|
+
/** @type {Response|import('./hub/FileResponse.js').FileResponse|undefined|string} */
|
|
263
264
|
let response;
|
|
264
265
|
|
|
265
266
|
// Check cache
|
package/src/utils/image.js
CHANGED
|
@@ -20,12 +20,11 @@ import { logger } from './logger.js';
|
|
|
20
20
|
let createCanvasFunction;
|
|
21
21
|
let ImageDataClass;
|
|
22
22
|
let loadImageFunction;
|
|
23
|
-
|
|
24
|
-
if (IS_BROWSER_OR_WEBWORKER) {
|
|
23
|
+
if (apis.IS_WEB_ENV) {
|
|
25
24
|
// Running in browser or web-worker
|
|
26
25
|
createCanvasFunction = (/** @type {number} */ width, /** @type {number} */ height) => {
|
|
27
26
|
if (!self.OffscreenCanvas) {
|
|
28
|
-
throw new Error('OffscreenCanvas not supported by this
|
|
27
|
+
throw new Error('OffscreenCanvas not supported by this environment.');
|
|
29
28
|
}
|
|
30
29
|
return new self.OffscreenCanvas(width, height);
|
|
31
30
|
};
|
|
@@ -134,7 +133,7 @@ export class RawImage {
|
|
|
134
133
|
* @returns {RawImage} The image object.
|
|
135
134
|
*/
|
|
136
135
|
static fromCanvas(canvas) {
|
|
137
|
-
if (!
|
|
136
|
+
if (!apis.IS_WEB_ENV) {
|
|
138
137
|
throw new Error('fromCanvas() is only supported in browser environments.');
|
|
139
138
|
}
|
|
140
139
|
|
|
@@ -165,7 +164,7 @@ export class RawImage {
|
|
|
165
164
|
* @returns {Promise<RawImage>} The image object.
|
|
166
165
|
*/
|
|
167
166
|
static async fromBlob(blob) {
|
|
168
|
-
if (
|
|
167
|
+
if (apis.IS_WEB_ENV) {
|
|
169
168
|
// Running in environment with canvas
|
|
170
169
|
const img = await loadImageFunction(blob);
|
|
171
170
|
|
|
@@ -379,7 +378,7 @@ export class RawImage {
|
|
|
379
378
|
height = (width / this.width) * this.height;
|
|
380
379
|
}
|
|
381
380
|
|
|
382
|
-
if (
|
|
381
|
+
if (apis.IS_WEB_ENV) {
|
|
383
382
|
// TODO use `resample` in browser environment
|
|
384
383
|
|
|
385
384
|
// Store number of channels before resizing
|
|
@@ -453,7 +452,7 @@ export class RawImage {
|
|
|
453
452
|
return this;
|
|
454
453
|
}
|
|
455
454
|
|
|
456
|
-
if (
|
|
455
|
+
if (apis.IS_WEB_ENV) {
|
|
457
456
|
// Store number of channels before padding
|
|
458
457
|
const numChannels = this.channels;
|
|
459
458
|
|
|
@@ -495,7 +494,7 @@ export class RawImage {
|
|
|
495
494
|
const crop_width = x_max - x_min + 1;
|
|
496
495
|
const crop_height = y_max - y_min + 1;
|
|
497
496
|
|
|
498
|
-
if (
|
|
497
|
+
if (apis.IS_WEB_ENV) {
|
|
499
498
|
// Store number of channels before resizing
|
|
500
499
|
const numChannels = this.channels;
|
|
501
500
|
|
|
@@ -542,7 +541,7 @@ export class RawImage {
|
|
|
542
541
|
const width_offset = (this.width - crop_width) / 2;
|
|
543
542
|
const height_offset = (this.height - crop_height) / 2;
|
|
544
543
|
|
|
545
|
-
if (
|
|
544
|
+
if (apis.IS_WEB_ENV) {
|
|
546
545
|
// Store number of channels before resizing
|
|
547
546
|
const numChannels = this.channels;
|
|
548
547
|
|
|
@@ -650,7 +649,7 @@ export class RawImage {
|
|
|
650
649
|
}
|
|
651
650
|
|
|
652
651
|
async toBlob(type = 'image/png', quality = 1) {
|
|
653
|
-
if (!
|
|
652
|
+
if (!apis.IS_WEB_ENV) {
|
|
654
653
|
throw new Error('toBlob() is only supported in browser environments.');
|
|
655
654
|
}
|
|
656
655
|
|
|
@@ -673,7 +672,7 @@ export class RawImage {
|
|
|
673
672
|
}
|
|
674
673
|
|
|
675
674
|
toCanvas() {
|
|
676
|
-
if (!
|
|
675
|
+
if (!apis.IS_WEB_ENV) {
|
|
677
676
|
throw new Error('toCanvas() is only supported in browser environments.');
|
|
678
677
|
}
|
|
679
678
|
|
|
@@ -774,7 +773,7 @@ export class RawImage {
|
|
|
774
773
|
* @returns {Promise<void>}
|
|
775
774
|
*/
|
|
776
775
|
async save(path) {
|
|
777
|
-
if (
|
|
776
|
+
if (apis.IS_WEB_ENV) {
|
|
778
777
|
if (apis.IS_WEBWORKER_ENV) {
|
|
779
778
|
throw new Error('Unable to save an image from a Web Worker.');
|
|
780
779
|
}
|
|
@@ -799,7 +798,7 @@ export class RawImage {
|
|
|
799
798
|
* @returns {import('sharp').Sharp} The Sharp instance.
|
|
800
799
|
*/
|
|
801
800
|
toSharp() {
|
|
802
|
-
if (
|
|
801
|
+
if (apis.IS_WEB_ENV) {
|
|
803
802
|
throw new Error('toSharp() is only supported in server-side environments.');
|
|
804
803
|
}
|
|
805
804
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simple Least Recently Used (LRU) cache implementation in JavaScript.
|
|
3
|
+
* This cache stores key-value pairs and evicts the least recently used item
|
|
4
|
+
* when the capacity is exceeded.
|
|
5
|
+
*/
|
|
6
|
+
export class LRUCache {
|
|
7
|
+
/** @type {number} */
|
|
8
|
+
#capacity;
|
|
9
|
+
|
|
10
|
+
/** @type {Map<any, any>} */
|
|
11
|
+
#cache;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates an LRUCache instance.
|
|
15
|
+
* @param {number} capacity The maximum number of items the cache can hold.
|
|
16
|
+
*/
|
|
17
|
+
constructor(capacity) {
|
|
18
|
+
this.#capacity = capacity;
|
|
19
|
+
this.#cache = new Map();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves the value associated with the given key and marks the key as recently used.
|
|
24
|
+
* @param {any} key The key to retrieve.
|
|
25
|
+
* @returns {any} The value associated with the key, or undefined if the key does not exist.
|
|
26
|
+
*/
|
|
27
|
+
get(key) {
|
|
28
|
+
if (!this.#cache.has(key)) return undefined;
|
|
29
|
+
const value = this.#cache.get(key);
|
|
30
|
+
this.#cache.delete(key);
|
|
31
|
+
this.#cache.set(key, value);
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Inserts or updates the key-value pair in the cache.
|
|
37
|
+
* If the key already exists, it is updated and marked as recently used.
|
|
38
|
+
* If the cache exceeds its capacity, the least recently used item is evicted.
|
|
39
|
+
* @param {any} key The key to add or update.
|
|
40
|
+
* @param {any} value The value to associate with the key.
|
|
41
|
+
*/
|
|
42
|
+
put(key, value) {
|
|
43
|
+
if (this.#cache.has(key)) {
|
|
44
|
+
this.#cache.delete(key);
|
|
45
|
+
}
|
|
46
|
+
this.#cache.set(key, value);
|
|
47
|
+
if (this.#cache.size > this.#capacity) {
|
|
48
|
+
this.#cache.delete(this.#cache.keys().next().value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Removes the entry for the given key from the cache.
|
|
54
|
+
* @param {any} key The key to delete.
|
|
55
|
+
* @returns {boolean} `true` if the entry existed and was removed, `false` otherwise.
|
|
56
|
+
*/
|
|
57
|
+
delete(key) {
|
|
58
|
+
return this.#cache.delete(key);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Clears the cache.
|
|
63
|
+
*/
|
|
64
|
+
clear() {
|
|
65
|
+
this.#cache.clear();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Utility for memoizing promises by key.
|
|
3
|
+
*
|
|
4
|
+
* Ensures that a given async operation is only initiated once per key.
|
|
5
|
+
* Subsequent calls with the same key return the same pending or resolved promise.
|
|
6
|
+
* Rejected promises are evicted from the cache so callers can retry.
|
|
7
|
+
*
|
|
8
|
+
* The cache is bounded by `MAX_CACHE_SIZE`. When the limit is exceeded, the
|
|
9
|
+
* least-recently-used entry is evicted.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { LRUCache } from './lru_cache.js';
|
|
13
|
+
|
|
14
|
+
const MAX_CACHE_SIZE = 100;
|
|
15
|
+
|
|
16
|
+
/** @type {LRUCache} */
|
|
17
|
+
const cache = new LRUCache(MAX_CACHE_SIZE);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns the cached promise for `key`, or calls `factory` to create one and caches it.
|
|
21
|
+
* Subsequent calls with the same key return the same promise whether it is still
|
|
22
|
+
* pending or already resolved, so the factory is never invoked more than once per key.
|
|
23
|
+
* If the promise rejects, the entry is removed from the cache so the operation can be retried.
|
|
24
|
+
*
|
|
25
|
+
* @template T
|
|
26
|
+
* @param {string} key A unique identifier for this async operation.
|
|
27
|
+
* @param {() => Promise<T>} factory A function that returns the promise to memoize.
|
|
28
|
+
* Only called when no entry exists for `key`.
|
|
29
|
+
* @returns {Promise<T>}
|
|
30
|
+
*/
|
|
31
|
+
export function memoizePromise(key, factory) {
|
|
32
|
+
const cached = cache.get(key);
|
|
33
|
+
if (cached !== undefined) {
|
|
34
|
+
return cached;
|
|
35
|
+
}
|
|
36
|
+
const promise = factory().then(
|
|
37
|
+
(value) => value,
|
|
38
|
+
(err) => {
|
|
39
|
+
cache.delete(key);
|
|
40
|
+
return Promise.reject(err);
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
cache.put(key, promise);
|
|
44
|
+
return promise;
|
|
45
|
+
}
|
|
@@ -49,8 +49,12 @@
|
|
|
49
49
|
* const modelId = "onnx-community/Qwen3-0.6B-ONNX";
|
|
50
50
|
* const options = { dtype: "q4" };
|
|
51
51
|
*
|
|
52
|
-
* //
|
|
53
|
-
* let
|
|
52
|
+
* // Quickly check if the model is cached (probably false)
|
|
53
|
+
* let cached = await ModelRegistry.is_cached(modelId, options);
|
|
54
|
+
* console.log(cached); // false
|
|
55
|
+
*
|
|
56
|
+
* // Get per-file cache detail
|
|
57
|
+
* let cacheStatus = await ModelRegistry.is_cached_files(modelId, options);
|
|
54
58
|
* console.log(cacheStatus);
|
|
55
59
|
* // {
|
|
56
60
|
* // allCached: false,
|
|
@@ -66,12 +70,8 @@
|
|
|
66
70
|
* console.log(output[0].generated_text.at(-1).content); // <think>...</think>\n\nThe capital of France is **Paris**.
|
|
67
71
|
*
|
|
68
72
|
* // Check if the model is cached (should be true now)
|
|
69
|
-
*
|
|
70
|
-
* console.log(
|
|
71
|
-
* // {
|
|
72
|
-
* // allCached: true,
|
|
73
|
-
* // files: [ { file: 'config.json', cached: true }, { file: 'onnx/model_q4.onnx', cached: true }, { file: 'generation_config.json', cached: true }, { file: 'tokenizer.json', cached: true }, { file: 'tokenizer_config.json', cached: true } ]
|
|
74
|
-
* // }
|
|
73
|
+
* cached = await ModelRegistry.is_cached(modelId, options);
|
|
74
|
+
* console.log(cached); // true
|
|
75
75
|
*
|
|
76
76
|
* // Clear the cache
|
|
77
77
|
* const clearResult = await ModelRegistry.clear_cache(modelId, options);
|
|
@@ -83,12 +83,8 @@
|
|
|
83
83
|
* // }
|
|
84
84
|
*
|
|
85
85
|
* // Check if the model is cached (should be false again)
|
|
86
|
-
*
|
|
87
|
-
* console.log(
|
|
88
|
-
* // {
|
|
89
|
-
* // allCached: false,
|
|
90
|
-
* // files: [ { file: 'config.json', cached: true }, { file: 'onnx/model_q4.onnx', cached: false }, { file: 'generation_config.json', cached: false }, { file: 'tokenizer.json', cached: false }, { file: 'tokenizer_config.json', cached: false } ]
|
|
91
|
-
* // }
|
|
86
|
+
* cached = await ModelRegistry.is_cached(modelId, options);
|
|
87
|
+
* console.log(cached); // false
|
|
92
88
|
* ```
|
|
93
89
|
*
|
|
94
90
|
* @module utils/model_registry
|
|
@@ -99,7 +95,7 @@ import { get_pipeline_files } from './get_pipeline_files.js';
|
|
|
99
95
|
import { get_model_files } from './get_model_files.js';
|
|
100
96
|
import { get_tokenizer_files } from './get_tokenizer_files.js';
|
|
101
97
|
import { get_processor_files } from './get_processor_files.js';
|
|
102
|
-
import { is_cached, is_pipeline_cached } from './is_cached.js';
|
|
98
|
+
import { is_cached, is_cached_files, is_pipeline_cached, is_pipeline_cached_files } from './is_cached.js';
|
|
103
99
|
import { get_file_metadata } from './get_file_metadata.js';
|
|
104
100
|
import { clear_cache, clear_pipeline_cache } from './clear_cache.js';
|
|
105
101
|
|
|
@@ -198,27 +194,31 @@ export class ModelRegistry {
|
|
|
198
194
|
}
|
|
199
195
|
|
|
200
196
|
/**
|
|
201
|
-
*
|
|
197
|
+
* Quickly checks if a model is fully cached by verifying `config.json` is present,
|
|
198
|
+
* then confirming all required files are cached.
|
|
199
|
+
* Returns a plain boolean — use `is_cached_files` if you need per-file detail.
|
|
202
200
|
*
|
|
203
201
|
* @param {string} modelId - The model id
|
|
204
202
|
* @param {Object} [options] - Optional parameters
|
|
203
|
+
* @param {string} [options.cache_dir] - Custom cache directory
|
|
204
|
+
* @param {string} [options.revision] - Model revision (default: 'main')
|
|
205
|
+
* @param {import('../../configs.js').PretrainedConfig} [options.config] - Pre-loaded config
|
|
205
206
|
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype=null] - Override dtype
|
|
206
207
|
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device=null] - Override device
|
|
207
|
-
* @returns {Promise<
|
|
208
|
+
* @returns {Promise<boolean>} Whether all required files are cached
|
|
208
209
|
*
|
|
209
210
|
* @example
|
|
210
|
-
* const
|
|
211
|
-
* console.log(
|
|
211
|
+
* const cached = await ModelRegistry.is_cached('onnx-community/bert-base-uncased-ONNX');
|
|
212
|
+
* console.log(cached); // true or false
|
|
212
213
|
*/
|
|
213
214
|
static async is_cached(modelId, options = {}) {
|
|
214
215
|
return is_cached(modelId, options);
|
|
215
216
|
}
|
|
216
217
|
|
|
217
218
|
/**
|
|
218
|
-
*
|
|
219
|
-
* Automatically determines which
|
|
219
|
+
* Checks if all files for a given model are already cached, with per-file detail.
|
|
220
|
+
* Automatically determines which files are needed using get_files().
|
|
220
221
|
*
|
|
221
|
-
* @param {string} task - The pipeline task (e.g., "text-generation", "background-removal")
|
|
222
222
|
* @param {string} modelId - The model id
|
|
223
223
|
* @param {Object} [options] - Optional parameters
|
|
224
224
|
* @param {string} [options.cache_dir] - Custom cache directory
|
|
@@ -229,13 +229,60 @@ export class ModelRegistry {
|
|
|
229
229
|
* @returns {Promise<import('./is_cached.js').CacheCheckResult>} Object with allCached boolean and files array with cache status
|
|
230
230
|
*
|
|
231
231
|
* @example
|
|
232
|
-
* const status = await ModelRegistry.
|
|
232
|
+
* const status = await ModelRegistry.is_cached_files('onnx-community/bert-base-uncased-ONNX');
|
|
233
233
|
* console.log(status.allCached); // true or false
|
|
234
|
+
* console.log(status.files); // [{ file: 'config.json', cached: true }, ...]
|
|
235
|
+
*/
|
|
236
|
+
static async is_cached_files(modelId, options = {}) {
|
|
237
|
+
return is_cached_files(modelId, options);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Quickly checks if all files for a specific pipeline task are cached by verifying
|
|
242
|
+
* `config.json` is present, then confirming all required files are cached.
|
|
243
|
+
* Returns a plain boolean — use `is_pipeline_cached_files` if you need per-file detail.
|
|
244
|
+
*
|
|
245
|
+
* @param {string} task - The pipeline task (e.g., "text-generation", "background-removal")
|
|
246
|
+
* @param {string} modelId - The model id
|
|
247
|
+
* @param {Object} [options] - Optional parameters
|
|
248
|
+
* @param {string} [options.cache_dir] - Custom cache directory
|
|
249
|
+
* @param {string} [options.revision] - Model revision (default: 'main')
|
|
250
|
+
* @param {import('../../configs.js').PretrainedConfig} [options.config] - Pre-loaded config
|
|
251
|
+
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype=null] - Override dtype
|
|
252
|
+
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device=null] - Override device
|
|
253
|
+
* @returns {Promise<boolean>} Whether all required files are cached
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* const cached = await ModelRegistry.is_pipeline_cached('text-generation', 'onnx-community/gpt2-ONNX');
|
|
257
|
+
* console.log(cached); // true or false
|
|
234
258
|
*/
|
|
235
259
|
static async is_pipeline_cached(task, modelId, options = {}) {
|
|
236
260
|
return is_pipeline_cached(task, modelId, options);
|
|
237
261
|
}
|
|
238
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Checks if all files for a specific pipeline task are already cached, with per-file detail.
|
|
265
|
+
* Automatically determines which components are needed based on the task.
|
|
266
|
+
*
|
|
267
|
+
* @param {string} task - The pipeline task (e.g., "text-generation", "background-removal")
|
|
268
|
+
* @param {string} modelId - The model id
|
|
269
|
+
* @param {Object} [options] - Optional parameters
|
|
270
|
+
* @param {string} [options.cache_dir] - Custom cache directory
|
|
271
|
+
* @param {string} [options.revision] - Model revision (default: 'main')
|
|
272
|
+
* @param {import('../../configs.js').PretrainedConfig} [options.config] - Pre-loaded config
|
|
273
|
+
* @param {import('../dtypes.js').DataType|Record<string, import('../dtypes.js').DataType>} [options.dtype=null] - Override dtype
|
|
274
|
+
* @param {import('../devices.js').DeviceType|Record<string, import('../devices.js').DeviceType>} [options.device=null] - Override device
|
|
275
|
+
* @returns {Promise<import('./is_cached.js').CacheCheckResult>} Object with allCached boolean and files array with cache status
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* const status = await ModelRegistry.is_pipeline_cached_files('text-generation', 'onnx-community/gpt2-ONNX');
|
|
279
|
+
* console.log(status.allCached); // true or false
|
|
280
|
+
* console.log(status.files); // [{ file: 'config.json', cached: true }, ...]
|
|
281
|
+
*/
|
|
282
|
+
static async is_pipeline_cached_files(task, modelId, options = {}) {
|
|
283
|
+
return is_pipeline_cached_files(task, modelId, options);
|
|
284
|
+
}
|
|
285
|
+
|
|
239
286
|
/**
|
|
240
287
|
* Get metadata for a specific file without downloading it.
|
|
241
288
|
*
|
|
@@ -7,6 +7,7 @@ import { getCache } from '../cache.js';
|
|
|
7
7
|
import { buildResourcePaths, checkCachedResource, getFetchHeaders, getFile } from '../hub.js';
|
|
8
8
|
import { isValidUrl } from '../hub/utils.js';
|
|
9
9
|
import { logger } from '../logger.js';
|
|
10
|
+
import { memoizePromise } from '../memoize_promise.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @typedef {import('../hub.js').PretrainedOptions} PretrainedOptions
|
|
@@ -34,7 +35,7 @@ async function fetch_file_head(urlOrPath) {
|
|
|
34
35
|
|
|
35
36
|
const headers = getFetchHeaders(urlOrPath);
|
|
36
37
|
headers.set('Range', 'bytes=0-0');
|
|
37
|
-
return env.fetch(urlOrPath, { method: 'GET', headers });
|
|
38
|
+
return env.fetch(urlOrPath, { method: 'GET', headers, cache: 'no-store' });
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/**
|
|
@@ -49,7 +50,18 @@ async function fetch_file_head(urlOrPath) {
|
|
|
49
50
|
* @param {PretrainedOptions} [options] An object containing optional parameters.
|
|
50
51
|
* @returns {Promise<{exists: boolean, size?: number, contentType?: string, fromCache?: boolean}>} A Promise that resolves to file metadata.
|
|
51
52
|
*/
|
|
52
|
-
export
|
|
53
|
+
export function get_file_metadata(path_or_repo_id, filename, options = {}) {
|
|
54
|
+
const key = JSON.stringify([
|
|
55
|
+
path_or_repo_id,
|
|
56
|
+
filename,
|
|
57
|
+
options?.revision,
|
|
58
|
+
options?.cache_dir,
|
|
59
|
+
options?.local_files_only,
|
|
60
|
+
]);
|
|
61
|
+
return memoizePromise(key, () => _get_file_metadata(path_or_repo_id, filename, options));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function _get_file_metadata(path_or_repo_id, filename, options) {
|
|
53
65
|
/** @type {import('../cache.js').CacheInterface | null} */
|
|
54
66
|
const cache = await getCache(options?.cache_dir);
|
|
55
67
|
const { localPath, remoteURL, proposedCacheKey, validModelId } = buildResourcePaths(
|