diff --git a/js/web/package-lock.json b/js/web/package-lock.json index e8e7c45fdc..3728af7c1f 100644 --- a/js/web/package-lock.json +++ b/js/web/package-lock.json @@ -30,6 +30,7 @@ "chai": "^4.3.7", "electron": "^28.1.4", "globby": "^13.1.3", + "jszip": "^3.10.1", "karma": "^6.4.1", "karma-browserstack-launcher": "^1.6.0", "karma-chai": "^0.1.0", @@ -840,6 +841,13 @@ "node": ">= 0.6" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -1865,6 +1873,13 @@ "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1992,6 +2007,13 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, "node_modules/isbinaryfile": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", @@ -2041,6 +2063,19 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "node_modules/karma": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", @@ -2257,6 +2292,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -2632,6 +2677,13 @@ "node": ">=4" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2709,6 +2761,13 @@ "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -2856,6 +2915,22 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2985,6 +3060,13 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3053,6 +3135,13 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3217,6 +3306,16 @@ "node": ">=8.0" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3431,6 +3530,13 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -4289,6 +4395,12 @@ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -5080,6 +5192,12 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5176,6 +5294,12 @@ "is-docker": "^2.0.0" } }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "isbinaryfile": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", @@ -5216,6 +5340,18 @@ "graceful-fs": "^4.1.6" } }, + "jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "karma": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz", @@ -5400,6 +5536,15 @@ "json-buffer": "3.0.1" } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -5682,6 +5827,12 @@ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", "dev": true }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -5738,6 +5889,12 @@ "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5833,6 +5990,21 @@ "unpipe": "1.0.0" } }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -5923,6 +6095,12 @@ "queue-microtask": "^1.2.2" } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5975,6 +6153,12 @@ "has-property-descriptors": "^1.0.2" } }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -6103,6 +6287,15 @@ "fs-extra": "^8.1.0" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6254,6 +6447,12 @@ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", diff --git a/js/web/package.json b/js/web/package.json index 784dcce000..5bc20e4208 100644 --- a/js/web/package.json +++ b/js/web/package.json @@ -47,6 +47,7 @@ "chai": "^4.3.7", "electron": "^28.1.4", "globby": "^13.1.3", + "jszip": "^3.10.1", "karma": "^6.4.1", "karma-browserstack-launcher": "^1.6.0", "karma-chai": "^0.1.0", diff --git a/js/web/script/test-runner-cli-args.ts b/js/web/script/test-runner-cli-args.ts index 088a66b24f..075cf9be7a 100644 --- a/js/web/script/test-runner-cli-args.ts +++ b/js/web/script/test-runner-cli-args.ts @@ -175,7 +175,7 @@ export interface TestRunnerCliArgs { /** * whether to enable model download */ - downloadModel: boolean; + downloadModel: Test.Config['downloadModel']; /** * Whether to enable file cache @@ -438,7 +438,8 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs } // Option: -m, --download-model - const downloadModel = args['download-model'] || args.m ? true : false; + const downloadModelFlag = args['download-model'] || args.m; + const downloadModel = downloadModelFlag === 'full' ? 'full' : downloadModelFlag ? 'model' : false; // Option: -t, --trace const trace = parseBooleanArg(args.trace || args.t, false); diff --git a/js/web/test/test-runner.ts b/js/web/test/test-runner.ts index 5de39535a5..863cf108e7 100644 --- a/js/web/test/test-runner.ts +++ b/js/web/test/test-runner.ts @@ -11,6 +11,7 @@ import { expect } from 'chai'; import * as ort from 'onnxruntime-common'; import { extname } from 'path'; import { inspect } from 'util'; +import JSZip from 'jszip'; import { Attribute } from '../lib/onnxjs/attribute'; import { InferenceHandler, resolveBackend, SessionHandler } from '../lib/onnxjs/backend'; @@ -875,17 +876,41 @@ export class OpTestContext { } } +const createCpuTensor = (type: ort.Tensor.Type, data: number[], dims: readonly number[]): ort.Tensor => { + let buffer: number[] | BigUint64Array | BigInt64Array | Uint16Array | Uint8Array = data; + if (type === 'uint64') { + buffer = BigUint64Array.from(data.map(BigInt)); + } else if (type === 'int64') { + buffer = BigInt64Array.from(data.map(BigInt)); + } else if (type === 'float16') { + const dataArr = Float16ArrayPolyfill.from(data); + buffer = new Uint16Array(dataArr.buffer, dataArr.byteOffset, dataArr.byteLength / 2); + } else if (type === 'uint4' || type === 'int4') { + buffer = new Uint8Array(calculateTensorSizeInBytes(tensorDataTypeStringToEnum(type), dims)!); + // encode (u)int4 data into Uint8Array + for (let j = 0; j < data.length; j++) { + /* eslint-disable no-bitwise */ + const byteIndex = j >> 1; + const bitOffset = (j & 1) << 2; + buffer[byteIndex] |= data[j] << bitOffset; + /* eslint-enable no-bitwise */ + } + } + return new ort.Tensor(type, buffer, dims); +}; + /** * a ProtoOpTestContext uses a protobuf model for operator test. used for ORT based backend. */ export class ProtoOpTestContext { - private readonly loadedData: Uint8Array; // model data, inputs, outputs + private readonly modelData: Uint8Array; + private readonly download: Promise | undefined; session: ort.InferenceSession; readonly backendHint: string; readonly ioBindingMode: Test.IOBindingMode; constructor( test: Test.OperatorTest, - private readonly downloadModel: boolean, + private readonly downloadModel: Test.Config['downloadModel'], private readonly sessionOptions: ort.InferenceSession.SessionOptions = {}, ) { const opsetImport = onnx.OperatorSetIdProto.create(test.opset); @@ -1070,23 +1095,77 @@ export class ProtoOpTestContext { this.backendHint = test.backend!; this.ioBindingMode = test.ioBinding; - this.loadedData = onnx.ModelProto.encode(model).finish().slice(); + this.modelData = onnx.ModelProto.encode(model).finish().slice(); if (this.downloadModel) { - const modelFile = new File([this.loadedData], `op_test_generated_model_${test.name}.onnx`, { - type: 'application/octet-stream', - }); - const modelTempUrl = URL.createObjectURL(modelFile); + const filename = `op_test_generated_model_${test.name}`; + + if (this.downloadModel === 'full') { + const zip = new JSZip(); + zip.file(`model.onnx`, this.modelData); + for (let i = 0; i < test.cases.length; i++) { + const subfolder = zip.folder(`test_data_set_${i}`)!; + for (let j = 0; j < test.cases[i].inputs.length; j++) { + const input = test.cases[i].inputs[j]; + if (input.data) { + const data = createCpuTensor(input.type, input.data, input.dims).data; + if (Array.isArray(data)) { + throw new Error('Only typed array is supported for input data'); + } + const inputProto = onnx.TensorProto.create({ + dims: input.dims, + dataType: tensorDataTypeStringToEnum(input.type), + name: `input_${j}`, + rawData: new Uint8Array(data.buffer, data.byteOffset, data.byteLength), + }); + subfolder.file(`input_${j}.pb`, onnx.TensorProto.encode(inputProto).finish()); + } + } + for (let j = 0; j < test.cases[i].outputs.length; j++) { + const output = test.cases[i].outputs[j]; + if (output.data) { + const data = createCpuTensor(output.type, output.data, output.dims).data; + if (Array.isArray(data)) { + throw new Error('Only typed array is supported for output data'); + } + const outputProto = onnx.TensorProto.create({ + dims: output.dims, + dataType: tensorDataTypeStringToEnum(output.type), + name: `output_${j}`, + rawData: new Uint8Array(data.buffer, data.byteOffset, data.byteLength), + }); + subfolder.file(`output_${j}.pb`, onnx.TensorProto.encode(outputProto).finish()); + } + } + } + this.download = zip.generateAsync({ type: 'blob' }).then( + (content) => + new File([content], `${filename}.zip`, { + type: 'application/zip', + }), + ); + } else { + this.download = Promise.resolve( + new File([this.modelData], `${filename}.onnx`, { + type: 'application/octet-stream', + }), + ); + } + } + } + async init(): Promise { + if (this.download) { + const file = await this.download!; + const modelTempUrl = URL.createObjectURL(file); const a = document.createElement('a'); a.href = modelTempUrl; - a.download = modelFile.name; + a.download = file.name; a.target = '_blank'; a.click(); URL.revokeObjectURL(modelTempUrl); } - } - async init(): Promise { - this.session = await ort.InferenceSession.create(this.loadedData, { + + this.session = await ort.InferenceSession.create(this.modelData, { executionProviders: [this.backendHint], preferredOutputLocation: this.ioBindingMode === 'gpu-location' ? ('gpu-buffer' as const) : undefined, ...this.sessionOptions, @@ -1107,32 +1186,9 @@ async function runProtoOpTestcase( const feeds: Record = {}; const fetches: Record> = {}; - const createTensor = (type: ort.Tensor.Type, data: number[], dims: readonly number[]): ort.Tensor => { - let buffer: number[] | BigUint64Array | BigInt64Array | Uint16Array | Uint8Array = data; - if (type === 'uint64') { - buffer = BigUint64Array.from(data.map(BigInt)); - } else if (type === 'int64') { - buffer = BigInt64Array.from(data.map(BigInt)); - } else if (type === 'float16') { - const dataArr = Float16ArrayPolyfill.from(data); - buffer = new Uint16Array(dataArr.buffer, dataArr.byteOffset, dataArr.byteLength / 2); - } else if (type === 'uint4' || type === 'int4') { - buffer = new Uint8Array(calculateTensorSizeInBytes(tensorDataTypeStringToEnum(type), dims)!); - // encode (u)int4 data into Uint8Array - for (let j = 0; j < data.length; j++) { - /* eslint-disable no-bitwise */ - const byteIndex = j >> 1; - const bitOffset = (j & 1) << 2; - buffer[byteIndex] |= data[j] << bitOffset; - /* eslint-enable no-bitwise */ - } - } - return new ort.Tensor(type, buffer, dims); - }; - testCase.inputs.forEach((input, i) => { if (input.data) { - feeds[`input_${i}`] = createTensor(input.type, input.data, input.dims); + feeds[`input_${i}`] = createCpuTensor(input.type, input.data, input.dims); } }); @@ -1140,7 +1196,7 @@ async function runProtoOpTestcase( const expectedOutputNames: string[] = []; testCase.outputs.forEach((output, i) => { if (output.data) { - outputs.push(createTensor(output.type, output.data, output.dims)); + outputs.push(createCpuTensor(output.type, output.data, output.dims)); expectedOutputNames.push(`output_${i}`); fetches[`output_${i}`] = { dims: output.dims, type: output.type }; } diff --git a/js/web/test/test-types.ts b/js/web/test/test-types.ts index 91fc932446..a268fbe54a 100644 --- a/js/web/test/test-types.ts +++ b/js/web/test/test-types.ts @@ -172,7 +172,7 @@ export declare namespace Test { log: ReadonlyArray<{ category: string; config: Logger.Config }>; profile: boolean; - downloadModel: boolean; + downloadModel: 'full' | 'model' | false; options: Options; } }