@automatalabs/react-native-transformers 0.1.1 → 0.1.3

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 (46) hide show
  1. package/README.md +5 -1
  2. package/app.plugin.js +1 -1
  3. package/dist/app.plugin.d.ts +3 -0
  4. package/dist/app.plugin.d.ts.map +1 -0
  5. package/dist/app.plugin.js +4 -0
  6. package/dist/app.plugin.js.map +1 -0
  7. package/dist/plugin/src/index.d.ts +4 -0
  8. package/dist/plugin/src/index.d.ts.map +1 -0
  9. package/dist/plugin/src/index.js +16 -0
  10. package/dist/plugin/src/index.js.map +1 -0
  11. package/dist/src/adapter/onnxruntime-web-webgpu.d.ts +47 -0
  12. package/dist/src/adapter/onnxruntime-web-webgpu.d.ts.map +1 -0
  13. package/dist/src/adapter/onnxruntime-web-webgpu.js +256 -0
  14. package/dist/src/adapter/onnxruntime-web-webgpu.js.map +1 -0
  15. package/dist/src/expoFileSystemCache.d.ts +17 -0
  16. package/dist/src/expoFileSystemCache.d.ts.map +1 -0
  17. package/dist/src/expoFileSystemCache.js +240 -0
  18. package/dist/src/expoFileSystemCache.js.map +1 -0
  19. package/dist/src/index.d.ts +3 -0
  20. package/dist/src/index.d.ts.map +1 -0
  21. package/dist/src/index.js +16 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/metro.d.ts +21 -0
  24. package/dist/src/metro.d.ts.map +1 -0
  25. package/dist/src/metro.js +90 -0
  26. package/dist/src/metro.js.map +1 -0
  27. package/dist/src/runtime.d.ts +17 -0
  28. package/dist/src/runtime.d.ts.map +1 -0
  29. package/dist/src/runtime.js +511 -0
  30. package/dist/src/runtime.js.map +1 -0
  31. package/dist/src/transformers.d.ts +19 -0
  32. package/dist/src/transformers.d.ts.map +1 -0
  33. package/dist/src/transformers.js +224 -0
  34. package/dist/src/transformers.js.map +1 -0
  35. package/dist/src/types.d.ts +96 -0
  36. package/dist/src/types.d.ts.map +1 -0
  37. package/dist/src/types.js +3 -0
  38. package/dist/src/types.js.map +1 -0
  39. package/package.json +58 -13
  40. package/plugin/src/index.js +0 -13
  41. package/src/adapter/onnxruntime-web-webgpu.js +0 -246
  42. package/src/expoFileSystemCache.js +0 -251
  43. package/src/index.js +0 -27
  44. package/src/metro.js +0 -66
  45. package/src/runtime.js +0 -535
  46. package/src/transformers.js +0 -225
