@huggingface/transformers 4.0.0-next.4 → 4.0.0-next.6

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.
Files changed (187) hide show
  1. package/README.md +15 -5
  2. package/dist/ort-wasm-simd-threaded.jsep.mjs +28 -28
  3. package/dist/transformers.js +3446 -2296
  4. package/dist/transformers.min.js +17 -19
  5. package/dist/transformers.node.cjs +3456 -2263
  6. package/dist/transformers.node.min.cjs +20 -22
  7. package/dist/transformers.node.min.mjs +20 -22
  8. package/dist/transformers.node.mjs +3426 -2258
  9. package/dist/transformers.web.js +1647 -471
  10. package/dist/transformers.web.min.js +18 -18
  11. package/package.json +4 -4
  12. package/src/backends/onnx.js +128 -53
  13. package/src/backends/utils/cacheWasm.js +28 -46
  14. package/src/configs.js +63 -3
  15. package/src/env.js +93 -11
  16. package/src/generation/logits_sampler.js +3 -15
  17. package/src/image_processors_utils.js +2 -6
  18. package/src/models/afmoe/modeling_afmoe.js +5 -0
  19. package/src/models/auto/image_processing_auto.js +2 -1
  20. package/src/models/auto/modeling_auto.js +16 -2
  21. package/src/models/auto/tokenization_auto.js +2 -1
  22. package/src/models/clap/feature_extraction_clap.js +2 -1
  23. package/src/models/marian/tokenization_marian.js +3 -2
  24. package/src/models/modeling_utils.js +45 -7
  25. package/src/models/models.js +10 -0
  26. package/src/models/olmo_hybrid/modeling_olmo_hybrid.js +5 -0
  27. package/src/models/paligemma/processing_paligemma.js +3 -2
  28. package/src/models/processors.js +2 -0
  29. package/src/models/qwen2_5_vl/modeling_qwen2_5_vl.js +5 -0
  30. package/src/models/qwen2_5_vl/processing_qwen2_5_vl.js +3 -0
  31. package/src/models/qwen2_moe/modeling_qwen2_moe.js +5 -0
  32. package/src/models/qwen2_vl/image_processing_qwen2_vl.js +54 -0
  33. package/src/models/qwen2_vl/modeling_qwen2_vl.js +45 -6
  34. package/src/models/qwen3_5/modeling_qwen3_5.js +3 -0
  35. package/src/models/qwen3_5_moe/modeling_qwen3_5_moe.js +3 -0
  36. package/src/models/qwen3_moe/modeling_qwen3_moe.js +5 -0
  37. package/src/models/qwen3_next/modeling_qwen3_next.js +5 -0
  38. package/src/models/qwen3_vl/modeling_qwen3_vl.js +3 -0
  39. package/src/models/qwen3_vl/processing_qwen3_vl.js +3 -0
  40. package/src/models/qwen3_vl_moe/modeling_qwen3_vl_moe.js +3 -0
  41. package/src/models/registry.js +21 -5
  42. package/src/models/session.js +16 -50
  43. package/src/models/whisper/feature_extraction_whisper.js +2 -1
  44. package/src/models/whisper/modeling_whisper.js +6 -5
  45. package/src/models/xlm/tokenization_xlm.js +2 -1
  46. package/src/pipelines/automatic-speech-recognition.js +3 -2
  47. package/src/pipelines/index.js +313 -0
  48. package/src/pipelines/text-generation.js +4 -0
  49. package/src/pipelines/text-to-audio.js +4 -2
  50. package/src/pipelines/zero-shot-classification.js +3 -2
  51. package/src/pipelines.js +139 -428
  52. package/src/tokenization_utils.js +42 -21
  53. package/src/transformers.js +6 -1
  54. package/src/utils/audio.js +2 -1
  55. package/src/utils/cache/FileCache.js +128 -0
  56. package/src/utils/cache.js +7 -4
  57. package/src/utils/core.js +23 -1
  58. package/src/utils/devices.js +22 -0
  59. package/src/utils/dtypes.js +55 -0
  60. package/src/utils/hub/{files.js → FileResponse.js} +0 -90
  61. package/src/utils/hub/utils.js +45 -5
  62. package/src/utils/hub.js +63 -22
  63. package/src/utils/image.js +14 -14
  64. package/src/utils/logger.js +67 -0
  65. package/src/utils/model-loader.js +35 -17
  66. package/src/utils/model_registry/ModelRegistry.js +346 -0
  67. package/src/utils/model_registry/clear_cache.js +128 -0
  68. package/src/utils/model_registry/get_file_metadata.js +149 -0
  69. package/src/utils/model_registry/get_files.js +42 -0
  70. package/src/utils/model_registry/get_model_files.js +193 -0
  71. package/src/utils/model_registry/get_pipeline_files.js +44 -0
  72. package/src/utils/model_registry/get_processor_files.js +20 -0
  73. package/src/utils/model_registry/get_tokenizer_files.js +21 -0
  74. package/src/utils/model_registry/is_cached.js +169 -0
  75. package/src/utils/random.js +225 -0
  76. package/src/utils/tensor.js +8 -21
  77. package/src/utils/video.js +2 -2
  78. package/types/backends/onnx.d.ts.map +1 -1
  79. package/types/backends/utils/cacheWasm.d.ts +3 -17
  80. package/types/backends/utils/cacheWasm.d.ts.map +1 -1
  81. package/types/configs.d.ts.map +1 -1
  82. package/types/env.d.ts +52 -27
  83. package/types/env.d.ts.map +1 -1
  84. package/types/generation/logits_sampler.d.ts +2 -2
  85. package/types/generation/logits_sampler.d.ts.map +1 -1
  86. package/types/image_processors_utils.d.ts.map +1 -1
  87. package/types/models/afmoe/modeling_afmoe.d.ts +8 -0
  88. package/types/models/afmoe/modeling_afmoe.d.ts.map +1 -0
  89. package/types/models/auto/image_processing_auto.d.ts.map +1 -1
  90. package/types/models/auto/modeling_auto.d.ts +6 -0
  91. package/types/models/auto/modeling_auto.d.ts.map +1 -1
  92. package/types/models/auto/tokenization_auto.d.ts.map +1 -1
  93. package/types/models/clap/feature_extraction_clap.d.ts.map +1 -1
  94. package/types/models/marian/tokenization_marian.d.ts.map +1 -1
  95. package/types/models/modeling_utils.d.ts +13 -2
  96. package/types/models/modeling_utils.d.ts.map +1 -1
  97. package/types/models/models.d.ts +10 -0
  98. package/types/models/olmo_hybrid/modeling_olmo_hybrid.d.ts +8 -0
  99. package/types/models/olmo_hybrid/modeling_olmo_hybrid.d.ts.map +1 -0
  100. package/types/models/paligemma/processing_paligemma.d.ts.map +1 -1
  101. package/types/models/processors.d.ts +2 -0
  102. package/types/models/qwen2_5_vl/modeling_qwen2_5_vl.d.ts +4 -0
  103. package/types/models/qwen2_5_vl/modeling_qwen2_5_vl.d.ts.map +1 -0
  104. package/types/models/qwen2_5_vl/processing_qwen2_5_vl.d.ts +4 -0
  105. package/types/models/qwen2_5_vl/processing_qwen2_5_vl.d.ts.map +1 -0
  106. package/types/models/qwen2_moe/modeling_qwen2_moe.d.ts +8 -0
  107. package/types/models/qwen2_moe/modeling_qwen2_moe.d.ts.map +1 -0
  108. package/types/models/qwen2_vl/image_processing_qwen2_vl.d.ts +3 -0
  109. package/types/models/qwen2_vl/image_processing_qwen2_vl.d.ts.map +1 -1
  110. package/types/models/qwen2_vl/modeling_qwen2_vl.d.ts +1 -0
  111. package/types/models/qwen2_vl/modeling_qwen2_vl.d.ts.map +1 -1
  112. package/types/models/qwen3_5/modeling_qwen3_5.d.ts +4 -0
  113. package/types/models/qwen3_5/modeling_qwen3_5.d.ts.map +1 -0
  114. package/types/models/qwen3_5_moe/modeling_qwen3_5_moe.d.ts +4 -0
  115. package/types/models/qwen3_5_moe/modeling_qwen3_5_moe.d.ts.map +1 -0
  116. package/types/models/qwen3_moe/modeling_qwen3_moe.d.ts +8 -0
  117. package/types/models/qwen3_moe/modeling_qwen3_moe.d.ts.map +1 -0
  118. package/types/models/qwen3_next/modeling_qwen3_next.d.ts +8 -0
  119. package/types/models/qwen3_next/modeling_qwen3_next.d.ts.map +1 -0
  120. package/types/models/qwen3_vl/modeling_qwen3_vl.d.ts +4 -0
  121. package/types/models/qwen3_vl/modeling_qwen3_vl.d.ts.map +1 -0
  122. package/types/models/qwen3_vl/processing_qwen3_vl.d.ts +4 -0
  123. package/types/models/qwen3_vl/processing_qwen3_vl.d.ts.map +1 -0
  124. package/types/models/qwen3_vl_moe/modeling_qwen3_vl_moe.d.ts +4 -0
  125. package/types/models/qwen3_vl_moe/modeling_qwen3_vl_moe.d.ts.map +1 -0
  126. package/types/models/registry.d.ts +2 -1
  127. package/types/models/registry.d.ts.map +1 -1
  128. package/types/models/session.d.ts.map +1 -1
  129. package/types/models/whisper/feature_extraction_whisper.d.ts.map +1 -1
  130. package/types/models/whisper/modeling_whisper.d.ts.map +1 -1
  131. package/types/models/xlm/tokenization_xlm.d.ts.map +1 -1
  132. package/types/pipelines/automatic-speech-recognition.d.ts.map +1 -1
  133. package/types/pipelines/index.d.ts +265 -0
  134. package/types/pipelines/index.d.ts.map +1 -0
  135. package/types/pipelines/text-generation.d.ts +5 -1
  136. package/types/pipelines/text-generation.d.ts.map +1 -1
  137. package/types/pipelines/text-to-audio.d.ts.map +1 -1
  138. package/types/pipelines/zero-shot-classification.d.ts.map +1 -1
  139. package/types/pipelines.d.ts +50 -291
  140. package/types/pipelines.d.ts.map +1 -1
  141. package/types/tokenization_utils.d.ts +44 -26
  142. package/types/tokenization_utils.d.ts.map +1 -1
  143. package/types/transformers.d.ts +4 -1
  144. package/types/transformers.d.ts.map +1 -1
  145. package/types/utils/audio.d.ts.map +1 -1
  146. package/types/utils/cache/FileCache.d.ts +39 -0
  147. package/types/utils/cache/FileCache.d.ts.map +1 -0
  148. package/types/utils/cache.d.ts +10 -4
  149. package/types/utils/cache.d.ts.map +1 -1
  150. package/types/utils/core.d.ts +59 -2
  151. package/types/utils/core.d.ts.map +1 -1
  152. package/types/utils/devices.d.ts +15 -0
  153. package/types/utils/devices.d.ts.map +1 -1
  154. package/types/utils/dtypes.d.ts +16 -0
  155. package/types/utils/dtypes.d.ts.map +1 -1
  156. package/types/utils/hub/{files.d.ts → FileResponse.d.ts} +1 -32
  157. package/types/utils/hub/FileResponse.d.ts.map +1 -0
  158. package/types/utils/hub/utils.d.ts +19 -3
  159. package/types/utils/hub/utils.d.ts.map +1 -1
  160. package/types/utils/hub.d.ts +36 -7
  161. package/types/utils/hub.d.ts.map +1 -1
  162. package/types/utils/logger.d.ts +28 -0
  163. package/types/utils/logger.d.ts.map +1 -0
  164. package/types/utils/model-loader.d.ts +15 -0
  165. package/types/utils/model-loader.d.ts.map +1 -1
  166. package/types/utils/model_registry/ModelRegistry.d.ts +271 -0
  167. package/types/utils/model_registry/ModelRegistry.d.ts.map +1 -0
  168. package/types/utils/model_registry/clear_cache.d.ts +74 -0
  169. package/types/utils/model_registry/clear_cache.d.ts.map +1 -0
  170. package/types/utils/model_registry/get_file_metadata.d.ts +20 -0
  171. package/types/utils/model_registry/get_file_metadata.d.ts.map +1 -0
  172. package/types/utils/model_registry/get_files.d.ts +23 -0
  173. package/types/utils/model_registry/get_files.d.ts.map +1 -0
  174. package/types/utils/model_registry/get_model_files.d.ts +22 -0
  175. package/types/utils/model_registry/get_model_files.d.ts.map +1 -0
  176. package/types/utils/model_registry/get_pipeline_files.d.ts +22 -0
  177. package/types/utils/model_registry/get_pipeline_files.d.ts.map +1 -0
  178. package/types/utils/model_registry/get_processor_files.d.ts +9 -0
  179. package/types/utils/model_registry/get_processor_files.d.ts.map +1 -0
  180. package/types/utils/model_registry/get_tokenizer_files.d.ts +9 -0
  181. package/types/utils/model_registry/get_tokenizer_files.d.ts.map +1 -0
  182. package/types/utils/model_registry/is_cached.d.ts +105 -0
  183. package/types/utils/model_registry/is_cached.d.ts.map +1 -0
  184. package/types/utils/random.d.ts +86 -0
  185. package/types/utils/random.d.ts.map +1 -0
  186. package/types/utils/tensor.d.ts.map +1 -1
  187. package/types/utils/hub/files.d.ts.map +0 -1
