Merge remote-tracking branch 'origin/main' into misc_tweaks

This commit is contained in:
Min Idzelis 2025-03-27 23:47:58 +00:00
commit a1ab910213
92 changed files with 2088 additions and 4895 deletions

View File

@ -395,16 +395,16 @@ jobs:
uv sync --extra cpu uv sync --extra cpu
- name: Lint with ruff - name: Lint with ruff
run: | run: |
uv run ruff check --output-format=github app export uv run ruff check --output-format=github immich_ml
- name: Check black formatting - name: Check black formatting
run: | run: |
uv run black --check app export uv run black --check immich_ml
- name: Run mypy type checking - name: Run mypy type checking
run: | run: |
uv run mypy --strict app/ uv run mypy --strict immich_ml/
- name: Run tests and coverage - name: Run tests and coverage
run: | run: |
uv run pytest app --cov=app --cov-report term-missing uv run pytest --cov=immich_ml --cov-report term-missing
github-files-formatting: github-files-formatting:
name: .github Files Formatting name: .github Files Formatting

216
cli/package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.56", "version": "2.2.57",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.56", "version": "2.2.57",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"chokidar": "^4.0.3", "chokidar": "^4.0.3",
@ -55,7 +55,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.2", "version": "1.130.3",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
@ -810,9 +810,9 @@
} }
}, },
"node_modules/@eslint/config-helpers": { "node_modules/@eslint/config-helpers": {
"version": "0.1.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz",
"integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -833,9 +833,9 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "3.3.0", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
"integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -894,9 +894,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.22.0", "version": "9.23.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
"integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1528,17 +1528,17 @@
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz",
"integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==", "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/type-utils": "8.26.1", "@typescript-eslint/type-utils": "8.27.0",
"@typescript-eslint/utils": "8.26.1", "@typescript-eslint/utils": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@ -1558,16 +1558,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz",
"integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==", "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -1583,14 +1583,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz",
"integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==", "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1" "@typescript-eslint/visitor-keys": "8.27.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -1601,14 +1601,14 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz",
"integrity": "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==", "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/utils": "8.26.1", "@typescript-eslint/utils": "8.27.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.1"
}, },
@ -1625,9 +1625,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz",
"integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==", "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1639,14 +1639,14 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz",
"integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==", "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -1666,16 +1666,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz",
"integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==", "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.26.1" "@typescript-eslint/typescript-estree": "8.27.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -1690,13 +1690,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz",
"integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==", "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -1721,9 +1721,9 @@
} }
}, },
"node_modules/@vitest/coverage-v8": { "node_modules/@vitest/coverage-v8": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.9.tgz",
"integrity": "sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==", "integrity": "sha512-15OACZcBtQ34keIEn19JYTVuMFTlFrClclwWjHo/IRPg/8ELpkgNTl0o7WLP9WO9XGH6+tip9CPYtEOrIDJvBA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1744,8 +1744,8 @@
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
}, },
"peerDependencies": { "peerDependencies": {
"@vitest/browser": "3.0.8", "@vitest/browser": "3.0.9",
"vitest": "3.0.8" "vitest": "3.0.9"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@vitest/browser": { "@vitest/browser": {
@ -1754,14 +1754,14 @@
} }
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz",
"integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==", "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"chai": "^5.2.0", "chai": "^5.2.0",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@ -1770,13 +1770,13 @@
} }
}, },
"node_modules/@vitest/mocker": { "node_modules/@vitest/mocker": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz",
"integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==", "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"estree-walker": "^3.0.3", "estree-walker": "^3.0.3",
"magic-string": "^0.30.17" "magic-string": "^0.30.17"
}, },
@ -1797,9 +1797,9 @@
} }
}, },
"node_modules/@vitest/pretty-format": { "node_modules/@vitest/pretty-format": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz",
"integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==", "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1810,13 +1810,13 @@
} }
}, },
"node_modules/@vitest/runner": { "node_modules/@vitest/runner": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz",
"integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==", "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
"funding": { "funding": {
@ -1824,13 +1824,13 @@
} }
}, },
"node_modules/@vitest/snapshot": { "node_modules/@vitest/snapshot": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz",
"integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==", "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.8", "@vitest/pretty-format": "3.0.9",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
@ -1839,9 +1839,9 @@
} }
}, },
"node_modules/@vitest/spy": { "node_modules/@vitest/spy": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz",
"integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==", "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1852,13 +1852,13 @@
} }
}, },
"node_modules/@vitest/utils": { "node_modules/@vitest/utils": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz",
"integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==", "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.8", "@vitest/pretty-format": "3.0.9",
"loupe": "^3.1.3", "loupe": "^3.1.3",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@ -2379,19 +2379,19 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.22.0", "version": "9.23.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz",
"integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.2", "@eslint/config-array": "^0.19.2",
"@eslint/config-helpers": "^0.1.0", "@eslint/config-helpers": "^0.2.0",
"@eslint/core": "^0.12.0", "@eslint/core": "^0.12.0",
"@eslint/eslintrc": "^3.3.0", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.22.0", "@eslint/js": "9.23.0",
"@eslint/plugin-kit": "^0.2.7", "@eslint/plugin-kit": "^0.2.7",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
@ -4432,9 +4432,9 @@
} }
}, },
"node_modules/vite-node": { "node_modules/vite-node": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz", "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz",
"integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==", "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -4475,19 +4475,19 @@
} }
}, },
"node_modules/vitest": { "node_modules/vitest": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz",
"integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==", "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/expect": "3.0.8", "@vitest/expect": "3.0.9",
"@vitest/mocker": "3.0.8", "@vitest/mocker": "3.0.9",
"@vitest/pretty-format": "^3.0.8", "@vitest/pretty-format": "^3.0.9",
"@vitest/runner": "3.0.8", "@vitest/runner": "3.0.9",
"@vitest/snapshot": "3.0.8", "@vitest/snapshot": "3.0.9",
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"chai": "^5.2.0", "chai": "^5.2.0",
"debug": "^4.4.0", "debug": "^4.4.0",
"expect-type": "^1.1.0", "expect-type": "^1.1.0",
@ -4499,7 +4499,7 @@
"tinypool": "^1.0.2", "tinypool": "^1.0.2",
"tinyrainbow": "^2.0.0", "tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0", "vite": "^5.0.0 || ^6.0.0",
"vite-node": "3.0.8", "vite-node": "3.0.9",
"why-is-node-running": "^2.3.0" "why-is-node-running": "^2.3.0"
}, },
"bin": { "bin": {
@ -4515,8 +4515,8 @@
"@edge-runtime/vm": "*", "@edge-runtime/vm": "*",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
"@vitest/browser": "3.0.8", "@vitest/browser": "3.0.9",
"@vitest/ui": "3.0.8", "@vitest/ui": "3.0.9",
"happy-dom": "*", "happy-dom": "*",
"jsdom": "*" "jsdom": "*"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.56", "version": "2.2.57",
"description": "Command Line Interface (CLI) for Immich", "description": "Command Line Interface (CLI) for Immich",
"type": "module", "type": "module",
"exports": "./dist/index.js", "exports": "./dist/index.js",

View File

@ -71,7 +71,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`. 1. If you do not already have it, download the latest [`hwaccel.ml.yml`][hw-file] file and ensure it's in the same folder as the `docker-compose.yml`.
2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend. 2. In the `docker-compose.yml` under `immich-machine-learning`, uncomment the `extends` section and change `cpu` to the appropriate backend.
3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino] to the `image` section's tag at the end of the line. 3. Still in `immich-machine-learning`, add one of -[armnn, cuda, rocm, openvino, rknn] to the `image` section's tag at the end of the line.
4. Redeploy the `immich-machine-learning` container with these updated settings. 4. Redeploy the `immich-machine-learning` container with these updated settings.
### Confirming Device Usage ### Confirming Device Usage

View File

@ -81,7 +81,7 @@ Memory and execution time estimates were obtained without acceleration on a 7800
**Memory (MiB)**: The peak RSS usage of the process afer performing the above timing benchmark. Does not include image decoding, concurrent processing, the web server, etc., which are relatively constant factors. **Memory (MiB)**: The peak RSS usage of the process afer performing the above timing benchmark. Does not include image decoding, concurrent processing, the web server, etc., which are relatively constant factors.
**Recall (%)**: Evaluated on Crossmodal-3600, the average of the recall@1, recall@5 and recall@10 results for zeroshot image retrieval. **Recall (%)**: Evaluated on Crossmodal-3600, the average of the recall@1, recall@5 and recall@10 results for zeroshot image retrieval. Chinese (Simplified), English, French, German, Italian, Japanese, Korean, Polish, Russian, Spanish and Turkish are additionally tested on XTD-10. Chinese (Simplified) and English are additionally tested on Flickr30k. The recall metrics are the average across all tested datasets.
**Pareto Optimal**: Whether the model is not completely outclassed by another model. Try to use models that are optimal for the languages relevant to you. Specifically, for a given model and language, if there's another model that's better for that language in at least one respect (memory usage, execution time, recall) while being at least as good for that language in every other way, then the model is not optimal for that language. **Pareto Optimal**: Whether the model is not completely outclassed by another model. Try to use models that are optimal for the languages relevant to you. Specifically, for a given model and language, if there's another model that's better for that language in at least one respect (memory usage, execution time, recall) while being at least as good for that language in every other way, then the model is not optimal for that language.
@ -93,59 +93,59 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>English</summary> <summary>English</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 75.73 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 85.99 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 75.44 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 85.96 | ❌ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 75.19 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 85.96 | ❌ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 75.09 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 85.93 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 75.07 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 85.78 | ❌ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 75.01 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 85.75 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 74.92 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 85.62 | ✅ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 74.9 | ❌ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 85.53 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 74.87 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 85.48 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 74.87 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 85.47 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 74.77 | ❌ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 85.09 | ❌ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 74.28 | ❌ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 85.03 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 74.26 | ✅ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 84.86 | ✅ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 73.15 | ✅ | | ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 84.61 | ❌ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 72.78 | ✅ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 84.17 | ❌ |
| ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 72.58 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 83.51 | ❌ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 72.57 | ❌ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 83.28 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 72.47 | ✅ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 83.24 | ❌ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 72.45 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 83.23 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 72.44 | ❌ | | ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 83.19 | ✅ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 72.37 | ❌ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 82.54 | ❌ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 71.64 | ✅ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 82.43 | ❌ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 71.63 | ❌ | | ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 82.36 | ❌ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 71.45 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 82.28 | ✅ |
| ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 71.33 | ❌ | | ViT-B-16-SigLIP__webli | 1081 | 5.77 | 81.9 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 71.19 | ❌ | | ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 81.9 | ❌ |
| ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 69.86 | ❌ | | ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 80.82 | ❌ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 69.66 | ❌ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 80.65 | ❌ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 69.38 | ❌ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 80.16 | ❌ |
| ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 68.78 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 79.78 | ❌ |
| ViT-L-14__laion400m_e31 | 2183 | 19.87 | 68.53 | ❌ | | ViT-L-14__laion400m_e31 | 2183 | 19.87 | 78.64 | ❌ |
| ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 68.53 | ❌ | | ViT-L-14__laion400m_e32 | 2218 | 19.73 | 78.6 | ❌ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 68.53 | ❌ | | ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 78.06 | ❌ |
| ViT-L-14__laion400m_e32 | 2218 | 19.73 | 68.51 | ❌ | | ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 78.06 | ❌ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 68.41 | ❌ | | ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 77.62 | ✅ |
| ViT-B-32__laion2b_e16 | 1004 | 2.38 | 68.41 | ❌ | | ViT-B-32__laion2b_e16 | 1004 | 2.38 | 77.47 | ❌ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 68.33 | ❌ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 76.91 | ❌ |
| ViT-B-16__laion400m_e31 | 991 | 5.04 | 66.96 | ✅ | | ViT-B-16__laion400m_e32 | 975 | 4.98 | 76.43 | ✅ |
| ViT-B-16__laion400m_e32 | 975 | 4.98 | 66.95 | ✅ | | ViT-B-16__laion400m_e31 | 991 | 5.04 | 76.35 | ❌ |
| ViT-B-32__laion400m_e31 | 999 | 2.28 | 65.65 | ✅ | | ViT-B-32__laion400m_e31 | 999 | 2.28 | 73.83 | ✅ |
| ViT-B-32__laion400m_e32 | 1003 | 2.35 | 65.49 | ❌ | | ViT-B-32__laion400m_e32 | 1003 | 2.35 | 73.62 | ❌ |
| ViT-L-14__openai | 2212 | 19.91 | 60.12 | ❌ | | RN50x64__openai | 5079 | 48.79 | 73.34 | ❌ |
| ViT-B-32__openai | 1004 | 2.26 | 59.37 | ✅ | | ViT-L-14__openai | 2212 | 19.91 | 72.99 | ❌ |
| RN50x64__openai | 5079 | 48.79 | 59.36 | ❌ | | ViT-L-14-336__openai | 2616 | 43.45 | 72.76 | ❌ |
| RN50x16__openai | 2221 | 15.87 | 59.17 | ❌ | | RN50x16__openai | 2221 | 15.87 | 72.59 | ❌ |
| ViT-L-14-336__openai | 2616 | 43.45 | 59.09 | ❌ | | RN50x4__openai | 1416 | 5.85 | 70.8 | ❌ |
| RN50__openai | 913 | 2.39 | 58.32 | ✅ | | ViT-B-16__openai | 985 | 5.03 | 70.01 | ❌ |
| ViT-B-16__openai | 985 | 5.03 | 58.27 | ❌ | | ViT-B-32__openai | 1004 | 2.26 | 69.9 | ✅ |
| RN50x4__openai | 1416 | 5.85 | 57.88 | ❌ | | RN101__openai | 1111 | 3.21 | 69.3 | ❌ |
| RN50__cc12m | 914 | 2.37 | 57.75 | ✅ | | RN50__openai | 913 | 2.39 | 69.02 | ✅ |
| RN101__openai | 1111 | 3.21 | 57.7 | ❌ | | RN50__cc12m | 914 | 2.37 | 64.59 | ✅ |
| RN101__yfcc15m | 1111 | 3.22 | 50.11 | ❌ | | RN101__yfcc15m | 1111 | 3.22 | 55.21 | ❌ |
| RN50__yfcc15m | 908 | 2.34 | 48.28 | ✅ | | RN50__yfcc15m | 908 | 2.34 | 53.63 | ✅ |
</details> </details>
<details> <details>
<summary>Arabic</summary> <summary>Arabic</summary>
@ -156,8 +156,8 @@ Memory and execution time estimates were obtained without acceleration on a 7800
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 74.03 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 74.03 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 73.19 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 73.19 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 69.31 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 69.31 | ✅ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 69.29 | ❌ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 69.29 | ❌ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 69.29 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 69.29 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 68.64 | ✅ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 68.64 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 68.35 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 68.35 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 68.25 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 68.25 | ✅ |
@ -195,25 +195,25 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>Chinese (Simplified)</summary> <summary>Chinese (Simplified)</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 77.49 | ✅ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 79.7 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 77.19 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 78.94 | ❌ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 76.98 | ❌ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 75.22 | ✅ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 72.89 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 74.8 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 72.65 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 73.91 | ❌ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 72.52 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 72.8 | ❌ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 67.83 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 72.77 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 67.81 | ❌ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 72.41 | ✅ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 67.51 | ❌ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 72.36 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 67.39 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 71.59 | ❌ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 67.33 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 71.37 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 67.23 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 71.3 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 67.05 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 71.11 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 66.87 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 70.95 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 66.24 | ❌ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 70.51 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 66.1 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 67.48 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 65.56 | ❌ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 66.84 | ✅ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 64.39 | ❌ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 65.7 | ✅ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 62.56 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 63.38 | ❌ |
</details> </details>
<details> <details>
<summary>Croatian</summary> <summary>Croatian</summary>
@ -324,8 +324,8 @@ Memory and execution time estimates were obtained without acceleration on a 7800
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 80.05 | ✅ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 80.05 | ✅ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 79.81 | ❌ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 79.81 | ❌ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 79.72 | ❌ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 79.72 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 79.72 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 79.72 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 79.64 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 79.64 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 79.49 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 79.49 | ✅ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 79.41 | ❌ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 79.41 | ❌ |
@ -357,8 +357,8 @@ Memory and execution time estimates were obtained without acceleration on a 7800
| ViT-L-14__laion400m_e32 | 2218 | 19.73 | 29.56 | ❌ | | ViT-L-14__laion400m_e32 | 2218 | 19.73 | 29.56 | ❌ |
| ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 29.54 | ✅ | | ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 29.54 | ✅ |
| ViT-B-32__laion2b_e16 | 1004 | 2.38 | 29.36 | ❌ | | ViT-B-32__laion2b_e16 | 1004 | 2.38 | 29.36 | ❌ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 27.76 | ❌ |
| ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 27.76 | ❌ | | ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 27.76 | ❌ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 27.76 | ❌ |
| ViT-B-16__laion400m_e32 | 975 | 4.98 | 25.67 | ✅ | | ViT-B-16__laion400m_e32 | 975 | 4.98 | 25.67 | ✅ |
| ViT-B-32__laion400m_e32 | 1003 | 2.35 | 25.59 | ❌ | | ViT-B-32__laion400m_e32 | 1003 | 2.35 | 25.59 | ❌ |
| ViT-B-16__laion400m_e31 | 991 | 5.04 | 25.53 | ❌ | | ViT-B-16__laion400m_e31 | 991 | 5.04 | 25.53 | ❌ |
@ -384,8 +384,8 @@ Memory and execution time estimates were obtained without acceleration on a 7800
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 34.27 | ❌ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 34.27 | ❌ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 34.14 | ❌ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 34.14 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 33.98 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 33.98 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 30.57 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 30.57 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 30.57 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 30.57 | ❌ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 30.05 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 30.05 | ✅ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 24.92 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 24.92 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 24.02 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 24.02 | ❌ |
@ -422,110 +422,111 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>French</summary> <summary>French</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 88.01 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 86.5 | ✅ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 87.74 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 86.5 | ❌ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 87.69 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 86.39 | ❌ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 87.6 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 86.15 | ❌ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 87.58 | ✅ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 86.1 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 87.51 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 86.07 | ❌ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 87.23 | ❌ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 86.06 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 86.9 | ✅ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 85.89 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 86.9 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 85.67 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 86.44 | ✅ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 85.67 | ✅ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 86.44 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 85.63 | ❌ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 86.28 | ❌ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 85.39 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 86.11 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 85.35 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 86.08 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 84.97 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 84.49 | ❌ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 83.8 | ✅ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 84.3 | ✅ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 82.96 | ❌ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 83.03 | ✅ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 82.91 | ✅ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 82.93 | ❌ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 82.52 | ❌ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 82.27 | ✅ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 81.21 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 82.14 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 80.23 | ✅ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 80.96 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 79.85 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 80.64 | ❌ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 79.47 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 80.28 | ✅ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 79.3 | ❌ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 79.65 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 77.49 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 77.4 | ✅ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 76.82 | ✅ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 76.88 | ✅ | | ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 75.94 | ✅ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 76.3 | ✅ | | ViT-B-16-SigLIP__webli | 1081 | 5.77 | 75.3 | ✅ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 75.68 | ❌ | | ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 75.24 | ❌ |
| ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 69.59 | ❌ | | ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 69.33 | ❌ |
| ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 68.36 | ❌ | | ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 64.41 | ❌ |
| ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 61.78 | ❌ | | ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 62.86 | ❌ |
| ViT-L-14__laion400m_e32 | 2218 | 19.73 | 58.4 | ❌ | | ViT-L-14__laion400m_e32 | 2218 | 19.73 | 59.27 | ❌ |
| ViT-L-14__laion400m_e31 | 2183 | 19.87 | 58.35 | ❌ | | ViT-L-14__laion400m_e31 | 2183 | 19.87 | 59.09 | ❌ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 57.17 | ❌ | | ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 58.25 | ❌ |
| ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 57.17 | ❌ | | ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 58.25 | ❌ |
| ViT-B-32__laion2b_e16 | 1004 | 2.38 | 57.05 | ✅ | | ViT-B-32__laion2b_e16 | 1004 | 2.38 | 56.97 | ✅ |
| ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 56.08 | ✅ | | ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 56.21 | ✅ |
| ViT-B-16__laion400m_e31 | 991 | 5.04 | 52.96 | ✅ | | ViT-B-32__laion400m_e31 | 999 | 2.28 | 53.36 | ✅ |
| ViT-B-16__laion400m_e32 | 975 | 4.98 | 52.83 | ✅ | | ViT-B-16__laion400m_e32 | 975 | 4.98 | 53.33 | ✅ |
| ViT-B-32__laion400m_e32 | 1003 | 2.35 | 51.88 | ❌ | | ViT-B-16__laion400m_e31 | 991 | 5.04 | 53.26 | ❌ |
| ViT-B-32__laion400m_e31 | 999 | 2.28 | 51.82 | ✅ | | ViT-B-32__laion400m_e32 | 1003 | 2.35 | 53.22 | ❌ |
| RN50x64__openai | 5079 | 48.79 | 42.86 | ❌ | | ViT-L-14__openai | 2212 | 19.91 | 46.34 | ❌ |
| ViT-L-14-336__openai | 2616 | 43.45 | 42.81 | ❌ | | RN50x64__openai | 5079 | 48.79 | 46.3 | ❌ |
| ViT-L-14__openai | 2212 | 19.91 | 42.54 | ❌ | | ViT-L-14-336__openai | 2616 | 43.45 | 45.95 | ❌ |
| RN50x16__openai | 2221 | 15.87 | 41.72 | ❌ | | RN50x16__openai | 2221 | 15.87 | 45.69 | ❌ |
| RN50x4__openai | 1416 | 5.85 | 38.85 | ❌ | | RN50x4__openai | 1416 | 5.85 | 42.48 | ❌ |
| RN101__openai | 1111 | 3.21 | 36.79 | ❌ | | RN101__openai | 1111 | 3.21 | 40.16 | ❌ |
| ViT-B-16__openai | 985 | 5.03 | 36.47 | ❌ | | ViT-B-16__openai | 985 | 5.03 | 40.1 | ❌ |
| ViT-B-32__openai | 1004 | 2.26 | 35.17 | ✅ | | ViT-B-32__openai | 1004 | 2.26 | 38.27 | ✅ |
| RN50__openai | 913 | 2.39 | 34.44 | ✅ | | RN50__openai | 913 | 2.39 | 37.8 | ✅ |
</details> </details>
<details> <details>
<summary>German</summary> <summary>German</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 90.04 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 87.32 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 89.97 | ✅ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 87.29 | ❌ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 89.85 | ❌ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 87.29 | ❌ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 89.81 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 87.21 | ✅ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 89.77 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 87.18 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 89.69 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 87.14 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 89.45 | ✅ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 87.07 | ❌ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 89.44 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 86.83 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 89.39 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 86.81 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 89.35 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 86.75 | ✅ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 89.03 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 86.74 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 88.82 | ✅ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 86.68 | ❌ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 88.55 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 86.56 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 88.42 | ❌ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 86.16 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 87.19 | ❌ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 84.54 | ❌ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 86.44 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 84.41 | ✅ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 84.81 | ✅ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 84.25 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 84.81 | ❌ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 83.8 | ❌ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 84.58 | ❌ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 82.59 | ✅ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 84.44 | ✅ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 81.53 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 83.33 | ✅ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 81.34 | ❌ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 82.75 | ❌ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 81.15 | ✅ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 82.32 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 81.05 | ❌ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 81.63 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 78.35 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 76.76 | ✅ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 76.56 | ✅ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 76.33 | ✅ | | ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 76.0 | ✅ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 75.19 | ✅ | | ViT-B-16-SigLIP__webli | 1081 | 5.77 | 75.21 | ✅ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 75.07 | ❌ | | ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 75.14 | ❌ |
| ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 64.61 | ❌ | | ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 65.86 | ❌ |
| ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 52.81 | ❌ | | ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 56.87 | ❌ |
| ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 42.88 | ❌ | | ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 47.19 | ❌ |
| ViT-L-14__laion400m_e32 | 2218 | 19.73 | 38.65 | ❌ | | ViT-L-14__laion400m_e32 | 2218 | 19.73 | 43.36 | ❌ |
| ViT-L-14__laion400m_e31 | 2183 | 19.87 | 38.37 | ❌ | | ViT-L-14__laion400m_e31 | 2183 | 19.87 | 43.0 | ❌ |
| ViT-B-32__laion2b_e16 | 1004 | 2.38 | 37.65 | ✅ | | ViT-B-32__laion2b_e16 | 1004 | 2.38 | 41.81 | ✅ |
| ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 36.6 | ✅ | | ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 40.43 | ✅ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 35.44 | ❌ | | ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 40.41 | ❌ |
| ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 35.44 | ❌ | | ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 40.41 | ❌ |
| ViT-B-16__laion400m_e31 | 991 | 5.04 | 32.46 | ✅ | | ViT-B-16__laion400m_e31 | 991 | 5.04 | 37.71 | ✅ |
| ViT-B-16__laion400m_e32 | 975 | 4.98 | 32.31 | ✅ | | ViT-B-16__laion400m_e32 | 975 | 4.98 | 37.64 | ✅ |
| ViT-B-32__laion400m_e31 | 999 | 2.28 | 31.85 | ✅ | | ViT-B-32__laion400m_e31 | 999 | 2.28 | 36.04 | ✅ |
| ViT-B-32__laion400m_e32 | 1003 | 2.35 | 31.81 | ❌ | | ViT-B-32__laion400m_e32 | 1003 | 2.35 | 35.9 | ❌ |
| RN50x64__openai | 5079 | 48.79 | 28.41 | ❌ | | RN50x64__openai | 5079 | 48.79 | 34.19 | ❌ |
| ViT-L-14__openai | 2212 | 19.91 | 27.63 | ❌ | | ViT-L-14__openai | 2212 | 19.91 | 33.1 | ❌ |
| ViT-L-14-336__openai | 2616 | 43.45 | 27.09 | ❌ | | ViT-L-14-336__openai | 2616 | 43.45 | 32.25 | ❌ |
| RN50x16__openai | 2221 | 15.87 | 24.48 | ❌ | | RN50x16__openai | 2221 | 15.87 | 30.56 | ❌ |
| RN50x4__openai | 1416 | 5.85 | 23.49 | ❌ | | RN50x4__openai | 1416 | 5.85 | 29.2 | ❌ |
| RN50__openai | 913 | 2.39 | 20.91 | ✅ | | ViT-B-16__openai | 985 | 5.03 | 25.77 | ❌ |
| ViT-B-16__openai | 985 | 5.03 | 20.83 | ❌ | | RN101__openai | 1111 | 3.21 | 25.46 | ❌ |
| RN101__openai | 1111 | 3.21 | 20.39 | ❌ | | RN50__openai | 913 | 2.39 | 24.92 | ✅ |
| ViT-B-32__openai | 1004 | 2.26 | 24.13 | ✅ |
</details> </details>
<details> <details>
<summary>Greek</summary> <summary>Greek</summary>
@ -542,10 +543,10 @@ Memory and execution time estimates were obtained without acceleration on a 7800
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 60.63 | ❌ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 60.63 | ❌ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 60.41 | ❌ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 60.41 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 60.1 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 60.1 | ❌ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 60.06 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 60.06 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 60.06 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 59.44 | ❌ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 60.06 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 59.44 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 59.44 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 59.44 | ❌ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 59.43 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 59.43 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 58.78 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 58.78 | ✅ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 53.42 | ❌ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 53.42 | ❌ |
@ -670,99 +671,104 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>Italian</summary> <summary>Italian</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 88.6 | ✅ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 87.17 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 88.25 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 86.91 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 88.12 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 86.83 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 88.04 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 86.77 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 87.97 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 86.67 | ✅ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 87.69 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 86.42 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 87.29 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 86.35 | ✅ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 87.06 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 86.34 | ❌ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 86.91 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 86.18 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 86.88 | ✅ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 86.17 | ❌ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 86.68 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 85.84 | ✅ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 86.61 | ❌ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 85.8 | ❌ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 85.55 | ❌ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 85.7 | ✅ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 85.37 | ❌ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 85.67 | ❌ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 83.78 | ✅ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 83.32 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 83.0 | ❌ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 82.95 | ❌ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 81.81 | ✅ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 82.73 | ❌ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 81.77 | ❌ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 82.72 | ❌ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 81.32 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 81.07 | ❌ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 80.97 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 80.8 | ✅ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 80.53 | ✅ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 80.6 | ✅ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 80.1 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 80.35 | ❌ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 79.71 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 78.79 | ✅ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 77.31 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 76.62 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 75.19 | ✅ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 76.51 | ✅ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 74.49 | ✅ | | ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 76.08 | ✅ |
| ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 74.04 | ❌ | | ViT-B-16-SigLIP__webli | 1081 | 5.77 | 75.29 | ✅ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 73.68 | ✅ | | ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 75.29 | ❌ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 73.57 | ✅ | | ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 74.84 | ❌ |
| ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 51.04 | ❌ | | ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 56.32 | ❌ |
| ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 41.73 | ❌ | | ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 47.25 | ❌ |
| ViT-L-14__laion400m_e32 | 2218 | 19.73 | 36.87 | ❌ | | ViT-L-14__laion400m_e32 | 2218 | 19.73 | 43.09 | ❌ |
| ViT-L-14__laion400m_e31 | 2183 | 19.87 | 36.84 | ❌ | | ViT-L-14__laion400m_e31 | 2183 | 19.87 | 42.99 | ❌ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 34.68 | ❌ | | ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 40.29 | ❌ |
| ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 34.68 | ❌ | | ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 40.29 | ❌ |
| ViT-B-32__laion2b_e16 | 1004 | 2.38 | 34.64 | ✅ | | ViT-B-32__laion2b_e16 | 1004 | 2.38 | 39.67 | ✅ |
| ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 33.8 | ✅ | | ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 39.03 | ✅ |
| ViT-B-16__laion400m_e32 | 975 | 4.98 | 30.11 | ✅ | | ViT-B-16__laion400m_e32 | 975 | 4.98 | 36.14 | ✅ |
| ViT-B-16__laion400m_e31 | 991 | 5.04 | 30.04 | ❌ | | ViT-B-16__laion400m_e31 | 991 | 5.04 | 35.89 | ❌ |
| ViT-B-32__laion400m_e32 | 1003 | 2.35 | 29.89 | ❌ | | ViT-B-32__laion400m_e32 | 1003 | 2.35 | 35.59 | ❌ |
| ViT-B-32__laion400m_e31 | 999 | 2.28 | 29.88 | ✅ | | ViT-B-32__laion400m_e31 | 999 | 2.28 | 35.56 | ✅ |
| RN50x64__openai | 5079 | 48.79 | 26.67 | ❌ | | RN50x64__openai | 5079 | 48.79 | 33.53 | ❌ |
| ViT-L-14__openai | 2212 | 19.91 | 25.51 | ❌ | | ViT-L-14__openai | 2212 | 19.91 | 32.19 | ❌ |
| ViT-L-14-336__openai | 2616 | 43.45 | 25.3 | ❌ | | ViT-L-14-336__openai | 2616 | 43.45 | 30.95 | ❌ |
| RN50x16__openai | 2221 | 15.87 | 21.37 | ❌ | | RN50x16__openai | 2221 | 15.87 | 28.85 | ❌ |
| RN50x4__openai | 1416 | 5.85 | 25.75 | ❌ |
| ViT-B-16__openai | 985 | 5.03 | 25.18 | ❌ |
| RN101__openai | 1111 | 3.21 | 24.48 | ❌ |
| RN50__openai | 913 | 2.39 | 23.89 | ✅ |
| ViT-B-32__openai | 1004 | 2.26 | 23.39 | ✅ |
</details> </details>
<details> <details>
<summary>Japanese</summary> <summary>Japanese</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 86.97 | ✅ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 83.95 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 85.15 | ❌ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 82.21 | ❌ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 84.69 | ❌ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 81.55 | ❌ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 81.77 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 78.72 | ✅ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 81.26 | ❌ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 78.53 | ❌ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 81.19 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 75.93 | ✅ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 69.99 | ❌ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 66.86 | ❌ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 68.58 | ❌ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 65.59 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 68.35 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 65.48 | ❌ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 68.29 | ❌ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 65.36 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 67.99 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 64.47 | ❌ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 67.68 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 64.17 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 67.67 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 64.08 | ❌ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 66.85 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 63.69 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 66.54 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 63.33 | ❌ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 65.77 | ❌ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 63.02 | ❌ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 61.48 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 58.39 | ✅ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 58.1 | ❌ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 56.38 | ❌ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 55.31 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 53.16 | ❌ |
</details> </details>
<details> <details>
<summary>Korean</summary> <summary>Korean</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 77.21 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 80.56 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 76.89 | ✅ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 80.53 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 75.72 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 77.09 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 75.06 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 77.08 | ✅ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 74.94 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 76.97 | ❌ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 74.36 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 76.92 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 74.09 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 76.58 | ✅ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 73.61 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 76.2 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 73.55 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 75.95 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 73.41 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 75.86 | ✅ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 73.18 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 75.67 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 72.79 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 75.49 | ❌ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 72.27 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 74.6 | ❌ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 71.73 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 74.52 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 71.12 | ❌ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 73.88 | ❌ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 70.25 | ✅ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 71.09 | ✅ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 67.54 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 68.87 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 67.37 | ✅ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 67.94 | ✅ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 65.44 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 66.39 | ✅ |
</details> </details>
<details> <details>
<summary>Maori</summary> <summary>Maori</summary>
@ -834,34 +840,34 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>Polish</summary> <summary>Polish</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 80.6 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 83.49 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 80.17 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 83.45 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 80.06 | ❌ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 83.11 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 80.04 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 82.99 | ✅ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 79.98 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 82.96 | ❌ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 79.8 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 82.93 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 79.72 | ✅ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 82.61 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 79.66 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 82.26 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 79.45 | ✅ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 82.24 | ✅ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 79.26 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 82.03 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 79.21 | ❌ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 82.03 | ❌ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 79.14 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 81.92 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 78.23 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 81.27 | ✅ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 75.33 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 80.0 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 74.7 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 79.65 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 74.63 | ❌ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 76.75 | ✅ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 73.69 | ✅ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 76.52 | ✅ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 73.44 | ❌ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 75.1 | ✅ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 70.34 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 73.9 | ❌ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 59.4 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 65.03 | ❌ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 59.14 | ❌ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 64.89 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 48.74 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 51.6 | ❌ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 48.35 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 51.29 | ❌ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 40.76 | ✅ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 46.15 | ✅ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 39.13 | ✅ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 41.55 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 39.09 | ❌ | | ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 41.17 | ✅ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 38.55 | ❌ | | ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 40.9 | ✅ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 38.46 | ❌ | | ViT-B-16-SigLIP__webli | 1081 | 5.77 | 40.76 | ✅ |
</details> </details>
<details> <details>
<summary>Portuguese</summary> <summary>Portuguese</summary>
@ -955,84 +961,87 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>Russian</summary> <summary>Russian</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 87.65 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 84.54 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 87.62 | ❌ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 84.41 | ❌ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 87.4 | ✅ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 84.36 | ❌ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 87.39 | ❌ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 84.31 | ❌ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 86.88 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 84.22 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 86.87 | ✅ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 83.9 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 86.74 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 83.69 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 86.26 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 83.5 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 85.98 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 83.31 | ❌ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 85.66 | ❌ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 83.21 | ❌ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 85.54 | ❌ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 83.11 | ✅ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 84.69 | ❌ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 82.7 | ❌ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 84.29 | ✅ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 82.69 | ❌ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 84.24 | ❌ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 80.91 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 82.86 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 79.75 | ❌ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 81.59 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 79.35 | ✅ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 80.56 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 78.91 | ❌ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 80.44 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 78.06 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 79.99 | ❌ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 76.44 | ✅ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 39.51 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 42.81 | ❌ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 39.16 | ❌ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 42.1 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 23.33 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 24.95 | ❌ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 22.4 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 24.25 | ❌ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 20.85 | ✅ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 20.44 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 20.41 | ❌ |
</details> </details>
<details> <details>
<summary>Spanish</summary> <summary>Spanish</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 84.24 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 85.47 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 83.94 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 85.44 | ✅ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 83.91 | ❌ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 85.32 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 83.78 | ✅ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 85.22 | ❌ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 83.71 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 85.15 | ❌ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 83.59 | ❌ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 84.81 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 83.2 | ✅ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 84.68 | ❌ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 83.0 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 84.6 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 82.91 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 84.55 | ✅ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 82.58 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 84.27 | ❌ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 82.5 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 84.15 | ✅ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 82.48 | ❌ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 83.87 | ❌ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 82.22 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 83.74 | ❌ |
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 81.34 | ❌ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 83.61 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 80.18 | ❌ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 83.15 | ❌ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 80.14 | ❌ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 81.7 | ❌ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 78.99 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 80.91 | ❌ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 78.19 | ✅ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 80.73 | ✅ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 78.15 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 80.69 | ❌ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 77.93 | ✅ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 80.3 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 77.64 | ❌ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 79.8 | ❌ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 77.21 | ❌ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 79.71 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 76.36 | ❌ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 79.64 | ✅ |
| ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 75.73 | ✅ | | ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 78.0 | ✅ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 75.56 | ✅ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 77.83 | ❌ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 75.01 | ✅ | | ViT-B-16-SigLIP__webli | 1081 | 5.77 | 76.87 | ✅ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 74.62 | ✅ | | ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 76.66 | ❌ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 74.6 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 75.99 | ✅ |
| ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 70.31 | ❌ | | ViT-SO400M-14-SigLIP-384__webli | 4417 | 72.19 | 71.96 | ❌ |
| ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 58.31 | ❌ | | ViT-H-14__laion2b-s32b-b79k | 4676 | 39.06 | 62.06 | ❌ |
| ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 49.56 | ❌ | | ViT-L-14__laion2b-s32b-b82k | 2233 | 20.56 | 53.78 | ❌ |
| ViT-L-14__laion400m_e32 | 2218 | 19.73 | 46.69 | ❌ | | ViT-L-14__laion400m_e32 | 2218 | 19.73 | 50.13 | ❌ |
| ViT-L-14__laion400m_e31 | 2183 | 19.87 | 46.53 | ❌ | | ViT-L-14__laion400m_e31 | 2183 | 19.87 | 50.0 | ❌ |
| ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 44.05 | ❌ | | ViT-B-16-plus-240__laion400m_e32 | 1246 | 6.95 | 47.39 | ❌ |
| ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 44.05 | ❌ | | ViT-B-16-plus-240__laion400m_e31 | 1263 | 6.94 | 47.39 | ❌ |
| ViT-B-32__laion2b_e16 | 1004 | 2.38 | 43.67 | ✅ | | ViT-B-32__laion2b_e16 | 1004 | 2.38 | 46.47 | ✅ |
| ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 42.5 | ✅ | | ViT-B-32__laion2b-s34b-b79k | 1001 | 2.29 | 45.68 | ✅ |
| ViT-B-16__laion400m_e32 | 975 | 4.98 | 41.03 | ✅ | | ViT-B-16__laion400m_e31 | 991 | 5.04 | 44.0 | ✅ |
| ViT-B-16__laion400m_e31 | 991 | 5.04 | 40.91 | ❌ | | ViT-B-16__laion400m_e32 | 975 | 4.98 | 43.98 | ✅ |
| ViT-B-32__laion400m_e31 | 999 | 2.28 | 40.3 | ✅ | | ViT-B-32__laion400m_e32 | 1003 | 2.35 | 43.8 | ❌ |
| ViT-B-32__laion400m_e32 | 1003 | 2.35 | 40.3 | ❌ | | ViT-B-32__laion400m_e31 | 999 | 2.28 | 43.73 | ✅ |
| RN50x64__openai | 5079 | 48.79 | 37.92 | ❌ | | RN50x64__openai | 5079 | 48.79 | 43.01 | ❌ |
| ViT-L-14-336__openai | 2616 | 43.45 | 37.7 | ❌ | | ViT-L-14__openai | 2212 | 19.91 | 42.96 | ❌ |
| ViT-L-14__openai | 2212 | 19.91 | 37.59 | ❌ | | ViT-L-14-336__openai | 2616 | 43.45 | 41.67 | ❌ |
| RN50x16__openai | 2221 | 15.87 | 34.75 | ❌ | | RN50x16__openai | 2221 | 15.87 | 40.21 | ❌ |
| ViT-B-16__openai | 985 | 5.03 | 32.1 | ❌ | | RN50x4__openai | 1416 | 5.85 | 36.06 | ❌ |
| RN50x4__openai | 1416 | 5.85 | 32.08 | ❌ | | ViT-B-16__openai | 985 | 5.03 | 35.67 | ❌ |
| RN101__openai | 1111 | 3.21 | 30.77 | ❌ | | RN101__openai | 1111 | 3.21 | 34.62 | ❌ |
| RN50__openai | 913 | 2.39 | 30.2 | ✅ | | ViT-B-32__openai | 1004 | 2.26 | 32.6 | ✅ |
| ViT-B-32__openai | 1004 | 2.26 | 29.84 | ✅ | | RN50__openai | 913 | 2.39 | 31.79 | ✅ |
</details> </details>
<details> <details>
<summary>Swahili</summary> <summary>Swahili</summary>
@ -1057,8 +1066,8 @@ Memory and execution time estimates were obtained without acceleration on a 7800
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 72.1 | ✅ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 72.1 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 72.06 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 72.06 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 71.84 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 71.84 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 71.7 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 71.7 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 71.7 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 71.7 | ✅ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 71.61 | ❌ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 71.61 | ❌ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 71.51 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 71.51 | ✅ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 71.45 | ✅ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 71.45 | ✅ |
@ -1115,31 +1124,34 @@ Memory and execution time estimates were obtained without acceleration on a 7800
<summary>Turkish</summary> <summary>Turkish</summary>
| Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal | | Model | Memory (MiB) | Execution Time (ms) | Recall (%) | Pareto Optimal |
|------------------------------------------------------|--------------|---------------------|------------|----------------| |------------------------------------------------------|--------------|---------------------|------------|----------------|
| nllb-clip-large-siglip__mrl | 4248 | 75.44 | 81.15 | ✅ | | nllb-clip-large-siglip__mrl | 4248 | 75.44 | 83.91 | ✅ |
| nllb-clip-large-siglip__v1 | 4226 | 75.05 | 80.89 | ✅ | | nllb-clip-large-siglip__v1 | 4226 | 75.05 | 83.74 | ✅ |
| nllb-clip-base-siglip__mrl | 4696 | 16.95 | 78.11 | ✅ | | nllb-clip-base-siglip__mrl | 4696 | 16.95 | 81.26 | ✅ |
| ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 77.51 | ✅ | | nllb-clip-base-siglip__v1 | 4675 | 15.17 | 80.21 | ✅ |
| nllb-clip-base-siglip__v1 | 4675 | 15.17 | 77.36 | ✅ | | ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 79.34 | ✅ |
| ViT-SO400M-16-SigLIP2-512__webli | 4050 | 107.67 | 77.28 | ❌ | | ViT-SO400M-14-SigLIP2-378__webli | 3940 | 72.25 | 79.22 | ✅ |
| XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 77.24 | ✅ | | XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k | 4014 | 39.14 | 78.9 | ✅ |
| ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 77.01 | ✅ | | ViT-SO400M-16-SigLIP2-384__webli | 3854 | 56.57 | 78.85 | ✅ |
| ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 76.37 | ❌ | | ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 78.29 | ✅ |
| ViT-SO400M-16-SigLIP2-256__webli | 3611 | 27.84 | 75.92 | ✅ | | ViT-gopt-16-SigLIP2-384__webli | 6585 | 146.84 | 78.27 | ❌ |
| ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 75.69 | ✅ | | ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 78.0 | ❌ |
| ViT-gopt-16-SigLIP2-256__webli | 6475 | 64.51 | 75.68 | ❌ | | ViT-SO400M-14-SigLIP2__webli | 3622 | 27.63 | 77.81 | ✅ |
| ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 75.54 | ✅ | | ViT-L-16-SigLIP2-512__webli | 3358 | 92.59 | 77.67 | ✅ |
| ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 75.16 | ✅ | | ViT-L-16-SigLIP2-384__webli | 3057 | 51.7 | 77.33 | ✅ |
| ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 73.83 | ✅ | | ViT-L-16-SigLIP2-256__webli | 2830 | 23.77 | 76.42 | ✅ |
| ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 70.15 | ✅ | | ViT-B-16-SigLIP-i18n-256__webli | 3029 | 6.87 | 72.44 | ✅ |
| XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 69.19 | ✅ | | XLM-Roberta-Base-ViT-B-32__laion5b_s13b_b90k | 3030 | 3.2 | 69.84 | ✅ |
| ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 66.72 | ❌ | | ViT-B-16-SigLIP2__webli | 3038 | 5.81 | 69.83 | ❌ |
| ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 64.76 | ❌ | | ViT-B-32-SigLIP2-256__webli | 3061 | 3.31 | 67.13 | ❌ |
| ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 38.8 | ❌ | | ViT-H-14-378-quickgelu__dfn5b | 5049 | 108.4 | 44.43 | ❌ |
| ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 38.48 | ❌ | | ViT-H-14-quickgelu__dfn5b | 4701 | 38.74 | 43.87 | ❌ |
| ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 30.83 | ❌ | | ViT-L-16-SigLIP-384__webli | 3396 | 47.6 | 35.1 | ❌ |
| ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 30.28 | ❌ | | ViT-L-16-SigLIP-256__webli | 3160 | 23.84 | 34.92 | ❌ |
| ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 21.31 | ✅ | | ViT-L-14-quickgelu__dfn2b | 2212 | 20.49 | 25.2 | ✅ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 20.08 | ✅ | | ViT-B-16-SigLIP-512__webli | 1828 | 26.17 | 24.55 | ✅ |
| ViT-B-16-SigLIP__webli | 1081 | 5.77 | 24.13 | ✅ |
| ViT-B-16-SigLIP-384__webli | 1128 | 13.53 | 24.08 | ❌ |
| ViT-B-16-SigLIP-256__webli | 1102 | 7.11 | 23.95 | ❌ |
</details> </details>
<details> <details>
<summary>Ukrainian</summary> <summary>Ukrainian</summary>

View File

@ -23,12 +23,12 @@ name: immich_remote_ml
services: services:
immich-machine-learning: immich-machine-learning:
container_name: immich_machine_learning container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino] to the image tag. # For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda # Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# extends: # extends:
# file: hwaccel.ml.yml # file: hwaccel.ml.yml
# service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable # service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes: volumes:
- model-cache:/cache - model-cache:/cache
restart: always restart: always

View File

@ -1,4 +1,8 @@
[ [
{
"label": "v1.130.3",
"url": "https://v1.130.3.archive.immich.app"
},
{ {
"label": "v1.130.2", "label": "v1.130.2",
"url": "https://v1.130.2.archive.immich.app" "url": "https://v1.130.2.archive.immich.app"

438
e2e/package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.130.2", "version": "1.130.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.130.2", "version": "1.130.3",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.1.0", "@eslint/eslintrc": "^3.1.0",
@ -45,7 +45,7 @@
}, },
"../cli": { "../cli": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.56", "version": "2.2.57",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
@ -95,7 +95,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.2", "version": "1.130.3",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
@ -829,9 +829,9 @@
} }
}, },
"node_modules/@eslint/config-helpers": { "node_modules/@eslint/config-helpers": {
"version": "0.1.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz",
"integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -852,9 +852,9 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "3.3.0", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
"integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -889,9 +889,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.22.0", "version": "9.23.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
"integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1258,13 +1258,13 @@
} }
}, },
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.51.0", "version": "1.51.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.0.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz",
"integrity": "sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA==", "integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright": "1.51.0" "playwright": "1.51.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -1274,9 +1274,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz",
"integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==", "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1288,9 +1288,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz",
"integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==", "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1302,9 +1302,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz",
"integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==", "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1316,9 +1316,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz",
"integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==", "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1330,9 +1330,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz",
"integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==", "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1344,9 +1344,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz",
"integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==", "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1358,9 +1358,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz",
"integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==", "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1372,9 +1372,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz",
"integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==", "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -1386,9 +1386,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz",
"integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==", "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1400,9 +1400,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz",
"integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==", "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1414,9 +1414,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-loongarch64-gnu": { "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz",
"integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==", "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@ -1428,9 +1428,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz",
"integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==", "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -1442,9 +1442,23 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz",
"integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==", "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz",
"integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@ -1456,9 +1470,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz",
"integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==", "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@ -1470,9 +1484,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz",
"integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==", "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1484,9 +1498,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz",
"integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==", "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1498,9 +1512,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz",
"integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==", "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1512,9 +1526,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz",
"integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==", "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -1526,9 +1540,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz",
"integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==", "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1892,17 +1906,17 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz",
"integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==", "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/type-utils": "8.26.1", "@typescript-eslint/type-utils": "8.27.0",
"@typescript-eslint/utils": "8.26.1", "@typescript-eslint/utils": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@ -1922,16 +1936,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz",
"integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==", "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -1947,14 +1961,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz",
"integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==", "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1" "@typescript-eslint/visitor-keys": "8.27.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -1965,14 +1979,14 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz",
"integrity": "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==", "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/utils": "8.26.1", "@typescript-eslint/utils": "8.27.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.1"
}, },
@ -1989,9 +2003,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz",
"integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==", "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -2003,14 +2017,14 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz",
"integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==", "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -2056,16 +2070,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz",
"integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==", "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.26.1" "@typescript-eslint/typescript-estree": "8.27.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2080,13 +2094,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz",
"integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==", "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -2111,9 +2125,9 @@
} }
}, },
"node_modules/@vitest/coverage-v8": { "node_modules/@vitest/coverage-v8": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.9.tgz",
"integrity": "sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==", "integrity": "sha512-15OACZcBtQ34keIEn19JYTVuMFTlFrClclwWjHo/IRPg/8ELpkgNTl0o7WLP9WO9XGH6+tip9CPYtEOrIDJvBA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2134,8 +2148,8 @@
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
}, },
"peerDependencies": { "peerDependencies": {
"@vitest/browser": "3.0.8", "@vitest/browser": "3.0.9",
"vitest": "3.0.8" "vitest": "3.0.9"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@vitest/browser": { "@vitest/browser": {
@ -2162,14 +2176,14 @@
} }
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz",
"integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==", "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"chai": "^5.2.0", "chai": "^5.2.0",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@ -2178,13 +2192,13 @@
} }
}, },
"node_modules/@vitest/mocker": { "node_modules/@vitest/mocker": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz",
"integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==", "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"estree-walker": "^3.0.3", "estree-walker": "^3.0.3",
"magic-string": "^0.30.17" "magic-string": "^0.30.17"
}, },
@ -2205,9 +2219,9 @@
} }
}, },
"node_modules/@vitest/pretty-format": { "node_modules/@vitest/pretty-format": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz",
"integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==", "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2218,13 +2232,13 @@
} }
}, },
"node_modules/@vitest/runner": { "node_modules/@vitest/runner": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz",
"integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==", "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
"funding": { "funding": {
@ -2232,13 +2246,13 @@
} }
}, },
"node_modules/@vitest/snapshot": { "node_modules/@vitest/snapshot": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz",
"integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==", "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.8", "@vitest/pretty-format": "3.0.9",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
@ -2247,9 +2261,9 @@
} }
}, },
"node_modules/@vitest/spy": { "node_modules/@vitest/spy": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz",
"integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==", "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2260,13 +2274,13 @@
} }
}, },
"node_modules/@vitest/utils": { "node_modules/@vitest/utils": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz",
"integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==", "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.8", "@vitest/pretty-format": "3.0.9",
"loupe": "^3.1.3", "loupe": "^3.1.3",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@ -3167,19 +3181,19 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.22.0", "version": "9.23.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz",
"integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.2", "@eslint/config-array": "^0.19.2",
"@eslint/config-helpers": "^0.1.0", "@eslint/config-helpers": "^0.2.0",
"@eslint/core": "^0.12.0", "@eslint/core": "^0.12.0",
"@eslint/eslintrc": "^3.3.0", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.22.0", "@eslint/js": "9.23.0",
"@eslint/plugin-kit": "^0.2.7", "@eslint/plugin-kit": "^0.2.7",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
@ -5222,9 +5236,9 @@
} }
}, },
"node_modules/pg": { "node_modules/pg": {
"version": "8.14.0", "version": "8.14.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.14.0.tgz", "resolved": "https://registry.npmjs.org/pg/-/pg-8.14.1.tgz",
"integrity": "sha512-nXbVpyoaXVmdqlKEzToFf37qzyeeh7mbiXsnoWvstSqohj88yaa/I/Rq/HEVn2QPSZEuLIJa/jSpRDyzjEx4FQ==", "integrity": "sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -5344,13 +5358,13 @@
} }
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.51.0", "version": "1.51.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.0.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz",
"integrity": "sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA==", "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.51.0" "playwright-core": "1.51.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -5363,9 +5377,9 @@
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.51.0", "version": "1.51.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.0.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz",
"integrity": "sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg==", "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@ -5423,9 +5437,9 @@
} }
}, },
"node_modules/postcss/node_modules/nanoid": { "node_modules/postcss/node_modules/nanoid": {
"version": "3.3.9", "version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -5833,9 +5847,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.35.0", "version": "4.37.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz",
"integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==", "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -5849,25 +5863,26 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm-eabi": "4.37.0",
"@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-android-arm64": "4.37.0",
"@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.37.0",
"@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-darwin-x64": "4.37.0",
"@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.37.0",
"@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.37.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.37.0",
"@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.37.0",
"@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.37.0",
"@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.37.0",
"@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.37.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0",
"@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.37.0",
"@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-musl": "4.37.0",
"@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.37.0",
"@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.37.0",
"@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.37.0",
"@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.37.0",
"@rollup/rollup-win32-x64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.37.0",
"@rollup/rollup-win32-x64-msvc": "4.37.0",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@ -6232,10 +6247,11 @@
} }
}, },
"node_modules/supertest": { "node_modules/supertest": {
"version": "7.0.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.0.tgz",
"integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", "integrity": "sha512-5QeSO8hSrKghtcWEoPiO036fxH0Ii2wVQfFZSP0oqQhmjk8bOLhDFXr4JrvaFmPuEWUoq4znY3uSi8UzLKxGqw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"methods": "^1.1.2", "methods": "^1.1.2",
"superagent": "^9.0.1" "superagent": "^9.0.1"
@ -6604,9 +6620,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "6.2.1", "version": "6.2.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz",
"integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==", "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -6676,9 +6692,9 @@
} }
}, },
"node_modules/vite-node": { "node_modules/vite-node": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz", "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz",
"integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==", "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -6732,19 +6748,19 @@
} }
}, },
"node_modules/vitest": { "node_modules/vitest": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz",
"integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==", "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/expect": "3.0.8", "@vitest/expect": "3.0.9",
"@vitest/mocker": "3.0.8", "@vitest/mocker": "3.0.9",
"@vitest/pretty-format": "^3.0.8", "@vitest/pretty-format": "^3.0.9",
"@vitest/runner": "3.0.8", "@vitest/runner": "3.0.9",
"@vitest/snapshot": "3.0.8", "@vitest/snapshot": "3.0.9",
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"chai": "^5.2.0", "chai": "^5.2.0",
"debug": "^4.4.0", "debug": "^4.4.0",
"expect-type": "^1.1.0", "expect-type": "^1.1.0",
@ -6756,7 +6772,7 @@
"tinypool": "^1.0.2", "tinypool": "^1.0.2",
"tinyrainbow": "^2.0.0", "tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0", "vite": "^5.0.0 || ^6.0.0",
"vite-node": "3.0.8", "vite-node": "3.0.9",
"why-is-node-running": "^2.3.0" "why-is-node-running": "^2.3.0"
}, },
"bin": { "bin": {
@ -6772,8 +6788,8 @@
"@edge-runtime/vm": "*", "@edge-runtime/vm": "*",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
"@vitest/browser": "3.0.8", "@vitest/browser": "3.0.9",
"@vitest/ui": "3.0.8", "@vitest/ui": "3.0.9",
"happy-dom": "*", "happy-dom": "*",
"jsdom": "*" "jsdom": "*"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.130.2", "version": "1.130.3",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",

View File

@ -51,7 +51,6 @@ ARG DEVICE
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
VIRTUAL_ENV=/opt/venv VIRTUAL_ENV=/opt/venv
WORKDIR /usr/src/app
RUN apt-get update && apt-get install -y --no-install-recommends g++ RUN apt-get update && apt-get install -y --no-install-recommends g++
@ -66,6 +65,8 @@ RUN if [ "$DEVICE" = "rocm" ]; then \
FROM python:3.11-slim-bookworm@sha256:7029b00486ac40bed03e36775b864d3f3d39dcbdf19cd45e6a52d541e6c178f0 AS prod-cpu FROM python:3.11-slim-bookworm@sha256:7029b00486ac40bed03e36775b864d3f3d39dcbdf19cd45e6a52d541e6c178f0 AS prod-cpu
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
FROM prod-cpu AS prod-openvino FROM prod-cpu AS prod-openvino
RUN apt-get update && \ RUN apt-get update && \
@ -94,7 +95,8 @@ FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091
FROM prod-cpu AS prod-armnn FROM prod-cpu AS prod-armnn
ENV LD_LIBRARY_PATH=/opt/armnn ENV LD_LIBRARY_PATH=/opt/armnn \
LD_PRELOAD=/usr/lib/libmimalloc.so.2
RUN apt-get update && apt-get install -y --no-install-recommends ocl-icd-libopencl1 mesa-opencl-icd libgomp1 && \ RUN apt-get update && apt-get install -y --no-install-recommends ocl-icd-libopencl1 mesa-opencl-icd libgomp1 && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
@ -114,6 +116,8 @@ COPY --from=builder-armnn \
FROM prod-cpu AS prod-rknn FROM prod-cpu AS prod-rknn
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
ADD --checksum=sha256:73993ed4b440460825f21611731564503cc1d5a0c123746477da6cd574f34885 https://github.com/airockchip/rknn-toolkit2/raw/refs/tags/v2.3.0/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so /usr/lib/ ADD --checksum=sha256:73993ed4b440460825f21611731564503cc1d5a0c123746477da6cd574f34885 https://github.com/airockchip/rknn-toolkit2/raw/refs/tags/v2.3.0/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so /usr/lib/
FROM prod-${DEVICE} AS prod FROM prod-${DEVICE} AS prod
@ -126,14 +130,18 @@ RUN apt-get update && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src/app RUN ln -s "/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2" /usr/lib/libmimalloc.so.2
WORKDIR /usr/src
ENV TRANSFORMERS_CACHE=/cache \ ENV TRANSFORMERS_CACHE=/cache \
PYTHONDONTWRITEBYTECODE=1 \ PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
PATH="/opt/venv/bin:$PATH" \ PATH="/opt/venv/bin:$PATH" \
PYTHONPATH=/usr/src \ PYTHONPATH=/usr/src \
DEVICE=${DEVICE} \ DEVICE=${DEVICE} \
VIRTUAL_ENV=/opt/venv VIRTUAL_ENV=/opt/venv \
LD_BIND_NOW=1 \
MACHINE_LEARNING_CACHE_FOLDER=/cache
# prevent core dumps # prevent core dumps
RUN echo "hard core 0" >> /etc/security/limits.conf && \ RUN echo "hard core 0" >> /etc/security/limits.conf && \
@ -141,9 +149,7 @@ RUN echo "hard core 0" >> /etc/security/limits.conf && \
echo 'ulimit -S -c 0 > /dev/null 2>&1' >> /etc/profile echo 'ulimit -S -c 0 > /dev/null 2>&1' >> /etc/profile
COPY --from=builder /opt/venv /opt/venv COPY --from=builder /opt/venv /opt/venv
COPY ann/ann.py /usr/src/ann/ann.py COPY immich_ml immich_ml
COPY start.sh log_conf.json gunicorn_conf.py ./
COPY app .
ARG BUILD_ID ARG BUILD_ID
ARG BUILD_IMAGE ARG BUILD_IMAGE
@ -161,6 +167,6 @@ ENV IMMICH_SOURCE_COMMIT=${BUILD_SOURCE_COMMIT}
ENV IMMICH_SOURCE_URL=https://github.com/immich-app/immich/commit/${BUILD_SOURCE_COMMIT} ENV IMMICH_SOURCE_URL=https://github.com/immich-app/immich/commit/${BUILD_SOURCE_COMMIT}
ENTRYPOINT ["tini", "--"] ENTRYPOINT ["tini", "--"]
CMD ["./start.sh"] CMD ["python", "-m", "immich_ml"]
HEALTHCHECK CMD python3 healthcheck.py HEALTHCHECK CMD python3 healthcheck.py

View File

@ -8,9 +8,8 @@ from fastapi.testclient import TestClient
from numpy.typing import NDArray from numpy.typing import NDArray
from PIL import Image from PIL import Image
from app.config import log from immich_ml.config import log
from immich_ml.main import app
from .main import app
@pytest.fixture @pytest.fixture
@ -25,7 +24,7 @@ def cv_image(pil_image: Image.Image) -> NDArray[np.float32]:
@pytest.fixture @pytest.fixture
def mock_get_model() -> Iterator[mock.Mock]: def mock_get_model() -> Iterator[mock.Mock]:
with mock.patch("app.models.cache.from_model_type", autospec=True) as mocked: with mock.patch("immich_ml.models.cache.from_model_type", autospec=True) as mocked:
yield mocked yield mocked
@ -104,14 +103,14 @@ def providers(request: pytest.FixtureRequest) -> Iterator[mock.Mock]:
raise ValueError("Missing marker 'providers'") raise ValueError("Missing marker 'providers'")
providers = marker.args[0] providers = marker.args[0]
with mock.patch("app.sessions.ort.ort.get_available_providers") as mocked: with mock.patch("immich_ml.sessions.ort.ort.get_available_providers") as mocked:
mocked.return_value = providers mocked.return_value = providers
yield providers yield providers
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def ort_pybind() -> Iterator[mock.Mock]: def ort_pybind() -> Iterator[mock.Mock]:
with mock.patch("app.sessions.ort.ort.capi._pybind_state") as mocked: with mock.patch("immich_ml.sessions.ort.ort.capi._pybind_state") as mocked:
yield mocked yield mocked
@ -126,25 +125,25 @@ def ov_device_ids(request: pytest.FixtureRequest, ort_pybind: mock.Mock) -> Iter
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def ort_session() -> Iterator[mock.Mock]: def ort_session() -> Iterator[mock.Mock]:
with mock.patch("app.sessions.ort.ort.InferenceSession") as mocked: with mock.patch("immich_ml.sessions.ort.ort.InferenceSession") as mocked:
yield mocked yield mocked
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def ann_session() -> Iterator[mock.Mock]: def ann_session() -> Iterator[mock.Mock]:
with mock.patch("app.sessions.ann.Ann") as mocked: with mock.patch("immich_ml.sessions.ann.Ann") as mocked:
yield mocked yield mocked
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def rknn_session() -> Iterator[mock.Mock]: def rknn_session() -> Iterator[mock.Mock]:
with mock.patch("app.sessions.rknn.RknnPoolExecutor") as mocked: with mock.patch("immich_ml.sessions.rknn.RknnPoolExecutor") as mocked:
yield mocked yield mocked
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def rmtree() -> Iterator[mock.Mock]: def rmtree() -> Iterator[mock.Mock]:
with mock.patch("app.models.base.rmtree", autospec=True) as mocked: with mock.patch("immich_ml.models.base.rmtree", autospec=True) as mocked:
mocked.avoids_symlink_attacks = True mocked.avoids_symlink_attacks = True
yield mocked yield mocked
@ -158,7 +157,7 @@ def path() -> Iterator[mock.Mock]:
path.with_suffix.return_value = path path.with_suffix.return_value = path
path.return_value = path path.return_value = path
with mock.patch("app.models.base.Path", return_value=path) as mocked: with mock.patch("immich_ml.models.base.Path", return_value=path) as mocked:
yield mocked yield mocked
@ -182,5 +181,5 @@ def exception() -> Iterator[mock.Mock]:
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def snapshot_download() -> Iterator[mock.Mock]: def snapshot_download() -> Iterator[mock.Mock]:
with mock.patch("app.models.base.snapshot_download") as mocked: with mock.patch("immich_ml.models.base.snapshot_download") as mocked:
yield mocked yield mocked

View File

@ -1 +0,0 @@
3.12

View File

@ -1,165 +0,0 @@
import json
import resource
from pathlib import Path
import typer
from tenacity import retry, stop_after_attempt, wait_fixed
from typing_extensions import Annotated
from .exporters.constants import DELETE_PATTERNS, SOURCE_TO_METADATA, ModelSource, ModelTask
from .exporters.onnx import export as onnx_export
from .exporters.rknn import export as rknn_export
app = typer.Typer(pretty_exceptions_show_locals=False)
def generate_readme(model_name: str, model_source: ModelSource) -> str:
(name, link, type) = SOURCE_TO_METADATA[model_source]
match model_source:
case ModelSource.MCLIP:
tags = ["immich", "clip", "multilingual"]
case ModelSource.OPENCLIP:
tags = ["immich", "clip"]
lowered = model_name.lower()
if "xlm" in lowered or "nllb" in lowered:
tags.append("multilingual")
case ModelSource.INSIGHTFACE:
tags = ["immich", "facial-recognition"]
case _:
raise ValueError(f"Unsupported model source {model_source}")
return f"""---
tags:
{" - " + "\n - ".join(tags)}
---
# Model Description
This repo contains ONNX exports for the associated {type} model by {name}. See the [{name}]({link}) repo for more info.
This repo is specifically intended for use with [Immich](https://immich.app/), a self-hosted photo library.
"""
def clean_name(model_name: str) -> str:
hf_model_name = model_name.split("/")[-1]
hf_model_name = hf_model_name.replace("xlm-roberta-large", "XLM-Roberta-Large")
hf_model_name = hf_model_name.replace("xlm-roberta-base", "XLM-Roberta-Base")
return hf_model_name
@app.command()
def export(model_name: str, model_source: ModelSource, output_dir: Path = Path("models"), cache: bool = True) -> None:
hf_model_name = clean_name(model_name)
output_dir = output_dir / hf_model_name
match model_source:
case ModelSource.MCLIP | ModelSource.OPENCLIP:
output_dir.mkdir(parents=True, exist_ok=True)
onnx_export(model_name, model_source, output_dir, cache=cache)
case ModelSource.INSIGHTFACE:
from huggingface_hub import snapshot_download
# TODO: start from insightface dump instead of downloading from HF
snapshot_download(f"immich-app/{hf_model_name}", local_dir=output_dir)
case _:
raise ValueError(f"Unsupported model source {model_source}")
try:
rknn_export(output_dir, cache=cache)
except Exception as e:
print(f"Failed to export model {model_name} to rknn: {e}")
(output_dir / "rknpu").unlink(missing_ok=True)
readme_path = output_dir / "README.md"
if not (cache or readme_path.exists()):
with open(readme_path, "w") as f:
f.write(generate_readme(model_name, model_source))
@app.command()
def profile(model_dir: Path, model_task: ModelTask, output_path: Path) -> None:
from timeit import timeit
import numpy as np
import onnxruntime as ort
np.random.seed(0)
sess_options = ort.SessionOptions()
sess_options.enable_cpu_mem_arena = False
providers = ["CPUExecutionProvider"]
provider_options = [{"arena_extend_strategy": "kSameAsRequested"}]
match model_task:
case ModelTask.SEARCH:
textual = ort.InferenceSession(
model_dir / "textual" / "model.onnx",
sess_options=sess_options,
providers=providers,
provider_options=provider_options,
)
tokens = {node.name: np.random.rand(*node.shape).astype(np.int32) for node in textual.get_inputs()}
visual = ort.InferenceSession(
model_dir / "visual" / "model.onnx",
sess_options=sess_options,
providers=providers,
provider_options=provider_options,
)
image = {node.name: np.random.rand(*node.shape).astype(np.float32) for node in visual.get_inputs()}
def predict() -> None:
textual.run(None, tokens)
visual.run(None, image)
case ModelTask.FACIAL_RECOGNITION:
detection = ort.InferenceSession(
model_dir / "detection" / "model.onnx",
sess_options=sess_options,
providers=providers,
provider_options=provider_options,
)
image = {node.name: np.random.rand(1, 3, 640, 640).astype(np.float32) for node in detection.get_inputs()}
recognition = ort.InferenceSession(
model_dir / "recognition" / "model.onnx",
sess_options=sess_options,
providers=providers,
provider_options=provider_options,
)
face = {node.name: np.random.rand(1, 3, 112, 112).astype(np.float32) for node in recognition.get_inputs()}
def predict() -> None:
detection.run(None, image)
recognition.run(None, face)
case _:
raise ValueError(f"Unsupported model task {model_task}")
predict()
ms = timeit(predict, number=100)
rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
json.dump({"pretrained_model": model_dir.name, "peak_rss": rss, "exec_time_ms": ms}, output_path.open("w"))
print(f"Model {model_dir.name} took {ms:.2f}ms per iteration using {rss / 1024:.2f}MiB of memory")
@app.command()
def upload(
model_dir: Path,
hf_organization: str = "immich-app",
hf_auth_token: Annotated[str | None, typer.Option(envvar="HF_AUTH_TOKEN")] = None,
) -> None:
from huggingface_hub import create_repo, upload_folder
repo_id = f"{hf_organization}/{model_dir.name}"
@retry(stop=stop_after_attempt(5), wait=wait_fixed(5))
def upload_model() -> None:
create_repo(repo_id, exist_ok=True, token=hf_auth_token)
upload_folder(
repo_id=repo_id,
folder_path=model_dir,
# remote repo files to be deleted before uploading
# deletion is in the same commit as the upload, so it's atomic
delete_patterns=DELETE_PATTERNS,
token=hf_auth_token,
)
upload_model()

View File

@ -1,3 +0,0 @@
from immich_model_exporter import app
app()

View File

@ -1,54 +0,0 @@
from enum import StrEnum
from typing import NamedTuple
class ModelSource(StrEnum):
INSIGHTFACE = "insightface"
MCLIP = "mclip"
OPENCLIP = "openclip"
class ModelTask(StrEnum):
FACIAL_RECOGNITION = "facial-recognition"
SEARCH = "clip"
class SourceMetadata(NamedTuple):
name: str
link: str
type: str
SOURCE_TO_METADATA = {
ModelSource.MCLIP: SourceMetadata("M-CLIP", "https://huggingface.co/M-CLIP", "CLIP"),
ModelSource.OPENCLIP: SourceMetadata("OpenCLIP", "https://github.com/mlfoundations/open_clip", "CLIP"),
ModelSource.INSIGHTFACE: SourceMetadata(
"InsightFace", "https://github.com/deepinsight/insightface/tree/master", "facial recognition"
),
}
SOURCE_TO_TASK = {
ModelSource.MCLIP: ModelTask.SEARCH,
ModelSource.OPENCLIP: ModelTask.SEARCH,
ModelSource.INSIGHTFACE: ModelTask.FACIAL_RECOGNITION,
}
RKNN_SOCS = ["rk3566", "rk3568", "rk3576", "rk3588"]
# glob to delete old UUID blobs when reuploading models
_uuid_char = "[a-fA-F0-9]"
_uuid_glob = _uuid_char * 8 + "-" + _uuid_char * 4 + "-" + _uuid_char * 4 + "-" + _uuid_char * 4 + "-" + _uuid_char * 12
DELETE_PATTERNS = [
"**/*onnx*",
"**/Constant*",
"**/*.weight",
"**/*.bias",
"**/*.proj",
"**/*in_proj_bias",
"**/*.npy",
"**/*.latent",
"**/*.pos_embed",
f"**/{_uuid_glob}",
]

View File

@ -1,20 +0,0 @@
from pathlib import Path
from ..constants import ModelSource
from .models import mclip, openclip
def export(
model_name: str, model_source: ModelSource, output_dir: Path, opset_version: int = 19, cache: bool = True
) -> None:
visual_dir = output_dir / "visual"
textual_dir = output_dir / "textual"
match model_source:
case ModelSource.MCLIP:
mclip.to_onnx(model_name, opset_version, visual_dir, textual_dir, cache=cache)
case ModelSource.OPENCLIP:
name, _, pretrained = model_name.partition("__")
config = openclip.OpenCLIPModelConfig(name, pretrained)
openclip.to_onnx(config, opset_version, visual_dir, textual_dir, cache=cache)
case _:
raise ValueError(f"Unsupported model source {model_source}")

View File

@ -1,77 +0,0 @@
import warnings
from pathlib import Path
from typing import Any
from .openclip import OpenCLIPModelConfig
from .openclip import to_onnx as openclip_to_onnx
from .util import get_model_path
_MCLIP_TO_OPENCLIP = {
"M-CLIP/XLM-Roberta-Large-Vit-B-32": OpenCLIPModelConfig("ViT-B-32", "openai"),
"M-CLIP/XLM-Roberta-Large-Vit-B-16Plus": OpenCLIPModelConfig("ViT-B-16-plus-240", "laion400m_e32"),
"M-CLIP/LABSE-Vit-L-14": OpenCLIPModelConfig("ViT-L-14", "openai"),
"M-CLIP/XLM-Roberta-Large-Vit-L-14": OpenCLIPModelConfig("ViT-L-14", "openai"),
}
def to_onnx(
model_name: str,
opset_version: int,
output_dir_visual: Path | str,
output_dir_textual: Path | str,
cache: bool = True,
) -> tuple[Path, Path]:
textual_path = get_model_path(output_dir_textual)
if not cache or not textual_path.exists():
import torch
from multilingual_clip.pt_multilingual_clip import MultilingualCLIP
from transformers import AutoTokenizer
torch.backends.mha.set_fastpath_enabled(False)
model = MultilingualCLIP.from_pretrained(model_name)
AutoTokenizer.from_pretrained(model_name).save_pretrained(output_dir_textual)
model.eval()
for param in model.parameters():
param.requires_grad_(False)
_export_text_encoder(model, textual_path, opset_version)
else:
print(f"Model {textual_path} already exists, skipping")
visual_path, _ = openclip_to_onnx(_MCLIP_TO_OPENCLIP[model_name], opset_version, output_dir_visual, cache=cache)
assert visual_path is not None, "Visual model export failed"
return visual_path, textual_path
def _export_text_encoder(model: Any, output_path: Path | str, opset_version: int) -> None:
import torch
from multilingual_clip.pt_multilingual_clip import MultilingualCLIP
output_path = Path(output_path)
def forward(self: MultilingualCLIP, input_ids: torch.Tensor, attention_mask: torch.Tensor) -> torch.Tensor:
embs = self.transformer(input_ids, attention_mask)[0]
embs = (embs * attention_mask.unsqueeze(2)).sum(dim=1) / attention_mask.sum(dim=1)[:, None]
embs = self.LinearTransformation(embs)
return torch.nn.functional.normalize(embs, dim=-1)
# unfortunately need to monkeypatch for tracing to work here
# otherwise it hits the 2GiB protobuf serialization limit
MultilingualCLIP.forward = forward
args = (torch.ones(1, 77, dtype=torch.int32), torch.ones(1, 77, dtype=torch.int32))
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)
torch.onnx.export(
model,
args,
output_path.as_posix(),
input_names=["input_ids", "attention_mask"],
output_names=["embedding"],
opset_version=opset_version,
# dynamic_axes={
# "input_ids": {0: "batch_size", 1: "sequence_length"},
# "attention_mask": {0: "batch_size", 1: "sequence_length"},
# },
)

View File

@ -1,151 +0,0 @@
import warnings
from dataclasses import dataclass
from functools import cached_property
from pathlib import Path
from typing import Any
from .util import get_model_path, save_config
@dataclass
class OpenCLIPModelConfig:
name: str
pretrained: str
@cached_property
def model_config(self) -> dict[str, Any]:
import open_clip
config: dict[str, Any] | None = open_clip.get_model_config(self.name)
if config is None:
raise ValueError(f"Unknown model {self.name}")
return config
@property
def image_size(self) -> int:
image_size: int = self.model_config["vision_cfg"]["image_size"]
return image_size
@property
def sequence_length(self) -> int:
context_length: int = self.model_config["text_cfg"].get("context_length", 77)
return context_length
def to_onnx(
model_cfg: OpenCLIPModelConfig,
opset_version: int,
output_dir_visual: Path | str | None = None,
output_dir_textual: Path | str | None = None,
cache: bool = True,
) -> tuple[Path | None, Path | None]:
visual_path = None
textual_path = None
if output_dir_visual is not None:
output_dir_visual = Path(output_dir_visual)
visual_path = get_model_path(output_dir_visual)
if output_dir_textual is not None:
output_dir_textual = Path(output_dir_textual)
textual_path = get_model_path(output_dir_textual)
if cache and ((textual_path is None or textual_path.exists()) and (visual_path is None or visual_path.exists())):
print(f"Models {textual_path} and {visual_path} already exist, skipping")
return visual_path, textual_path
import open_clip
import torch
from transformers import AutoTokenizer
torch.backends.mha.set_fastpath_enabled(False)
model = open_clip.create_model(
model_cfg.name,
pretrained=model_cfg.pretrained,
jit=False,
require_pretrained=True,
)
text_vision_cfg = open_clip.get_model_config(model_cfg.name)
model.eval()
for param in model.parameters():
param.requires_grad_(False)
if visual_path is not None and output_dir_visual is not None:
if not cache or not visual_path.exists():
save_config(
open_clip.get_model_preprocess_cfg(model),
output_dir_visual / "preprocess_cfg.json",
)
save_config(text_vision_cfg, output_dir_visual.parent / "config.json")
_export_image_encoder(model, model_cfg, visual_path, opset_version)
else:
print(f"Model {visual_path} already exists, skipping")
if textual_path is not None and output_dir_textual is not None:
if not cache or not textual_path.exists():
tokenizer_name = text_vision_cfg["text_cfg"].get("hf_tokenizer_name", "openai/clip-vit-base-patch32")
AutoTokenizer.from_pretrained(tokenizer_name).save_pretrained(output_dir_textual)
_export_text_encoder(model, model_cfg, textual_path, opset_version)
else:
print(f"Model {textual_path} already exists, skipping")
return visual_path, textual_path
def _export_image_encoder(
model: Any, model_cfg: OpenCLIPModelConfig, output_path: Path | str, opset_version: int
) -> None:
import torch
output_path = Path(output_path)
def encode_image(image: torch.Tensor) -> torch.Tensor:
output = model.encode_image(image, normalize=True)
assert isinstance(output, torch.Tensor)
return output
model.forward = encode_image
args = (torch.randn(1, 3, model_cfg.image_size, model_cfg.image_size),)
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)
torch.onnx.export(
model,
args,
output_path.as_posix(),
input_names=["image"],
output_names=["embedding"],
opset_version=opset_version,
# dynamic_axes={"image": {0: "batch_size"}},
)
def _export_text_encoder(
model: Any, model_cfg: OpenCLIPModelConfig, output_path: Path | str, opset_version: int
) -> None:
import torch
output_path = Path(output_path)
def encode_text(text: torch.Tensor) -> torch.Tensor:
output = model.encode_text(text, normalize=True)
assert isinstance(output, torch.Tensor)
return output
model.forward = encode_text
args = (torch.ones(1, model_cfg.sequence_length, dtype=torch.int32),)
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)
torch.onnx.export(
model,
args,
output_path.as_posix(),
input_names=["text"],
output_names=["embedding"],
opset_version=opset_version,
# dynamic_axes={"text": {0: "batch_size"}},
)

View File

@ -1,15 +0,0 @@
import json
from pathlib import Path
from typing import Any
def get_model_path(output_dir: Path | str) -> Path:
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
return output_dir / "model.onnx"
def save_config(config: Any, output_path: Path | str) -> None:
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
json.dump(config, output_path.open("w"))

View File

@ -1,96 +0,0 @@
from pathlib import Path
from .constants import RKNN_SOCS
def _export_platform(
model_dir: Path,
target_platform: str,
inputs: list[str] | None = None,
input_size_list: list[list[int]] | None = None,
fuse_matmul_softmax_matmul_to_sdpa: bool = True,
cache: bool = True,
) -> None:
from rknn.api import RKNN
input_path = model_dir / "model.onnx"
output_path = model_dir / "rknpu" / target_platform / "model.rknn"
if cache and output_path.exists():
print(f"Model {input_path} already exists at {output_path}, skipping")
return
print(f"Exporting model {input_path} to {output_path}")
rknn = RKNN(verbose=False)
rknn.config(
target_platform=target_platform,
disable_rules=["fuse_matmul_softmax_matmul_to_sdpa"] if not fuse_matmul_softmax_matmul_to_sdpa else [],
enable_flash_attention=False,
model_pruning=True,
)
ret = rknn.load_onnx(model=input_path.as_posix(), inputs=inputs, input_size_list=input_size_list)
if ret != 0:
raise RuntimeError("Load failed!")
ret = rknn.build(do_quantization=False)
if ret != 0:
raise RuntimeError("Build failed!")
output_path.parent.mkdir(parents=True, exist_ok=True)
ret = rknn.export_rknn(output_path.as_posix())
if ret != 0:
raise RuntimeError("Export rknn model failed!")
def _export_platforms(
model_dir: Path,
inputs: list[str] | None = None,
input_size_list: list[list[int]] | None = None,
cache: bool = True,
) -> None:
fuse_matmul_softmax_matmul_to_sdpa = True
for soc in RKNN_SOCS:
try:
_export_platform(
model_dir,
soc,
inputs=inputs,
input_size_list=input_size_list,
fuse_matmul_softmax_matmul_to_sdpa=fuse_matmul_softmax_matmul_to_sdpa,
cache=cache,
)
except Exception as e:
print(f"Failed to export model for {soc}: {e}")
if "inputs or 'outputs' must be set" in str(e):
print("Retrying without fuse_matmul_softmax_matmul_to_sdpa")
fuse_matmul_softmax_matmul_to_sdpa = False
_export_platform(
model_dir,
soc,
inputs=inputs,
input_size_list=input_size_list,
fuse_matmul_softmax_matmul_to_sdpa=fuse_matmul_softmax_matmul_to_sdpa,
cache=cache,
)
def export(model_dir: Path, cache: bool = True) -> None:
textual = model_dir / "textual"
visual = model_dir / "visual"
detection = model_dir / "detection"
recognition = model_dir / "recognition"
if textual.is_dir():
_export_platforms(textual, cache=cache)
if visual.is_dir():
_export_platforms(visual, cache=cache)
if detection.is_dir():
_export_platforms(detection, inputs=["input.1"], input_size_list=[[1, 3, 640, 640]], cache=cache)
if recognition.is_dir():
_export_platforms(recognition, inputs=["input.1"], input_size_list=[[1, 3, 112, 112]], cache=cache)

View File

@ -1,22 +0,0 @@
import json
from pathlib import Path
models_dir = Path("models")
model_to_embed_dim = {}
for model_dir in models_dir.iterdir():
if not model_dir.is_dir():
continue
config_path = model_dir / "config.json"
if not config_path.exists():
print(f"Skipping {model_dir.name} as it does not have a config.json")
continue
with open(config_path) as f:
config = json.load(f)
embed_dim = config.get("embed_dim")
if embed_dim is None:
print(f"Skipping {model_dir.name} as it does not have an embed_dim")
continue
print(f"{model_dir.name}: {embed_dim}")
model_to_embed_dim[model_dir.name] = {"dimSize": embed_dim}
print(json.dumps(model_to_embed_dim))

View File

@ -1,121 +0,0 @@
import polars as pl
def collapsed_table(language: str, df: pl.DataFrame) -> str:
with pl.Config(
tbl_formatting="ASCII_MARKDOWN",
tbl_hide_column_data_types=True,
tbl_hide_dataframe_shape=True,
fmt_str_lengths=100,
tbl_rows=1000,
tbl_width_chars=1000,
):
return f"<details>\n<summary>{language}</summary>\n{str(df)}\n</details>"
languages = {
"en": "English",
"ar": "Arabic",
"bn": "Bengali",
"zh": "Chinese (Simplified)",
"hr": "Croatian",
"quz": "Cusco Quechua",
"cs": "Czech",
"da": "Danish",
"nl": "Dutch",
"fil": "Filipino",
"fi": "Finnish",
"fr": "French",
"de": "German",
"el": "Greek",
"he": "Hebrew",
"hi": "Hindi",
"hu": "Hungarian",
"id": "Indonesian",
"it": "Italian",
"ja": "Japanese",
"ko": "Korean",
"mi": "Maori",
"no": "Norwegian",
"fa": "Persian",
"pl": "Polish",
"pt": "Portuguese",
"ro": "Romanian",
"ru": "Russian",
"es": "Spanish",
"sw": "Swahili",
"sv": "Swedish",
"te": "Telugu",
"th": "Thai",
"tr": "Turkish",
"uk": "Ukrainian",
"vi": "Vietnamese",
}
profile_df = pl.scan_ndjson("profiling/*.json").select("pretrained_model", "peak_rss", "exec_time_ms")
eval_df = pl.scan_ndjson("results/*.json").select("model", "pretrained", "language", "metrics")
eval_df = eval_df.with_columns(
model=pl.col("model")
.str.replace("xlm-roberta-base", "XLM-Roberta-Base")
.str.replace("xlm-roberta-large", "XLM-Roberta-Large")
)
eval_df = eval_df.with_columns(pretrained_model=pl.concat_str(pl.col("model"), pl.col("pretrained"), separator="__"))
eval_df = eval_df.drop("model", "pretrained")
eval_df = eval_df.join(profile_df, on="pretrained_model")
eval_df = eval_df.with_columns(
recall=(
pl.col("metrics").struct.field("image_retrieval_recall@1")
+ pl.col("metrics").struct.field("image_retrieval_recall@5")
+ pl.col("metrics").struct.field("image_retrieval_recall@10")
)
* (100 / 3)
)
pareto_front = eval_df.join_where(
eval_df.select("language", "peak_rss", "exec_time_ms", "recall").rename(
{
"language": "language_other",
"peak_rss": "peak_rss_other",
"exec_time_ms": "exec_time_ms_other",
"recall": "recall_other",
}
),
(pl.col("language") == pl.col("language_other"))
& (pl.col("peak_rss_other") <= pl.col("peak_rss"))
& (pl.col("exec_time_ms_other") <= pl.col("exec_time_ms"))
& (pl.col("recall_other") >= pl.col("recall"))
& (
(pl.col("peak_rss_other") < pl.col("peak_rss"))
| (pl.col("exec_time_ms_other") < pl.col("exec_time_ms"))
| (pl.col("recall_other") > pl.col("recall"))
),
)
eval_df = eval_df.join(pareto_front, on=["pretrained_model", "language"], how="left")
eval_df = eval_df.with_columns(is_pareto=pl.col("recall_other").is_null())
eval_df = (
eval_df.drop("peak_rss_other", "exec_time_ms_other", "recall_other", "language_other")
.unique(subset=["pretrained_model", "language"])
.collect()
)
eval_df.write_parquet("model_info.parquet")
eval_df = eval_df.drop("metrics")
eval_df = eval_df.filter(pl.col("recall") >= 20)
eval_df = eval_df.sort("recall", descending=True)
eval_df = eval_df.select(
pl.col("pretrained_model").alias("Model"),
(pl.col("peak_rss") / 1024).round().cast(pl.UInt32).alias("Memory (MiB)"),
pl.col("exec_time_ms").round(2).alias("Execution Time (ms)"),
pl.col("language").alias("Language"),
pl.col("recall").round(2).alias("Recall (%)"),
pl.when(pl.col("is_pareto")).then(pl.lit("")).otherwise(pl.lit("")).alias("Pareto Optimal"),
)
for language in languages:
lang_df = eval_df.filter(pl.col("Language") == language).drop("Language")
if lang_df.shape[0] == 0:
continue
print(collapsed_table(languages[language], lang_df))

View File

@ -1,171 +0,0 @@
import subprocess
from pathlib import Path
from exporters.constants import ModelSource
from immich_model_exporter import clean_name
from immich_model_exporter.exporters.constants import SOURCE_TO_TASK
mclip = [
"M-CLIP/LABSE-Vit-L-14",
"M-CLIP/XLM-Roberta-Large-Vit-B-16Plus",
"M-CLIP/XLM-Roberta-Large-Vit-B-32",
"M-CLIP/XLM-Roberta-Large-Vit-L-14",
]
openclip = [
"RN101__openai",
"RN101__yfcc15m",
"RN50__cc12m",
"RN50__openai",
"RN50__yfcc15m",
"RN50x16__openai",
"RN50x4__openai",
"RN50x64__openai",
"ViT-B-16-SigLIP-256__webli",
"ViT-B-16-SigLIP-384__webli",
"ViT-B-16-SigLIP-512__webli",
"ViT-B-16-SigLIP-i18n-256__webli",
"ViT-B-16-SigLIP2__webli",
"ViT-B-16-SigLIP__webli",
"ViT-B-16-plus-240__laion400m_e31",
"ViT-B-16-plus-240__laion400m_e32",
"ViT-B-16__laion400m_e31",
"ViT-B-16__laion400m_e32",
"ViT-B-16__openai",
"ViT-B-32-SigLIP2-256__webli",
"ViT-B-32__laion2b-s34b-b79k",
"ViT-B-32__laion2b_e16",
"ViT-B-32__laion400m_e31",
"ViT-B-32__laion400m_e32",
"ViT-B-32__openai",
"ViT-H-14-378-quickgelu__dfn5b",
"ViT-H-14-quickgelu__dfn5b",
"ViT-H-14__laion2b-s32b-b79k",
"ViT-L-14-336__openai",
"ViT-L-14-quickgelu__dfn2b",
"ViT-L-14__laion2b-s32b-b82k",
"ViT-L-14__laion400m_e31",
"ViT-L-14__laion400m_e32",
"ViT-L-14__openai",
"ViT-L-16-SigLIP-256__webli",
"ViT-L-16-SigLIP-384__webli",
"ViT-L-16-SigLIP2-256__webli",
"ViT-L-16-SigLIP2-384__webli",
"ViT-L-16-SigLIP2-512__webli",
"ViT-SO400M-14-SigLIP-384__webli",
"ViT-SO400M-14-SigLIP2-378__webli",
"ViT-SO400M-14-SigLIP2__webli",
"ViT-SO400M-16-SigLIP2-256__webli",
"ViT-SO400M-16-SigLIP2-384__webli",
"ViT-SO400M-16-SigLIP2-512__webli",
"ViT-gopt-16-SigLIP2-256__webli",
"ViT-gopt-16-SigLIP2-384__webli",
"nllb-clip-base-siglip__mrl",
"nllb-clip-base-siglip__v1",
"nllb-clip-large-siglip__mrl",
"nllb-clip-large-siglip__v1",
"xlm-roberta-base-ViT-B-32__laion5b_s13b_b90k",
"xlm-roberta-large-ViT-H-14__frozen_laion5b_s13b_b90k",
]
insightface = [
"antelopev2",
"buffalo_l",
"buffalo_m",
"buffalo_s",
]
def export_models(models: list[str], source: ModelSource) -> None:
profiling_dir = Path("profiling")
profiling_dir.mkdir(exist_ok=True)
for model in models:
try:
model_dir = f"models/{clean_name(model)}"
task = SOURCE_TO_TASK[source]
print(f"Processing model {model}")
subprocess.check_call(["python", "-m", "immich_model_exporter", "export", model, source])
subprocess.check_call(
[
"python",
"-m",
"immich_model_exporter",
"profile",
model_dir,
task,
"--output_path",
profiling_dir / f"{model}.json",
]
)
subprocess.check_call(["python", "-m", "immich_model_exporter", "upload", model_dir])
except Exception as e:
print(f"Failed to export model {model}: {e}")
if __name__ == "__main__":
export_models(mclip, ModelSource.MCLIP)
export_models(openclip, ModelSource.OPENCLIP)
export_models(insightface, ModelSource.INSIGHTFACE)
Path("results").mkdir(exist_ok=True)
subprocess.check_call(
[
"python",
"clip_benchmark",
"eval",
"--pretrained_model",
*[name.replace("__", ",") for name in openclip],
"--task",
"zeroshot_retrieval",
"--dataset",
"crossmodal3600",
"--batch_size",
"64",
"--language",
"ar",
"bn",
"cs",
"da",
"de",
"el",
"en",
"es",
"fa",
"fi",
"fil",
"fr",
"he",
"hi",
"hr",
"hu",
"id",
"it",
"ja",
"ko",
"mi",
"nl",
"no",
"pl",
"pt",
"quz",
"ro",
"ru",
"sv",
"sw",
"te",
"th",
"tr",
"uk",
"vi",
"zh",
"--recall_k",
"1",
"5",
"10",
"--no_amp",
"--output",
"results/{dataset}_{language}_{model}_{pretrained}.json",
]
)

View File

@ -1,60 +0,0 @@
[project]
name = "immich_model_exporter"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10, <4.0"
dependencies = [
"huggingface-hub>=0.29.3",
"multilingual-clip>=1.0.10",
"onnx>=1.14.1",
"onnxruntime>=1.16.0",
"open-clip-torch>=2.31.0",
"typer>=0.15.2",
"rknn-toolkit2>=2.3.0",
"transformers>=4.49.0",
"tenacity>=9.0.0",
"clip-benchmark>=1.6.1",
"polars>=1.25.2",
]
[dependency-groups]
dev = ["black>=23.3.0", "mypy>=1.3.0", "ruff>=0.0.272"]
[tool.uv]
override-dependencies = [
"onnx>=1.16.0,<2",
"onnxruntime>=1.18.2,<2",
"torch>=2.4",
"torchvision>=0.21",
]
[tool.hatch.build.targets.sdist]
include = ["immich_model_exporter"]
[tool.hatch.build.targets.wheel]
include = ["immich_model_exporter"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.mypy]
python_version = "3.12"
follow_imports = "silent"
warn_redundant_casts = true
disallow_any_generics = true
check_untyped_defs = true
disallow_untyped_defs = true
ignore_missing_imports = true
[tool.ruff]
line-length = 120
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I"]
[tool.black]
line-length = 120
target-version = ['py312']

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
import os
import signal
import subprocess
from pathlib import Path
from .config import log, non_prefixed_settings, settings
if source_ref := os.getenv("IMMICH_SOURCE_REF"):
log.info(f"Initializing Immich ML [{source_ref}]")
else:
log.info("Initializing Immich ML")
module_dir = Path(__file__).parent
try:
with subprocess.Popen(
[
"python",
"-m",
"gunicorn",
"immich_ml.main:app",
"-k",
"immich_ml.config.CustomUvicornWorker",
"-c",
module_dir / "gunicorn_conf.py",
"-b",
f"{non_prefixed_settings.immich_host}:{non_prefixed_settings.immich_port}",
"-w",
str(settings.workers),
"-t",
str(settings.worker_timeout),
"--log-config-json",
module_dir / "log_conf.json",
"--keep-alive",
str(settings.http_keepalive_timeout_s),
"--graceful-timeout",
"10",
],
) as cmd:
cmd.wait()
except KeyboardInterrupt:
cmd.send_signal(signal.SIGINT)
exit(cmd.returncode)

View File

@ -51,12 +51,12 @@ class Settings(BaseSettings):
protected_namespaces=("settings_",), protected_namespaces=("settings_",),
) )
cache_folder: Path = Path("/cache") cache_folder: Path = (Path.home() / ".cache" / "immich_ml").resolve()
model_ttl: int = 300 model_ttl: int = 300
model_ttl_poll_s: int = 10 model_ttl_poll_s: int = 10
host: str = "0.0.0.0"
port: int = 3003
workers: int = 1 workers: int = 1
worker_timeout: int = 300
http_keepalive_timeout_s: int = 2
test_full: bool = False test_full: bool = False
request_threads: int = os.cpu_count() or 4 request_threads: int = os.cpu_count() or 4
model_inter_op_threads: int = 0 model_inter_op_threads: int = 0
@ -74,9 +74,11 @@ class Settings(BaseSettings):
return os.environ.get("MACHINE_LEARNING_DEVICE_ID", "0") return os.environ.get("MACHINE_LEARNING_DEVICE_ID", "0")
class LogSettings(BaseSettings): class NonPrefixedSettings(BaseSettings):
model_config = SettingsConfigDict(case_sensitive=False) model_config = SettingsConfigDict(case_sensitive=False)
immich_host: str = "[::]"
immich_port: int = 3003
immich_log_level: str = "info" immich_log_level: str = "info"
no_color: bool = False no_color: bool = False
@ -100,14 +102,14 @@ LOG_LEVELS: dict[str, int] = {
} }
settings = Settings() settings = Settings()
log_settings = LogSettings() non_prefixed_settings = NonPrefixedSettings()
LOG_LEVEL = LOG_LEVELS.get(log_settings.immich_log_level.lower(), logging.INFO) LOG_LEVEL = LOG_LEVELS.get(non_prefixed_settings.immich_log_level.lower(), logging.INFO)
class CustomRichHandler(RichHandler): class CustomRichHandler(RichHandler):
def __init__(self) -> None: def __init__(self) -> None:
console = Console(color_system="standard", no_color=log_settings.no_color) console = Console(color_system="standard", no_color=non_prefixed_settings.no_color)
self.excluded = ["uvicorn", "starlette", "fastapi"] self.excluded = ["uvicorn", "starlette", "fastapi"]
super().__init__( super().__init__(
show_path=False, show_path=False,

View File

@ -0,0 +1,21 @@
{
"version": 1,
"disable_existing_loggers": false,
"handlers": {
"console": {
"class": "immich_ml.config.CustomRichHandler"
}
},
"loggers": {
"gunicorn.error": {
"handlers": [
"console"
]
}
},
"root": {
"handlers": [
"console"
]
}
}

View File

@ -18,9 +18,9 @@ from PIL.Image import Image
from pydantic import ValidationError from pydantic import ValidationError
from starlette.formparsers import MultiPartParser from starlette.formparsers import MultiPartParser
from app.models import get_model_deps from immich_ml.models import get_model_deps
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from app.models.transforms import decode_pil from immich_ml.models.transforms import decode_pil
from .config import PreloadModelData, log, settings from .config import PreloadModelData, log, settings
from .models.cache import ModelCache from .models.cache import ModelCache

View File

@ -1,9 +1,9 @@
from typing import Any from typing import Any
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from app.models.clip.textual import MClipTextualEncoder, OpenClipTextualEncoder from immich_ml.models.clip.textual import MClipTextualEncoder, OpenClipTextualEncoder
from app.models.clip.visual import OpenClipVisualEncoder from immich_ml.models.clip.visual import OpenClipVisualEncoder
from app.schemas import ModelSource, ModelTask, ModelType from immich_ml.schemas import ModelSource, ModelTask, ModelType
from .constants import get_model_source from .constants import get_model_source
from .facial_recognition.detection import FaceDetector from .facial_recognition.detection import FaceDetector

View File

@ -7,9 +7,9 @@ from typing import Any, ClassVar
from huggingface_hub import snapshot_download from huggingface_hub import snapshot_download
import ann.ann import immich_ml.sessions.ann.loader
import app.sessions.rknn as rknn import immich_ml.sessions.rknn as rknn
from app.sessions.ort import OrtSession from immich_ml.sessions.ort import OrtSession
from ..config import clean_name, log, settings from ..config import clean_name, log, settings
from ..schemas import ModelFormat, ModelIdentity, ModelSession, ModelTask, ModelType from ..schemas import ModelFormat, ModelIdentity, ModelSession, ModelTask, ModelType
@ -171,7 +171,7 @@ class InferenceModel(ABC):
def _model_format_default(self) -> ModelFormat: def _model_format_default(self) -> ModelFormat:
if rknn.is_available: if rknn.is_available:
return ModelFormat.RKNN return ModelFormat.RKNN
elif ann.ann.is_available and settings.ann: elif immich_ml.sessions.ann.loader.is_available and settings.ann:
return ModelFormat.ARMNN return ModelFormat.ARMNN
else: else:
return ModelFormat.ONNX return ModelFormat.ONNX

View File

@ -4,8 +4,8 @@ from aiocache.backends.memory import SimpleMemoryCache
from aiocache.lock import OptimisticLock from aiocache.lock import OptimisticLock
from aiocache.plugins import TimingPlugin from aiocache.plugins import TimingPlugin
from app.models import from_model_type from immich_ml.models import from_model_type
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from ..schemas import ModelTask, ModelType, has_profiling from ..schemas import ModelTask, ModelType, has_profiling

View File

@ -8,10 +8,10 @@ import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from tokenizers import Encoding, Tokenizer from tokenizers import Encoding, Tokenizer
from app.config import log from immich_ml.config import log
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from app.models.transforms import clean_text, serialize_np_array from immich_ml.models.transforms import clean_text, serialize_np_array
from app.schemas import ModelSession, ModelTask, ModelType from immich_ml.schemas import ModelSession, ModelTask, ModelType
class BaseCLIPTextualEncoder(InferenceModel): class BaseCLIPTextualEncoder(InferenceModel):

View File

@ -8,9 +8,9 @@ import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from PIL import Image from PIL import Image
from app.config import log from immich_ml.config import log
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from app.models.transforms import ( from immich_ml.models.transforms import (
crop_pil, crop_pil,
decode_pil, decode_pil,
get_pil_resampling, get_pil_resampling,
@ -19,7 +19,7 @@ from app.models.transforms import (
serialize_np_array, serialize_np_array,
to_numpy, to_numpy,
) )
from app.schemas import ModelSession, ModelTask, ModelType from immich_ml.schemas import ModelSession, ModelTask, ModelType
class BaseCLIPVisualEncoder(InferenceModel): class BaseCLIPVisualEncoder(InferenceModel):

View File

@ -1,5 +1,5 @@
from app.config import clean_name from immich_ml.config import clean_name
from app.schemas import ModelSource from immich_ml.schemas import ModelSource
_OPENCLIP_MODELS = { _OPENCLIP_MODELS = {
"RN101__openai", "RN101__openai",

View File

@ -4,9 +4,9 @@ import numpy as np
from insightface.model_zoo import RetinaFace from insightface.model_zoo import RetinaFace
from numpy.typing import NDArray from numpy.typing import NDArray
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from app.models.transforms import decode_cv2 from immich_ml.models.transforms import decode_cv2
from app.schemas import FaceDetectionOutput, ModelSession, ModelTask, ModelType from immich_ml.schemas import FaceDetectionOutput, ModelSession, ModelTask, ModelType
class FaceDetector(InferenceModel): class FaceDetector(InferenceModel):

View File

@ -10,10 +10,17 @@ from numpy.typing import NDArray
from onnx.tools.update_model_dims import update_inputs_outputs_dims from onnx.tools.update_model_dims import update_inputs_outputs_dims
from PIL import Image from PIL import Image
from app.config import log, settings from immich_ml.config import log, settings
from app.models.base import InferenceModel from immich_ml.models.base import InferenceModel
from app.models.transforms import decode_cv2, serialize_np_array from immich_ml.models.transforms import decode_cv2, serialize_np_array
from app.schemas import FaceDetectionOutput, FacialRecognitionOutput, ModelFormat, ModelSession, ModelTask, ModelType from immich_ml.schemas import (
FaceDetectionOutput,
FacialRecognitionOutput,
ModelFormat,
ModelSession,
ModelTask,
ModelType,
)
class FaceRecognizer(InferenceModel): class FaceRecognizer(InferenceModel):

View File

@ -6,10 +6,10 @@ from typing import Any, NamedTuple
import numpy as np import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from ann.ann import Ann from immich_ml.config import log, settings
from app.schemas import SessionNode from immich_ml.schemas import SessionNode
from ..config import log, settings from .loader import Ann
class AnnSession: class AnnSession:

View File

@ -7,7 +7,7 @@ from typing import Any, Protocol, TypeVar
import numpy as np import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from app.config import log from immich_ml.config import log
try: try:
CDLL("libmali.so") # fail if libmali.so is not mounted into container CDLL("libmali.so") # fail if libmali.so is not mounted into container

View File

@ -7,8 +7,8 @@ import numpy as np
import onnxruntime as ort import onnxruntime as ort
from numpy.typing import NDArray from numpy.typing import NDArray
from app.models.constants import SUPPORTED_PROVIDERS from immich_ml.models.constants import SUPPORTED_PROVIDERS
from app.schemas import SessionNode from immich_ml.schemas import SessionNode
from ..config import log, settings from ..config import log, settings

View File

@ -6,8 +6,8 @@ from typing import Any, NamedTuple
import numpy as np import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from app.config import log, settings from immich_ml.config import log, settings
from app.schemas import SessionNode from immich_ml.schemas import SessionNode
from .rknnpool import RknnPoolExecutor, is_available, soc_name from .rknnpool import RknnPoolExecutor, is_available, soc_name

View File

@ -10,8 +10,8 @@ from typing import Callable
import numpy as np import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
from app.config import log from immich_ml.config import log
from app.models.constants import RKNN_COREMASK_SUPPORTED_SOCS, RKNN_SUPPORTED_SOCS from immich_ml.models.constants import RKNN_COREMASK_SUPPORTED_SOCS, RKNN_SUPPORTED_SOCS
def get_soc(device_tree_path: Path | str) -> str | None: def get_soc(device_tree_path: Path | str) -> str | None:

View File

@ -1,15 +0,0 @@
{
"version": 1,
"disable_existing_loggers": false,
"handlers": {
"console": {
"class": "app.config.CustomRichHandler"
}
},
"loggers": {
"gunicorn.error": {
"handlers": ["console"]
}
},
"root": { "handlers": ["console"] }
}

View File

@ -1,5 +1,5 @@
[project] [project]
name = "machine-learning" name = "immich-ml"
version = "1.129.0" version = "1.129.0"
description = "" description = ""
authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }] authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }]
@ -66,10 +66,10 @@ explicit = true
onnxruntime-gpu = { index = "cuda12" } onnxruntime-gpu = { index = "cuda12" }
[tool.hatch.build.targets.sdist] [tool.hatch.build.targets.sdist]
include = ["app"] include = ["immich_ml"]
[tool.hatch.build.targets.wheel] [tool.hatch.build.targets.wheel]
include = ["app"] include = ["immich_ml"]
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]

View File

@ -1,31 +0,0 @@
#!/usr/bin/env sh
echo "Initializing Immich ML $IMMICH_SOURCE_REF"
if ! [ "$DEVICE" = "openvino" ]; then
: "${MACHINE_LEARNING_WORKER_TIMEOUT:=120}"
else
: "${MACHINE_LEARNING_WORKER_TIMEOUT:=300}"
fi
# mimalloc seems to increase memory usage dramatically with openvino, need to investigate
if ! [ "$DEVICE" = "openvino" ] && ! [ "$DEVICE" = "rocm" ]; then
lib_path="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2"
export LD_PRELOAD="$lib_path"
export LD_BIND_NOW=1
fi
: "${IMMICH_HOST:=[::]}"
: "${IMMICH_PORT:=3003}"
: "${MACHINE_LEARNING_WORKERS:=1}"
: "${MACHINE_LEARNING_HTTP_KEEPALIVE_TIMEOUT_S:=2}"
gunicorn app.main:app \
-k app.config.CustomUvicornWorker \
-c gunicorn_conf.py \
-b "$IMMICH_HOST":"$IMMICH_PORT" \
-w "$MACHINE_LEARNING_WORKERS" \
-t "$MACHINE_LEARNING_WORKER_TIMEOUT" \
--log-config-json log_conf.json \
--keep-alive "$MACHINE_LEARNING_HTTP_KEEPALIVE_TIMEOUT_S" \
--graceful-timeout 0

View File

@ -18,19 +18,18 @@ from PIL import Image
from pytest import MonkeyPatch from pytest import MonkeyPatch
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from app.main import load, preload_models from immich_ml.config import Settings, settings
from app.models.clip.textual import MClipTextualEncoder, OpenClipTextualEncoder from immich_ml.main import load, preload_models
from app.models.clip.visual import OpenClipVisualEncoder from immich_ml.models.base import InferenceModel
from app.models.facial_recognition.detection import FaceDetector from immich_ml.models.cache import ModelCache
from app.models.facial_recognition.recognition import FaceRecognizer from immich_ml.models.clip.textual import MClipTextualEncoder, OpenClipTextualEncoder
from app.sessions.ann import AnnSession from immich_ml.models.clip.visual import OpenClipVisualEncoder
from app.sessions.ort import OrtSession from immich_ml.models.facial_recognition.detection import FaceDetector
from app.sessions.rknn import RknnSession, run_inference from immich_ml.models.facial_recognition.recognition import FaceRecognizer
from immich_ml.schemas import ModelFormat, ModelTask, ModelType
from .config import Settings, settings from immich_ml.sessions.ann import AnnSession
from .models.base import InferenceModel from immich_ml.sessions.ort import OrtSession
from .models.cache import ModelCache from immich_ml.sessions.rknn import RknnSession, run_inference
from .schemas import ModelFormat, ModelTask, ModelType
class TestBase: class TestBase:
@ -47,7 +46,7 @@ class TestBase:
def test_sets_default_model_format(self, mocker: MockerFixture) -> None: def test_sets_default_model_format(self, mocker: MockerFixture) -> None:
mocker.patch.object(settings, "ann", True) mocker.patch.object(settings, "ann", True)
mocker.patch("ann.ann.is_available", False) mocker.patch("immich_ml.sessions.ann.loader.is_available", False)
encoder = OpenClipTextualEncoder("ViT-B-32__openai") encoder = OpenClipTextualEncoder("ViT-B-32__openai")
@ -55,7 +54,7 @@ class TestBase:
def test_sets_default_model_format_to_armnn_if_available(self, path: mock.Mock, mocker: MockerFixture) -> None: def test_sets_default_model_format_to_armnn_if_available(self, path: mock.Mock, mocker: MockerFixture) -> None:
mocker.patch.object(settings, "ann", True) mocker.patch.object(settings, "ann", True)
mocker.patch("ann.ann.is_available", True) mocker.patch("immich_ml.sessions.ann.loader.is_available", True)
path.suffix = ".armnn" path.suffix = ".armnn"
encoder = OpenClipTextualEncoder("ViT-B-32__openai", cache_dir=path) encoder = OpenClipTextualEncoder("ViT-B-32__openai", cache_dir=path)
@ -64,7 +63,7 @@ class TestBase:
def test_sets_model_format_kwarg(self, mocker: MockerFixture) -> None: def test_sets_model_format_kwarg(self, mocker: MockerFixture) -> None:
mocker.patch.object(settings, "ann", False) mocker.patch.object(settings, "ann", False)
mocker.patch("ann.ann.is_available", False) mocker.patch("immich_ml.sessions.ann.loader.is_available", False)
encoder = OpenClipTextualEncoder("ViT-B-32__openai", model_format=ModelFormat.ARMNN) encoder = OpenClipTextualEncoder("ViT-B-32__openai", model_format=ModelFormat.ARMNN)
@ -72,7 +71,7 @@ class TestBase:
def test_sets_default_model_format_to_rknn_if_available(self, mocker: MockerFixture) -> None: def test_sets_default_model_format_to_rknn_if_available(self, mocker: MockerFixture) -> None:
mocker.patch.object(settings, "rknn", True) mocker.patch.object(settings, "rknn", True)
mocker.patch("app.sessions.rknn.is_available", True) mocker.patch("immich_ml.sessions.rknn.is_available", True)
encoder = OpenClipTextualEncoder("ViT-B-32__openai") encoder = OpenClipTextualEncoder("ViT-B-32__openai")
@ -294,7 +293,7 @@ class TestOrtSession:
assert session.sess_options.intra_op_num_threads == 0 assert session.sess_options.intra_op_num_threads == 0
def test_sets_default_sess_options_sets_threads_if_non_cpu_and_set_threads(self, mocker: MockerFixture) -> None: def test_sets_default_sess_options_sets_threads_if_non_cpu_and_set_threads(self, mocker: MockerFixture) -> None:
mock_settings = mocker.patch("app.sessions.ort.settings", autospec=True) mock_settings = mocker.patch("immich_ml.sessions.ort.settings", autospec=True)
mock_settings.model_inter_op_threads = 2 mock_settings.model_inter_op_threads = 2
mock_settings.model_intra_op_threads = 4 mock_settings.model_intra_op_threads = 4
@ -373,8 +372,8 @@ class TestRknnSession:
def test_creates_rknn_session(self, rknn_session: mock.Mock, info: mock.Mock, mocker: MockerFixture) -> None: def test_creates_rknn_session(self, rknn_session: mock.Mock, info: mock.Mock, mocker: MockerFixture) -> None:
model_path = mock.MagicMock(spec=Path) model_path = mock.MagicMock(spec=Path)
tpe = 1 tpe = 1
mocker.patch("app.sessions.rknn.soc_name", "rk3566") mocker.patch("immich_ml.sessions.rknn.soc_name", "rk3566")
mocker.patch("app.sessions.rknn.is_available", True) mocker.patch("immich_ml.sessions.rknn.is_available", True)
RknnSession(model_path) RknnSession(model_path)
rknn_session.assert_called_once_with(model_path=model_path.as_posix(), tpes=tpe, func=run_inference) rknn_session.assert_called_once_with(model_path=model_path.as_posix(), tpes=tpe, func=run_inference)
@ -384,7 +383,7 @@ class TestRknnSession:
def test_run_rknn(self, rknn_session: mock.Mock, mocker: MockerFixture) -> None: def test_run_rknn(self, rknn_session: mock.Mock, mocker: MockerFixture) -> None:
rknn_session.return_value.load.return_value = 123 rknn_session.return_value.load.return_value = 123
np_spy = mocker.spy(np, "ascontiguousarray") np_spy = mocker.spy(np, "ascontiguousarray")
mocker.patch("app.sessions.rknn.soc_name", "rk3566") mocker.patch("immich_ml.sessions.rknn.soc_name", "rk3566")
session = RknnSession(Path("ViT-B-32__openai")) session = RknnSession(Path("ViT-B-32__openai"))
[input1, input2] = [np.random.rand(1, 3, 224, 224).astype(np.float32) for _ in range(2)] [input1, input2] = [np.random.rand(1, 3, 224, 224).astype(np.float32) for _ in range(2)]
input_feed = {"input.1": input1, "input.2": input2} input_feed = {"input.1": input1, "input.2": input2}
@ -434,7 +433,7 @@ class TestCLIP:
mocked = mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value mocked = mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mocked.run.return_value = [[self.embedding]] mocked.run.return_value = [[self.embedding]]
mocker.patch("app.models.clip.textual.Tokenizer.from_file", autospec=True) mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True)
clip_encoder = OpenClipTextualEncoder("ViT-B-32__openai", cache_dir="test_cache") clip_encoder = OpenClipTextualEncoder("ViT-B-32__openai", cache_dir="test_cache")
embedding_str = clip_encoder.predict("test search query") embedding_str = clip_encoder.predict("test search query")
@ -454,7 +453,7 @@ class TestCLIP:
mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg) mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg) mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("app.models.clip.textual.Tokenizer.from_file", autospec=True).return_value mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)] mock_ids = [randint(0, 50000) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids) mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids)
@ -480,7 +479,7 @@ class TestCLIP:
mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg) mocker.patch.object(OpenClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg) mocker.patch.object(OpenClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("app.models.clip.textual.Tokenizer.from_file", autospec=True).return_value mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)] mock_ids = [randint(0, 50000) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids) mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids)
@ -505,7 +504,7 @@ class TestCLIP:
mocker.patch.object(MClipTextualEncoder, "model_cfg", clip_model_cfg) mocker.patch.object(MClipTextualEncoder, "model_cfg", clip_model_cfg)
mocker.patch.object(MClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg) mocker.patch.object(MClipTextualEncoder, "tokenizer_cfg", clip_tokenizer_cfg)
mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value mocker.patch.object(InferenceModel, "_make_session", autospec=True).return_value
mock_tokenizer = mocker.patch("app.models.clip.textual.Tokenizer.from_file", autospec=True).return_value mock_tokenizer = mocker.patch("immich_ml.models.clip.textual.Tokenizer.from_file", autospec=True).return_value
mock_ids = [randint(0, 50000) for _ in range(77)] mock_ids = [randint(0, 50000) for _ in range(77)]
mock_attention_mask = [randint(0, 1) for _ in range(77)] mock_attention_mask = [randint(0, 1) for _ in range(77)]
mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids, attention_mask=mock_attention_mask) mock_tokenizer.encode.return_value = SimpleNamespace(ids=mock_ids, attention_mask=mock_attention_mask)
@ -597,12 +596,12 @@ class TestFaceRecognition:
def test_recognition_adds_batch_axis_for_ort( def test_recognition_adds_batch_axis_for_ort(
self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture
) -> None: ) -> None:
onnx = mocker.patch("app.models.facial_recognition.recognition.onnx", autospec=True) onnx = mocker.patch("immich_ml.models.facial_recognition.recognition.onnx", autospec=True)
update_dims = mocker.patch( update_dims = mocker.patch(
"app.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True "immich_ml.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True
) )
mocker.patch("app.models.base.InferenceModel.download") mocker.patch("immich_ml.models.base.InferenceModel.download")
mocker.patch("app.models.facial_recognition.recognition.ArcFaceONNX") mocker.patch("immich_ml.models.facial_recognition.recognition.ArcFaceONNX")
ort_session.return_value.get_inputs.return_value = [SimpleNamespace(name="input.1", shape=(1, 3, 224, 224))] ort_session.return_value.get_inputs.return_value = [SimpleNamespace(name="input.1", shape=(1, 3, 224, 224))]
ort_session.return_value.get_outputs.return_value = [SimpleNamespace(name="output.1", shape=(1, 800))] ort_session.return_value.get_outputs.return_value = [SimpleNamespace(name="output.1", shape=(1, 800))]
path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".onnx" path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".onnx"
@ -631,12 +630,12 @@ class TestFaceRecognition:
def test_recognition_does_not_add_batch_axis_if_exists( def test_recognition_does_not_add_batch_axis_if_exists(
self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture
) -> None: ) -> None:
onnx = mocker.patch("app.models.facial_recognition.recognition.onnx", autospec=True) onnx = mocker.patch("immich_ml.models.facial_recognition.recognition.onnx", autospec=True)
update_dims = mocker.patch( update_dims = mocker.patch(
"app.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True "immich_ml.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True
) )
mocker.patch("app.models.base.InferenceModel.download") mocker.patch("immich_ml.models.base.InferenceModel.download")
mocker.patch("app.models.facial_recognition.recognition.ArcFaceONNX") mocker.patch("immich_ml.models.facial_recognition.recognition.ArcFaceONNX")
path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".onnx" path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".onnx"
inputs = [SimpleNamespace(name="input.1", shape=("batch", 3, 224, 224))] inputs = [SimpleNamespace(name="input.1", shape=("batch", 3, 224, 224))]
@ -655,12 +654,12 @@ class TestFaceRecognition:
def test_recognition_does_not_add_batch_axis_for_armnn( def test_recognition_does_not_add_batch_axis_for_armnn(
self, ann_session: mock.Mock, path: mock.Mock, mocker: MockerFixture self, ann_session: mock.Mock, path: mock.Mock, mocker: MockerFixture
) -> None: ) -> None:
onnx = mocker.patch("app.models.facial_recognition.recognition.onnx", autospec=True) onnx = mocker.patch("immich_ml.models.facial_recognition.recognition.onnx", autospec=True)
update_dims = mocker.patch( update_dims = mocker.patch(
"app.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True "immich_ml.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True
) )
mocker.patch("app.models.base.InferenceModel.download") mocker.patch("immich_ml.models.base.InferenceModel.download")
mocker.patch("app.models.facial_recognition.recognition.ArcFaceONNX") mocker.patch("immich_ml.models.facial_recognition.recognition.ArcFaceONNX")
path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".armnn" path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".armnn"
inputs = [SimpleNamespace(name="input.1", shape=("batch", 3, 224, 224))] inputs = [SimpleNamespace(name="input.1", shape=("batch", 3, 224, 224))]
@ -679,12 +678,12 @@ class TestFaceRecognition:
def test_recognition_does_not_add_batch_axis_for_openvino( def test_recognition_does_not_add_batch_axis_for_openvino(
self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture
) -> None: ) -> None:
onnx = mocker.patch("app.models.facial_recognition.recognition.onnx", autospec=True) onnx = mocker.patch("immich_ml.models.facial_recognition.recognition.onnx", autospec=True)
update_dims = mocker.patch( update_dims = mocker.patch(
"app.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True "immich_ml.models.facial_recognition.recognition.update_inputs_outputs_dims", autospec=True
) )
mocker.patch("app.models.base.InferenceModel.download") mocker.patch("immich_ml.models.base.InferenceModel.download")
mocker.patch("app.models.facial_recognition.recognition.ArcFaceONNX") mocker.patch("immich_ml.models.facial_recognition.recognition.ArcFaceONNX")
path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".onnx" path.return_value.__truediv__.return_value.__truediv__.return_value.suffix = ".onnx"
inputs = [SimpleNamespace(name="input.1", shape=("batch", 3, 224, 224))] inputs = [SimpleNamespace(name="input.1", shape=("batch", 3, 224, 224))]
@ -733,13 +732,13 @@ class TestCache:
) )
assert len(model_cache.cache._cache) == 2 assert len(model_cache.cache._cache) == 2
@mock.patch("app.models.cache.OptimisticLock", autospec=True) @mock.patch("immich_ml.models.cache.OptimisticLock", autospec=True)
async def test_model_ttl(self, mock_lock_cls: mock.Mock, mock_get_model: mock.Mock) -> None: async def test_model_ttl(self, mock_lock_cls: mock.Mock, mock_get_model: mock.Mock) -> None:
model_cache = ModelCache() model_cache = ModelCache()
await model_cache.get("test_model_name", ModelType.RECOGNITION, ModelTask.FACIAL_RECOGNITION, ttl=100) await model_cache.get("test_model_name", ModelType.RECOGNITION, ModelTask.FACIAL_RECOGNITION, ttl=100)
mock_lock_cls.return_value.__aenter__.return_value.cas.assert_called_with(mock.ANY, ttl=100) mock_lock_cls.return_value.__aenter__.return_value.cas.assert_called_with(mock.ANY, ttl=100)
@mock.patch("app.models.cache.SimpleMemoryCache.expire") @mock.patch("immich_ml.models.cache.SimpleMemoryCache.expire")
async def test_revalidate_get(self, mock_cache_expire: mock.Mock, mock_get_model: mock.Mock) -> None: async def test_revalidate_get(self, mock_cache_expire: mock.Mock, mock_get_model: mock.Mock) -> None:
model_cache = ModelCache(revalidate=True) model_cache = ModelCache(revalidate=True)
await model_cache.get("test_model_name", ModelType.RECOGNITION, ModelTask.FACIAL_RECOGNITION, ttl=100) await model_cache.get("test_model_name", ModelType.RECOGNITION, ModelTask.FACIAL_RECOGNITION, ttl=100)
@ -784,7 +783,7 @@ class TestCache:
assert settings.preload.clip.visual == "ViT-B-32__openai" assert settings.preload.clip.visual == "ViT-B-32__openai"
model_cache = ModelCache() model_cache = ModelCache()
monkeypatch.setattr("app.main.model_cache", model_cache) monkeypatch.setattr("immich_ml.main.model_cache", model_cache)
await preload_models(settings.preload) await preload_models(settings.preload)
mock_get_model.assert_has_calls( mock_get_model.assert_has_calls(
@ -807,7 +806,7 @@ class TestCache:
assert settings.preload.facial_recognition.recognition == "buffalo_s" assert settings.preload.facial_recognition.recognition == "buffalo_s"
model_cache = ModelCache() model_cache = ModelCache()
monkeypatch.setattr("app.main.model_cache", model_cache) monkeypatch.setattr("immich_ml.main.model_cache", model_cache)
await preload_models(settings.preload) await preload_models(settings.preload)
mock_get_model.assert_has_calls( mock_get_model.assert_has_calls(
@ -832,7 +831,7 @@ class TestCache:
assert settings.preload.facial_recognition.detection == "buffalo_s" assert settings.preload.facial_recognition.detection == "buffalo_s"
model_cache = ModelCache() model_cache = ModelCache()
monkeypatch.setattr("app.main.model_cache", model_cache) monkeypatch.setattr("immich_ml.main.model_cache", model_cache)
await preload_models(settings.preload) await preload_models(settings.preload)
mock_get_model.assert_has_calls( mock_get_model.assert_has_calls(

298
machine-learning/uv.lock generated
View File

@ -927,155 +927,7 @@ wheels = [
] ]
[[package]] [[package]]
name = "iniconfig" name = "immich-ml"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
]
[[package]]
name = "insightface"
version = "0.7.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "albumentations" },
{ name = "cython" },
{ name = "easydict" },
{ name = "matplotlib" },
{ name = "numpy" },
{ name = "onnx" },
{ name = "pillow" },
{ name = "prettytable" },
{ name = "requests" },
{ name = "scikit-image" },
{ name = "scikit-learn" },
{ name = "scipy" },
{ name = "tqdm" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/8d/0f4af90999ca96cf8cb846eb5ae27c5ef5b390f9c090dd19e4fa76364c13/insightface-0.7.3.tar.gz", hash = "sha256:f191f719612ebb37018f41936814500544cd0f86e6fcd676c023f354c668ddf7", size = 439490 }
[[package]]
name = "itsdangerous"
version = "2.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7f/a1/d3fb83e7a61fa0c0d3d08ad0a94ddbeff3731c05212617dff3a94e097f08/itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a", size = 56143 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", size = 15749 },
]
[[package]]
name = "jinja2"
version = "3.1.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markupsafe" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 },
]
[[package]]
name = "joblib"
version = "1.3.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/15/0f/d3b33b9f106dddef461f6df1872b7881321b247f3d255b87f61a7636f7fe/joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1", size = 1987720 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/10/40/d551139c85db202f1f384ba8bcf96aca2f329440a844f924c8a0040b6d02/joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9", size = 302207 },
]
[[package]]
name = "kiwisolver"
version = "1.4.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b9/2d/226779e405724344fc678fcc025b812587617ea1a48b9442628b688e85ea/kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec", size = 97552 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f1/56/cb02dcefdaab40df636b91e703b172966b444605a0ea313549f3ffc05bd3/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af", size = 127397 },
{ url = "https://files.pythonhosted.org/packages/0e/c1/d084f8edb26533a191415d5173157080837341f9a06af9dd1a75f727abb4/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3", size = 68125 },
{ url = "https://files.pythonhosted.org/packages/23/11/6fb190bae4b279d712a834e7b1da89f6dcff6791132f7399aa28a57c3565/kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4", size = 66211 },
{ url = "https://files.pythonhosted.org/packages/b3/13/5e9e52feb33e9e063f76b2c5eb09cb977f5bba622df3210081bfb26ec9a3/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1", size = 1637145 },
{ url = "https://files.pythonhosted.org/packages/6f/40/4ab1fdb57fced80ce5903f04ae1aed7c1d5939dda4fd0c0aa526c12fe28a/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff", size = 1617849 },
{ url = "https://files.pythonhosted.org/packages/49/ca/61ef43bd0832c7253b370735b0c38972c140c8774889b884372a629a8189/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a", size = 1400921 },
{ url = "https://files.pythonhosted.org/packages/68/6f/854f6a845c00b4257482468e08d8bc386f4929ee499206142378ba234419/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa", size = 1513009 },
{ url = "https://files.pythonhosted.org/packages/50/65/76f303377167d12eb7a9b423d6771b39fe5c4373e4a42f075805b1f581ae/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c", size = 1444819 },
{ url = "https://files.pythonhosted.org/packages/7e/ee/98cdf9dde129551467138b6e18cc1cc901e75ecc7ffb898c6f49609f33b1/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b", size = 1817054 },
{ url = "https://files.pythonhosted.org/packages/e6/5b/ab569016ec4abc7b496f6cb8a3ab511372c99feb6a23d948cda97e0db6da/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770", size = 1918613 },
{ url = "https://files.pythonhosted.org/packages/93/ac/39b9f99d2474b1ac7af1ddfe5756ddf9b6a8f24c5f3a32cd4c010317fc6b/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0", size = 1872650 },
{ url = "https://files.pythonhosted.org/packages/40/5b/be568548266516b114d1776120281ea9236c732fb6032a1f8f3b1e5e921c/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525", size = 1827415 },
{ url = "https://files.pythonhosted.org/packages/d4/80/c0c13d2a17a12937a19ef378bf35e94399fd171ed6ec05bcee0f038e1eaf/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b", size = 1838094 },
{ url = "https://files.pythonhosted.org/packages/70/d1/5ab93ee00ca5af708929cc12fbe665b6f1ed4ad58088e70dc00e87e0d107/kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238", size = 46585 },
{ url = "https://files.pythonhosted.org/packages/4a/a1/8a9c9be45c642fa12954855d8b3a02d9fd8551165a558835a19508fec2e6/kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276", size = 56095 },
{ url = "https://files.pythonhosted.org/packages/2a/eb/9e099ad7c47c279995d2d20474e1821100a5f10f847739bd65b1c1f02442/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5", size = 127403 },
{ url = "https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90", size = 68156 },
{ url = "https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797", size = 66166 },
{ url = "https://files.pythonhosted.org/packages/f1/68/f472bf16c9141bb1bea5c0b8c66c68fc1ccb048efdbd8f0872b92125724e/kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9", size = 1334300 },
{ url = "https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437", size = 1426579 },
{ url = "https://files.pythonhosted.org/packages/f3/a3/804fc7c8bf233806ec0321c9da35971578620f2ab4fafe67d76100b3ce52/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9", size = 1541360 },
{ url = "https://files.pythonhosted.org/packages/07/ef/286e1d26524854f6fbd6540e8364d67a8857d61038ac743e11edc42fe217/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da", size = 1470091 },
{ url = "https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e", size = 1426259 },
{ url = "https://files.pythonhosted.org/packages/d0/f3/a0925611c9d6c2f37c5935a39203cadec6883aa914e013b46c84c4c2e641/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8", size = 1847516 },
{ url = "https://files.pythonhosted.org/packages/da/85/82d59bb8f7c4c9bb2785138b72462cb1b161668f8230c58bbb28c0403cd5/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d", size = 1946228 },
{ url = "https://files.pythonhosted.org/packages/34/3c/6a37f444c0233993881e5db3a6a1775925d4d9d2f2609bb325bb1348ed94/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0", size = 1901716 },
{ url = "https://files.pythonhosted.org/packages/cd/7e/180425790efc00adfd47db14e1e341cb4826516982334129012b971121a6/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f", size = 1852871 },
{ url = "https://files.pythonhosted.org/packages/1b/9a/13c68b2edb1fa74321e60893a9a5829788e135138e68060cf44e2d92d2c3/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f", size = 1870265 },
{ url = "https://files.pythonhosted.org/packages/9f/0a/fa56a0fdee5da2b4c79899c0f6bd1aefb29d9438c2d66430e78793571c6b/kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac", size = 46649 },
{ url = "https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355", size = 56116 },
{ url = "https://files.pythonhosted.org/packages/f3/7a/debbce859be1a2711eb8437818107137192007b88d17b5cfdb556f457b42/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a", size = 125484 },
{ url = "https://files.pythonhosted.org/packages/2d/e0/bf8df75ba93b9e035cc6757dd5dcaf63084fdc1c846ae134e818bd7e0f03/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192", size = 67332 },
{ url = "https://files.pythonhosted.org/packages/26/61/58bb691f6880588be3a4801d199bd776032ece07203faf3e4a8b377f7d9b/kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45", size = 64987 },
{ url = "https://files.pythonhosted.org/packages/8e/a3/96ac5413068b237c006f54dd8d70114e8756d70e3da7613c5aef20627e22/kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7", size = 1370613 },
{ url = "https://files.pythonhosted.org/packages/4d/12/f48539e6e17068b59c7f12f4d6214b973431b8e3ac83af525cafd27cebec/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db", size = 1463183 },
{ url = "https://files.pythonhosted.org/packages/f3/70/26c99be8eb034cc8e3f62e0760af1fbdc97a842a7cbc252f7978507d41c2/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff", size = 1581248 },
{ url = "https://files.pythonhosted.org/packages/17/f6/f75f20e543639b09b2de7fc864274a5a9b96cda167a6210a1d9d19306b9d/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228", size = 1508815 },
{ url = "https://files.pythonhosted.org/packages/e3/d5/bc0f22ac108743062ab703f8d6d71c9c7b077b8839fa358700bfb81770b8/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16", size = 1466042 },
{ url = "https://files.pythonhosted.org/packages/75/18/98142500f21d6838bcab49ec919414a1f0c6d049d21ddadf139124db6a70/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9", size = 1885159 },
{ url = "https://files.pythonhosted.org/packages/21/49/a241eff9e0ee013368c1d17957f9d345b0957493c3a43d82ebb558c90b0a/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162", size = 1981694 },
{ url = "https://files.pythonhosted.org/packages/90/90/9490c3de4788123041b1d600d64434f1eed809a2ce9f688075a22166b289/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4", size = 1941579 },
{ url = "https://files.pythonhosted.org/packages/b7/bb/a0cc488ef2aa92d7d304318c8549d3ec8dfe6dd3c2c67a44e3922b77bc4f/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3", size = 1888168 },
{ url = "https://files.pythonhosted.org/packages/4f/e9/9c0de8e45fef3d63f85eed3b1757f9aa511065942866331ef8b99421f433/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a", size = 1908464 },
{ url = "https://files.pythonhosted.org/packages/a3/60/4f0fd50b08f5be536ea0cef518ac7255d9dab43ca40f3b93b60e3ddf80dd/kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20", size = 46473 },
{ url = "https://files.pythonhosted.org/packages/63/50/2746566bdf4a6a842d117367d05c90cfb87ac04e9e2845aa1fa21f071362/kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9", size = 56004 },
]
[[package]]
name = "lazy-loader"
version = "0.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0e/3a/1630a735bfdf9eb857a3b9a53317a1e1658ea97a1b4b39dcb0f71dae81f8/lazy_loader-0.3.tar.gz", hash = "sha256:3b68898e34f5b2a29daaaac172c6555512d0f32074f147e2254e4a6d9d838f37", size = 12268 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a1/c3/65b3814e155836acacf720e5be3b5757130346670ac454fee29d3eda1381/lazy_loader-0.3-py3-none-any.whl", hash = "sha256:1e9e76ee8631e264c62ce10006718e80b2cfc74340d17d1031e0f84af7478554", size = 9087 },
]
[[package]]
name = "locust"
version = "2.33.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "configargparse" },
{ name = "flask" },
{ name = "flask-cors" },
{ name = "flask-login" },
{ name = "gevent", marker = "python_full_version != '3.13.*'" },
{ name = "geventhttpclient" },
{ name = "msgpack" },
{ name = "psutil" },
{ name = "pywin32", marker = "sys_platform == 'win32'" },
{ name = "pyzmq" },
{ name = "requests" },
{ name = "setuptools" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
{ name = "werkzeug" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/9e/09ee87dc12b240248731080bfd460c7d384aadb3171f6d03a4e7314cd0e1/locust-2.33.2.tar.gz", hash = "sha256:e626ed0156f36cec94c3c6b030fc91046469e7e2f5c2e91a99aab0f28b84977e", size = 2237716 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9c/c7/bb55ac53173d3e92b1b2577d0f36439500406ca5be476a27b7bc01ae8a75/locust-2.33.2-py3-none-any.whl", hash = "sha256:a2f3b53dcd5ed22cecee874cd989912749663d82ec9b030637d3e43044e5878e", size = 2254591 },
]
[[package]]
name = "machine-learning"
version = "1.129.0" version = "1.129.0"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
@ -1224,6 +1076,154 @@ types = [
{ name = "types-ujson", specifier = ">=5.10.0.20240515" }, { name = "types-ujson", specifier = ">=5.10.0.20240515" },
] ]
[[package]]
name = "iniconfig"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
]
[[package]]
name = "insightface"
version = "0.7.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "albumentations" },
{ name = "cython" },
{ name = "easydict" },
{ name = "matplotlib" },
{ name = "numpy" },
{ name = "onnx" },
{ name = "pillow" },
{ name = "prettytable" },
{ name = "requests" },
{ name = "scikit-image" },
{ name = "scikit-learn" },
{ name = "scipy" },
{ name = "tqdm" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/8d/0f4af90999ca96cf8cb846eb5ae27c5ef5b390f9c090dd19e4fa76364c13/insightface-0.7.3.tar.gz", hash = "sha256:f191f719612ebb37018f41936814500544cd0f86e6fcd676c023f354c668ddf7", size = 439490 }
[[package]]
name = "itsdangerous"
version = "2.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7f/a1/d3fb83e7a61fa0c0d3d08ad0a94ddbeff3731c05212617dff3a94e097f08/itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a", size = 56143 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", size = 15749 },
]
[[package]]
name = "jinja2"
version = "3.1.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markupsafe" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 },
]
[[package]]
name = "joblib"
version = "1.3.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/15/0f/d3b33b9f106dddef461f6df1872b7881321b247f3d255b87f61a7636f7fe/joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1", size = 1987720 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/10/40/d551139c85db202f1f384ba8bcf96aca2f329440a844f924c8a0040b6d02/joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9", size = 302207 },
]
[[package]]
name = "kiwisolver"
version = "1.4.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b9/2d/226779e405724344fc678fcc025b812587617ea1a48b9442628b688e85ea/kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec", size = 97552 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f1/56/cb02dcefdaab40df636b91e703b172966b444605a0ea313549f3ffc05bd3/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af", size = 127397 },
{ url = "https://files.pythonhosted.org/packages/0e/c1/d084f8edb26533a191415d5173157080837341f9a06af9dd1a75f727abb4/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3", size = 68125 },
{ url = "https://files.pythonhosted.org/packages/23/11/6fb190bae4b279d712a834e7b1da89f6dcff6791132f7399aa28a57c3565/kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4", size = 66211 },
{ url = "https://files.pythonhosted.org/packages/b3/13/5e9e52feb33e9e063f76b2c5eb09cb977f5bba622df3210081bfb26ec9a3/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1", size = 1637145 },
{ url = "https://files.pythonhosted.org/packages/6f/40/4ab1fdb57fced80ce5903f04ae1aed7c1d5939dda4fd0c0aa526c12fe28a/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff", size = 1617849 },
{ url = "https://files.pythonhosted.org/packages/49/ca/61ef43bd0832c7253b370735b0c38972c140c8774889b884372a629a8189/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a", size = 1400921 },
{ url = "https://files.pythonhosted.org/packages/68/6f/854f6a845c00b4257482468e08d8bc386f4929ee499206142378ba234419/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa", size = 1513009 },
{ url = "https://files.pythonhosted.org/packages/50/65/76f303377167d12eb7a9b423d6771b39fe5c4373e4a42f075805b1f581ae/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c", size = 1444819 },
{ url = "https://files.pythonhosted.org/packages/7e/ee/98cdf9dde129551467138b6e18cc1cc901e75ecc7ffb898c6f49609f33b1/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b", size = 1817054 },
{ url = "https://files.pythonhosted.org/packages/e6/5b/ab569016ec4abc7b496f6cb8a3ab511372c99feb6a23d948cda97e0db6da/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770", size = 1918613 },
{ url = "https://files.pythonhosted.org/packages/93/ac/39b9f99d2474b1ac7af1ddfe5756ddf9b6a8f24c5f3a32cd4c010317fc6b/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0", size = 1872650 },
{ url = "https://files.pythonhosted.org/packages/40/5b/be568548266516b114d1776120281ea9236c732fb6032a1f8f3b1e5e921c/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525", size = 1827415 },
{ url = "https://files.pythonhosted.org/packages/d4/80/c0c13d2a17a12937a19ef378bf35e94399fd171ed6ec05bcee0f038e1eaf/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b", size = 1838094 },
{ url = "https://files.pythonhosted.org/packages/70/d1/5ab93ee00ca5af708929cc12fbe665b6f1ed4ad58088e70dc00e87e0d107/kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238", size = 46585 },
{ url = "https://files.pythonhosted.org/packages/4a/a1/8a9c9be45c642fa12954855d8b3a02d9fd8551165a558835a19508fec2e6/kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276", size = 56095 },
{ url = "https://files.pythonhosted.org/packages/2a/eb/9e099ad7c47c279995d2d20474e1821100a5f10f847739bd65b1c1f02442/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5", size = 127403 },
{ url = "https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90", size = 68156 },
{ url = "https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797", size = 66166 },
{ url = "https://files.pythonhosted.org/packages/f1/68/f472bf16c9141bb1bea5c0b8c66c68fc1ccb048efdbd8f0872b92125724e/kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9", size = 1334300 },
{ url = "https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437", size = 1426579 },
{ url = "https://files.pythonhosted.org/packages/f3/a3/804fc7c8bf233806ec0321c9da35971578620f2ab4fafe67d76100b3ce52/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9", size = 1541360 },
{ url = "https://files.pythonhosted.org/packages/07/ef/286e1d26524854f6fbd6540e8364d67a8857d61038ac743e11edc42fe217/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da", size = 1470091 },
{ url = "https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e", size = 1426259 },
{ url = "https://files.pythonhosted.org/packages/d0/f3/a0925611c9d6c2f37c5935a39203cadec6883aa914e013b46c84c4c2e641/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8", size = 1847516 },
{ url = "https://files.pythonhosted.org/packages/da/85/82d59bb8f7c4c9bb2785138b72462cb1b161668f8230c58bbb28c0403cd5/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d", size = 1946228 },
{ url = "https://files.pythonhosted.org/packages/34/3c/6a37f444c0233993881e5db3a6a1775925d4d9d2f2609bb325bb1348ed94/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0", size = 1901716 },
{ url = "https://files.pythonhosted.org/packages/cd/7e/180425790efc00adfd47db14e1e341cb4826516982334129012b971121a6/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f", size = 1852871 },
{ url = "https://files.pythonhosted.org/packages/1b/9a/13c68b2edb1fa74321e60893a9a5829788e135138e68060cf44e2d92d2c3/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f", size = 1870265 },
{ url = "https://files.pythonhosted.org/packages/9f/0a/fa56a0fdee5da2b4c79899c0f6bd1aefb29d9438c2d66430e78793571c6b/kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac", size = 46649 },
{ url = "https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355", size = 56116 },
{ url = "https://files.pythonhosted.org/packages/f3/7a/debbce859be1a2711eb8437818107137192007b88d17b5cfdb556f457b42/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a", size = 125484 },
{ url = "https://files.pythonhosted.org/packages/2d/e0/bf8df75ba93b9e035cc6757dd5dcaf63084fdc1c846ae134e818bd7e0f03/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192", size = 67332 },
{ url = "https://files.pythonhosted.org/packages/26/61/58bb691f6880588be3a4801d199bd776032ece07203faf3e4a8b377f7d9b/kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45", size = 64987 },
{ url = "https://files.pythonhosted.org/packages/8e/a3/96ac5413068b237c006f54dd8d70114e8756d70e3da7613c5aef20627e22/kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7", size = 1370613 },
{ url = "https://files.pythonhosted.org/packages/4d/12/f48539e6e17068b59c7f12f4d6214b973431b8e3ac83af525cafd27cebec/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db", size = 1463183 },
{ url = "https://files.pythonhosted.org/packages/f3/70/26c99be8eb034cc8e3f62e0760af1fbdc97a842a7cbc252f7978507d41c2/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff", size = 1581248 },
{ url = "https://files.pythonhosted.org/packages/17/f6/f75f20e543639b09b2de7fc864274a5a9b96cda167a6210a1d9d19306b9d/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228", size = 1508815 },
{ url = "https://files.pythonhosted.org/packages/e3/d5/bc0f22ac108743062ab703f8d6d71c9c7b077b8839fa358700bfb81770b8/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16", size = 1466042 },
{ url = "https://files.pythonhosted.org/packages/75/18/98142500f21d6838bcab49ec919414a1f0c6d049d21ddadf139124db6a70/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9", size = 1885159 },
{ url = "https://files.pythonhosted.org/packages/21/49/a241eff9e0ee013368c1d17957f9d345b0957493c3a43d82ebb558c90b0a/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162", size = 1981694 },
{ url = "https://files.pythonhosted.org/packages/90/90/9490c3de4788123041b1d600d64434f1eed809a2ce9f688075a22166b289/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4", size = 1941579 },
{ url = "https://files.pythonhosted.org/packages/b7/bb/a0cc488ef2aa92d7d304318c8549d3ec8dfe6dd3c2c67a44e3922b77bc4f/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3", size = 1888168 },
{ url = "https://files.pythonhosted.org/packages/4f/e9/9c0de8e45fef3d63f85eed3b1757f9aa511065942866331ef8b99421f433/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a", size = 1908464 },
{ url = "https://files.pythonhosted.org/packages/a3/60/4f0fd50b08f5be536ea0cef518ac7255d9dab43ca40f3b93b60e3ddf80dd/kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20", size = 46473 },
{ url = "https://files.pythonhosted.org/packages/63/50/2746566bdf4a6a842d117367d05c90cfb87ac04e9e2845aa1fa21f071362/kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9", size = 56004 },
]
[[package]]
name = "lazy-loader"
version = "0.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0e/3a/1630a735bfdf9eb857a3b9a53317a1e1658ea97a1b4b39dcb0f71dae81f8/lazy_loader-0.3.tar.gz", hash = "sha256:3b68898e34f5b2a29daaaac172c6555512d0f32074f147e2254e4a6d9d838f37", size = 12268 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a1/c3/65b3814e155836acacf720e5be3b5757130346670ac454fee29d3eda1381/lazy_loader-0.3-py3-none-any.whl", hash = "sha256:1e9e76ee8631e264c62ce10006718e80b2cfc74340d17d1031e0f84af7478554", size = 9087 },
]
[[package]]
name = "locust"
version = "2.33.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "configargparse" },
{ name = "flask" },
{ name = "flask-cors" },
{ name = "flask-login" },
{ name = "gevent", marker = "python_full_version != '3.13.*'" },
{ name = "geventhttpclient" },
{ name = "msgpack" },
{ name = "psutil" },
{ name = "pywin32", marker = "sys_platform == 'win32'" },
{ name = "pyzmq" },
{ name = "requests" },
{ name = "setuptools" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
{ name = "werkzeug" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/9e/09ee87dc12b240248731080bfd460c7d384aadb3171f6d03a4e7314cd0e1/locust-2.33.2.tar.gz", hash = "sha256:e626ed0156f36cec94c3c6b030fc91046469e7e2f5c2e91a99aab0f28b84977e", size = 2237716 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9c/c7/bb55ac53173d3e92b1b2577d0f36439500406ca5be476a27b7bc01ae8a75/locust-2.33.2-py3-none-any.whl", hash = "sha256:a2f3b53dcd5ed22cecee874cd989912749663d82ec9b030637d3e43044e5878e", size = 2254591 },
]
[[package]] [[package]]
name = "markdown-it-py" name = "markdown-it-py"
version = "3.0.0" version = "3.0.0"

View File

@ -35,8 +35,8 @@ platform :android do
task: 'bundle', task: 'bundle',
build_type: 'Release', build_type: 'Release',
properties: { properties: {
"android.injected.version.code" => 190, "android.injected.version.code" => 191,
"android.injected.version.name" => "1.130.2", "android.injected.version.name" => "1.130.3",
} }
) )
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')

View File

@ -541,7 +541,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198; CURRENT_PROJECT_VERSION = 199;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -685,7 +685,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198; CURRENT_PROJECT_VERSION = 199;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -715,7 +715,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198; CURRENT_PROJECT_VERSION = 199;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -748,7 +748,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198; CURRENT_PROJECT_VERSION = 199;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@ -791,7 +791,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198; CURRENT_PROJECT_VERSION = 199;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
@ -831,7 +831,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198; CURRENT_PROJECT_VERSION = 199;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2F67MQ8R79; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;

View File

@ -78,7 +78,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.130.0</string> <string>1.130.3</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@ -93,7 +93,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>198</string> <string>199</string>
<key>FLTEnableImpeller</key> <key>FLTEnableImpeller</key>
<true/> <true/>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@ -19,7 +19,7 @@ platform :ios do
desc "iOS Release" desc "iOS Release"
lane :release do lane :release do
increment_version_number( increment_version_number(
version_number: "1.130.2" version_number: "1.130.3"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@ -737,6 +737,11 @@ class SyncService {
album.thumbnail.value = thumb; album.thumbnail.value = thumb;
try { try {
await _albumRepository.create(album); await _albumRepository.create(album);
final int assetCount =
await _albumMediaRepository.getAssetCount(album.localId!);
await _eTagRepository.upsertAll([
ETag(id: album.eTagKeyAssetCount, assetCount: assetCount),
]);
_log.info("Added a new local album to DB: ${album.name}"); _log.info("Added a new local album to DB: ${album.name}");
} catch (e) { } catch (e) {
_log.severe("Failed to add new local album ${album.name} to DB", e); _log.severe("Failed to add new local album ${album.name} to DB", e);

View File

@ -210,6 +210,9 @@ class LoginForm extends HookConsumerWidget {
.getOAuthServerUrl(sanitizeUrl(serverEndpointController.text)); .getOAuthServerUrl(sanitizeUrl(serverEndpointController.text));
isLoading.value = true; isLoading.value = true;
// Invalidate all api repository provider instance to take into account new access token
invalidateAllApiRepositoryProviders(ref);
} catch (error, stack) { } catch (error, stack) {
log.severe('Error getting OAuth server Url: $error', stack); log.severe('Error getting OAuth server Url: $error', stack);

View File

@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.130.2 - API version: 1.130.3
- Generator version: 7.8.0 - Generator version: 7.8.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen

View File

@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone description: Immich - selfhosted backup media file on mobile phone
publish_to: 'none' publish_to: 'none'
version: 1.130.2+190 version: 1.130.3+191
environment: environment:
sdk: '>=3.3.0 <4.0.0' sdk: '>=3.3.0 <4.0.0'

View File

@ -7656,7 +7656,7 @@
"info": { "info": {
"title": "Immich", "title": "Immich",
"description": "Immich API", "description": "Immich API",
"version": "1.130.2", "version": "1.130.3",
"contact": {} "contact": {}
}, },
"tags": [], "tags": [],

View File

@ -1,12 +1,12 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.2", "version": "1.130.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.2", "version": "1.130.3",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"

View File

@ -1,6 +1,6 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.2", "version": "1.130.3",
"description": "Auto-generated TypeScript SDK for the Immich API", "description": "Auto-generated TypeScript SDK for the Immich API",
"type": "module", "type": "module",
"main": "./build/index.js", "main": "./build/index.js",

View File

@ -1,6 +1,6 @@
/** /**
* Immich * Immich
* 1.130.2 * 1.130.3
* DO NOT MODIFY - This file has been generated using oazapfts. * DO NOT MODIFY - This file has been generated using oazapfts.
* See https://www.npmjs.com/package/oazapfts * See https://www.npmjs.com/package/oazapfts
*/ */

1571
server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "immich", "name": "immich",
"version": "1.130.2", "version": "1.130.3",
"description": "", "description": "",
"author": "", "author": "",
"private": true, "private": true,
@ -44,11 +44,11 @@
"@nestjs/schedule": "^5.0.0", "@nestjs/schedule": "^5.0.0",
"@nestjs/swagger": "^11.0.2", "@nestjs/swagger": "^11.0.2",
"@nestjs/websockets": "^11.0.4", "@nestjs/websockets": "^11.0.4",
"@opentelemetry/auto-instrumentations-node": "^0.56.0", "@opentelemetry/auto-instrumentations-node": "^0.57.0",
"@opentelemetry/context-async-hooks": "^1.24.0", "@opentelemetry/context-async-hooks": "^1.24.0",
"@opentelemetry/exporter-prometheus": "^0.57.0", "@opentelemetry/exporter-prometheus": "^0.200.0",
"@opentelemetry/sdk-node": "^0.57.0", "@opentelemetry/sdk-node": "^0.200.0",
"@react-email/components": "^0.0.33", "@react-email/components": "^0.0.34",
"@socket.io/redis-adapter": "^8.3.0", "@socket.io/redis-adapter": "^8.3.0",
"archiver": "^7.0.0", "archiver": "^7.0.0",
"async-lock": "^1.4.0", "async-lock": "^1.4.0",

View File

@ -93,7 +93,7 @@ select
"exif" as "exifInfo" "exif" as "exifInfo"
from from
"assets" "assets"
inner join "exif" on "assets"."id" = "exif"."assetId" left join "exif" on "assets"."id" = "exif"."assetId"
inner join "albums_assets_assets" on "albums_assets_assets"."assetsId" = "assets"."id" inner join "albums_assets_assets" on "albums_assets_assets"."assetsId" = "assets"."id"
where where
"albums_assets_assets"."albumsId" = "albums"."id" "albums_assets_assets"."albumsId" = "albums"."id"

View File

@ -68,7 +68,7 @@ const withAssets = (eb: ExpressionBuilder<DB, 'albums'>) => {
eb eb
.selectFrom('assets') .selectFrom('assets')
.selectAll('assets') .selectAll('assets')
.innerJoin('exif', 'assets.id', 'exif.assetId') .leftJoin('exif', 'assets.id', 'exif.assetId')
.select((eb) => eb.table('exif').as('exifInfo')) .select((eb) => eb.table('exif').as('exifInfo'))
.innerJoin('albums_assets_assets', 'albums_assets_assets.assetsId', 'assets.id') .innerJoin('albums_assets_assets', 'albums_assets_assets.assetsId', 'assets.id')
.whereRef('albums_assets_assets.albumsId', '=', 'albums.id') .whereRef('albums_assets_assets.albumsId', '=', 'albums.id')

View File

@ -7,8 +7,10 @@ import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'; import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';
import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'; import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core';
import { PgInstrumentation } from '@opentelemetry/instrumentation-pg'; import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';
import { NodeSDK, contextBase, metrics, resources } from '@opentelemetry/sdk-node'; import { resourceFromAttributes } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; import { AggregationType } from '@opentelemetry/sdk-metrics';
import { NodeSDK, contextBase } from '@opentelemetry/sdk-node';
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
import { ClassConstructor } from 'class-transformer'; import { ClassConstructor } from 'class-transformer';
import { snakeCase, startCase } from 'lodash'; import { snakeCase, startCase } from 'lodash';
import { MetricService } from 'nestjs-otel'; import { MetricService } from 'nestjs-otel';
@ -49,10 +51,9 @@ export class MetricGroupRepository {
} }
} }
const aggregation = new metrics.ExplicitBucketHistogramAggregation( const aggregationBoundaries = [
[0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10_000], 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10_000,
true, ];
);
let instance: NodeSDK | undefined; let instance: NodeSDK | undefined;
@ -61,9 +62,9 @@ export const bootstrapTelemetry = (port: number) => {
throw new Error('OpenTelemetry SDK already started'); throw new Error('OpenTelemetry SDK already started');
} }
instance = new NodeSDK({ instance = new NodeSDK({
resource: new resources.Resource({ resource: resourceFromAttributes({
[SemanticResourceAttributes.SERVICE_NAME]: `immich`, [ATTR_SERVICE_NAME]: `immich`,
[SemanticResourceAttributes.SERVICE_VERSION]: serverVersion.toString(), [ATTR_SERVICE_VERSION]: serverVersion.toString(),
}), }),
metricReader: new PrometheusExporter({ port }), metricReader: new PrometheusExporter({ port }),
contextManager: new AsyncLocalStorageContextManager(), contextManager: new AsyncLocalStorageContextManager(),
@ -73,7 +74,16 @@ export const bootstrapTelemetry = (port: number) => {
new NestInstrumentation(), new NestInstrumentation(),
new PgInstrumentation(), new PgInstrumentation(),
], ],
views: [new metrics.View({ aggregation, instrumentName: '*', instrumentUnit: 'ms' })], views: [
{
instrumentName: '*',
instrumentUnit: 'ms',
aggregation: {
type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
options: { boundaries: aggregationBoundaries },
},
},
],
}); });
instance.start(); instance.start();

236
web/package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "immich-web", "name": "immich-web",
"version": "1.130.2", "version": "1.130.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich-web", "name": "immich-web",
"version": "1.130.2", "version": "1.130.3",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@formatjs/icu-messageformat-parser": "^2.9.8", "@formatjs/icu-messageformat-parser": "^2.9.8",
@ -70,7 +70,7 @@
"prettier-plugin-sort-json": "^4.1.1", "prettier-plugin-sort-json": "^4.1.1",
"prettier-plugin-svelte": "^3.3.3", "prettier-plugin-svelte": "^3.3.3",
"rollup-plugin-visualizer": "^5.14.0", "rollup-plugin-visualizer": "^5.14.0",
"svelte": "^5.22.6", "svelte": "^5.25.3",
"svelte-check": "^4.1.5", "svelte-check": "^4.1.5",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tslib": "^2.6.2", "tslib": "^2.6.2",
@ -81,7 +81,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.130.2", "version": "1.130.3",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"
@ -710,9 +710,9 @@
} }
}, },
"node_modules/@eslint/config-helpers": { "node_modules/@eslint/config-helpers": {
"version": "0.1.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz",
"integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -733,9 +733,9 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "3.3.0", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
"integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -770,9 +770,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.22.0", "version": "9.23.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
"integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -2112,9 +2112,9 @@
} }
}, },
"node_modules/@sveltejs/kit": { "node_modules/@sveltejs/kit": {
"version": "2.19.0", "version": "2.20.2",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.19.0.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.2.tgz",
"integrity": "sha512-UTx28Ad4sYsLU//gqkEo5aFOPFBRT2uXCmXTsURqhurDCvzkVwXruJgBcHDaMiK6RKKpYRteDUaXYqZyGPgCXQ==", "integrity": "sha512-Dv8TOAZC9vyfcAB9TMsvUEJsRbklRTeNfcYBPaeH6KnABJ99i3CvCB2eNx8fiiliIqe+9GIchBg4RodRH5p1BQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2582,17 +2582,17 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz",
"integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==", "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/type-utils": "8.26.1", "@typescript-eslint/type-utils": "8.27.0",
"@typescript-eslint/utils": "8.26.1", "@typescript-eslint/utils": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@ -2612,16 +2612,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz",
"integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==", "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -2637,14 +2637,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz",
"integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==", "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1" "@typescript-eslint/visitor-keys": "8.27.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2655,14 +2655,14 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz",
"integrity": "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==", "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/typescript-estree": "8.27.0",
"@typescript-eslint/utils": "8.26.1", "@typescript-eslint/utils": "8.27.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.1"
}, },
@ -2679,9 +2679,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz",
"integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==", "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -2693,14 +2693,14 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz",
"integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==", "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.26.1", "@typescript-eslint/visitor-keys": "8.27.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -2746,16 +2746,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz",
"integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==", "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.26.1" "@typescript-eslint/typescript-estree": "8.27.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -2770,13 +2770,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.26.1", "version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz",
"integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==", "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.26.1", "@typescript-eslint/types": "8.27.0",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -2801,9 +2801,9 @@
} }
}, },
"node_modules/@vitest/coverage-v8": { "node_modules/@vitest/coverage-v8": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.9.tgz",
"integrity": "sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==", "integrity": "sha512-15OACZcBtQ34keIEn19JYTVuMFTlFrClclwWjHo/IRPg/8ELpkgNTl0o7WLP9WO9XGH6+tip9CPYtEOrIDJvBA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2824,8 +2824,8 @@
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
}, },
"peerDependencies": { "peerDependencies": {
"@vitest/browser": "3.0.8", "@vitest/browser": "3.0.9",
"vitest": "3.0.8" "vitest": "3.0.9"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@vitest/browser": { "@vitest/browser": {
@ -2852,14 +2852,14 @@
} }
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz",
"integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==", "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"chai": "^5.2.0", "chai": "^5.2.0",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@ -2868,13 +2868,13 @@
} }
}, },
"node_modules/@vitest/mocker": { "node_modules/@vitest/mocker": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz",
"integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==", "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"estree-walker": "^3.0.3", "estree-walker": "^3.0.3",
"magic-string": "^0.30.17" "magic-string": "^0.30.17"
}, },
@ -2895,9 +2895,9 @@
} }
}, },
"node_modules/@vitest/pretty-format": { "node_modules/@vitest/pretty-format": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz",
"integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==", "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2908,13 +2908,13 @@
} }
}, },
"node_modules/@vitest/runner": { "node_modules/@vitest/runner": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz",
"integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==", "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
"funding": { "funding": {
@ -2922,13 +2922,13 @@
} }
}, },
"node_modules/@vitest/snapshot": { "node_modules/@vitest/snapshot": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz",
"integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==", "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.8", "@vitest/pretty-format": "3.0.9",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",
"pathe": "^2.0.3" "pathe": "^2.0.3"
}, },
@ -2937,9 +2937,9 @@
} }
}, },
"node_modules/@vitest/spy": { "node_modules/@vitest/spy": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz",
"integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==", "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2950,13 +2950,13 @@
} }
}, },
"node_modules/@vitest/utils": { "node_modules/@vitest/utils": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz",
"integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==", "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.8", "@vitest/pretty-format": "3.0.9",
"loupe": "^3.1.3", "loupe": "^3.1.3",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@ -4203,19 +4203,19 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.22.0", "version": "9.23.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz",
"integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.2", "@eslint/config-array": "^0.19.2",
"@eslint/config-helpers": "^0.1.0", "@eslint/config-helpers": "^0.2.0",
"@eslint/core": "^0.12.0", "@eslint/core": "^0.12.0",
"@eslint/eslintrc": "^3.3.0", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.22.0", "@eslint/js": "9.23.0",
"@eslint/plugin-kit": "^0.2.7", "@eslint/plugin-kit": "^0.2.7",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
@ -4293,9 +4293,9 @@
} }
}, },
"node_modules/eslint-plugin-svelte": { "node_modules/eslint-plugin-svelte": {
"version": "3.1.0", "version": "3.3.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.1.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.3.3.tgz",
"integrity": "sha512-hSQyLDkuuHPJby1ixZfUVrfLON42mT0Odf18MbwAgFUPuyIwJlhy3acUY1/bxt+Njucq/dQxR543zYDqkBNLmw==", "integrity": "sha512-imzGqIgWbfsb/CR14d3k3M8MiVNGet+l9mjPhvo1Rm0Nxi0rNn4/eELqyR8FWlgKBMlGkOp2kshRJm0xpxNfHQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -8350,9 +8350,9 @@
} }
}, },
"node_modules/svelte": { "node_modules/svelte": {
"version": "5.23.0", "version": "5.25.3",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.23.0.tgz", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.25.3.tgz",
"integrity": "sha512-v0lL3NuKontiCxholEiAXCB+BYbndlKbwlDMK0DS86WgGELMJSpyqCSbJeMEMBDwOglnS7Ar2Rq0wwa/z2L8Vg==", "integrity": "sha512-J9rcZ/xVJonAoESqVGHHZhrNdVbrCfkdB41BP6eiwHMoFShD9it3yZXApVYMHdGfCshBsZCKsajwJeBbS/M1zg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.3.0", "@ampproject/remapping": "^2.3.0",
@ -9675,9 +9675,9 @@
} }
}, },
"node_modules/vite-node": { "node_modules/vite-node": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz", "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz",
"integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==", "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -9735,19 +9735,19 @@
} }
}, },
"node_modules/vitest": { "node_modules/vitest": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz",
"integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==", "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/expect": "3.0.8", "@vitest/expect": "3.0.9",
"@vitest/mocker": "3.0.8", "@vitest/mocker": "3.0.9",
"@vitest/pretty-format": "^3.0.8", "@vitest/pretty-format": "^3.0.9",
"@vitest/runner": "3.0.8", "@vitest/runner": "3.0.9",
"@vitest/snapshot": "3.0.8", "@vitest/snapshot": "3.0.9",
"@vitest/spy": "3.0.8", "@vitest/spy": "3.0.9",
"@vitest/utils": "3.0.8", "@vitest/utils": "3.0.9",
"chai": "^5.2.0", "chai": "^5.2.0",
"debug": "^4.4.0", "debug": "^4.4.0",
"expect-type": "^1.1.0", "expect-type": "^1.1.0",
@ -9759,7 +9759,7 @@
"tinypool": "^1.0.2", "tinypool": "^1.0.2",
"tinyrainbow": "^2.0.0", "tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0", "vite": "^5.0.0 || ^6.0.0",
"vite-node": "3.0.8", "vite-node": "3.0.9",
"why-is-node-running": "^2.3.0" "why-is-node-running": "^2.3.0"
}, },
"bin": { "bin": {
@ -9775,8 +9775,8 @@
"@edge-runtime/vm": "*", "@edge-runtime/vm": "*",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
"@vitest/browser": "3.0.8", "@vitest/browser": "3.0.9",
"@vitest/ui": "3.0.8", "@vitest/ui": "3.0.9",
"happy-dom": "*", "happy-dom": "*",
"jsdom": "*" "jsdom": "*"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "immich-web", "name": "immich-web",
"version": "1.130.2", "version": "1.130.3",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"scripts": { "scripts": {
"dev": "vite dev --host 0.0.0.0 --port 3000", "dev": "vite dev --host 0.0.0.0 --port 3000",
@ -56,7 +56,7 @@
"prettier-plugin-sort-json": "^4.1.1", "prettier-plugin-sort-json": "^4.1.1",
"prettier-plugin-svelte": "^3.3.3", "prettier-plugin-svelte": "^3.3.3",
"rollup-plugin-visualizer": "^5.14.0", "rollup-plugin-visualizer": "^5.14.0",
"svelte": "^5.22.6", "svelte": "^5.25.3",
"svelte-check": "^4.1.5", "svelte-check": "^4.1.5",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tslib": "^2.6.2", "tslib": "^2.6.2",

View File

@ -170,7 +170,7 @@
</div> </div>
</form> </form>
</div> </div>
<TemplateSettings {defaultConfig} {config} {savedConfig} {onReset} {onSave} /> <TemplateSettings {config} {savedConfig} />
<SettingButtonsRow <SettingButtonsRow
onReset={(options) => onReset({ ...options, configKeys: ['notifications', 'templates'] })} onReset={(options) => onReset({ ...options, configKeys: ['notifications', 'templates'] })}

View File

@ -11,15 +11,10 @@
import { mdiEyeOutline } from '@mdi/js'; import { mdiEyeOutline } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings';
interface Props { interface Props {
savedConfig: SystemConfigDto; savedConfig: SystemConfigDto;
defaultConfig: SystemConfigDto;
config: SystemConfigDto; config: SystemConfigDto;
disabled?: boolean;
onReset: SettingsResetEvent;
onSave: SettingsSaveEvent;
} }
let { savedConfig, config = $bindable() }: Props = $props(); let { savedConfig, config = $bindable() }: Props = $props();

View File

@ -482,7 +482,6 @@
{preloadAssets} {preloadAssets}
onPreviousAsset={() => navigateAsset('previous')} onPreviousAsset={() => navigateAsset('previous')}
onNextAsset={() => navigateAsset('next')} onNextAsset={() => navigateAsset('next')}
onClose={closeViewer}
haveFadeTransition={false} haveFadeTransition={false}
{sharedLink} {sharedLink}
/> />
@ -527,7 +526,6 @@
{preloadAssets} {preloadAssets}
onPreviousAsset={() => navigateAsset('previous')} onPreviousAsset={() => navigateAsset('previous')}
onNextAsset={() => navigateAsset('next')} onNextAsset={() => navigateAsset('next')}
onClose={closeViewer}
{sharedLink} {sharedLink}
haveFadeTransition={$slideshowState === SlideshowState.None || $slideshowTransition} haveFadeTransition={$slideshowState === SlideshowState.None || $slideshowTransition}
/> />

View File

@ -32,7 +32,6 @@
onNextAsset?: (() => void) | null; onNextAsset?: (() => void) | null;
copyImage?: () => Promise<void>; copyImage?: () => Promise<void>;
zoomToggle?: (() => void) | null; zoomToggle?: (() => void) | null;
onClose?: () => void;
} }
let { let {

View File

@ -18,10 +18,8 @@
circle?: boolean; circle?: boolean;
hidden?: boolean; hidden?: boolean;
border?: boolean; border?: boolean;
preload?: boolean;
hiddenIconClass?: string; hiddenIconClass?: string;
onComplete?: (() => void) | undefined; onComplete?: (() => void) | undefined;
onClick?: (() => void) | undefined;
} }
let { let {

View File

@ -1,6 +1,4 @@
<script lang="ts"> <script lang="ts">
import { press, tap } from 'svelte-gestures';
import Icon from '$lib/components/elements/icon.svelte'; import Icon from '$lib/components/elements/icon.svelte';
import { ProjectionType } from '$lib/constants'; import { ProjectionType } from '$lib/constants';
import { getAssetThumbnailUrl, isSharedLink } from '$lib/utils'; import { getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
@ -74,7 +72,7 @@
IMAGE_THUMBNAIL: { THUMBHASH_FADE_DURATION }, IMAGE_THUMBNAIL: { THUMBHASH_FADE_DURATION },
} = TUNABLES; } = TUNABLES;
let isTouchDevice = $derived(mobileDevice.hoverNone); let usingMobileDevice = $derived(mobileDevice.pointerCoarse);
let focussableElement: HTMLElement | undefined = $state(); let focussableElement: HTMLElement | undefined = $state();
let mouseOver = $state(false); let mouseOver = $state(false);
let loaded = $state(false); let loaded = $state(false);
@ -103,10 +101,8 @@
} }
onClick?.($state.snapshot(asset)); onClick?.($state.snapshot(asset));
}; };
const handleClick = (e: MouseEvent) => { const handleClick = (e: MouseEvent) => {
if (isTouchDevice) {
return;
}
if (e.ctrlKey || e.metaKey) { if (e.ctrlKey || e.metaKey) {
return; return;
} }
@ -116,7 +112,7 @@
}; };
const onMouseEnter = () => { const onMouseEnter = () => {
if (isTouchDevice) { if (usingMobileDevice) {
return; return;
} }
mouseOver = true; mouseOver = true;
@ -126,6 +122,25 @@
const onMouseLeave = () => { const onMouseLeave = () => {
mouseOver = false; mouseOver = false;
}; };
function longPress(element: HTMLElement, { onLongPress }: { onLongPress: () => void }) {
let timer: ReturnType<typeof setTimeout>;
const start = (event: TouchEvent) => {
timer = setTimeout(() => {
onLongPress();
event.preventDefault();
}, 350);
};
const end = () => clearTimeout(timer);
element.addEventListener('touchstart', start);
element.addEventListener('touchend', end);
return {
destroy: () => {
element.removeEventListener('touchstart', start);
element.removeEventListener('touchend', end);
},
};
}
</script> </script>
<div <div
@ -146,9 +161,6 @@
></canvas> ></canvas>
{/if} {/if}
<!-- svelte queries for all links on afterNavigate, leading to performance problems in asset-grid which updates
the navigation url on scroll. Replace this with button for now. -->
<!-- as of iOS17, there is a preference for long press speed, which is not available for mobile web. <!-- as of iOS17, there is a preference for long press speed, which is not available for mobile web.
The defaults are as follows: The defaults are as follows:
fast: 200ms fast: 200ms
@ -163,10 +175,7 @@
class:cursor-pointer={!disabled} class:cursor-pointer={!disabled}
onmouseenter={onMouseEnter} onmouseenter={onMouseEnter}
onmouseleave={onMouseLeave} onmouseleave={onMouseLeave}
use:press={() => ({ timeframe: 350, triggerBeforeFinished: true })} use:longPress={{ onLongPress: () => onSelect?.($state.snapshot(asset)) }}
use:tap={() => ({ timeframe: 350 })}
onpress={(evt) => (evt.detail.pointerType === 'mouse' ? void 0 : onSelect?.($state.snapshot(asset)))}
ontap={(evt) => (evt.detail.pointerType === 'mouse' ? void 0 : callClickHandlers())}
onkeydown={(evt) => { onkeydown={(evt) => {
if (evt.key === 'Enter') { if (evt.key === 'Enter') {
callClickHandlers(); callClickHandlers();
@ -182,7 +191,7 @@
onfocus={handleFocus} onfocus={handleFocus}
data-testid="container-with-tabindex" data-testid="container-with-tabindex"
> >
{#if !isTouchDevice && mouseOver && !disableMouseOver} {#if !usingMobileDevice && mouseOver && !disableMouseOver}
<!-- lazy show the url on mouse over--> <!-- lazy show the url on mouse over-->
<a <a
class="absolute z-30 {className} top-[41px]" class="absolute z-30 {className} top-[41px]"
@ -229,7 +238,7 @@
class:rounded-xl={selected} class:rounded-xl={selected}
> >
<!-- Gradient overlay on hover --> <!-- Gradient overlay on hover -->
{#if !isTouchDevice} {#if !usingMobileDevice}
<div <div
class="absolute z-10 h-full w-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100" class="absolute z-10 h-full w-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100"
class:rounded-xl={selected} class:rounded-xl={selected}

View File

@ -136,7 +136,7 @@
<div class="flex flex-wrap gap-1 bg-immich-bg p-2 pb-8 dark:bg-immich-dark-bg md:px-8 mt-16"> <div class="flex flex-wrap gap-1 bg-immich-bg p-2 pb-8 dark:bg-immich-dark-bg md:px-8 mt-16">
<PeopleInfiniteScroll {people} hasNextPage={true} {loadNextPage}> <PeopleInfiniteScroll {people} hasNextPage={true} {loadNextPage}>
{#snippet children({ person, index })} {#snippet children({ person })}
{@const hidden = personIsHidden[person.id]} {@const hidden = personIsHidden[person.id]}
<button <button
type="button" type="button"
@ -146,7 +146,6 @@
aria-label={person.name ? $t('hide_named_person', { values: { name: person.name } }) : $t('hide_person')} aria-label={person.name ? $t('hide_named_person', { values: { name: person.name } }) : $t('hide_person')}
> >
<ImageThumbnail <ImageThumbnail
preload={index < 20}
{hidden} {hidden}
shadow shadow
url={getPeopleThumbnailUrl(person)} url={getPeopleThumbnailUrl(person)}

View File

@ -100,7 +100,6 @@
url={getPeopleThumbnailUrl(person)} url={getPeopleThumbnailUrl(person)}
altText={person.name} altText={person.name}
widthStyle="100%" widthStyle="100%"
onClick={() => changePersonToMerge(person)}
/> />
</button> </button>
</div> </div>

View File

@ -20,14 +20,13 @@
interface Props { interface Props {
person: PersonResponseDto; person: PersonResponseDto;
preload?: boolean;
onSetBirthDate: () => void; onSetBirthDate: () => void;
onMergePeople: () => void; onMergePeople: () => void;
onHidePerson: () => void; onHidePerson: () => void;
onToggleFavorite: () => void; onToggleFavorite: () => void;
} }
let { person, preload = false, onSetBirthDate, onMergePeople, onHidePerson, onToggleFavorite }: Props = $props(); let { person, onSetBirthDate, onMergePeople, onHidePerson, onToggleFavorite }: Props = $props();
let showVerticalDots = $state(false); let showVerticalDots = $state(false);
</script> </script>
@ -48,7 +47,6 @@
<div class="w-full h-full rounded-xl brightness-95 filter"> <div class="w-full h-full rounded-xl brightness-95 filter">
<ImageThumbnail <ImageThumbnail
shadow shadow
{preload}
url={getPeopleThumbnailUrl(person)} url={getPeopleThumbnailUrl(person)}
altText={person.name} altText={person.name}
title={person.name} title={person.name}

View File

@ -18,7 +18,7 @@
let allTags: TagResponseDto[] = $state([]); let allTags: TagResponseDto[] = $state([]);
let tagMap = $derived(Object.fromEntries(allTags.map((tag) => [tag.id, tag]))); let tagMap = $derived(Object.fromEntries(allTags.map((tag) => [tag.id, tag])));
let selectedIds = $state(new SvelteSet<string>()); let selectedIds = new SvelteSet<string>();
let disabled = $derived(selectedIds.size === 0); let disabled = $derived(selectedIds.size === 0);
let allowCreate: boolean = $state(true); let allowCreate: boolean = $state(true);

View File

@ -83,7 +83,7 @@
let bottomSectionHeight = 60; let bottomSectionHeight = 60;
let leadout = $state(false); let leadout = $state(false);
const usingMobileDevice = $derived(mobileDevice.hoverNone); const usingMobileDevice = $derived(mobileDevice.pointerCoarse);
const scrollTo = (top: number) => { const scrollTo = (top: number) => {
element?.scrollTo({ top }); element?.scrollTo({ top });

View File

@ -14,7 +14,6 @@
timelineBottomOffset?: number; timelineBottomOffset?: number;
height?: number; height?: number;
assetStore: AssetStore; assetStore: AssetStore;
invisible?: boolean;
scrubOverallPercent?: number; scrubOverallPercent?: number;
scrubBucketPercent?: number; scrubBucketPercent?: number;
scrubBucket?: { bucketDate: string | undefined }; scrubBucket?: { bucketDate: string | undefined };
@ -268,7 +267,7 @@
globalThis.removeEventListener('touchmove', onTouchMove); globalThis.removeEventListener('touchmove', onTouchMove);
}; };
}); });
const usingMobileDevice = $derived(mobileDevice.hoverNone); const usingMobileDevice = $derived(mobileDevice.pointerCoarse);
const width = $derived(isDragging ? '100vw' : usingMobileDevice ? '20px' : '60px'); const width = $derived(isDragging ? '100vw' : usingMobileDevice ? '20px' : '60px');
</script> </script>

View File

@ -13,7 +13,6 @@
flippedLogo?: boolean; flippedLogo?: boolean;
isSelected?: boolean; isSelected?: boolean;
preloadData?: boolean; preloadData?: boolean;
moreInformation?: Snippet;
dropDownContent?: Snippet; dropDownContent?: Snippet;
dropdownOpen?: boolean; dropdownOpen?: boolean;
} }

View File

@ -24,6 +24,7 @@
const { isViewing: showAssetViewer, asset: viewingAsset, setAsset } = assetViewingStore; const { isViewing: showAssetViewer, asset: viewingAsset, setAsset } = assetViewingStore;
const getAssetIndex = (id: string) => assets.findIndex((asset) => asset.id === id); const getAssetIndex = (id: string) => assets.findIndex((asset) => asset.id === id);
// eslint-disable-next-line svelte/no-unnecessary-state-wrap
let selectedAssetIds = $state(new SvelteSet<string>()); let selectedAssetIds = $state(new SvelteSet<string>());
let trashCount = $derived(assets.length - selectedAssetIds.size); let trashCount = $derived(assets.length - selectedAssetIds.size);

View File

@ -579,6 +579,9 @@ export class AssetStore {
initTask = new CancellableTask( initTask = new CancellableTask(
() => { () => {
this.isInitialized = true; this.isInitialized = true;
if (this.#options.albumId || this.#options.personId) {
return;
}
this.connect(); this.connect();
}, },
() => { () => {

View File

@ -1,11 +1,11 @@
import { MediaQuery } from 'svelte/reactivity'; import { MediaQuery } from 'svelte/reactivity';
const hoverNone = new MediaQuery('hover: none'); const pointerCoarse = new MediaQuery('pointer:coarse');
const maxMd = new MediaQuery('max-width: 767px'); const maxMd = new MediaQuery('max-width: 767px');
export const mobileDevice = { export const mobileDevice = {
get hoverNone() { get pointerCoarse() {
return hoverNone.current; return pointerCoarse.current;
}, },
get maxMd() { get maxMd() {
return maxMd.current; return maxMd.current;

View File

@ -394,7 +394,7 @@
} }
}); });
let album = $state(data.album); let album = $derived(data.album);
let albumId = $derived(album.id); let albumId = $derived(album.id);
$effect(() => { $effect(() => {
@ -404,6 +404,7 @@
}); });
let assetStore = new AssetStore(); let assetStore = new AssetStore();
$effect(() => { $effect(() => {
if (viewMode === AlbumPageViewMode.VIEW) { if (viewMode === AlbumPageViewMode.VIEW) {
void assetStore.updateOptions({ albumId, order: albumOrder }); void assetStore.updateOptions({ albumId, order: albumOrder });

View File

@ -408,13 +408,12 @@
{#if countVisiblePeople > 0 && (!searchName || searchedPeopleLocal.length > 0)} {#if countVisiblePeople > 0 && (!searchName || searchedPeopleLocal.length > 0)}
<PeopleInfiniteScroll people={showPeople} hasNextPage={!!nextPage && !searchName} {loadNextPage}> <PeopleInfiniteScroll people={showPeople} hasNextPage={!!nextPage && !searchName} {loadNextPage}>
{#snippet children({ person, index })} {#snippet children({ person })}
<div <div
class="p-2 rounded-xl hover:bg-gray-200 border-2 hover:border-immich-primary/50 hover:shadow-sm dark:hover:bg-immich-dark-primary/20 hover:dark:border-immich-dark-primary/25 border-transparent transition-all" class="p-2 rounded-xl hover:bg-gray-200 border-2 hover:border-immich-primary/50 hover:shadow-sm dark:hover:bg-immich-dark-primary/20 hover:dark:border-immich-dark-primary/25 border-transparent transition-all"
> >
<PeopleCard <PeopleCard
{person} {person}
preload={index < 20}
onSetBirthDate={() => handleSetBirthDate(person)} onSetBirthDate={() => handleSetBirthDate(person)}
onMergePeople={() => handleMergePeople(person)} onMergePeople={() => handleMergePeople(person)}
onHidePerson={() => handleHidePerson(person)} onHidePerson={() => handleHidePerson(person)}