diff --git a/README.md b/README.md index 447bda6..af75938 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,12 @@ sist2 (Simple incremental search tool) * Recursive scan inside archive files \*\* * OCR support with tesseract \*\*\* * Stats page & disk utilisation visualization +* Named-entity recognition (client-side) \*\*\*\* \* See [format support](#format-support) \*\* See [Archive files](#archive-files) \*\*\* See [OCR](#ocr) +\*\*\*\* See [Named-Entity Recognition](#NER) ## Getting Started @@ -56,7 +58,7 @@ services: entrypoint: python3 /root/sist2-admin/sist2_admin/app.py ``` -Navigate to http://localhost:8080/ to configure sist2-admin. +Navigate to http://localhost:8080/ to configure sist2-admin. ### Using the executable file *(Linux/WSL only)* @@ -67,10 +69,9 @@ Navigate to http://localhost:8080/ to configure sist2-admin. docker run -d -p 9200:9200 -e "discovery.type=single-node" elasticsearch:7.17.9 ``` -2. Download the [latest sist2 release](https://github.com/simon987/sist2/releases). -Select the file corresponding to your CPU architecture and mark the binary as executable with `chmod +x`. -3. See [usage guide](docs/USAGE.md) for command line usage. - +2. Download the [latest sist2 release](https://github.com/simon987/sist2/releases). + Select the file corresponding to your CPU architecture and mark the binary as executable with `chmod +x`. +3. See [usage guide](docs/USAGE.md) for command line usage. Example usage: @@ -124,7 +125,7 @@ The `simon987/sist2` image comes with common languages (hin, jpn, eng, fra, rus, spa, chi_sim, deu) pre-installed. You can use the `+` separator to specify multiple languages. The language -name must be identical to the `*.traineddata` file installed on your system +name must be identical to the `*.traineddata` file installed on your system (use `chi_sim` rather than `chi-sim`). Examples: @@ -135,6 +136,29 @@ sist2 scan --ocr-images --ocr-lang eng ~/Images/Screenshots/ sist2 scan --ocr-ebooks --ocr-images --ocr-lang eng+chi_sim ~/Chinese-Bilingual/ ``` +### NER + +sist2 v3.0.4+ supports named-entity recognition (NER). Simply add a supported repository URL to +**Configuration** > **Machine learning options** > **Model repositories** +to enable it. + +The text processing is done in your browser, no data is sent to any third-party services. +See [simon987/sist2-ner-models](https://raw.githubusercontent.com/simon987/sist2-ner-models/main/repo.json) for more details. + +#### List of available repositories: + +| URL | Maintainer | Purpose | +|---------------------------------------------------------------------------------------------------------|-----------------------------------------|---------| +| [simon987/sist2-ner-models](https://raw.githubusercontent.com/simon987/sist2-ner-models/main/repo.json) | [simon987](https://github.com/simon987) | General | + + +
+ Screenshot + +![ner](docs/ner.png) + +
+ ## Build from source You can compile **sist2** by yourself if you don't want to use the pre-compiled binaries diff --git a/docs/ner.png b/docs/ner.png new file mode 100644 index 0000000..f670c9c Binary files /dev/null and b/docs/ner.png differ diff --git a/sist2-vue/package-lock.json b/sist2-vue/package-lock.json index 5d586b6..d5b045f 100644 --- a/sist2-vue/package-lock.json +++ b/sist2-vue/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@auth0/auth0-spa-js": "^2.0.2", "@egjs/vue-infinitegrid": "3.3.0", + "@tensorflow/tfjs": "^4.4.0", "axios": "^0.25.0", "bootstrap-vue": "^2.21.2", "core-js": "^3.6.5", @@ -2073,6 +2074,204 @@ "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", "dev": true }, + "node_modules/@tensorflow/tfjs": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.4.0.tgz", + "integrity": "sha512-EmCsnzdvawyk4b+4JKaLLuicHcJQRZtL1zSy9AWJLiiHTbDDseYgLxfaCEfLk8v2bUe7SBXwl3n3B7OjgvH11Q==", + "dependencies": { + "@tensorflow/tfjs-backend-cpu": "4.4.0", + "@tensorflow/tfjs-backend-webgl": "4.4.0", + "@tensorflow/tfjs-converter": "4.4.0", + "@tensorflow/tfjs-core": "4.4.0", + "@tensorflow/tfjs-data": "4.4.0", + "@tensorflow/tfjs-layers": "4.4.0", + "argparse": "^1.0.10", + "chalk": "^4.1.0", + "core-js": "3.29.1", + "regenerator-runtime": "^0.13.5", + "yargs": "^16.0.3" + }, + "bin": { + "tfjs-custom-module": "dist/tools/custom_module/cli.js" + } + }, + "node_modules/@tensorflow/tfjs-backend-cpu": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.4.0.tgz", + "integrity": "sha512-d4eln500/qNym78z9IrUUzF0ITBoJGLrxV8xd92kLVoXhg35Mm+zqUXShjFcrH8joOHOFuST0qZ0TbDDqcPzPA==", + "dependencies": { + "@types/seedrandom": "^2.4.28", + "seedrandom": "^3.0.5" + }, + "engines": { + "yarn": ">= 1.3.2" + }, + "peerDependencies": { + "@tensorflow/tfjs-core": "4.4.0" + } + }, + "node_modules/@tensorflow/tfjs-backend-webgl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.4.0.tgz", + "integrity": "sha512-TzQKvfAPgGt9cMG+5bVoTckoG1xr/PVJM/uODkPvzcMqi3j97kuWDXwkYJIgXldStmfiKkU7f5CmyD3Cq3E6BA==", + "dependencies": { + "@tensorflow/tfjs-backend-cpu": "4.4.0", + "@types/offscreencanvas": "~2019.3.0", + "@types/seedrandom": "^2.4.28", + "@types/webgl-ext": "0.0.30", + "seedrandom": "^3.0.5" + }, + "engines": { + "yarn": ">= 1.3.2" + }, + "peerDependencies": { + "@tensorflow/tfjs-core": "4.4.0" + } + }, + "node_modules/@tensorflow/tfjs-converter": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.4.0.tgz", + "integrity": "sha512-JUjpRStrAuw37tgPd5UENu0UjQVuJT09yF7KpOur4BriJ0uQqrbEZHMPHmvUtr5nYzkqlXJTuXIyxvEY/olNpg==", + "peerDependencies": { + "@tensorflow/tfjs-core": "4.4.0" + } + }, + "node_modules/@tensorflow/tfjs-core": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.4.0.tgz", + "integrity": "sha512-Anxpc7cAOA0Q7EUXdTbQKMg3reFvrdkgDlaYzH9ZfkMq2CgLV4Au6E/s6HmbYn/VrAtWy9mLY5c/lLJqh4764g==", + "dependencies": { + "@types/long": "^4.0.1", + "@types/offscreencanvas": "~2019.7.0", + "@types/seedrandom": "^2.4.28", + "@types/webgl-ext": "0.0.30", + "@webgpu/types": "0.1.30", + "long": "4.0.0", + "node-fetch": "~2.6.1", + "seedrandom": "^3.0.5" + }, + "engines": { + "yarn": ">= 1.3.2" + } + }, + "node_modules/@tensorflow/tfjs-core/node_modules/@types/offscreencanvas": { + "version": "2019.7.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", + "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" + }, + "node_modules/@tensorflow/tfjs-data": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.4.0.tgz", + "integrity": "sha512-aY4eq4cgrsrXeBU6ABZAAN3tV0fG4YcHd0z+cYuNXnCo+VEQLJnPmhn+xymZ4VQZQH4GXbVS4dV9pXMclFNRFw==", + "dependencies": { + "@types/node-fetch": "^2.1.2", + "node-fetch": "~2.6.1", + "string_decoder": "^1.3.0" + }, + "peerDependencies": { + "@tensorflow/tfjs-core": "4.4.0", + "seedrandom": "^3.0.5" + } + }, + "node_modules/@tensorflow/tfjs-data/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/@tensorflow/tfjs-data/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/@tensorflow/tfjs-layers": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.4.0.tgz", + "integrity": "sha512-OGC7shfiD9Gc698hINHK4y9slOJvu5m54tVNm4xf+WSNrw/avvgpar6yyoL5bakYIZNQvFNK75Yr8VRPR7oPeQ==", + "peerDependencies": { + "@tensorflow/tfjs-core": "4.4.0" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@tensorflow/tfjs/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@tensorflow/tfjs/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -2190,6 +2389,11 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "node_modules/@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -2205,8 +2409,16 @@ "node_modules/@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", - "dev": true + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + }, + "node_modules/@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -2214,6 +2426,11 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, + "node_modules/@types/offscreencanvas": { + "version": "2019.3.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz", + "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==" + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -2238,6 +2455,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "node_modules/@types/seedrandom": { + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", + "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" + }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -2266,6 +2488,11 @@ "@types/node": "*" } }, + "node_modules/@types/webgl-ext": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz", + "integrity": "sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==" + }, "node_modules/@types/webpack-env": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz", @@ -3644,6 +3871,11 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@webgpu/types": { + "version": "0.1.30", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.30.tgz", + "integrity": "sha512-9AXJSmL3MzY8ZL//JjudA//q+2kBRGhLBFpkdGksWIuxrMy81nFrCzj2Am+mbh8WoU6rXmv7cY5E3rdlyru2Qg==" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -3829,6 +4061,14 @@ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -3853,6 +4093,11 @@ "lodash": "^4.17.14" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -4551,42 +4796,6 @@ "node": ">=8" } }, - "node_modules/cli-highlight/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/cli-highlight/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cli-highlight/node_modules/yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/cli-spinners": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", @@ -4617,7 +4826,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -4674,6 +4882,17 @@ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -4877,9 +5096,14 @@ "dev": true }, "node_modules/core-js": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.12.1.tgz", - "integrity": "sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==" + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", + "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } }, "node_modules/core-js-compat": { "version": "3.27.1", @@ -5726,6 +5950,14 @@ "robust-predicates": "^3.0.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5951,8 +6183,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/emojis-list": { "version": "3.0.0", @@ -6046,7 +6277,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -6631,6 +6861,19 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6730,7 +6973,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -7364,7 +7606,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -7953,6 +8194,11 @@ "node": ">=4" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -8079,7 +8325,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -8088,7 +8333,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -9675,8 +9919,7 @@ "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { "version": "0.15.1", @@ -9757,7 +10000,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9978,6 +10220,11 @@ "node": ">= 8.9.0" } }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -10382,6 +10629,11 @@ "node": ">= 6" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -10417,7 +10669,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10431,7 +10682,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10443,7 +10693,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -11681,7 +11930,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11698,7 +11946,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -11713,7 +11960,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -11724,8 +11970,7 @@ "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/wrappy": { "version": "1.0.2", @@ -11754,6 +11999,14 @@ } } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -11768,6 +12021,31 @@ "engines": { "node": ">= 6" } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } } }, "dependencies": { @@ -13226,6 +13504,149 @@ "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", "dev": true }, + "@tensorflow/tfjs": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.4.0.tgz", + "integrity": "sha512-EmCsnzdvawyk4b+4JKaLLuicHcJQRZtL1zSy9AWJLiiHTbDDseYgLxfaCEfLk8v2bUe7SBXwl3n3B7OjgvH11Q==", + "requires": { + "@tensorflow/tfjs-backend-cpu": "4.4.0", + "@tensorflow/tfjs-backend-webgl": "4.4.0", + "@tensorflow/tfjs-converter": "4.4.0", + "@tensorflow/tfjs-core": "4.4.0", + "@tensorflow/tfjs-data": "4.4.0", + "@tensorflow/tfjs-layers": "4.4.0", + "argparse": "^1.0.10", + "chalk": "^4.1.0", + "core-js": "3.29.1", + "regenerator-runtime": "^0.13.5", + "yargs": "^16.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@tensorflow/tfjs-backend-cpu": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.4.0.tgz", + "integrity": "sha512-d4eln500/qNym78z9IrUUzF0ITBoJGLrxV8xd92kLVoXhg35Mm+zqUXShjFcrH8joOHOFuST0qZ0TbDDqcPzPA==", + "requires": { + "@types/seedrandom": "^2.4.28", + "seedrandom": "^3.0.5" + } + }, + "@tensorflow/tfjs-backend-webgl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.4.0.tgz", + "integrity": "sha512-TzQKvfAPgGt9cMG+5bVoTckoG1xr/PVJM/uODkPvzcMqi3j97kuWDXwkYJIgXldStmfiKkU7f5CmyD3Cq3E6BA==", + "requires": { + "@tensorflow/tfjs-backend-cpu": "4.4.0", + "@types/offscreencanvas": "~2019.3.0", + "@types/seedrandom": "^2.4.28", + "@types/webgl-ext": "0.0.30", + "seedrandom": "^3.0.5" + } + }, + "@tensorflow/tfjs-converter": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.4.0.tgz", + "integrity": "sha512-JUjpRStrAuw37tgPd5UENu0UjQVuJT09yF7KpOur4BriJ0uQqrbEZHMPHmvUtr5nYzkqlXJTuXIyxvEY/olNpg==", + "requires": {} + }, + "@tensorflow/tfjs-core": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.4.0.tgz", + "integrity": "sha512-Anxpc7cAOA0Q7EUXdTbQKMg3reFvrdkgDlaYzH9ZfkMq2CgLV4Au6E/s6HmbYn/VrAtWy9mLY5c/lLJqh4764g==", + "requires": { + "@types/long": "^4.0.1", + "@types/offscreencanvas": "~2019.7.0", + "@types/seedrandom": "^2.4.28", + "@types/webgl-ext": "0.0.30", + "@webgpu/types": "0.1.30", + "long": "4.0.0", + "node-fetch": "~2.6.1", + "seedrandom": "^3.0.5" + }, + "dependencies": { + "@types/offscreencanvas": { + "version": "2019.7.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", + "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" + } + } + }, + "@tensorflow/tfjs-data": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.4.0.tgz", + "integrity": "sha512-aY4eq4cgrsrXeBU6ABZAAN3tV0fG4YcHd0z+cYuNXnCo+VEQLJnPmhn+xymZ4VQZQH4GXbVS4dV9pXMclFNRFw==", + "requires": { + "@types/node-fetch": "^2.1.2", + "node-fetch": "~2.6.1", + "string_decoder": "^1.3.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "@tensorflow/tfjs-layers": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.4.0.tgz", + "integrity": "sha512-OGC7shfiD9Gc698hINHK4y9slOJvu5m54tVNm4xf+WSNrw/avvgpar6yyoL5bakYIZNQvFNK75Yr8VRPR7oPeQ==", + "requires": {} + }, "@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -13340,6 +13761,11 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -13355,8 +13781,16 @@ "@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", - "dev": true + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + }, + "@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } }, "@types/normalize-package-data": { "version": "2.4.1", @@ -13364,6 +13798,11 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, + "@types/offscreencanvas": { + "version": "2019.3.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz", + "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==" + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -13388,6 +13827,11 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/seedrandom": { + "version": "2.4.30", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz", + "integrity": "sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==" + }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -13416,6 +13860,11 @@ "@types/node": "*" } }, + "@types/webgl-ext": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/webgl-ext/-/webgl-ext-0.0.30.tgz", + "integrity": "sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==" + }, "@types/webpack-env": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz", @@ -14452,6 +14901,11 @@ "@xtuc/long": "4.2.2" } }, + "@webgpu/types": { + "version": "0.1.30", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.30.tgz", + "integrity": "sha512-9AXJSmL3MzY8ZL//JjudA//q+2kBRGhLBFpkdGksWIuxrMy81nFrCzj2Am+mbh8WoU6rXmv7cY5E3rdlyru2Qg==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -14595,6 +15049,14 @@ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -14616,6 +15078,11 @@ "lodash": "^4.17.14" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -15133,33 +15600,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", - "dev": true } } }, @@ -15184,7 +15624,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -15235,6 +15674,14 @@ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -15400,9 +15847,9 @@ "dev": true }, "core-js": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.12.1.tgz", - "integrity": "sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==" + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", + "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==" }, "core-js-compat": { "version": "3.27.1", @@ -16009,6 +16456,11 @@ "robust-predicates": "^3.0.0" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -16193,8 +16645,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "emojis-list": { "version": "3.0.0", @@ -16274,8 +16725,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -16712,6 +17162,16 @@ } } }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -16781,8 +17241,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.1.1", @@ -17262,8 +17721,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.3", @@ -17719,6 +18177,11 @@ } } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -17822,14 +18285,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -18973,8 +19434,7 @@ "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regenerator-transform": { "version": "0.15.1", @@ -19044,8 +19504,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-from-string": { "version": "2.0.2", @@ -19208,6 +19667,11 @@ "ajv-keywords": "^3.5.2" } }, + "seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -19561,6 +20025,11 @@ } } }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -19592,7 +20061,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -19603,7 +20071,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" }, @@ -19611,8 +20078,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" } } }, @@ -20524,7 +20990,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -20535,7 +21000,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -20544,7 +21008,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -20552,8 +21015,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -20570,6 +21032,11 @@ "dev": true, "requires": {} }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -20581,6 +21048,25 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" } } } diff --git a/sist2-vue/package.json b/sist2-vue/package.json index aa68105..ec4cfbf 100644 --- a/sist2-vue/package.json +++ b/sist2-vue/package.json @@ -9,6 +9,7 @@ "dependencies": { "@auth0/auth0-spa-js": "^2.0.2", "@egjs/vue-infinitegrid": "3.3.0", + "@tensorflow/tfjs": "^4.4.0", "axios": "^0.25.0", "bootstrap-vue": "^2.21.2", "core-js": "^3.6.5", diff --git a/sist2-vue/src/App.vue b/sist2-vue/src/App.vue index e34074c..34ed80b 100644 --- a/sist2-vue/src/App.vue +++ b/sist2-vue/src/App.vue @@ -1,383 +1,395 @@ diff --git a/sist2-vue/src/components/AnalyzedContentSpan.vue b/sist2-vue/src/components/AnalyzedContentSpan.vue new file mode 100644 index 0000000..7201539 --- /dev/null +++ b/sist2-vue/src/components/AnalyzedContentSpan.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/sist2-vue/src/components/AnalyzedContentSpanContainer.vue b/sist2-vue/src/components/AnalyzedContentSpanContainer.vue new file mode 100644 index 0000000..997b83d --- /dev/null +++ b/sist2-vue/src/components/AnalyzedContentSpanContainer.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/sist2-vue/src/components/LazyContentDiv.vue b/sist2-vue/src/components/LazyContentDiv.vue index 819d9df..6c21175 100644 --- a/sist2-vue/src/components/LazyContentDiv.vue +++ b/sist2-vue/src/components/LazyContentDiv.vue @@ -1,6 +1,36 @@ - \ No newline at end of file diff --git a/sist2-vue/src/i18n/messages.ts b/sist2-vue/src/i18n/messages.ts index 653a8f3..9fe1308 100644 --- a/sist2-vue/src/i18n/messages.ts +++ b/sist2-vue/src/i18n/messages.ts @@ -49,6 +49,7 @@ export default { configReset: "Reset configuration", searchOptions: "Search options", treemapOptions: "Treemap options", + mlOptions: "Machine learning options", displayOptions: "Display options", opt: { lang: "Language", @@ -78,7 +79,10 @@ export default { simpleLightbox: "Disable animations in image viewer", showTagPickerFilter: "Display the tag filter bar", featuredFields: "Featured fields Javascript template string. Will appear in the search results.", - featuredFieldsList: "Available variables" + featuredFieldsList: "Available variables", + autoAnalyze: "Automatically analyze text", + defaultModel: "Default model", + mlRepositories: "Model repositories (one per line)" }, queryMode: { simple: "Simple", @@ -171,6 +175,12 @@ export default { selectedIndex: "selected index", selectedIndices: "selected indices", }, + ml: { + analyzeText: "Analyze", + auto: "Auto", + repoFetchError: "Failed to get list of models. Check browser console for more details.", + repoFetchErrorTitle: "Could not fetch model repositories", + } }, de: { filePage: { diff --git a/sist2-vue/src/ml/BertNerModel.js b/sist2-vue/src/ml/BertNerModel.js new file mode 100644 index 0000000..3183336 --- /dev/null +++ b/sist2-vue/src/ml/BertNerModel.js @@ -0,0 +1,77 @@ +import BertTokenizer from "@/ml/BertTokenizer"; +import * as tf from "@tensorflow/tfjs"; +import axios from "axios"; + +export default class BertNerModel { + vocabUrl; + modelUrl; + + id2label; + _tokenizer; + _model; + inputSize = 128; + + _previousWordId = null; + + constructor(vocabUrl, modelUrl, id2label) { + this.vocabUrl = vocabUrl; + this.modelUrl = modelUrl; + this.id2label = id2label; + } + + async init(onProgress) { + await Promise.all([this.loadTokenizer(), this.loadModel(onProgress)]); + } + + async loadTokenizer() { + const vocab = (await axios.get(this.vocabUrl)).data; + this._tokenizer = new BertTokenizer(vocab); + } + + async loadModel(onProgress) { + this._model = await tf.loadGraphModel(this.modelUrl, {onProgress}); + } + + alignLabels(labels, wordIds, words) { + const result = []; + + for (let i = 0; i < this.inputSize; i++) { + const label = labels[i]; + const wordId = wordIds[i]; + + if (wordId === -1) { + continue; + } + if (wordId === this._previousWordId) { + continue; + } + + result.push({ + word: words[wordId].text, wordIndex: words[wordId].index, label: label + }); + this._previousWordId = wordId; + } + + return result; + } + + async predict(text, callback) { + this._previousWordId = null; + const encoded = this._tokenizer.encodeText(text, this.inputSize) + + for (let chunk of encoded.inputChunks) { + const rawResult = tf.tidy(() => this._model.execute({ + input_ids: tf.tensor2d(chunk.inputIds, [1, this.inputSize], "int32"), + token_type_ids: tf.tensor2d(chunk.segmentIds, [1, this.inputSize], "int32"), + attention_mask: tf.tensor2d(chunk.inputMask, [1, this.inputSize], "int32"), + })); + + const labelIds = await tf.argMax(rawResult, -1); + const labelIdsArray = await labelIds.array(); + const labels = labelIdsArray[0].map(id => this.id2label[id]); + rawResult.dispose() + + callback(this.alignLabels(labels, chunk.wordIds, encoded.words)) + } + } +} \ No newline at end of file diff --git a/sist2-vue/src/ml/BertTokenizer.js b/sist2-vue/src/ml/BertTokenizer.js new file mode 100644 index 0000000..0ea24ad --- /dev/null +++ b/sist2-vue/src/ml/BertTokenizer.js @@ -0,0 +1,184 @@ +import {zip, chunk} from "underscore"; + +const UNK_INDEX = 100; +const CLS_INDEX = 101; +const SEP_INDEX = 102; +const CONTINUING_SUBWORD_PREFIX = "##"; + +function isWhitespace(ch) { + return /\s/.test(ch); +} + +function isInvalid(ch) { + return (ch.charCodeAt(0) === 0 || ch.charCodeAt(0) === 0xfffd); +} + +const punctuations = '[~`!@#$%^&*(){}[];:"\'<,.>?/\\|-_+='; + +/** To judge whether it's a punctuation. */ +function isPunctuation(ch) { + return punctuations.indexOf(ch) !== -1; +} + +export default class BertTokenizer { + vocab; + + constructor(vocab) { + this.vocab = vocab; + } + + tokenize(text) { + const charOriginalIndex = []; + const cleanedText = this.cleanText(text, charOriginalIndex); + const origTokens = cleanedText.split(' '); + + let charCount = 0; + const tokens = origTokens.map((token) => { + token = token.toLowerCase(); + const tokens = this.runSplitOnPunctuation(token, charCount, charOriginalIndex); + charCount += token.length + 1; + return tokens; + }); + + let flattenTokens = []; + for (let index = 0; index < tokens.length; index++) { + flattenTokens = flattenTokens.concat(tokens[index]); + } + return flattenTokens; + } + + /* Performs invalid character removal and whitespace cleanup on text. */ + cleanText(text, charOriginalIndex) { + text = text.replace(/\?/g, "").trim(); + + const stringBuilder = []; + let originalCharIndex = 0; + let newCharIndex = 0; + + for (const ch of text) { + // Skip the characters that cannot be used. + if (isInvalid(ch)) { + originalCharIndex += ch.length; + continue; + } + if (isWhitespace(ch)) { + if (stringBuilder.length > 0 && stringBuilder[stringBuilder.length - 1] !== ' ') { + stringBuilder.push(' '); + charOriginalIndex[newCharIndex] = originalCharIndex; + originalCharIndex += ch.length; + } else { + originalCharIndex += ch.length; + continue; + } + } else { + stringBuilder.push(ch); + charOriginalIndex[newCharIndex] = originalCharIndex; + originalCharIndex += ch.length; + } + newCharIndex++; + } + return stringBuilder.join(''); + } + + /* Splits punctuation on a piece of text. */ + runSplitOnPunctuation(text, count, charOriginalIndex) { + const tokens = []; + let startNewWord = true; + for (const ch of text) { + if (isPunctuation(ch)) { + tokens.push({text: ch, index: charOriginalIndex[count]}); + count += ch.length; + startNewWord = true; + } else { + if (startNewWord) { + tokens.push({text: '', index: charOriginalIndex[count]}); + startNewWord = false; + } + tokens[tokens.length - 1].text += ch; + count += ch.length; + } + } + return tokens; + } + + encode(words) { + let outputTokens = []; + const wordIds = []; + + for (let i = 0; i < words.length; i++) { + let chars = [...words[i].text]; + + let isUnknown = false; + let start = 0; + let subTokens = []; + + while (start < chars.length) { + let end = chars.length; + let currentSubstring = null; + while (start < end) { + let substr = chars.slice(start, end).join(''); + + if (start > 0) { + substr = CONTINUING_SUBWORD_PREFIX + substr; + } + if (this.vocab.includes(substr)) { + currentSubstring = this.vocab.indexOf(substr); + break; + } + + --end; + } + if (currentSubstring == null) { + isUnknown = true; + break; + } + subTokens.push(currentSubstring); + start = end; + } + + if (isUnknown) { + outputTokens.push(UNK_INDEX); + wordIds.push(i); + } else { + subTokens.forEach(tok => { + outputTokens.push(tok); + wordIds.push(i) + }); + } + } + + return {tokens: outputTokens, wordIds}; + } + + encodeText(inputText, inputSize) { + + const tokenized = this.tokenize(inputText); + const encoded = this.encode(tokenized); + + const encodedTokenChunks = chunk(encoded.tokens, inputSize - 2); + const encodedWordIdChunks = chunk(encoded.wordIds, inputSize - 2); + + const chunks = []; + + zip(encodedTokenChunks, encodedWordIdChunks).forEach(([tokens, wordIds]) => { + const inputIds = [CLS_INDEX, ...tokens, SEP_INDEX]; + const segmentIds = Array(inputIds.length).fill(0); + const inputMask = Array(inputIds.length).fill(1); + wordIds = [-1, ...wordIds, -1]; + + while (inputIds.length < inputSize) { + inputIds.push(0); + inputMask.push(0); + segmentIds.push(0); + wordIds.push(-1); + } + + chunks.push({inputIds, inputMask, segmentIds, wordIds}) + }); + + return { + inputChunks: chunks, + words: tokenized + }; + } +} \ No newline at end of file diff --git a/sist2-vue/src/ml/modelsRepo.js b/sist2-vue/src/ml/modelsRepo.js new file mode 100644 index 0000000..16edb2e --- /dev/null +++ b/sist2-vue/src/ml/modelsRepo.js @@ -0,0 +1,43 @@ +import axios from "axios"; + +class ModelsRepo { + _repositories; + data = {}; + + async init(repositories) { + this._repositories = repositories; + + const data = await Promise.all(this._repositories.map(this._loadRepository)); + + data.forEach(models => { + models.forEach(model => { + this.data[model.name] = model; + }) + }); + } + + async _loadRepository(repository) { + const data = (await axios.get(repository)).data; + data.forEach(model => { + model["modelUrl"] = new URL(model["modelPath"], repository).href; + model["vocabUrl"] = new URL(model["vocabPath"], repository).href; + }); + return data; + } + + getOptions() { + return Object.values(this.data).map(model => ({ + text: `${model.name} (${Math.round(model.size / (1024*1024))}MB)`, + value: model.name + })); + } + + getDefaultModel() { + if (Object.values(this.data).length === 0) { + return null; + } + return Object.values(this.data).find(model => model.default).name; + } +} + +export default new ModelsRepo(); \ No newline at end of file diff --git a/sist2-vue/src/store/index.ts b/sist2-vue/src/store/index.ts index e095070..37a06ca 100644 --- a/sist2-vue/src/store/index.ts +++ b/sist2-vue/src/store/index.ts @@ -57,6 +57,9 @@ export default new Vuex.Store({ optVidPreviewInterval: 700, optSimpleLightbox: true, optShowTagPickerFilter: true, + optMlRepositories: "https://raw.githubusercontent.com/simon987/sist2-ner-models/main/repo.json", + optAutoAnalyze: false, + optMlDefaultModel: null, _onLoadSelectedIndices: [] as string[], _onLoadSelectedMimeTypes: [] as string[], @@ -86,7 +89,11 @@ export default new Vuex.Store({ uiMimeMap: [] as any[], - auth0Token: null + auth0Token: null, + mlModel: { + model: null, + name: null + }, }, mutations: { setUiShowDetails: (state, val) => state.uiShowDetails = val, @@ -172,6 +179,9 @@ export default new Vuex.Store({ setOptVidPreviewInterval: (state, val) => state.optVidPreviewInterval = val, setOptSimpleLightbox: (state, val) => state.optSimpleLightbox = val, setOptShowTagPickerFilter: (state, val) => state.optShowTagPickerFilter = val, + setOptAutoAnalyze: (state, val) => {state.optAutoAnalyze = val}, + setOptMlRepositories: (state, val) => {state.optMlRepositories = val}, + setOptMlDefaultModel: (state, val) => {state.optMlDefaultModel = val}, setOptLightboxLoadOnlyCurrent: (state, val) => state.optLightboxLoadOnlyCurrent = val, setOptLightboxSlideDuration: (state, val) => state.optLightboxSlideDuration = val, @@ -194,6 +204,7 @@ export default new Vuex.Store({ // noop }, setAuth0Token: (state, val) => state.auth0Token = val, + setMlModel: (state, val) => state.mlModel = val, }, actions: { setSist2Info: (store, val) => { @@ -350,6 +361,7 @@ export default new Vuex.Store({ }, modules: {}, getters: { + mlModel: (state) => state.mlModel, seed: (state) => state.seed, getPathText: (state) => state.pathText, indices: state => state.indices, @@ -416,5 +428,12 @@ export default new Vuex.Store({ optSimpleLightbox: state => state.optSimpleLightbox, optShowTagPickerFilter: state => state.optShowTagPickerFilter, optFeaturedFields: state => state.optFeaturedFields, + optMlRepositories: state => state.optMlRepositories, + mlRepositoryList: state => { + const repos = state.optMlRepositories.split("\n") + return repos[0] == "" ? [] : repos; + }, + optMlDefaultModel: state => state.optMlDefaultModel, + optAutoAnalyze: state => state.optAutoAnalyze, } }) \ No newline at end of file diff --git a/sist2-vue/src/views/Configuration.vue b/sist2-vue/src/views/Configuration.vue index 80dc2e0..84e20ff 100644 --- a/sist2-vue/src/views/Configuration.vue +++ b/sist2-vue/src/views/Configuration.vue @@ -1,202 +1,218 @@ \ No newline at end of file diff --git a/src/sist.h b/src/sist.h index 6fb7e36..f660aa4 100644 --- a/src/sist.h +++ b/src/sist.h @@ -51,11 +51,11 @@ #include #include "git_hash.h" -#define VERSION "3.0.3" +#define VERSION "3.0.4" static const char *const Version = VERSION; static const int VersionMajor = 3; static const int VersionMinor = 0; -static const int VersionPatch = 3; +static const int VersionPatch = 4; #ifndef SIST_PLATFORM #define SIST_PLATFORM unknown