@@ -1,4 +1,5 @@
1
1
  import { ERROR_MAPPING, REPO_ID_REGEX } from './constants.js';
2
+ import { logger } from '../logger.js';
2
3
 
3
4
  /**
4
5
  * Joins multiple parts of a path into a single path, while handling leading and trailing slashes.
@@ -79,16 +80,21 @@ export function handleError(status, remoteURL, fatal) {
79
80
  /**
80
81
  * Read and track progress when reading a Response object
81
82
  *
82
- * @param {Response|import('./files.js').FileResponse} response The Response object to read
83
+ * @param {Response|import('./FileResponse.js').FileResponse} response The Response object to read
83
84
  * @param {(data: {progress: number, loaded: number, total: number}) => void} progress_callback The function to call with progress updates
85
+ * @param {number} [expectedSize] The expected size of the file (used when content-length header is missing)
84
86
  * @returns {Promise<Uint8Array>} A Promise that resolves with the Uint8Array buffer
85
87
  */
86
- export async function readResponse(response, progress_callback) {
88
+ export async function readResponse(response, progress_callback, expectedSize) {
87
89
  const contentLength = response.headers.get('Content-Length');
88
- if (contentLength === null) {
89
- console.warn('Unable to determine content-length from response headers. Will expand buffer when needed.');
90
+
91
+ // Use content-length if available, otherwise fall back to expectedSize (from metadata)
92
+ let total = contentLength ? parseInt(contentLength, 10) : (expectedSize ?? 0);
93
+
94
+ if (contentLength === null && !expectedSize) {
95
+ logger.warn('Unable to determine content-length from response headers. Will expand buffer when needed.');
90
96
  }
91
- let total = parseInt(contentLength ?? '0');
97
+
92
98
  let buffer = new Uint8Array(total);
93
99
  let loaded = 0;
94
100
 
@@ -126,3 +132,37 @@ export async function readResponse(response, progress_callback) {
126
132
 
127
133
  return buffer;
128
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,9 +6,12 @@
6
6
 
7
7
  import { apis, env } from '../env.js';
8
8
  import { dispatchCallback } from './core.js';
9
- import { FileResponse, FileCache } from './hub/files.js';
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';
13
+ import { get_file_metadata } from './model_registry/get_file_metadata.js';
14
+ import { logger } from './logger.js';
12
15
 
13
16
  export { MAX_EXTERNAL_DATA_CHUNKS } from './hub/constants.js';
14
17
 
@@ -37,7 +40,7 @@ export { MAX_EXTERNAL_DATA_CHUNKS } from './hub/constants.js';
37
40
  * @typedef {Object} ModelSpecificPretrainedOptions Options for loading a pretrained model.
38
41
  * @property {string} [subfolder='onnx'] In case the relevant files are located inside a subfolder of the model repo on huggingface.co,
39
42
  * you can specify the folder name here.
40
- * @property {string} [model_file_name=null] If specified, load the model with this name (excluding the .onnx suffix). Currently only valid for encoder- or decoder-only models.
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.
41
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.
42
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.
43
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).
@@ -63,14 +66,30 @@ export async function getFile(urlOrPath) {
63
66
  : urlOrPath.toString()
64
67
  : urlOrPath,
65
68
  );
66
- } else if (typeof process !== 'undefined' && process?.release?.name === 'node') {
69
+ } else {
70
+ return env.fetch(urlOrPath, {
71
+ headers: getFetchHeaders(urlOrPath),
72
+ });
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Generates appropriate HTTP headers for fetching resources.
78
+ * In Node.js environments, adds User-Agent and Authorization headers when applicable.
79
+ * In browser environments, returns minimal headers for security.
80
+ *
81
+ * @param {URL|string} urlOrPath The URL or path being fetched.
82
+ * @returns {Headers} A Headers object with appropriate headers for the request.
83
+ */
84
+ export function getFetchHeaders(urlOrPath) {
85
+ const isNode = typeof process !== 'undefined' && process?.release?.name === 'node';
86
+ const headers = new Headers();
87
+
88
+ if (isNode) {
67
89
  const IS_CI = !!process.env?.TESTING_REMOTELY;
68
90
  const version = env.version;
69
-
70
- const headers = new Headers();
71
91
  headers.set('User-Agent', `transformers.js/${version}; is_ci/${IS_CI};`);
72
92
 
73
- // Check whether we are making a request to the Hugging Face Hub.
74
93
  const isHFURL = isValidUrl(urlOrPath, ['http:', 'https:'], ['huggingface.co', 'hf.co']);
75
94
  if (isHFURL) {
76
95
  // If an access token is present in the environment variables,
@@ -81,13 +100,13 @@ export async function getFile(urlOrPath) {
81
100
  headers.set('Authorization', `Bearer ${token}`);
82
101
  }
83
102
  }
84
- return fetch(urlOrPath, { headers });
85
103
  } else {
86
104
  // Running in a browser-environment, so we use default headers
87
105
  // NOTE: We do not allow passing authorization headers in the browser,
88
106
  // since this would require exposing the token to the client.
89
- return fetch(urlOrPath);
90
107
  }
108
+
109
+ return headers;
91
110
  }
92
111
 
93
112
  /**
@@ -103,7 +122,7 @@ export async function getFile(urlOrPath) {
103
122
  * @returns {{ requestURL: string, localPath: string, remoteURL: string, proposedCacheKey: string, validModelId: boolean }}
104
123
  * An object containing all the paths and URLs for the resource.
105
124
  */
106
- function buildResourcePaths(path_or_repo_id, filename, options = {}, cache = null) {
125
+ export function buildResourcePaths(path_or_repo_id, filename, options = {}, cache = null) {
107
126
  const revision = options.revision ?? 'main';
108
127
  const requestURL = pathJoin(path_or_repo_id, filename);
109
128
 
@@ -142,7 +161,7 @@ function buildResourcePaths(path_or_repo_id, filename, options = {}, cache = nul
142
161
  * @param {import('./cache.js').CacheInterface | null} cache The cache instance to check.
143
162
  * @param {string} localPath The local path to try first.
144
163
  * @param {string} proposedCacheKey The proposed cache key to try second.
145
- * @returns {Promise<Response|import('./hub/files.js').FileResponse|undefined|string>}
164
+ * @returns {Promise<Response|import('./hub/FileResponse.js').FileResponse|undefined|string>}
146
165
  * The cached response if found, undefined otherwise.
147
166
  */
148
167
  export async function checkCachedResource(cache, localPath, proposedCacheKey) {
@@ -164,7 +183,7 @@ export async function checkCachedResource(cache, localPath, proposedCacheKey) {
164
183
  * @param {string} filename The name of the file to cache.
165
184
  * @param {import('./cache.js').CacheInterface} cache The cache instance to store in.
166
185
  * @param {string} cacheKey The cache key to use.
167
- * @param {Response|import('./hub/files.js').FileResponse} response The response to cache.
186
+ * @param {Response|import('./hub/FileResponse.js').FileResponse} response The response to cache.
168
187
  * @param {Uint8Array} [result] The result buffer if already read.
169
188
  * @param {PretrainedOptions} [options] Options containing progress callback and context for progress updates.
170
189
  * @returns {Promise<void>}
@@ -200,7 +219,7 @@ export async function storeCachedResource(path_or_repo_id, filename, cache, cach
200
219
  .catch((err) => {
201
220
  // Do not crash if unable to add to cache (e.g., QuotaExceededError).
202
221
  // Rather, log a warning and proceed with execution.
203
- console.warn(`Unable to add response to browser cache: ${err}.`);
222
+ logger.warn(`Unable to add response to browser cache: ${err}.`);
204
223
  });
205
224
  }
206
225
  }
@@ -241,7 +260,7 @@ export async function loadResourceFile(
241
260
  // Whether to cache the final response in the end.
242
261
  let toCacheResponse = false;
243
262
 
244
- /** @type {Response|import('./hub/files.js').FileResponse|undefined|string} */
263
+ /** @type {Response|import('./hub/FileResponse.js').FileResponse|undefined|string} */
245
264
  let response;
246
265
 
247
266
  // Check cache
@@ -262,7 +281,7 @@ export async function loadResourceFile(
262
281
  } catch (e) {
263
282
  // Something went wrong while trying to get the file locally.
264
283
  // NOTE: error handling is done in the next step (since `response` will be undefined)
265
- console.warn(`Unable to load from local path "${localPath}": "${e}"`);
284
+ logger.warn(`Unable to load from local path "${localPath}": "${e}"`);
266
285
  }
267
286
  } else if (options.local_files_only) {
268
287
  throw new Error(`\`local_files_only=true\`, but attempted to load a remote file from: ${requestURL}.`);
@@ -354,14 +373,36 @@ export async function loadResourceFile(
354
373
  total: buffer.length,
355
374
  });
356
375
  } else {
357
- buffer = await readResponse(response, (data) => {
358
- dispatchCallback(options.progress_callback, {
359
- status: 'progress',
360
- name: path_or_repo_id,
361
- file: filename,
362
- ...data,
363
- });
364
- });
376
+ // Get expected file size from response headers or metadata
377
+ // This helps with progress tracking when content-length is missing
378
+ let expectedSize;
379
+ const contentLength = response.headers.get('content-length');
380
+ if (contentLength) {
381
+ expectedSize = parseInt(contentLength, 10);
382
+ } else {
383
+ // Try to get size from metadata (useful when content-length is missing during download)
384
+ try {
385
+ const metadata = await get_file_metadata(path_or_repo_id, filename, options);
386
+ if (metadata.size) {
387
+ expectedSize = metadata.size;
388
+ }
389
+ } catch (e) {
390
+ // Ignore metadata fetch errors
391
+ }
392
+ }
393
+
394
+ buffer = await readResponse(
395
+ response,
396
+ (data) => {
397
+ dispatchCallback(options.progress_callback, {
398
+ status: 'progress',
399
+ name: path_or_repo_id,
400
+ file: filename,
401
+ ...data,
402
+ });
403
+ },
404
+ expectedSize,
405
+ );
365
406
  }
366
407
  }
367
408
  result = buffer;
@@ -15,16 +15,16 @@ import { saveBlob } from './io.js';
15
15
 
16
16
  // Will be empty (or not used) if running in browser or web-worker
17
17
  import sharp from 'sharp';
18
+ import { logger } from './logger.js';
18
19
 
19
20
  let createCanvasFunction;
20
21
  let ImageDataClass;
21
22
  let loadImageFunction;
22
- const IS_BROWSER_OR_WEBWORKER = apis.IS_BROWSER_ENV || apis.IS_WEBWORKER_ENV;
23
- if (IS_BROWSER_OR_WEBWORKER) {
23
+ if (apis.IS_WEB_ENV) {
24
24
  // Running in browser or web-worker
25
25
  createCanvasFunction = (/** @type {number} */ width, /** @type {number} */ height) => {
26
26
  if (!self.OffscreenCanvas) {
27
- throw new Error('OffscreenCanvas not supported by this browser.');
27
+ throw new Error('OffscreenCanvas not supported by this environment.');
28
28
  }
29
29
  return new self.OffscreenCanvas(width, height);
30
30
  };
@@ -133,7 +133,7 @@ export class RawImage {
133
133
  * @returns {RawImage} The image object.
134
134
  */
135
135
  static fromCanvas(canvas) {
136
- if (!IS_BROWSER_OR_WEBWORKER) {
136
+ if (!apis.IS_WEB_ENV) {
137
137
  throw new Error('fromCanvas() is only supported in browser environments.');
138
138
  }
139
139
 
@@ -164,7 +164,7 @@ export class RawImage {
164
164
  * @returns {Promise<RawImage>} The image object.
165
165
  */
166
166
  static async fromBlob(blob) {
167
- if (IS_BROWSER_OR_WEBWORKER) {
167
+ if (apis.IS_WEB_ENV) {
168
168
  // Running in environment with canvas
169
169
  const img = await loadImageFunction(blob);
170
170
 
@@ -378,7 +378,7 @@ export class RawImage {
378
378
  height = (width / this.width) * this.height;
379
379
  }
380
380
 
381
- if (IS_BROWSER_OR_WEBWORKER) {
381
+ if (apis.IS_WEB_ENV) {
382
382
  // TODO use `resample` in browser environment
383
383
 
384
384
  // Store number of channels before resizing
@@ -406,7 +406,7 @@ export class RawImage {
406
406
  case 'box':
407
407
  case 'hamming':
408
408
  if (resampleMethod === 'box' || resampleMethod === 'hamming') {
409
- console.warn(
409
+ logger.warn(
410
410
  `Resampling method ${resampleMethod} is not yet supported. Using bilinear instead.`,
411
411
  );
412
412
  resampleMethod = 'bilinear';
@@ -452,7 +452,7 @@ export class RawImage {
452
452
  return this;
453
453
  }
454
454
 
455
- if (IS_BROWSER_OR_WEBWORKER) {
455
+ if (apis.IS_WEB_ENV) {
456
456
  // Store number of channels before padding
457
457
  const numChannels = this.channels;
458
458
 
@@ -494,7 +494,7 @@ export class RawImage {
494
494
  const crop_width = x_max - x_min + 1;
495
495
  const crop_height = y_max - y_min + 1;
496
496
 
497
- if (IS_BROWSER_OR_WEBWORKER) {
497
+ if (apis.IS_WEB_ENV) {
498
498
  // Store number of channels before resizing
499
499
  const numChannels = this.channels;
500
500
 
@@ -541,7 +541,7 @@ export class RawImage {
541
541
  const width_offset = (this.width - crop_width) / 2;
542
542
  const height_offset = (this.height - crop_height) / 2;
543
543
 
544
- if (IS_BROWSER_OR_WEBWORKER) {
544
+ if (apis.IS_WEB_ENV) {
545
545
  // Store number of channels before resizing
546
546
  const numChannels = this.channels;
547
547
 
@@ -649,7 +649,7 @@ export class RawImage {
649
649
  }
650
650
 
651
651
  async toBlob(type = 'image/png', quality = 1) {
652
- if (!IS_BROWSER_OR_WEBWORKER) {
652
+ if (!apis.IS_WEB_ENV) {
653
653
  throw new Error('toBlob() is only supported in browser environments.');
654
654
  }
655
655
 
@@ -672,7 +672,7 @@ export class RawImage {
672
672
  }
673
673
 
674
674
  toCanvas() {
675
- if (!IS_BROWSER_OR_WEBWORKER) {
675
+ if (!apis.IS_WEB_ENV) {
676
676
  throw new Error('toCanvas() is only supported in browser environments.');
677
677
  }
678
678
 
@@ -773,7 +773,7 @@ export class RawImage {
773
773
  * @returns {Promise<void>}
774
774
  */
775
775
  async save(path) {
776
- if (IS_BROWSER_OR_WEBWORKER) {
776
+ if (apis.IS_WEB_ENV) {
777
777
  if (apis.IS_WEBWORKER_ENV) {
778
778
  throw new Error('Unable to save an image from a Web Worker.');
779
779
  }
@@ -798,7 +798,7 @@ export class RawImage {
798
798
  * @returns {import('sharp').Sharp} The Sharp instance.
799
799
  */
800
800
  toSharp() {
801
- if (IS_BROWSER_OR_WEBWORKER) {
801
+ if (apis.IS_WEB_ENV) {
802
802
  throw new Error('toSharp() is only supported in server-side environments.');
803
803
  }
804
804
 
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file Logger utility for Transformers.js with configurable log levels.
3
+ *
4
+ * @module utils/logger
5
+ */
6
+
7
+ import { env, LogLevel } from '../env.js';
8
+
9
+ /**
10
+ * Logger that respects the configured log level in env.logLevel.
11
+ *
12
+ * @example
13
+ * import { logger } from './utils/logger.js';
14
+ * logger.info('Model loaded successfully');
15
+ * logger.warn('Deprecated method used');
16
+ * logger.error('Failed to load model');
17
+ * logger.debug('Token count:', tokens.length);
18
+ */
19
+ export const logger = {
20
+ /**
21
+ * Log an error message. Only suppressed when logLevel is NONE.
22
+ * @param {...any} args - Arguments to log
23
+ */
24
+ error(...args) {
25
+ if (env.logLevel <= LogLevel.ERROR) {
26
+ console.error(...args);
27
+ }
28
+ },
29
+
30
+ /**
31
+ * Log a warning message. Shown when logLevel <= WARNING.
32
+ * @param {...any} args - Arguments to log
33
+ */
34
+ warn(...args) {
35
+ if (env.logLevel <= LogLevel.WARNING) {
36
+ console.warn(...args);
37
+ }
38
+ },
39
+
40
+ /**
41
+ * Log an info message. Shown when logLevel <= INFO.
42
+ * @param {...any} args - Arguments to log
43
+ */
44
+ info(...args) {
45
+ if (env.logLevel <= LogLevel.INFO) {
46
+ console.log(...args);
47
+ }
48
+ },
49
+
50
+ /**
51
+ * Log a debug message. Only shown when logLevel is DEBUG.
52
+ * @param {...any} args - Arguments to log
53
+ */
54
+ debug(...args) {
55
+ if (env.logLevel <= LogLevel.DEBUG) {
56
+ console.log(...args);
57
+ }
58
+ },
59
+
60
+ /**
61
+ * Log a message (alias for info). Shown when logLevel <= INFO.
62
+ * @param {...any} args - Arguments to log
63
+ */
64
+ log(...args) {
65
+ this.info(...args);
66
+ },
67
+ };
@@ -1,6 +1,37 @@
1
1
  import { getModelFile, MAX_EXTERNAL_DATA_CHUNKS } from './hub.js';
2
2
  import { apis } from '../env.js';
3
3
 
4
+ /**
5
+ * Resolves an `use_external_data_format` config value to the number of data chunks for a given file.
6
+ * @param {import('./hub.js').ExternalData|Record<string, import('./hub.js').ExternalData>|null|undefined} config The external data format configuration.
7
+ * @param {string} fullName The full ONNX file name (e.g., "model_quantized.onnx").
8
+ * @param {string} fileName The base file name (e.g., "model").
9
+ * @returns {number} The number of external data chunks (0 if none).
10
+ */
11
+ export function resolveExternalDataFormat(config, fullName, fileName) {
12
+ if (!config) return 0;
13
+ if (typeof config === 'object' && config !== null) {
14
+ if (config.hasOwnProperty(fullName)) return +config[fullName];
15
+ if (config.hasOwnProperty(fileName)) return +config[fileName];
16
+ return 0;
17
+ }
18
+ return +config; // (false=0, true=1, number remains the same)
19
+ }
20
+
21
+ /**
22
+ * Generates the file names for external data chunks.
23
+ * @param {string} fullName The full ONNX file name (e.g., "model_quantized.onnx").
24
+ * @param {number} numChunks The number of external data chunks.
25
+ * @returns {string[]} Array of external data file names.
26
+ */
27
+ export function getExternalDataChunkNames(fullName, numChunks) {
28
+ const names = [];
29
+ for (let i = 0; i < numChunks; ++i) {
30
+ names.push(`${fullName}_data${i === 0 ? '' : '_' + i}`);
31
+ }
32
+ return names;
33
+ }
34
+
4
35
  /**
5
36
  * Loads the core model file.
6
37
  *
@@ -42,28 +73,15 @@ export async function getModelDataFiles(
42
73
  /** @type {Promise<string|{path: string, data: Uint8Array}>[]} */
43
74
  let externalDataPromises = [];
44
75
 
45
- if (use_external_data_format) {
46
- let external_data_format;
47
- if (typeof use_external_data_format === 'object') {
48
- if (use_external_data_format.hasOwnProperty(baseName)) {
49
- external_data_format = use_external_data_format[baseName];
50
- } else if (use_external_data_format.hasOwnProperty(fileName)) {
51
- external_data_format = use_external_data_format[fileName];
52
- } else {
53
- external_data_format = false;
54
- }
55
- } else {
56
- external_data_format = use_external_data_format;
57
- }
58
-
59
- const num_chunks = +external_data_format; // (false=0, true=1, number remains the same)
76
+ const num_chunks = resolveExternalDataFormat(use_external_data_format, baseName, fileName);
77
+ if (num_chunks > 0) {
60
78
  if (num_chunks > MAX_EXTERNAL_DATA_CHUNKS) {
61
79
  throw new Error(
62
80
  `The number of external data chunks (${num_chunks}) exceeds the maximum allowed value (${MAX_EXTERNAL_DATA_CHUNKS}).`,
63
81
  );
64
82
  }
65
- for (let i = 0; i < num_chunks; ++i) {
66
- const path = `${baseName}_data${i === 0 ? '' : '_' + i}`;
83
+ const chunkNames = getExternalDataChunkNames(baseName, num_chunks);
84
+ for (const path of chunkNames) {
67
85
  const fullPath = `${options.subfolder ?? ''}/${path}`;
68
86
  externalDataPromises.push(
69
87
  new Promise(async (resolve, reject) => {