@@ -1,246 +0,0 @@
1
- const { NativeModules } = require('react-native');
2
- const ortReactNative = require('onnxruntime-react-native');
3
- const { sanitizeSessionOptions } = require('../runtime');
4
-
5
- const Module = NativeModules?.Onnxruntime;
6
-
7
- if (typeof globalThis.OrtApi === 'undefined' && typeof Module?.install === 'function') {
8
- Module.install();
9
- }
10
-
11
- const OrtApi =
12
- globalThis.OrtApi ??
13
- new Proxy(
14
- {},
15
- {
16
- get() {
17
- throw new Error(
18
- 'OrtApi is not initialized. Please make sure Onnxruntime installation is successful.',
19
- );
20
- },
21
- },
22
- );
23
-
24
- const dataTypeStrings = [
25
- undefined,
26
- 'float32',
27
- 'uint8',
28
- 'int8',
29
- 'uint16',
30
- 'int16',
31
- 'int32',
32
- 'int64',
33
- 'string',
34
- 'bool',
35
- 'float16',
36
- 'float64',
37
- 'uint32',
38
- 'uint64',
39
- undefined,
40
- undefined,
41
- undefined,
42
- undefined,
43
- undefined,
44
- undefined,
45
- undefined,
46
- 'uint4',
47
- 'int4',
48
- ];
49
-
50
- function fillNamesAndMetadata(rawMetadata = []) {
51
- const names = [];
52
- const metadata = [];
53
-
54
- for (const item of rawMetadata) {
55
- names.push(item.name);
56
-
57
- if (!item.isTensor) {
58
- metadata.push({
59
- name: item.name,
60
- isTensor: false,
61
- });
62
- continue;
63
- }
64
-
65
- const type = dataTypeStrings[item.type];
66
- if (type === undefined) {
67
- throw new Error(`Unsupported data type: ${item.type}`);
68
- }
69
-
70
- const shape = [];
71
- for (let index = 0; index < item.shape.length; index += 1) {
72
- const dim = item.shape[index];
73
- if (dim === -1) {
74
- shape.push(item.symbolicDimensions[index]);
75
- } else if (dim >= 0) {
76
- shape.push(dim);
77
- } else {
78
- throw new Error(`Invalid dimension: ${dim}`);
79
- }
80
- }
81
-
82
- metadata.push({
83
- name: item.name,
84
- isTensor: true,
85
- type,
86
- shape,
87
- });
88
- }
89
-
90
- return [names, metadata];
91
- }
92
-
93
- function getLogLevelValue(logLevel) {
94
- switch (logLevel) {
95
- case 'verbose':
96
- return 0;
97
- case 'info':
98
- return 1;
99
- case 'warning':
100
- case undefined:
101
- return 2;
102
- case 'error':
103
- return 3;
104
- case 'fatal':
105
- return 4;
106
- default:
107
- throw new Error(`Unsupported log level: ${logLevel}`);
108
- }
109
- }
110
-
111
- function normalizeCreateArguments(args) {
112
- const [arg0, arg1, arg2, arg3] = args;
113
-
114
- if (typeof arg0 === 'string') {
115
- if (arg1 !== undefined && (typeof arg1 !== 'object' || arg1 === null || Array.isArray(arg1))) {
116
- throw new TypeError("'options' must be an object.");
117
- }
118
-
119
- return {
120
- modelPath: arg0,
121
- modelBytes: null,
122
- options: arg1 ?? {},
123
- };
124
- }
125
-
126
- if (arg0 instanceof Uint8Array) {
127
- if (arg1 !== undefined && (typeof arg1 !== 'object' || arg1 === null || Array.isArray(arg1))) {
128
- throw new TypeError("'options' must be an object.");
129
- }
130
-
131
- return {
132
- modelPath: null,
133
- modelBytes: arg0,
134
- options: arg1 ?? {},
135
- };
136
- }
137
-
138
- if (
139
- arg0 instanceof ArrayBuffer ||
140
- (typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer)
141
- ) {
142
- let byteOffset = 0;
143
- let byteLength = arg0.byteLength;
144
- let options = {};
145
-
146
- if (typeof arg1 === 'object' && arg1 !== null) {
147
- options = arg1;
148
- } else if (typeof arg1 === 'number') {
149
- byteOffset = arg1;
150
- byteLength = typeof arg2 === 'number' ? arg2 : arg0.byteLength - byteOffset;
151
- options = typeof arg3 === 'object' && arg3 !== null ? arg3 : {};
152
- } else if (arg1 !== undefined) {
153
- throw new TypeError("'options' must be an object.");
154
- }
155
-
156
- return {
157
- modelPath: null,
158
- modelBytes: new Uint8Array(arg0, byteOffset, byteLength),
159
- options,
160
- };
161
- }
162
-
163
- throw new TypeError("Unexpected argument[0]: must be 'path' or 'buffer'.");
164
- }
165
-
166
- function toExactArrayBuffer(uint8Array) {
167
- if (uint8Array.byteOffset === 0 && uint8Array.byteLength === uint8Array.buffer.byteLength) {
168
- return uint8Array.buffer;
169
- }
170
-
171
- return uint8Array.buffer.slice(
172
- uint8Array.byteOffset,
173
- uint8Array.byteOffset + uint8Array.byteLength,
174
- );
175
- }
176
-
177
- class ReactNativeSessionHandler {
178
- #inferenceSession;
179
-
180
- constructor(session) {
181
- this.#inferenceSession = session;
182
-
183
- const [inputNames, inputMetadata] = fillNamesAndMetadata(session.inputMetadata);
184
- const [outputNames, outputMetadata] = fillNamesAndMetadata(session.outputMetadata);
185
-
186
- this.inputNames = inputNames;
187
- this.outputNames = outputNames;
188
- this.inputMetadata = inputMetadata;
189
- this.outputMetadata = outputMetadata;
190
- }
191
-
192
- async run(feeds, fetches, options) {
193
- return this.#inferenceSession.run(feeds, fetches, options);
194
- }
195
-
196
- async dispose() {
197
- this.#inferenceSession.dispose();
198
- }
199
-
200
- async release() {
201
- this.#inferenceSession.dispose();
202
- }
203
-
204
- startProfiling() {
205
- // no-op; profiling is enabled at load time by session options if requested
206
- }
207
-
208
- endProfiling() {
209
- return this.#inferenceSession.endProfiling();
210
- }
211
- }
212
-
213
- class PatchedInferenceSession extends ortReactNative.InferenceSession {
214
- static #initialized = false;
215
-
216
- static async create(...args) {
217
- const { modelPath, modelBytes, options } = normalizeCreateArguments(args);
218
- const sessionOptions = sanitizeSessionOptions({
219
- ...options,
220
- ortExtLibPath: options?.ortExtLibPath ?? Module?.ORT_EXTENSIONS_PATH,
221
- });
222
-
223
- if (!PatchedInferenceSession.#initialized) {
224
- PatchedInferenceSession.#initialized = true;
225
- OrtApi.initOrtOnce(getLogLevelValue(ortReactNative.env.logLevel), ortReactNative.Tensor);
226
- }
227
-
228
- const session = OrtApi.createInferenceSession();
229
-
230
- if (typeof modelPath === 'string') {
231
- await session.loadModel(modelPath, sessionOptions);
232
- } else {
233
- await session.loadModel(toExactArrayBuffer(modelBytes), sessionOptions);
234
- }
235
-
236
- return new PatchedInferenceSession(new ReactNativeSessionHandler(session));
237
- }
238
- }
239
-
240
- module.exports = {
241
- ...ortReactNative,
242
- InferenceSession: PatchedInferenceSession,
243
- Tensor: ortReactNative.Tensor,
244
- env: ortReactNative.env,
245
- listSupportedBackends: OrtApi.listSupportedBackends ?? ortReactNative.listSupportedBackends,
246
- };
@@ -1,251 +0,0 @@
1
- const { Directory, File, Paths } = require('expo-file-system');
2
-
3
- const DEFAULT_MODEL_CACHE_PATH_SEGMENTS = Object.freeze([
4
- 'automatalabs-react-native-transformers',
5
- 'models',
6
- ]);
7
-
8
- function hashString(value) {
9
- let hash = 0x811c9dc5;
10
-
11
- for (let index = 0; index < value.length; index += 1) {
12
- hash ^= value.charCodeAt(index);
13
- hash = Math.imul(hash, 0x01000193);
14
- }
15
-
16
- return (hash >>> 0).toString(16).padStart(8, '0');
17
- }
18
-
19
- function sanitizeSegment(value) {
20
- const normalized = encodeURIComponent(String(value))
21
- .replace(/%/g, '_')
22
- .replace(/[^A-Za-z0-9._-]+/g, '_')
23
- .replace(/_+/g, '_')
24
- .replace(/^_+|_+$/g, '');
25
-
26
- return normalized.slice(0, 120) || 'index';
27
- }
28
-
29
- function getRequestPathSegments(request) {
30
- const value = String(request ?? '');
31
-
32
- try {
33
- const url = new URL(value);
34
- const segments = [sanitizeSegment(url.protocol.replace(/:$/, '')), sanitizeSegment(url.host)];
35
- const pathnameSegments = url.pathname.split('/').filter(Boolean).map((segment) => sanitizeSegment(segment));
36
-
37
- segments.push(...pathnameSegments);
38
-
39
- if (segments.length === 2) {
40
- segments.push('index');
41
- }
42
-
43
- if (url.search) {
44
- segments[segments.length - 1] = `${segments[segments.length - 1]}__q_${hashString(url.search)}`;
45
- }
46
-
47
- return segments;
48
- } catch {
49
- const segments = value.split('/').filter(Boolean).map((segment) => sanitizeSegment(segment));
50
- return segments.length > 0 ? segments : ['index'];
51
- }
52
- }
53
-
54
- function ensureDirectory(directory) {
55
- if (!directory.exists) {
56
- directory.create({
57
- intermediates: true,
58
- idempotent: true,
59
- });
60
- }
61
- }
62
-
63
- function deleteIfExists(file) {
64
- if (file?.exists) {
65
- try {
66
- file.delete();
67
- } catch {
68
- // ignore cleanup failures
69
- }
70
- }
71
- }
72
-
73
- function getCachePaths(rootDirectory, request) {
74
- const requestPathSegments = getRequestPathSegments(request);
75
- const directorySegments = requestPathSegments.slice(0, -1);
76
- const leafSegment = requestPathSegments.at(-1) ?? 'index';
77
- const requestHash = hashString(String(request ?? ''));
78
- const baseName = `${leafSegment}__${requestHash}`;
79
- const directory = new Directory(rootDirectory, ...directorySegments);
80
-
81
- return {
82
- directory,
83
- dataFile: new File(directory, `${baseName}.data`),
84
- metadataFile: new File(directory, `${baseName}.meta.json`),
85
- tempDataFile: new File(directory, `${baseName}.tmp.data`),
86
- tempMetadataFile: new File(directory, `${baseName}.tmp.meta.json`),
87
- };
88
- }
89
-
90
- async function readMetadata(metadataFile) {
91
- if (!metadataFile.exists) {
92
- return null;
93
- }
94
-
95
- try {
96
- return JSON.parse(await metadataFile.text());
97
- } catch {
98
- return null;
99
- }
100
- }
101
-
102
- function createResponseHeaders(dataFile, metadata) {
103
- const headers = new Headers(metadata?.headers ?? {});
104
-
105
- if (!headers.has('content-length')) {
106
- headers.set('content-length', String(dataFile.size ?? 0));
107
- }
108
-
109
- return headers;
110
- }
111
-
112
- async function writeMetadata(metadataFile, tempMetadataFile, metadata) {
113
- deleteIfExists(tempMetadataFile);
114
- tempMetadataFile.create({
115
- intermediates: true,
116
- overwrite: true,
117
- });
118
- tempMetadataFile.write(JSON.stringify(metadata));
119
- deleteIfExists(metadataFile);
120
- tempMetadataFile.move(metadataFile);
121
- }
122
-
123
- async function writeResponseToFile(file, response, progressCallback) {
124
- deleteIfExists(file);
125
- file.create({
126
- intermediates: true,
127
- overwrite: true,
128
- });
129
-
130
- const total = Number.parseInt(response.headers.get('content-length') ?? '0', 10) || 0;
131
- let loaded = 0;
132
-
133
- if (response.body?.getReader) {
134
- const reader = response.body.getReader();
135
- const handle = file.open();
136
-
137
- try {
138
- while (true) {
139
- const { done, value } = await reader.read();
140
-
141
- if (done) {
142
- break;
143
- }
144
-
145
- if (value && value.length > 0) {
146
- handle.writeBytes(value);
147
- loaded += value.length;
148
- progressCallback?.({
149
- progress: total > 0 ? (loaded / total) * 100 : 0,
150
- loaded,
151
- total,
152
- });
153
- }
154
- }
155
- } finally {
156
- handle.close();
157
- }
158
- } else {
159
- const bytes = new Uint8Array(await response.arrayBuffer());
160
- file.write(bytes);
161
- loaded = bytes.length;
162
- progressCallback?.({
163
- progress: 100,
164
- loaded,
165
- total: total || loaded,
166
- });
167
- }
168
- }
169
-
170
- function normalizeCacheRootDirectory(directory) {
171
- if (directory instanceof Directory) {
172
- return directory;
173
- }
174
-
175
- if (typeof directory === 'string') {
176
- return new Directory(directory);
177
- }
178
-
179
- return new Directory(Paths.cache, ...DEFAULT_MODEL_CACHE_PATH_SEGMENTS);
180
- }
181
-
182
- function getDefaultExpoFileSystemModelCacheDirectory() {
183
- return normalizeCacheRootDirectory();
184
- }
185
-
186
- function createExpoFileSystemCache(options = {}) {
187
- const rootDirectory = normalizeCacheRootDirectory(options.directory);
188
- ensureDirectory(rootDirectory);
189
-
190
- return {
191
- async match(request) {
192
- const { dataFile, metadataFile } = getCachePaths(rootDirectory, request);
193
-
194
- if (!dataFile.exists) {
195
- return undefined;
196
- }
197
-
198
- const metadata = await readMetadata(metadataFile);
199
- return new Response(dataFile, {
200
- headers: createResponseHeaders(dataFile, metadata),
201
- status: metadata?.status ?? 200,
202
- });
203
- },
204
-
205
- async put(request, response, progressCallback = undefined) {
206
- const { directory, dataFile, metadataFile, tempDataFile, tempMetadataFile } = getCachePaths(
207
- rootDirectory,
208
- request,
209
- );
210
-
211
- ensureDirectory(directory);
212
-
213
- try {
214
- await writeResponseToFile(tempDataFile, response, progressCallback);
215
- deleteIfExists(dataFile);
216
- tempDataFile.move(dataFile);
217
-
218
- await writeMetadata(metadataFile, tempMetadataFile, {
219
- request: String(request ?? ''),
220
- status: response.status ?? 200,
221
- headers: Object.fromEntries(response.headers.entries()),
222
- cachedAt: Date.now(),
223
- });
224
- } catch (error) {
225
- deleteIfExists(tempDataFile);
226
- deleteIfExists(tempMetadataFile);
227
- throw error;
228
- }
229
- },
230
-
231
- async delete(request) {
232
- const { dataFile, metadataFile } = getCachePaths(rootDirectory, request);
233
- const hadData = dataFile.exists;
234
- const hadMetadata = metadataFile.exists;
235
-
236
- deleteIfExists(dataFile);
237
- deleteIfExists(metadataFile);
238
-
239
- return hadData || hadMetadata;
240
- },
241
-
242
- get directory() {
243
- return rootDirectory;
244
- },
245
- };
246
- }
247
-
248
- module.exports = {
249
- createExpoFileSystemCache,
250
- getDefaultExpoFileSystemModelCacheDirectory,
251
- };
package/src/index.js DELETED
@@ -1,27 +0,0 @@
1
- const {
2
- installTransformersReactNativeGlobals,
3
- configureTransformersEnvironment,
4
- ensureTransformersFetch,
5
- getSupportedExecutionProviderNames,
6
- getDefaultExecutionProviders,
7
- rewriteExecutionProviders,
8
- sanitizeSessionOptions,
9
- normalizeTransformersConfig,
10
- normalizeTransformersOptions,
11
- createExpoFileSystemCache,
12
- getDefaultExpoFileSystemModelCacheDirectory,
13
- } = require('./runtime');
14
-
15
- module.exports = {
16
- installTransformersReactNativeGlobals,
17
- configureTransformersEnvironment,
18
- ensureTransformersFetch,
19
- getSupportedExecutionProviderNames,
20
- getDefaultExecutionProviders,
21
- rewriteExecutionProviders,
22
- sanitizeSessionOptions,
23
- normalizeTransformersConfig,
24
- normalizeTransformersOptions,
25
- createExpoFileSystemCache,
26
- getDefaultExpoFileSystemModelCacheDirectory,
27
- };
package/src/metro.js DELETED
@@ -1,66 +0,0 @@
1
- const path = require('node:path');
2
-
3
- function mergeUnique(existing = [], additions = []) {
4
- return Array.from(new Set([...(existing ?? []), ...additions]));
5
- }
6
-
7
- function getTransformersReactNativeAliases(overrides = {}) {
8
- const packageRoot = path.resolve(__dirname, '..');
9
- const adapterPath = path.join(packageRoot, 'src/adapter/onnxruntime-web-webgpu.js');
10
- const wrapperPath = path.join(packageRoot, 'src/transformers.js');
11
- const transformersNodeEntryPath = require.resolve('@huggingface/transformers', {
12
- paths: [process.cwd(), packageRoot],
13
- });
14
- const transformersWebEntryPath = path.join(path.dirname(transformersNodeEntryPath), 'transformers.web.js');
15
- const onnxruntimePackagePath = require.resolve('onnxruntime-react-native/package.json', {
16
- paths: [process.cwd(), packageRoot],
17
- });
18
- const onnxruntimeCommonPath = require.resolve('onnxruntime-common', {
19
- paths: [process.cwd(), path.dirname(onnxruntimePackagePath), packageRoot],
20
- });
21
-
22
- return {
23
- '@huggingface/transformers': wrapperPath,
24
- '@automatalabs/react-native-transformers/internal-transformers-web': transformersWebEntryPath,
25
- 'onnxruntime-node': adapterPath,
26
- 'onnxruntime-web': adapterPath,
27
- 'onnxruntime-web/webgpu': adapterPath,
28
- 'onnxruntime-common': onnxruntimeCommonPath,
29
- ...overrides,
30
- };
31
- }
32
-
33
- function withTransformersReactNativeMetro(config, options = {}) {
34
- const { aliases: aliasOverrides, watchFolders = [] } = options;
35
- const aliases = getTransformersReactNativeAliases(aliasOverrides);
36
- const previousResolveRequest = config?.resolver?.resolveRequest;
37
-
38
- return {
39
- ...config,
40
- watchFolders: mergeUnique(config?.watchFolders, watchFolders),
41
- resolver: {
42
- ...config.resolver,
43
- assetExts: mergeUnique(config?.resolver?.assetExts, ['onnx', 'ort']),
44
- resolveRequest(context, moduleName, platform) {
45
- const alias =
46
- aliases[moduleName] ??
47
- (moduleName.startsWith('onnxruntime-web/') ? aliases['onnxruntime-web'] : undefined);
48
-
49
- if (alias) {
50
- return context.resolveRequest(context, alias, platform);
51
- }
52
-
53
- if (previousResolveRequest) {
54
- return previousResolveRequest(context, moduleName, platform);
55
- }
56
-
57
- return context.resolveRequest(context, moduleName, platform);
58
- },
59
- },
60
- };
61
- }
62
-
63
- module.exports = {
64
- getTransformersReactNativeAliases,
65
- withTransformersReactNativeMetro,
66
- };