From f533902c755b5bc9e95c7df6122cc70cbe078ecf Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Sun, 5 Oct 2025 19:50:52 -0400 Subject: [PATCH] feat: semantic search (1/n) Signed-off-by: Aaron Pham --- docs/embeddings/hnsw.bin | Bin 0 -> 8480 bytes docs/embeddings/manifest.json | 1 + docs/embeddings/vectors-000.bin | Bin 0 -> 261120 bytes index.d.ts | 1 + package-lock.json | 810 +++++++++++------- package.json | 2 + quartz.config.ts | 16 +- quartz/cfg.ts | 28 + quartz/components/Search.tsx | 63 +- quartz/components/renderPage.tsx | 7 + quartz/components/scripts/search.inline.ts | 802 +++++++++++++---- quartz/components/scripts/semantic.inline.ts | 182 ++++ quartz/components/scripts/util.ts | 65 ++ quartz/components/styles/search.scss | 97 ++- quartz/embed_build.py | 542 ++++++++++++ quartz/plugins/emitters/404.tsx | 2 +- quartz/plugins/emitters/componentResources.ts | 47 +- quartz/plugins/emitters/contentPage.tsx | 2 +- quartz/plugins/emitters/folderPage.tsx | 2 +- quartz/plugins/emitters/index.ts | 3 +- quartz/plugins/emitters/semantic.ts | 235 +++++ quartz/plugins/emitters/tagPage.tsx | 2 +- quartz/workers/semantic.worker.ts | 548 ++++++++++++ 23 files changed, 2955 insertions(+), 502 deletions(-) create mode 100644 docs/embeddings/hnsw.bin create mode 100644 docs/embeddings/manifest.json create mode 100644 docs/embeddings/vectors-000.bin create mode 100644 quartz/components/scripts/semantic.inline.ts create mode 100644 quartz/embed_build.py create mode 100644 quartz/plugins/emitters/semantic.ts create mode 100644 quartz/workers/semantic.worker.ts diff --git a/docs/embeddings/hnsw.bin b/docs/embeddings/hnsw.bin new file mode 100644 index 0000000000000000000000000000000000000000..3cdd4c1185497b61870c1671d7121621d5198021 GIT binary patch literal 8480 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

D9`@WN#UfRoK4P`p6|7dM#W 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

WZGK%>F+}f4C-w5X5Pw^m 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 literal 0 HcmV?d00001 diff --git a/index.d.ts b/index.d.ts index 9011ee38f..df9db0786 100644 --- a/index.d.ts +++ b/index.d.ts @@ -13,3 +13,4 @@ interface CustomEventMap { type ContentIndex = Record declare const fetchData: Promise +declare const semanticCfg: import("./quartz/cfg").GlobalConfiguration["semanticSearch"] diff --git a/package-lock.json b/package-lock.json index 25df1907d..b19a2b72e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@clack/prompts": "^0.11.0", "@floating-ui/dom": "^1.7.4", + "@huggingface/transformers": "^3.7.5", "@myriaddreamin/rehype-typst": "^0.6.0", "@napi-rs/simple-git": "0.1.22", "@tweenjs/tween.js": "^25.0.0", @@ -35,6 +36,7 @@ "mdast-util-to-string": "^4.0.0", "micromorph": "^0.4.5", "minimatch": "^10.0.3", + "onnxruntime-web": "^1.23.0", "pixi.js": "^8.13.2", "preact": "^10.27.2", "preact-render-to-string": "^6.6.1", @@ -647,6 +649,47 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, + "node_modules/@huggingface/jinja": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.1.tgz", + "integrity": "sha512-yUZLld4lrM9iFxHCwFQ7D1HW2MWMwSbeB7WzWqFYDWK+rEb+WldkLdAJxUPOmgICMHZLzZGVcVjFh3w/YGubng==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@huggingface/transformers": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.7.5.tgz", + "integrity": "sha512-5jvrIwHyRXfOKVaGKYvUZM6ZjJKQXWeKzIOdKBE5pdzPSNzTwBNx5NdWcGElf4Ddv7Dl2mWsvJh+G5RnCUxMmA==", + "license": "Apache-2.0", + "dependencies": { + "@huggingface/jinja": "^0.5.1", + "onnxruntime-node": "1.21.0", + "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", + "sharp": "^0.34.1" + } + }, + "node_modules/@huggingface/transformers/node_modules/onnxruntime-common": { + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", + "license": "MIT" + }, + "node_modules/@huggingface/transformers/node_modules/onnxruntime-web": { + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", + "license": "MIT", + "dependencies": { + "flatbuffers": "^25.1.24", + "guid-typescript": "^1.0.9", + "long": "^5.2.3", + "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", + "platform": "^1.3.6", + "protobufjs": "^7.2.4" + } + }, "node_modules/@img/colour": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", @@ -1095,6 +1138,18 @@ "node": "20 || >=22" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@myriaddreamin/rehype-typst": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@myriaddreamin/rehype-typst/-/rehype-typst-0.6.0.tgz", @@ -1616,6 +1671,70 @@ "integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==", "license": "MIT" }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, "node_modules/@shikijs/core": { "version": "1.26.2", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.26.2.tgz", @@ -2053,7 +2172,6 @@ "version": "24.6.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.6.0.tgz", "integrity": "sha512-F1CBxgqwOMc4GKJ7eY22hWhBVQuMYTtqI8L0FcszYcpYX0fzfDGpez22Xau8Mgm7O9fI+zA/TYIdq3tGWfweBA==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.13.0" @@ -2223,6 +2341,13 @@ } ] }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -2345,6 +2470,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/citeproc": { "version": "2.4.63", "resolved": "https://registry.npmjs.org/citeproc/-/citeproc-2.4.63.tgz", @@ -2861,6 +2995,40 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delaunator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", @@ -2886,6 +3054,12 @@ "node": ">=8" } }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -2926,6 +3100,30 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.25.10", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", @@ -3164,6 +3362,12 @@ "node": ">=8" } }, + "node_modules/flatbuffers": { + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "license": "Apache-2.0" + }, "node_modules/flexsearch": { "version": "0.8.205", "resolved": "https://registry.npmjs.org/flexsearch/-/flexsearch-0.8.205.tgz", @@ -3284,6 +3488,39 @@ "node": ">= 6" } }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-15.0.0.tgz", @@ -3304,6 +3541,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -3338,6 +3587,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/guid-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", + "license": "ISC" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3347,6 +3602,18 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -3932,6 +4199,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, "node_modules/katex": { "version": "0.16.21", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz", @@ -4232,6 +4505,12 @@ "node": ">= 0.4" } }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -4250,6 +4529,30 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mathjax-full": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", @@ -5250,6 +5553,27 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/mj-context-menu": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", @@ -5316,6 +5640,15 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/oniguruma-to-es": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-1.0.0.tgz", @@ -5326,6 +5659,49 @@ "regex-recursion": "^5.1.1" } }, + "node_modules/onnxruntime-common": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", + "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", + "license": "MIT" + }, + "node_modules/onnxruntime-node": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", + "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", + "hasInstallScript": true, + "license": "MIT", + "os": [ + "win32", + "darwin", + "linux" + ], + "dependencies": { + "global-agent": "^3.0.0", + "onnxruntime-common": "1.21.0", + "tar": "^7.0.1" + } + }, + "node_modules/onnxruntime-web": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.23.0.tgz", + "integrity": "sha512-w0bvC2RwDxphOUFF8jFGZ/dYw+duaX20jM6V4BIZJPCfK4QuCpB/pVREV+hjYbT3x4hyfa2ZbTaWx4e1Vot0fQ==", + "license": "MIT", + "dependencies": { + "flatbuffers": "^25.1.24", + "guid-typescript": "^1.0.9", + "long": "^5.2.3", + "onnxruntime-common": "1.23.0", + "platform": "^1.3.6", + "protobufjs": "^7.2.4" + } + }, + "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.23.0.tgz", + "integrity": "sha512-Auz8S9D7vpF8ok7fzTobvD1XdQDftRf/S7pHmjeCr3Xdymi4z1C7zx4vnT6nnUjbpelZdGwda0BmWHCCTMKUTg==", + "license": "MIT" + }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -5473,6 +5849,12 @@ "url": "https://opencollective.com/pixijs" } }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "license": "MIT" + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -5543,6 +5925,30 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6002,6 +6408,29 @@ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "license": "BSD-3-Clause", + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/roarr/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, "node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", @@ -6113,326 +6542,6 @@ "sass-embedded-win32-x64": "1.79.4" } }, - "node_modules/sass-embedded-android-arm": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.79.4.tgz", - "integrity": "sha512-YOVpDGDcwWUQvktpJhYo4zOkknDpdX6ALpaeHDTX6GBUvnZfx+Widh76v+QFUhiJQ/I/hndXg1jv/PKilOHRrw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-arm64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.79.4.tgz", - "integrity": "sha512-0JAZ8TtXYv9yI3Yasaq03xvo7DLJOmD+Exb30oJKxXcWTAV9TB0ZWKoIRsFxbCyPxyn7ouxkaCEXQtaTRKrmfw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-ia32": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.79.4.tgz", - "integrity": "sha512-IjO3RoyvNN84ZyfAR5s/a8TIdNPfClb7CLGrswB3BN/NElYIJUJMVHD6+Y8W9QwBIZ8DrK1IdLFSTV8nn82xMA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-riscv64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.79.4.tgz", - "integrity": "sha512-uOT8nXmKxSwuIdcqvElVWBFcm/+YcIvmwfoKbpuuSOSxUe9eqFzxo+fk7ILhynzf6FBlvRUH5DcjGj+sXtCc3w==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-android-x64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.79.4.tgz", - "integrity": "sha512-W2FQoj3Z2J2DirNs3xSBVvrhMuqLnsqvOPulxOkhL/074+faKOZZnPx2tZ5zsHbY97SonciiU0SV0mm98xI42w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-darwin-arm64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.79.4.tgz", - "integrity": "sha512-pcYtbN1VUAAcfgyHeX8ySndDWGjIvcq6rldduktPbGGuAlEWFDfnwjTbv0hS945ggdzZ6TFnaFlLEDr0SjKzBA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-darwin-x64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.79.4.tgz", - "integrity": "sha512-ir8CFTfc4JLx/qCP8LK1/3pWv35nRyAQkUK7lBIKM6hWzztt64gcno9rZIk4SpHr7Z/Bp1IYWWRS4ZT+4HmsbA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-arm": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.79.4.tgz", - "integrity": "sha512-H/XEE3rY7c+tY0qDaELjPjC6VheAhBo1tPJQ6UHoBEf8xrbT/RT3dWiIS8grp9Vk54RCn05BEB/+POaljvvKGA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-arm64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.79.4.tgz", - "integrity": "sha512-XIVn2mCuA422SR2kmKjF6jhjMs1Vrt1DbZ/ktSp+eR0sU4ugu2htg45GajiUFSKKRj7Sc+cBdThq1zPPsDLf1w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-ia32": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.79.4.tgz", - "integrity": "sha512-3nqZxV4nuUTb1ahLexVl4hsnx1KKwiGdHEf1xHWTZai6fYFMcwyNPrHySCQzFHqb5xiqSpPzzrKjuDhF6+guuQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-arm": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.79.4.tgz", - "integrity": "sha512-HnbU1DEiQdUayioNzxh2WlbTEgQRBPTgIIvof8J63QLmVItUqE7EkWYkSUy4RhO+8NsuN9wzGmGTzFBvTImU7g==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-arm64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.79.4.tgz", - "integrity": "sha512-C6qX06waPEfDgOHR8jXoYxl0EtIXOyBDyyonrLO3StRjWjGx7XMQj2hA/KXSsV+Hr71fBOsaViosqWXPzTbEiQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-ia32": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.79.4.tgz", - "integrity": "sha512-y5b0fdOPWyhj4c+mc88GvQiC5onRH1V0iNaWNjsiZ+L4hHje6T98nDLrCJn0fz5GQnXjyLCLZduMWbfV0QjHGg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-riscv64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.79.4.tgz", - "integrity": "sha512-G2M5ADMV9SqnkwpM0S+UzDz7xR2njCOhofku/sDMZABzAjQQWTsAykKoGmzlT98fTw2HbNhb6u74umf2WLhCfw==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-musl-x64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.79.4.tgz", - "integrity": "sha512-kQm8dCU3DXf7DtUGWYPiPs03KJYKvFeiZJHhSx993DCM8D2b0wCXWky0S0Z46gf1sEur0SN4Lvnt1WczTqxIBw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-riscv64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.79.4.tgz", - "integrity": "sha512-GaTI/mXYWYSzG5wxtM4H2cozLpATyh+4l+rO9FFKOL8e1sUOLAzTeRdU2nSBYCuRqsxRuTZIwCXhSz9Q3NRuNA==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-linux-x64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.79.4.tgz", - "integrity": "sha512-f9laGkqHgC01h99Qt4LsOV+OLMffjvUcTu14hYWqMS9QVX5a4ihMwpf1NoAtTUytb7cVF3rYY/NVGuXt6G3ppQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-arm64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.79.4.tgz", - "integrity": "sha512-cidBvtaA2cJ6dNlwQEa8qak+ezypurzKs0h0QAHLH324+j/6Jum7LCnQhZRPYJBFjHl+WYd7KwzPnJ2X5USWnQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-ia32": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.79.4.tgz", - "integrity": "sha512-hexdmNTIZGTKNTzlMcdvEXzYuxOJcY89zqgsf45aQ2YMy4y2M8dTOxRI/Vz7p4iRxVp1Jow6LCtaLHrNI2Ordg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-embedded-win32-x64": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.79.4.tgz", - "integrity": "sha512-73yrpiWIbti6DkxhWURklkgSLYKfU9itDmvHxB+oYSb4vQveIApqTwSyTOuIUb/6Da/EsgEpdJ4Lbj4sLaMZWA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/satori": { "version": "0.18.3", "resolved": "https://registry.npmjs.org/satori/-/satori-0.18.3.tgz", @@ -6488,6 +6597,27 @@ "node": ">=10" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT" + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/serve-handler": { "version": "6.1.6", "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", @@ -6771,6 +6901,22 @@ "node": ">=14" } }, + "node_modules/tar": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz", + "integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -6858,6 +7004,18 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", @@ -6876,7 +7034,6 @@ "version": "7.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz", "integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==", - "dev": true, "license": "MIT" }, "node_modules/unicode-trie": { @@ -7211,6 +7368,15 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/yargs": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", diff --git a/package.json b/package.json index fdbc8c434..1cf3a0f40 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "dependencies": { "@clack/prompts": "^0.11.0", "@floating-ui/dom": "^1.7.4", + "@huggingface/transformers": "^3.7.5", "@myriaddreamin/rehype-typst": "^0.6.0", "@napi-rs/simple-git": "0.1.22", "@tweenjs/tween.js": "^25.0.0", @@ -61,6 +62,7 @@ "mdast-util-to-string": "^4.0.0", "micromorph": "^0.4.5", "minimatch": "^10.0.3", + "onnxruntime-web": "^1.23.0", "pixi.js": "^8.13.2", "preact": "^10.27.2", "preact-render-to-string": "^6.6.1", diff --git a/quartz.config.ts b/quartz.config.ts index b3db3d60d..6d3fcb4e9 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -1,6 +1,18 @@ -import { QuartzConfig } from "./quartz/cfg" +import { GlobalConfiguration, QuartzConfig } from "./quartz/cfg" import * as Plugin from "./quartz/plugins" +const semanticSearch: GlobalConfiguration["semanticSearch"] = { + enable: true, + model: "onnx-community/embeddinggemma-300m-ONNX", + aot: true, + dims: 768, + dtype: "fp32", + shardSizeRows: 1024, + hnsw: { M: 16, efConstruction: 200 }, + chunking: { chunkSize: 256, chunkOverlap: 64 }, + vllm: { enable: true, concurrency: 16, batchSize: 128 }, +} + /** * Quartz 4 Configuration * @@ -52,6 +64,7 @@ const config: QuartzConfig = { }, }, }, + semanticSearch, }, plugins: { transformers: [ @@ -84,6 +97,7 @@ const config: QuartzConfig = { enableSiteMap: true, enableRSS: true, }), + Plugin.SemanticIndex(semanticSearch), Plugin.Assets(), Plugin.Static(), Plugin.Favicon(), diff --git a/quartz/cfg.ts b/quartz/cfg.ts index 57dff5c75..734f0a3d8 100644 --- a/quartz/cfg.ts +++ b/quartz/cfg.ts @@ -78,6 +78,34 @@ export interface GlobalConfiguration { * Region Codes: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 */ locale: ValidLocale + /** Semantic search configuration */ + semanticSearch?: { + enable: boolean + model: string + aot: boolean + dtype: "fp32" | "fp16" + dims: number + shardSizeRows: number + manifestUrl?: string + manifestBaseUrl?: string + disableCache?: boolean + hnsw: { + M: number + efConstruction: number + efSearch?: number + } + chunking: { + chunkSize: number + chunkOverlap: number + noChunking?: boolean + } + vllm?: { + enable: boolean + vllmUrl?: string + concurrency: number + batchSize: number + } + } } export interface QuartzConfig { diff --git a/quartz/components/Search.tsx b/quartz/components/Search.tsx index 6e932d2ef..6dbd38a0f 100644 --- a/quartz/components/Search.tsx +++ b/quartz/components/Search.tsx @@ -7,10 +7,12 @@ import { i18n } from "../i18n" export interface SearchOptions { enablePreview: boolean + includeButton: boolean } const defaultOptions: SearchOptions = { enablePreview: true, + includeButton: true, } export default ((userOpts?: Partial) => { @@ -29,19 +31,54 @@ export default ((userOpts?: Partial) => {

{i18n(cfg.locale).components.search.title}

-
-
- -
-
-
+ +
+
+ +
+ + +
+
+ + +
) } diff --git a/quartz/components/renderPage.tsx b/quartz/components/renderPage.tsx index 3ebfe4879..4e19d1238 100644 --- a/quartz/components/renderPage.tsx +++ b/quartz/components/renderPage.tsx @@ -25,6 +25,7 @@ const headerRegex = new RegExp(/h[1-6]/) export function pageResources( baseDir: FullSlug | RelativeURL, staticResources: StaticResources, + cfg?: GlobalConfiguration, ): StaticResources { const contentIndexPath = joinSegments(baseDir, "static/contentIndex.json") const contentIndexScript = `const fetchData = fetch("${contentIndexPath}").then(data => data.json())` @@ -48,6 +49,12 @@ export function pageResources( spaPreserve: true, script: contentIndexScript, }, + { + loadTime: "beforeDOMReady", + contentType: "inline", + spaPreserve: true, + script: `const semanticCfg = ${JSON.stringify(cfg?.semanticSearch ?? {})};`, + }, ...staticResources.js, ], additionalHead: staticResources.additionalHead, diff --git a/quartz/components/scripts/search.inline.ts b/quartz/components/scripts/search.inline.ts index 6a84a50e0..eedbe871f 100644 --- a/quartz/components/scripts/search.inline.ts +++ b/quartz/components/scripts/search.inline.ts @@ -1,6 +1,14 @@ import FlexSearch, { DefaultDocumentSearchResults } from "flexsearch" -import { ContentDetails } from "../../plugins/emitters/contentIndex" -import { registerEscapeHandler, removeAllChildren } from "./util" +import type { ContentDetails } from "../../plugins/emitters/contentIndex" +import { SemanticClient, type SemanticResult } from "./semantic.inline" +import { + registerEscapeHandler, + removeAllChildren, + highlight, + tokenizeTerm, + encode, + fetchCanonical, +} from "./util" import { FullSlug, normalizeRelativeURLs, resolveRelative } from "../../util/path" interface Item { @@ -14,17 +22,110 @@ interface Item { // Can be expanded with things like "term" in the future type SearchType = "basic" | "tags" -let searchType: SearchType = "basic" -let currentSearchTerm: string = "" -const encoder = (str: string) => { - return str - .toLowerCase() - .split(/\s+/) - .filter((token) => token.length > 0) +type SearchMode = "lexical" | "semantic" +const SEARCH_MODE_STORAGE_KEY = "quartz:search:mode" + +const loadStoredSearchMode = (): SearchMode | null => { + if (typeof window === "undefined") { + return null + } + + try { + const stored = window.localStorage.getItem(SEARCH_MODE_STORAGE_KEY) + return stored === "lexical" || stored === "semantic" ? stored : null + } catch (err) { + console.warn("[Search] failed to read stored search mode:", err) + return null + } } -let index = new FlexSearch.Document({ - encode: encoder, +const persistSearchMode = (mode: SearchMode) => { + if (typeof window === "undefined") { + return + } + + try { + window.localStorage.setItem(SEARCH_MODE_STORAGE_KEY, mode) + } catch (err) { + console.warn("[Search] failed to persist search mode:", err) + } +} + +let searchMode: SearchMode = "lexical" +let currentSearchTerm: string = "" +let rawSearchTerm: string = "" +let semantic: SemanticClient | null = null +let semanticReady = false +let semanticInitFailed = false +type SimilarityResult = { item: Item; similarity: number } +let chunkMetadata: Record = {} +let manifestIds: string[] = [] + +/** + * Get parent document slug for a chunk ID + */ +function getParentSlug(slug: string): string { + const meta = chunkMetadata[slug] + return meta ? meta.parentSlug : slug +} + +/** + * Aggregate semantic search results from chunks to documents using RRF + * @param results Raw semantic results (chunk-level) + * @param slugToDocIndex Map from document slug to index in idDataMap + * @returns Object with rrfScores (for ranking) and maxScores (for display) + */ +function aggregateChunkResults( + results: SemanticResult[], + slugToDocIndex: Map, +): { rrfScores: Map; maxScores: Map } { + // Group chunks by parent document + const docChunks = new Map>() + + results.forEach(({ id, score }) => { + // id is an index into manifestIds (the chunk IDs from embeddings) + const chunkSlug = manifestIds[id] + if (!chunkSlug) return + + // Get parent document slug + const parentSlug = getParentSlug(chunkSlug) + + if (!docChunks.has(parentSlug)) { + docChunks.set(parentSlug, []) + } + + docChunks.get(parentSlug)!.push({ score }) + }) + + // Apply RRF for ranking and track max similarity for display + const rrfScores = new Map() + const maxScores = new Map() + const RRF_K = 60 + + for (const [parentSlug, chunks] of docChunks) { + const docIdx = slugToDocIndex.get(parentSlug as FullSlug) + if (typeof docIdx !== "number") continue + + // Sort chunks by score descending to assign per-document ranks + chunks.sort((a, b) => b.score - a.score) + + // RRF formula: sum(1 / (k + rank)) across all chunks, using per-document ranks + const rrfScore = chunks.reduce((sum, _, rank) => sum + 1.0 / (RRF_K + rank), 0) + + // Max similarity score for display (original 0-1 range) + const maxScore = chunks[0].score + + rrfScores.set(docIdx, rrfScore) + maxScores.set(docIdx, maxScore) + } + + return { rrfScores, maxScores } +} + +// Initialize the FlexSearch Document instance with the appropriate configuration +const index = new FlexSearch.Document({ + tokenize: "forward", + encode, document: { id: "id", tag: "tags", @@ -41,73 +142,18 @@ let index = new FlexSearch.Document({ field: "tags", tokenize: "forward", }, + { + field: "aliases", + tokenize: "forward", + }, ], }, }) const p = new DOMParser() const fetchContentCache: Map = new Map() -const contextWindowWords = 30 -const numSearchResults = 8 -const numTagResults = 5 - -const tokenizeTerm = (term: string) => { - const tokens = term.split(/\s+/).filter((t) => t.trim() !== "") - const tokenLen = tokens.length - if (tokenLen > 1) { - for (let i = 1; i < tokenLen; i++) { - tokens.push(tokens.slice(0, i + 1).join(" ")) - } - } - - return tokens.sort((a, b) => b.length - a.length) // always highlight longest terms first -} - -function highlight(searchTerm: string, text: string, trim?: boolean) { - const tokenizedTerms = tokenizeTerm(searchTerm) - let tokenizedText = text.split(/\s+/).filter((t) => t !== "") - - let startIndex = 0 - let endIndex = tokenizedText.length - 1 - if (trim) { - const includesCheck = (tok: string) => - tokenizedTerms.some((term) => tok.toLowerCase().startsWith(term.toLowerCase())) - const occurrencesIndices = tokenizedText.map(includesCheck) - - let bestSum = 0 - let bestIndex = 0 - for (let i = 0; i < Math.max(tokenizedText.length - contextWindowWords, 0); i++) { - const window = occurrencesIndices.slice(i, i + contextWindowWords) - const windowSum = window.reduce((total, cur) => total + (cur ? 1 : 0), 0) - if (windowSum >= bestSum) { - bestSum = windowSum - bestIndex = i - } - } - - startIndex = Math.max(bestIndex - contextWindowWords, 0) - endIndex = Math.min(startIndex + 2 * contextWindowWords, tokenizedText.length - 1) - tokenizedText = tokenizedText.slice(startIndex, endIndex) - } - - const slice = tokenizedText - .map((tok) => { - // see if this tok is prefixed by any search terms - for (const searchTok of tokenizedTerms) { - if (tok.toLowerCase().includes(searchTok.toLowerCase())) { - const regex = new RegExp(searchTok.toLowerCase(), "gi") - return tok.replace(regex, `$&`) - } - } - return tok - }) - .join(" ") - - return `${startIndex === 0 ? "" : "..."}${slice}${ - endIndex === tokenizedText.length - 1 ? "" : "..." - }` -} - +const numSearchResults = 10 +const numTagResults = 10 function highlightHTML(searchTerm: string, el: HTMLElement) { const p = new DOMParser() const tokenizedTerms = tokenizeTerm(searchTerm) @@ -149,7 +195,11 @@ function highlightHTML(searchTerm: string, el: HTMLElement) { return html.body } -async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: ContentIndex) { +async function setupSearch( + searchElement: HTMLDivElement, + currentSlug: FullSlug, + data: ContentIndex, +) { const container = searchElement.querySelector(".search-container") as HTMLElement if (!container) return @@ -164,12 +214,183 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: const searchLayout = searchElement.querySelector(".search-layout") as HTMLElement if (!searchLayout) return + const searchSpace = searchElement?.querySelector(".search-space") as HTMLFormElement + if (!searchSpace) return + + // Create semantic search progress bar + const progressBar = document.createElement("div") + progressBar.className = "semantic-search-progress" + progressBar.style.cssText = ` + position: absolute; + bottom: 0; + left: 0; + height: 2px; + width: 0; + background: var(--secondary); + transition: width 0.3s ease, opacity 0.3s ease; + opacity: 0; + z-index: 9999; + ` + searchBar.parentElement?.appendChild(progressBar) + + const startSemanticProgress = () => { + progressBar.style.opacity = "1" + progressBar.style.width = "0" + setTimeout(() => { + progressBar.style.width = "100%" + }, 10) + } + + const completeSemanticProgress = () => { + progressBar.style.opacity = "0" + setTimeout(() => { + progressBar.style.width = "0" + }, 300) + } + + const resetProgressBar = () => { + progressBar.style.opacity = "0" + progressBar.style.width = "0" + } + const idDataMap = Object.keys(data) as FullSlug[] + const slugToIndex = new Map() + idDataMap.forEach((slug, idx) => slugToIndex.set(slug, idx)) + const modeToggle = searchSpace.querySelector(".search-mode-toggle") as HTMLDivElement | null + const modeButtons = modeToggle + ? Array.from(modeToggle.querySelectorAll(".mode-option")) + : [] + const appendLayout = (el: HTMLElement) => { searchLayout.appendChild(el) } const enablePreview = searchLayout.dataset.preview === "true" + if (!semantic && !semanticInitFailed) { + const client = new SemanticClient(semanticCfg) + try { + await client.ensureReady() + semantic = client + semanticReady = true + + // Load chunk metadata and IDs from manifest + try { + const manifestUrl = "/embeddings/manifest.json" + const res = await fetch(manifestUrl) + if (res.ok) { + const manifest = await res.json() + chunkMetadata = manifest.chunkMetadata || {} + manifestIds = manifest.ids || [] + console.debug( + `[Search] Loaded manifest: ${manifestIds.length} chunks, ${Object.keys(chunkMetadata).length} chunked documents`, + ) + } + } catch (err) { + console.warn("[Search] failed to load chunk metadata:", err) + chunkMetadata = {} + manifestIds = [] + } + } catch (err) { + console.warn("[SemanticClient] initialization failed:", err) + client.dispose() + semantic = null + semanticReady = false + semanticInitFailed = true + } + } else if (semantic && !semanticReady) { + try { + await semantic.ensureReady() + semanticReady = true + } catch (err) { + console.warn("[SemanticClient] became unavailable:", err) + semantic.dispose() + semantic = null + semanticReady = false + semanticInitFailed = true + } + } + const storedMode = loadStoredSearchMode() + if (storedMode === "semantic") { + if (semanticReady) { + searchMode = storedMode + } + } else if (storedMode === "lexical") { + searchMode = storedMode + } + if (!semanticReady && searchMode === "semantic") { + searchMode = "lexical" + } + let searchSeq = 0 + let runSearchTimer: number | null = null + let lastInputAt = 0 + searchLayout.dataset.mode = searchMode + + const updateModeUI = (mode: SearchMode) => { + modeButtons.forEach((button) => { + const btnMode = (button.dataset.mode as SearchMode) ?? "lexical" + const isActive = btnMode === mode + button.classList.toggle("active", isActive) + button.setAttribute("aria-pressed", String(isActive)) + }) + if (modeToggle) { + modeToggle.dataset.mode = mode + } + searchLayout.dataset.mode = mode + } + + const computeDebounceDelay = (term: string): number => { + const trimmed = term.trim() + const lastTerm = currentSearchTerm + const isExtension = + lastTerm.length > 0 && trimmed.length > lastTerm.length && trimmed.startsWith(lastTerm) + const isRetraction = lastTerm.length > trimmed.length + const isReplacement = + lastTerm.length > 0 && !trimmed.startsWith(lastTerm) && !lastTerm.startsWith(trimmed) + const baseFullQueryDelay = 200 + const semanticPenalty = searchMode === "semantic" ? 60 : 0 + + if (isExtension && trimmed.length > 2) { + return baseFullQueryDelay + semanticPenalty + } + + if (isReplacement && trimmed.length > 3) { + return Math.max(90, baseFullQueryDelay - 80) + } + + if (isRetraction) { + return 90 + } + + return baseFullQueryDelay + (searchMode === "semantic" ? 40 : 0) + } + + const triggerSearchWithMode = (mode: SearchMode) => { + if (mode === "semantic" && !semanticReady) { + return + } + if (searchMode === mode) return + searchMode = mode + updateModeUI(mode) + persistSearchMode(searchMode) + if (rawSearchTerm.trim() !== "") { + searchLayout.classList.add("display-results") + const token = ++searchSeq + void runSearch(rawSearchTerm, token) + } + } + + updateModeUI(searchMode) + + modeButtons.forEach((button) => { + const btnMode = (button.dataset.mode as SearchMode) ?? "lexical" + if (btnMode === "semantic") { + button.disabled = !semanticReady + button.setAttribute("aria-disabled", String(!semanticReady)) + } + const handler = () => triggerSearchWithMode(btnMode) + button.addEventListener("click", handler) + window.addCleanup(() => button.removeEventListener("click", handler)) + }) let preview: HTMLDivElement | undefined = undefined let previewInner: HTMLDivElement | undefined = undefined const results = document.createElement("div") @@ -193,18 +414,25 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: searchLayout.classList.remove("display-results") searchType = "basic" // reset search type after closing searchButton.focus() + resetProgressBar() } - function showSearch(searchTypeNew: SearchType) { - searchType = searchTypeNew - if (sidebar) sidebar.style.zIndex = "1" + function showSearch(type: SearchType) { container.classList.add("active") + if (type === "tags") { + searchBar.value = "#" + rawSearchTerm = "#" + } searchBar.focus() } let currentHover: HTMLInputElement | null = null + async function shortcutHandler(e: HTMLElementEventMap["keydown"]) { - if (e.key === "k" && (e.ctrlKey || e.metaKey) && !e.shiftKey) { + const paletteOpen = document.querySelector("search#palette-container") as HTMLDivElement + if (paletteOpen && paletteOpen.classList.contains("active")) return + + if ((e.key === "/" || e.key === "k") && (e.ctrlKey || e.metaKey) && !e.shiftKey) { e.preventDefault() const searchBarOpen = container.classList.contains("active") searchBarOpen ? hideSearch() : showSearch("basic") @@ -214,9 +442,6 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: e.preventDefault() const searchBarOpen = container.classList.contains("active") searchBarOpen ? hideSearch() : showSearch("tags") - - // add "#" prefix for tag search - searchBar.value = "#" return } @@ -226,20 +451,29 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: // If search is active, then we will render the first result and display accordingly if (!container.classList.contains("active")) return - if (e.key === "Enter" && !e.isComposing) { + if (e.key === "Enter") { // If result has focus, navigate to that one, otherwise pick first result + let anchor: HTMLAnchorElement | undefined if (results.contains(document.activeElement)) { - const active = document.activeElement as HTMLInputElement - if (active.classList.contains("no-match")) return - await displayPreview(active) - active.click() + anchor = document.activeElement as HTMLAnchorElement + if (anchor.classList.contains("no-match")) return + await displayPreview(anchor) + e.preventDefault() + anchor.click() } else { - const anchor = document.getElementsByClassName("result-card")[0] as HTMLInputElement | null + anchor = document.getElementsByClassName("result-card")[0] as HTMLAnchorElement if (!anchor || anchor.classList.contains("no-match")) return await displayPreview(anchor) + e.preventDefault() anchor.click() } - } else if (e.key === "ArrowUp" || (e.shiftKey && e.key === "Tab")) { + if (anchor !== undefined) + window.spaNavigate(new URL(new URL(anchor.href).pathname, window.location.toString())) + } else if ( + e.key === "ArrowUp" || + (e.shiftKey && e.key === "Tab") || + (e.ctrlKey && e.key === "p") + ) { e.preventDefault() if (results.contains(document.activeElement)) { // If an element in results-container already has focus, focus previous one @@ -252,7 +486,7 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: if (prevResult) currentHover = prevResult await displayPreview(prevResult) } - } else if (e.key === "ArrowDown" || e.key === "Tab") { + } else if (e.key === "ArrowDown" || e.key === "Tab" || (e.ctrlKey && e.key === "n")) { e.preventDefault() // The results should already been focused, so we need to find the next one. // The activeElement is the search bar, so we need to find the first result and focus it. @@ -269,25 +503,40 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: } } - const formatForDisplay = (term: string, id: number) => { + const formatForDisplay = (term: string, id: number, renderType: SearchType) => { const slug = idDataMap[id] + const aliases: string[] = data[slug].aliases ?? [] + const target = aliases.find((alias) => alias.toLowerCase().includes(term.toLowerCase())) ?? "" + + // Check if query contains title words (for boosting exact matches) + const queryTokens = tokenizeTerm(term) + const titleTokens = tokenizeTerm(data[slug].title ?? "") + const titleMatch = titleTokens.some((t) => queryTokens.includes(t)) + return { id, slug, - title: searchType === "tags" ? data[slug].title : highlight(term, data[slug].title ?? ""), + title: + renderType === "tags" || target + ? data[slug].title + : highlight(term, data[slug].title ?? ""), + target, content: highlight(term, data[slug].content ?? "", true), - tags: highlightTags(term.substring(1), data[slug].tags), + tags: highlightTags(term, data[slug].tags, renderType), + aliases: aliases, + titleMatch, // Add title match flag for boosting } } - function highlightTags(term: string, tags: string[]) { - if (!tags || searchType !== "tags") { + function highlightTags(term: string, tags: string[], renderType: SearchType) { + if (!tags || renderType !== "tags") { return [] } + const tagTerm = term.toLowerCase() return tags .map((tag) => { - if (tag.toLowerCase().includes(term.toLowerCase())) { + if (tag.toLowerCase().includes(tagTerm)) { return `
  • #${tag}

  • ` } else { return `
  • #${tag}

  • ` @@ -300,24 +549,40 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: return new URL(resolveRelative(currentSlug, slug), location.toString()) } - const resultToHTML = ({ slug, title, content, tags }: Item) => { + const resultToHTML = ({ item, percent }: { item: Item; percent: number | null }) => { + const { slug, title, content, tags, target } = item const htmlTags = tags.length > 0 ? `
      ${tags.join("")}
    ` : `` const itemTile = document.createElement("a") + const titleContent = target ? highlight(currentSearchTerm, target) : title + const subscript = target ? `${slug}` : `` + let percentLabel = "—" + let percentAttr = "" + if (percent !== null && Number.isFinite(percent)) { + const bounded = Math.max(0, Math.min(100, percent)) + percentLabel = `${bounded.toFixed(1)}%` + percentAttr = bounded.toFixed(3) + } itemTile.classList.add("result-card") itemTile.id = slug itemTile.href = resolveUrl(slug).toString() - itemTile.innerHTML = ` -

    ${title}

    - ${htmlTags} -

    ${content}

    - ` - itemTile.addEventListener("click", (event) => { - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return - hideSearch() - }) + itemTile.innerHTML = `
    +

    ${titleContent}

    + ${subscript}${htmlTags} + ${searchMode === "semantic" ? ` ${percentLabel}` : ""} + ${enablePreview && window.innerWidth > 600 ? "" : `

    ${content}

    `} +
    ` + if (percentAttr) itemTile.dataset.scorePercent = percentAttr + else delete itemTile.dataset.scorePercent - const handler = (event: MouseEvent) => { - if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return + const handler = (evt: MouseEvent) => { + if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return + const anchor = evt.currentTarget as HTMLAnchorElement | null + if (!anchor) return + evt.preventDefault() + const href = anchor.getAttribute("href") + if (!href) return + const url = new URL(href, window.location.toString()) + window.spaNavigate(url) hideSearch() } @@ -335,15 +600,22 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: return itemTile } - async function displayResults(finalResults: Item[]) { + async function displayResults(finalResults: SimilarityResult[]) { removeAllChildren(results) if (finalResults.length === 0) { results.innerHTML = `

    No results.

    Try another search term?

    ` + currentHover = null } else { - results.append(...finalResults.map(resultToHTML)) + const decorated = finalResults.map(({ item, similarity }) => { + if (!Number.isFinite(similarity)) return { item, percent: null } + const bounded = Math.max(-1, Math.min(1, similarity)) + const percent = ((bounded + 1) / 2) * 100 + return { item, percent } + }) + results.append(...decorated.map(resultToHTML)) } if (finalResults.length === 0 && preview) { @@ -363,8 +635,8 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: return fetchContentCache.get(slug) as Element[] } - const targetUrl = resolveUrl(slug).toString() - const contents = await fetch(targetUrl) + const targetUrl = resolveUrl(slug) + const contents = await fetchCanonical(targetUrl) .then((res) => res.text()) .then((contents) => { if (contents === undefined) { @@ -394,73 +666,297 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: const highlights = [...preview.getElementsByClassName("highlight")].sort( (a, b) => b.innerHTML.length - a.innerHTML.length, ) - highlights[0]?.scrollIntoView({ block: "start" }) + if (highlights.length > 0) { + const highlight = highlights[0] + const container = preview + if (container && highlight) { + // Get the relative positions + const containerRect = container.getBoundingClientRect() + const highlightRect = highlight.getBoundingClientRect() + // Calculate the scroll position relative to the container + const relativeTop = highlightRect.top - containerRect.top + container.scrollTop - 20 // 20px buffer + // Smoothly scroll the container + container.scrollTo({ + top: relativeTop, + behavior: "smooth", + }) + } + } } - async function onType(e: HTMLElementEventMap["input"]) { + async function runSearch(rawTerm: string, token: number) { if (!searchLayout || !index) return - currentSearchTerm = (e.target as HTMLInputElement).value - searchLayout.classList.toggle("display-results", currentSearchTerm !== "") - searchType = currentSearchTerm.startsWith("#") ? "tags" : "basic" + const trimmed = rawTerm.trim() + if (trimmed === "") { + removeAllChildren(results) + if (preview) { + removeAllChildren(preview) + } + currentHover = null + searchLayout.classList.remove("display-results") + resetProgressBar() + return + } - let searchResults: DefaultDocumentSearchResults - if (searchType === "tags") { - currentSearchTerm = currentSearchTerm.substring(1).trim() - const separatorIndex = currentSearchTerm.indexOf(" ") - if (separatorIndex != -1) { - // search by title and content index and then filter by tag (implemented in flexsearch) - const tag = currentSearchTerm.substring(0, separatorIndex) - const query = currentSearchTerm.substring(separatorIndex + 1).trim() - searchResults = await index.searchAsync({ - query: query, - // return at least 10000 documents, so it is enough to filter them by tag (implemented in flexsearch) + const modeForRanking: SearchMode = searchMode + const initialType: SearchType = trimmed.startsWith("#") ? "tags" : "basic" + let workingType: SearchType = initialType + let highlightTerm = trimmed + let tagTerm = "" + let searchResults: DefaultDocumentSearchResults = [] + + if (initialType === "tags") { + tagTerm = trimmed.substring(1).trim() + const separatorIndex = tagTerm.indexOf(" ") + if (separatorIndex !== -1) { + const tag = tagTerm.substring(0, separatorIndex).trim() + const query = tagTerm.substring(separatorIndex + 1).trim() + const results = await index.searchAsync({ + query, limit: Math.max(numSearchResults, 10000), - index: ["title", "content"], + index: ["title", "content", "aliases"], tag: { tags: tag }, }) - for (let searchResult of searchResults) { - searchResult.result = searchResult.result.slice(0, numSearchResults) - } - // set search type to basic and remove tag from term for proper highlightning and scroll - searchType = "basic" - currentSearchTerm = query + if (token !== searchSeq) return + searchResults = Object.values(results) + workingType = "basic" + highlightTerm = query } else { - // default search by tags index - searchResults = await index.searchAsync({ - query: currentSearchTerm, + const results = await index.searchAsync({ + query: tagTerm, limit: numSearchResults, index: ["tags"], }) + if (token !== searchSeq) return + searchResults = Object.values(results) + highlightTerm = tagTerm } - } else if (searchType === "basic") { - searchResults = await index.searchAsync({ - query: currentSearchTerm, + } else { + const results = await index.searchAsync({ + query: highlightTerm, limit: numSearchResults, - index: ["title", "content"], + index: ["title", "content", "aliases"], }) + if (token !== searchSeq) return + searchResults = Object.values(results) + } + + const coerceIds = (hit?: DefaultDocumentSearchResults[number]): number[] => { + if (!hit) return [] + return hit.result + .map((value: Id) => { + if (typeof value === "number") { + return value + } + const parsed = Number.parseInt(String(value), 10) + return Number.isNaN(parsed) ? null : parsed + }) + .filter((value): value is number => value !== null) } const getByField = (field: string): number[] => { - const results = searchResults.filter((x) => x.field === field) - return results.length === 0 ? [] : ([...results[0].result] as number[]) + const hit = searchResults.find((x) => x.field === field) + return coerceIds(hit) } - // order titles ahead of content const allIds: Set = new Set([ + ...getByField("aliases"), ...getByField("title"), ...getByField("content"), ...getByField("tags"), ]) - const finalResults = [...allIds].map((id) => formatForDisplay(currentSearchTerm, id)) - await displayResults(finalResults) + + currentSearchTerm = highlightTerm + + const candidateItems = new Map() + const ensureItem = (id: number): Item | null => { + const slug = idDataMap[id] + if (!slug) return null + const cached = candidateItems.get(slug) + if (cached) return cached + const item = formatForDisplay(highlightTerm, id, workingType) + if (item) { + candidateItems.set(slug, item) + return item + } + return null + } + + const baseIndices: number[] = [] + for (const id of allIds) { + const item = ensureItem(id) + if (!item) continue + const idx = slugToIndex.get(item.slug) + if (typeof idx === "number") { + baseIndices.push(idx) + } + } + + let semanticIds: number[] = [] + const semanticSimilarity = new Map() + + const integrateIds = (ids: number[]) => { + ids.forEach((docId) => { + ensureItem(docId) + }) + } + + const orchestrator = semanticReady && semantic ? semantic : null + + const resolveSimilarity = (item: Item): number => { + const semanticHit = semanticSimilarity.get(item.id) + return semanticHit ?? Number.NaN + } + + const render = async () => { + if (token !== searchSeq) return + const useSemantic = semanticReady && semanticIds.length > 0 + const weights = + modeForRanking === "semantic" && useSemantic + ? { base: 0.3, semantic: 1.0 } + : { base: 1.0, semantic: useSemantic ? 0.3 : 0 } + const rrf = new Map() + const push = (ids: number[], weight: number, applyTitleBoost: boolean = false) => { + if (!ids.length || weight <= 0) return + ids.forEach((docId, rank) => { + const slug = idDataMap[docId] + if (!slug) return + const item = ensureItem(docId) + if (!item) return + + // Apply title boost for FlexSearch results (1.5x boost for exact title matches) + let effectiveWeight = weight + if (applyTitleBoost && item.titleMatch) { + effectiveWeight *= 1.5 + } + + const prev = rrf.get(slug) ?? 0 + rrf.set(slug, prev + effectiveWeight / (1 + rank)) + }) + } + + push(baseIndices, weights.base, true) // FlexSearch with title boost + push(semanticIds, weights.semantic, false) // Semantic without boost + + const rankedEntries = Array.from(candidateItems.values()) + .map((item) => ({ item, score: rrf.get(item.slug) ?? 0 })) + .sort((a, b) => b.score - a.score) + .slice(0, numSearchResults) + + const displayEntries: SimilarityResult[] = [] + for (const entry of rankedEntries) { + const similarity = resolveSimilarity(entry.item) + displayEntries.push({ item: entry.item, similarity }) + } + + await displayResults(displayEntries) + } + + await render() + + if (workingType === "tags" || !orchestrator || !semanticReady || highlightTerm.length < 2) { + return + } + + const showProgress = modeForRanking === "semantic" + if (showProgress) { + startSemanticProgress() + } + + try { + const { semantic: semRes } = await orchestrator.search( + highlightTerm, + numSearchResults * 3, // Request more chunks to ensure good document coverage + ) + if (token !== searchSeq) { + if (showProgress) completeSemanticProgress() + return + } + + // Aggregate chunk results to document level using RRF + const { rrfScores: semRrfScores, maxScores: semMaxScores } = aggregateChunkResults( + semRes, + slugToIndex, + ) + + // Use RRF scores for ranking + semanticIds = Array.from(semRrfScores.entries()) + .sort((a, b) => b[1] - a[1]) + .slice(0, numSearchResults) + .map(([docIdx]) => docIdx) + + // Use max chunk similarity for display (0-1 range) + semanticSimilarity.clear() + semMaxScores.forEach((score, docIdx) => { + semanticSimilarity.set(docIdx, score) + }) + + integrateIds(semanticIds) + if (showProgress) completeSemanticProgress() + } catch (err) { + console.warn("[SemanticClient] search failed:", err) + if (showProgress) completeSemanticProgress() + orchestrator.dispose() + semantic = null + semanticReady = false + semanticInitFailed = true + if (searchMode === "semantic") { + searchMode = "lexical" + updateModeUI(searchMode) + } + modeButtons.forEach((button) => { + if ((button.dataset.mode as SearchMode) === "semantic") { + button.disabled = true + button.setAttribute("aria-disabled", "true") + } + }) + } + + await render() + } + + function onType(e: HTMLElementEventMap["input"]) { + if (!searchLayout || !index) return + rawSearchTerm = (e.target as HTMLInputElement).value + const hasQuery = rawSearchTerm.trim() !== "" + searchLayout.classList.toggle("display-results", hasQuery) + const term = rawSearchTerm + const token = ++searchSeq + if (runSearchTimer !== null) { + window.clearTimeout(runSearchTimer) + runSearchTimer = null + } + if (!hasQuery) { + void runSearch("", token) + return + } + const now = performance.now() + lastInputAt = now + const delay = computeDebounceDelay(term) + const scheduledAt = lastInputAt + runSearchTimer = window.setTimeout(() => { + if (scheduledAt !== lastInputAt) { + return + } + runSearchTimer = null + void runSearch(term, token) + }, delay) } document.addEventListener("keydown", shortcutHandler) window.addCleanup(() => document.removeEventListener("keydown", shortcutHandler)) - searchButton.addEventListener("click", () => showSearch("basic")) - window.addCleanup(() => searchButton.removeEventListener("click", () => showSearch("basic"))) + const openHandler = () => showSearch("basic") + searchButton.addEventListener("click", openHandler) + window.addCleanup(() => searchButton.removeEventListener("click", openHandler)) searchBar.addEventListener("input", onType) window.addCleanup(() => searchBar.removeEventListener("input", onType)) + window.addCleanup(() => { + if (runSearchTimer !== null) { + window.clearTimeout(runSearchTimer) + runSearchTimer = null + } + resetProgressBar() + }) registerEscapeHandler(container, hideSearch) await fillDocument(data) @@ -468,24 +964,26 @@ async function setupSearch(searchElement: Element, currentSlug: FullSlug, data: /** * Fills flexsearch document with data - * @param index index to fill * @param data data to fill index with */ let indexPopulated = false async function fillDocument(data: ContentIndex) { if (indexPopulated) return let id = 0 - const promises: Array> = [] + const promises = [] for (const [slug, fileData] of Object.entries(data)) { promises.push( - index.addAsync(id++, { + //@ts-ignore + index.addAsync({ id, slug: slug as FullSlug, title: fileData.title, content: fileData.content, tags: fileData.tags, + aliases: fileData.aliases, }), ) + id++ } await Promise.all(promises) @@ -495,7 +993,9 @@ async function fillDocument(data: ContentIndex) { document.addEventListener("nav", async (e: CustomEventMap["nav"]) => { const currentSlug = e.detail.url const data = await fetchData - const searchElement = document.getElementsByClassName("search") + const searchElement = document.getElementsByClassName( + "search", + ) as HTMLCollectionOf for (const element of searchElement) { await setupSearch(element, currentSlug, data) } diff --git a/quartz/components/scripts/semantic.inline.ts b/quartz/components/scripts/semantic.inline.ts new file mode 100644 index 000000000..167091c02 --- /dev/null +++ b/quartz/components/scripts/semantic.inline.ts @@ -0,0 +1,182 @@ +export type SemanticResult = { id: number; score: number } + +type ProgressMessage = { + type: "progress" + loadedRows: number + totalRows: number +} + +type ReadyMessage = { type: "ready" } + +type ResultMessage = { + type: "search-result" + seq: number + semantic: SemanticResult[] +} + +type ErrorMessage = { type: "error"; seq?: number; message: string } + +type SearchPayload = { + semantic: SemanticResult[] +} + +type PendingResolver = { + resolve: (payload: SearchPayload) => void + reject: (err: Error) => void +} + +export class SemanticClient { + private ready: Promise + private resolveReady!: () => void + private worker: Worker | null = null + private pending = new Map() + private seq = 0 + private disposed = false + private readySettled = false + private configured = false + private lastError: Error | null = null + + constructor(private cfg?: any) { + this.ready = new Promise((resolve) => { + this.resolveReady = () => { + if (this.readySettled) return + this.readySettled = true + resolve() + } + }) + + if (this.cfg?.enable === false) { + this.lastError = new Error("semantic search disabled by configuration") + this.resolveReady() + return + } + + this.boot() + } + + private boot() { + try { + this.worker = new Worker("/semantic.worker.js", { type: "module" }) + } catch (err) { + this.handleFatal(err) + return + } + this.setupWorker() + this.startInit() + } + + private setupWorker() { + if (!this.worker) return + this.worker.onmessage = ( + event: MessageEvent, + ) => { + const msg = event.data + if (msg.type === "progress") { + // Progress updates during initialization - can be logged if needed + return + } + if (msg.type === "ready") { + this.configured = true + this.lastError = null + this.resolveReady() + return + } + if (msg.type === "search-result") { + const pending = this.pending.get(msg.seq) + if (pending) { + this.pending.delete(msg.seq) + pending.resolve({ semantic: msg.semantic ?? [] }) + } + return + } + if (msg.type === "error") { + if (typeof msg.seq === "number") { + const pending = this.pending.get(msg.seq) + if (pending) { + this.pending.delete(msg.seq) + pending.reject(new Error(msg.message)) + } + } else { + this.handleFatal(msg.message) + } + } + } + } + + private startInit() { + if (!this.worker) return + const manifestUrl = + typeof this.cfg?.manifestUrl === "string" && this.cfg.manifestUrl.length > 0 + ? this.cfg.manifestUrl + : "/embeddings/manifest.json" + const disableCache = Boolean(this.cfg?.disableCache) + const baseUrl = + typeof this.cfg?.manifestBaseUrl === "string" ? this.cfg.manifestBaseUrl : undefined + this.worker.postMessage({ + type: "init", + cfg: this.cfg, + manifestUrl, + baseUrl, + disableCache, + }) + } + + private rejectAll(err: Error, fatal = false) { + for (const [id, pending] of this.pending.entries()) { + pending.reject(err) + this.pending.delete(id) + } + if (fatal) { + this.lastError = err + this.configured = false + if (!this.readySettled) { + this.resolveReady() + } + } + } + + private handleFatal(err: unknown) { + const error = err instanceof Error ? err : new Error(String(err)) + console.error("[SemanticClient] initialization failure:", error) + this.rejectAll(error, true) + if (this.worker) { + this.worker.postMessage({ type: "reset" }) + this.worker.terminate() + this.worker = null + } + } + + async ensureReady() { + await this.ready + if (!this.configured) { + throw this.lastError ?? new Error("semantic search unavailable") + } + } + + async search(text: string, k: number): Promise { + if (this.disposed) { + throw new Error("semantic client has been disposed") + } + await this.ensureReady() + if (!this.worker || !this.configured) { + throw this.lastError ?? new Error("worker unavailable") + } + return new Promise((resolve, reject) => { + const seq = ++this.seq + this.pending.set(seq, { resolve, reject }) + this.worker?.postMessage({ type: "search", text, k, seq }) + }) + } + + dispose() { + if (this.disposed) return + this.disposed = true + this.rejectAll(new Error("semantic client disposed")) + if (this.worker) { + this.worker.postMessage({ type: "reset" }) + this.worker.terminate() + } + this.worker = null + this.configured = false + } +} diff --git a/quartz/components/scripts/util.ts b/quartz/components/scripts/util.ts index f71790104..de0681f78 100644 --- a/quartz/components/scripts/util.ts +++ b/quartz/components/scripts/util.ts @@ -44,3 +44,68 @@ export async function fetchCanonical(url: URL): Promise { const [_, redirect] = text.match(canonicalRegex) ?? [] return redirect ? fetch(`${new URL(redirect, url)}`) : res } + +const contextWindowWords = 30 +export const tokenizeTerm = (term: string) => { + const tokens = term.split(/\s+/).filter((t) => t.trim() !== "") + const tokenLen = tokens.length + if (tokenLen > 1) { + for (let i = 1; i < tokenLen; i++) { + tokens.push(tokens.slice(0, i + 1).join(" ")) + } + } + + return tokens.sort((a, b) => b.length - a.length) // always highlight longest terms first +} + +export function highlight(searchTerm: string, text: string, trim?: boolean) { + const tokenizedTerms = tokenizeTerm(searchTerm) + let tokenizedText = text.split(/\s+/).filter((t) => t !== "") + + let startIndex = 0 + let endIndex = tokenizedText.length - 1 + if (trim) { + const includesCheck = (tok: string) => + tokenizedTerms.some((term) => tok.toLowerCase().startsWith(term.toLowerCase())) + const occurrencesIndices = tokenizedText.map(includesCheck) + + let bestSum = 0 + let bestIndex = 0 + for (let i = 0; i < Math.max(tokenizedText.length - contextWindowWords, 0); i++) { + const window = occurrencesIndices.slice(i, i + contextWindowWords) + const windowSum = window.reduce((total, cur) => total + (cur ? 1 : 0), 0) + if (windowSum >= bestSum) { + bestSum = windowSum + bestIndex = i + } + } + + startIndex = Math.max(bestIndex - contextWindowWords, 0) + endIndex = Math.min(startIndex + 2 * contextWindowWords, tokenizedText.length - 1) + tokenizedText = tokenizedText.slice(startIndex, endIndex) + } + + const slice = tokenizedText + .map((tok) => { + // see if this tok is prefixed by any search terms + for (const searchTok of tokenizedTerms) { + if (tok.toLowerCase().includes(searchTok.toLowerCase())) { + const regex = new RegExp(searchTok.toLowerCase(), "gi") + return tok.replace(regex, `$&`) + } + } + return tok + }) + .join(" ") + + return `${startIndex === 0 ? "" : "..."}${slice}${ + endIndex === tokenizedText.length - 1 ? "" : "..." + }` +} + +// To be used with search and everything else with flexsearch +export const encode = (str: string) => + str + .toLowerCase() + .split(/\s+/) + .filter((token) => token.length > 0) diff --git a/quartz/components/styles/search.scss b/quartz/components/styles/search.scss index bb58948ae..685f0fc31 100644 --- a/quartz/components/styles/search.scss +++ b/quartz/components/styles/search.scss @@ -77,16 +77,97 @@ margin-bottom: 2em; } - & > input { + & > .input-container { + align-items: center; + gap: 0.5rem; + display: flex; + flex-wrap: wrap; + position: relative; box-sizing: border-box; - padding: 0.5em 1em; - font-family: var(--bodyFont); - color: var(--dark); - font-size: 1.1em; - border: 1px solid var(--lightgray); - &:focus { - outline: none; + .search-bar { + flex: 1 1 auto; + min-width: 0; + box-sizing: border-box; + padding: 0.5em 1em; + font-family: var(--bodyFont); + color: var(--dark); + font-size: 1.1em; + border: none; + background: transparent; + + &:focus { + outline: none; + } + } + + .semantic-search-progress { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 2px; + background-color: var(--secondary); + width: 0; + opacity: 0; + transition: + width 0.3s ease, + opacity 0.2s ease; + pointer-events: none; + } + + .search-mode-toggle { + display: inline-flex; + align-items: center; + border-radius: 9999px; + height: 1.4rem; + background-color: color-mix(in srgb, var(--darkgray) 12%, transparent); + margin-right: 1rem; + + .mode-option { + border: none; + background: transparent; + font: inherit; + color: var(--gray); + border-radius: 9999px; + cursor: pointer; + transition: + background-color 0.2s ease, + color 0.2s ease; + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.5rem; + height: 1.5rem; + position: relative; + + &:focus-visible { + outline: 2px solid var(--tertiary); + outline-offset: 2px; + } + + &.active { + background-color: var(--secondary); + color: var(--light); + } + + svg { + width: 18px; + height: 18px; + } + + .sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + } + } } } diff --git a/quartz/embed_build.py b/quartz/embed_build.py new file mode 100644 index 000000000..63ade1be5 --- /dev/null +++ b/quartz/embed_build.py @@ -0,0 +1,542 @@ +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "langchain-text-splitters", +# "numpy", +# "openai", +# "sentence-transformers", +# "tiktoken", +# ] +# /// + +from __future__ import annotations + +import os, json, argparse, hashlib, math, random, logging + +from pathlib import Path +from functools import lru_cache +from collections.abc import Iterable +from concurrent.futures import ThreadPoolExecutor, as_completed + +import tiktoken, numpy as np + +from openai import OpenAI +from langchain_text_splitters import RecursiveCharacterTextSplitter + + +logger = logging.getLogger(__name__) +DEFAULT_VLLM_URL = os.environ.get("VLLM_URL") or os.environ.get("VLLM_EMBED_URL") or "http://127.0.0.1:8000/v1" + + +def resolve_vllm_base_url(url: str) -> str: + if not url: + raise ValueError("vLLM URL must be non-empty") + + trimmed = url.rstrip("/") + if trimmed.endswith("/v1/embeddings"): + trimmed = trimmed[: -len("/embeddings")] + elif trimmed.endswith("/embeddings"): + trimmed = trimmed[: trimmed.rfind("/")] + + if not trimmed.endswith("/v1"): + trimmed = f"{trimmed}/v1" + + return trimmed + + +def load_jsonl(fp: str) -> Iterable[dict]: + with open(fp, "r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line: + continue + yield json.loads(line) + + +def l2_normalize_rows(x: np.ndarray) -> np.ndarray: + # x: [N, D] + norms = np.linalg.norm(x, ord=2, axis=1, keepdims=True) + norms[norms == 0] = 1.0 + return x / norms + + +@lru_cache(maxsize=1) +def get_tiktoken_encoder(): + # Get the o200k_base tokenizer (GPT-4o) with caching + # change this if you want something else. + return tiktoken.get_encoding("o200k_base") + + +def count_tokens(text: str) -> int: + # Count tokens using o200k_base encoding + encoder = get_tiktoken_encoder() + return len(encoder.encode(text)) + + +def get_text_splitter(chunk_size: int, overlap: int): + encoder = get_tiktoken_encoder() + return RecursiveCharacterTextSplitter( + chunk_size=chunk_size * 4, # character approximation + chunk_overlap=overlap * 4, + separators=["\n\n", "\n", ". ", " ", ""], + length_function=lambda t: len(encoder.encode(t)), + is_separator_regex=False, + ) + + +def chunk_document( + doc: dict, max_tokens: int = 512, overlap_tokens: int = 128, min_chunk_size: int = 100 +) -> list[dict]: + """ + Chunk a document if it exceeds max_tokens + + Args: + doc: {'slug': str, 'title': str, 'text': str} + max_tokens: Maximum tokens per chunk + overlap_tokens: Overlap between chunks + min_chunk_size: Minimum chunk size (avoid tiny chunks) + + Returns: + List of chunk dicts with metadata + """ + text = doc["text"] + token_count = count_tokens(text) + + # No chunking needed + if token_count <= max_tokens: + return [ + { + "slug": doc["slug"], + "title": doc.get("title", doc["slug"]), + "text": text, + "chunk_id": 0, + "parent_slug": doc["slug"], + "is_chunked": False, + } + ] + + # Apply chunking + splitter = get_text_splitter(max_tokens, overlap_tokens) + raw_chunks = splitter.split_text(text) + + # Filter out tiny chunks + valid_chunks = [c for c in raw_chunks if count_tokens(c) >= min_chunk_size] + + return [ + { + "slug": f"{doc['slug']}#chunk{i}", + "title": doc.get("title", doc["slug"]), + "text": chunk, + "chunk_id": i, + "parent_slug": doc["slug"], + "is_chunked": True, + } + for i, chunk in enumerate(valid_chunks) + ] + + +def write_shards(vectors: np.ndarray, shard_size: int, dtype: str, out_dir: Path) -> list[dict]: + out_dir.mkdir(parents=True, exist_ok=True) + rows, dims = vectors.shape + shards_meta: list[dict] = [] + np_dtype = np.float16 if dtype == "fp16" else np.float32 + bytes_per_value = np.dtype(np_dtype).itemsize + row_offset = 0 + for si, start in enumerate(range(0, rows, shard_size)): + end = min(start + shard_size, rows) + shard = vectors[start:end] # [n, dims] + bin_path = out_dir / f"vectors-{si:03d}.bin" + payload = shard.astype(np_dtype, copy=False).tobytes(order="C") + digest = hashlib.sha256(payload).hexdigest() + with open(bin_path, "wb") as f: + f.write(payload) + shard_rows = int(shard.shape[0]) + shards_meta.append( + { + "path": f"/embeddings/{bin_path.name}", + "rows": shard_rows, + "rowOffset": row_offset, + "byteLength": len(payload), + "sha256": digest, + "byteStride": dims * bytes_per_value, + }, + ) + row_offset += shard_rows + return shards_meta + + +def write_hnsw_graph(levels: list[list[list[int]]], rows: int, out_path: Path) -> tuple[list[dict], str]: + out_path.parent.mkdir(parents=True, exist_ok=True) + offset = 0 + meta: list[dict] = [] + digest = hashlib.sha256() + with open(out_path, "wb") as f: + for lvl in levels: + indptr = np.zeros(rows + 1, dtype=np.uint32) + edge_accum: list[int] = [] + for idx in range(rows): + neighbors = lvl[idx] if idx < len(lvl) else [] + indptr[idx + 1] = indptr[idx] + len(neighbors) + edge_accum.extend(neighbors) + indptr_bytes = indptr.tobytes(order="C") + indptr_offset = offset + f.write(indptr_bytes) + digest.update(indptr_bytes) + offset += len(indptr_bytes) + + if edge_accum: + indices = np.asarray(edge_accum, dtype=np.uint32) + indices_bytes = indices.tobytes(order="C") + else: + indices = np.zeros(0, dtype=np.uint32) + indices_bytes = indices.tobytes(order="C") + indices_offset = offset + f.write(indices_bytes) + digest.update(indices_bytes) + offset += len(indices_bytes) + + meta.append( + { + "level": len(meta), + "indptr": { + "offset": indptr_offset, + "elements": int(indptr.shape[0]), + "byteLength": len(indptr_bytes), + }, + "indices": { + "offset": indices_offset, + "elements": int(indices.shape[0]), + "byteLength": len(indices_bytes), + }, + }, + ) + return meta, digest.hexdigest() + + + +def embed_vllm( + texts: list[str], + model_id: str, + vllm_url: str, + batch_size: int = 64, + concurrency: int = 8, +) -> np.ndarray: + base_url = resolve_vllm_base_url(vllm_url) + api_key = os.environ.get("VLLM_API_KEY") or os.environ.get("OPENAI_API_KEY") or "not-set" + client = OpenAI(base_url=base_url, api_key=api_key, timeout=300) + + def list_available_models() -> list[str]: + models: list[str] = [] + page = client.models.list() + models.extend(model.id for model in page.data) + while getattr(page, "has_more", False) and page.data: + cursor = page.data[-1].id + page = client.models.list(after=cursor) + models.extend(model.id for model in page.data) + return models + + try: + available_models = list_available_models() + except Exception as exc: + raise RuntimeError(f"failed to query {base_url}/models: {exc}") from exc + + if model_id not in available_models: + suggestions = ", ".join(sorted(available_models)) if available_models else "" + logger.warning( + "model '%s' not served by vLLM at %s. Available models: %s. Use the first model, results may differ during semantic search (you can omit this message if your weights is a ONNX checkpoint of the same model.)", model_id, base_url, suggestions, + ) + model_id = available_models[0] + + # Apply model-specific prefixes for documents (asymmetric search) + model_lower = model_id.lower() + if "e5" in model_lower: + # E5 models: use "passage:" prefix for documents + prefixed = [f"passage: {t}" for t in texts] + elif "qwen" in model_lower and "embedding" in model_lower: + # Qwen3-Embedding: documents use plain text (no prefix) + prefixed = texts + elif "embeddinggemma" in model_lower: + # embeddinggemma: use "title: none | text:" prefix for documents + prefixed = [f"title: none | text: {t}" for t in texts] + else: + # Default: no prefix for unknown models + prefixed = texts + + print( + "Embedding" + f" {len(prefixed)} texts with vLLM" + f" (model={model_id}, batch_size={batch_size}, concurrency={concurrency})", + ) + + # Create batches + batches = [] + for i in range(0, len(prefixed), batch_size): + batch = prefixed[i : i + batch_size] + batches.append((i, batch)) + + # Function to send a single batch request + def send_batch(batch_info: tuple[int, list[str]]) -> tuple[int, list[np.ndarray]]: + idx, batch = batch_info + response = client.embeddings.create(model=model_id, input=batch) + embeddings = [np.asarray(item.embedding, dtype=np.float32) for item in response.data] + return (idx, embeddings) + + # Send batches concurrently (or sequentially if only 1 batch) + results: dict[int, list[np.ndarray]] = {} + if len(batches) == 1: + # Single batch - no need for threading + idx, embeddings = send_batch(batches[0]) + results[idx] = embeddings + else: + # Multiple batches - use concurrent requests + with ThreadPoolExecutor(max_workers=concurrency) as executor: + futures = {executor.submit(send_batch, batch_info): batch_info[0] for batch_info in batches} + completed = 0 + for future in as_completed(futures): + idx, embeddings = future.result() + results[idx] = embeddings + completed += 1 + if completed % max(1, len(batches) // 10) == 0 or completed == len(batches): + print(f" Completed {completed}/{len(batches)} batches ({completed * 100 // len(batches)}%)") + + # Reconstruct in order + out: list[np.ndarray] = [] + for i in sorted(results.keys()): + out.extend(results[i]) + + return np.stack(out, axis=0) + + +def embed_hf(texts: list[str], model_id: str, device: str) -> np.ndarray: + # Prefer sentence-transformers for E5 and similar embed models + from sentence_transformers import SentenceTransformer + + model = SentenceTransformer(model_id, device=device) + + # Apply model-specific prefixes for documents (asymmetric search) + model_lower = model_id.lower() + if "e5" in model_lower: + # E5 models: use "passage:" prefix for documents + prefixed = [f"passage: {t}" for t in texts] + elif "qwen" in model_lower and "embedding" in model_lower: + # Qwen3-Embedding: documents use plain text (no prefix) + prefixed = texts + elif "embeddinggemma" in model_lower: + # embeddinggemma: use "title: none | text:" prefix for documents + prefixed = [f"title: none | text: {t}" for t in texts] + else: + # Default: no prefix for unknown models + prefixed = texts + + vecs = model.encode( + prefixed, + batch_size=64, + normalize_embeddings=True, + convert_to_numpy=True, + show_progress_bar=True, + ) + return vecs.astype(np.float32, copy=False) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--jsonl", default="public/embeddings-text.jsonl") + ap.add_argument("--model", default=os.environ.get("SEM_MODEL", "intfloat/multilingual-e5-large")) + ap.add_argument("--dims", type=int, default=int(os.environ.get("SEM_DIMS", "1024"))) + ap.add_argument("--dtype", choices=["fp16", "fp32"], default=os.environ.get("SEM_DTYPE", "fp32")) + ap.add_argument("--shard-size", type=int, default=int(os.environ.get("SEM_SHARD", "1024"))) + ap.add_argument("--out", default="public/embeddings") + ap.add_argument("--use-vllm", action="store_true", default=bool(os.environ.get("USE_VLLM", ""))) + ap.add_argument( + "--vllm-url", + default=DEFAULT_VLLM_URL, + help="Base URL for the vLLM OpenAI-compatible server (accepts either /v1 or /v1/embeddings)", + ) + ap.add_argument("--chunk-size", type=int, default=512, help="Max tokens per chunk") + ap.add_argument("--chunk-overlap", type=int, default=128, help="Overlap tokens between chunks") + ap.add_argument("--no-chunking", action="store_true", help="Disable chunking (embed full docs)") + ap.add_argument( + "--concurrency", + type=int, + default=int(os.environ.get("VLLM_CONCURRENCY", "8")), + help="Number of concurrent requests to vLLM (default: 8)", + ) + ap.add_argument( + "--batch-size", + type=int, + default=int(os.environ.get("VLLM_BATCH_SIZE", "64")), + help="Batch size for vLLM requests (default: 64)", + ) + args = ap.parse_args() + + recs = list(load_jsonl(args.jsonl)) + if not recs: + print("No input found in public/embeddings-text.jsonl; run the site build first to emit JSONL.") + return + + # Apply chunking + if args.no_chunking: + chunks = recs + chunk_metadata = {} + print(f"Chunking disabled. Processing {len(chunks)} full documents") + else: + chunks = [] + chunk_metadata = {} + for rec in recs: + doc_chunks = chunk_document(rec, max_tokens=args.chunk_size, overlap_tokens=args.chunk_overlap) + chunks.extend(doc_chunks) + # Build chunk metadata map + for chunk in doc_chunks: + if chunk["is_chunked"]: + chunk_metadata[chunk["slug"]] = { + "parentSlug": chunk["parent_slug"], + "chunkId": chunk["chunk_id"], + } + chunked_count = sum(1 for c in chunks if c.get("is_chunked", False)) + print(f"Chunked {len(recs)} documents into {len(chunks)} chunks ({chunked_count} chunked, {len(chunks) - chunked_count} unchanged)") + print(f" Chunk size: {args.chunk_size} tokens, overlap: {args.chunk_overlap} tokens") + + ids = [c["slug"] for c in chunks] + titles = [c.get("title", c["slug"]) for c in chunks] + texts = [c["text"] for c in chunks] + + if args.use_vllm: + vecs = embed_vllm( + texts, + args.model, + args.vllm_url, + batch_size=args.batch_size, + concurrency=args.concurrency, + ) + else: + device = "cuda" if os.environ.get("CUDA_VISIBLE_DEVICES") else "cpu" + vecs = embed_hf(texts, args.model, device) + + # Coerce dims and re-normalize + if vecs.shape[1] != args.dims: + if vecs.shape[1] > args.dims: + vecs = vecs[:, : args.dims] + else: + vecs = np.pad(vecs, ((0, 0), (0, args.dims - vecs.shape[1]))) + vecs = l2_normalize_rows(vecs.astype(np.float32, copy=False)) + + out_dir = Path(args.out) + shards = write_shards(vecs, args.shard_size, args.dtype, out_dir) + + # Build a lightweight HNSW graph and store it in a compact binary layout + def hnsw_build(data: np.ndarray, M: int = 16, efC: int = 200, seed: int = 0) -> dict: + rng = random.Random(seed) + N, D = data.shape + levels: list[list[list[int]]] = [] # levels[L][i] = neighbors of node i at level L + + # random level assignment using 1/e distribution + node_levels = [] + for _ in range(N): + lvl = 0 + while rng.random() < 1 / math.e: + lvl += 1 + node_levels.append(lvl) + max_level = max(node_levels) if N > 0 else 0 + for _ in range(max_level + 1): + levels.append([[] for _ in range(N)]) + + def sim(i: int, j: int) -> float: + return float((data[i] * data[j]).sum()) + + entry = 0 if N > 0 else -1 + + def search_layer(q: int, ep: int, ef: int, L: int) -> list[int]: + if ep < 0: + return [] + visited = set() + cand: list[tuple[float, int]] = [] + top: list[tuple[float, int]] = [] + def push(node: int): + if node in visited: + return + visited.add(node) + cand.append((sim(q, node), node)) + push(ep) + while cand: + cand.sort(reverse=True) + s, v = cand.pop(0) + if len(top) >= ef and s <= top[-1][0]: + break + top.append((s, v)) + for u in levels[L][v]: + push(u) + top.sort(reverse=True) + return [n for _, n in top] + + for i in range(N): + if i == 0: + continue + lvl = node_levels[i] + ep = entry + for L in range(max_level, lvl, -1): + c = search_layer(i, ep, 1, L) + if c: + ep = c[0] + for L in range(min(max_level, lvl), -1, -1): + W = search_layer(i, ep, efC, L) + # Select top M by similarity + neigh = sorted(((sim(i, j), j) for j in W if j != i), reverse=True)[:M] + for _, e in neigh: + if e not in levels[L][i]: + levels[L][i].append(e) + if i not in levels[L][e]: + levels[L][e].append(i) + + # trim neighbors to M + for L in range(len(levels)): + for i in range(N): + if len(levels[L][i]) > M: + # keep top M by sim + nb = levels[L][i] + nb = sorted(nb, key=lambda j: sim(i, j), reverse=True)[:M] + levels[L][i] = nb + + return { + "M": M, + "efConstruction": efC, + "entryPoint": entry, + "maxLevel": max_level, + "levels": levels, + } + + hnsw = hnsw_build(vecs, M=16, efC=200) + hnsw_meta, hnsw_sha = write_hnsw_graph(hnsw["levels"], int(vecs.shape[0]), out_dir / "hnsw.bin") + + manifest = { + "version": 2, + "dims": args.dims, + "dtype": args.dtype, + "normalized": True, + "rows": int(vecs.shape[0]), + "shardSizeRows": args.shard_size, + "vectors": { + "dtype": args.dtype, + "rows": int(vecs.shape[0]), + "dims": args.dims, + "shards": shards, + }, + "ids": ids, + "titles": titles, + "chunkMetadata": chunk_metadata, + "hnsw": { + "M": hnsw["M"], + "efConstruction": hnsw["efConstruction"], + "entryPoint": hnsw["entryPoint"], + "maxLevel": hnsw["maxLevel"], + "graph": { + "path": "/embeddings/hnsw.bin", + "sha256": hnsw_sha, + "levels": hnsw_meta, + }, + }, + } + (out_dir / "manifest.json").write_text(json.dumps(manifest, ensure_ascii=False), encoding="utf-8") + print(f"Wrote {len(shards)} vector shard(s), HNSW graph, and manifest to {out_dir}") + +if __name__ == "__main__": + main() diff --git a/quartz/plugins/emitters/404.tsx b/quartz/plugins/emitters/404.tsx index 04a006dd1..8eba6ba2f 100644 --- a/quartz/plugins/emitters/404.tsx +++ b/quartz/plugins/emitters/404.tsx @@ -40,7 +40,7 @@ export const NotFoundPage: QuartzEmitterPlugin = () => { description: notFound, frontmatter: { title: notFound, tags: [] }, }) - const externalResources = pageResources(path, resources) + const externalResources = pageResources(path, resources, ctx.cfg.configuration) const componentData: QuartzComponentProps = { ctx, fileData: vfile.data, diff --git a/quartz/plugins/emitters/componentResources.ts b/quartz/plugins/emitters/componentResources.ts index f97fddec2..4340af50f 100644 --- a/quartz/plugins/emitters/componentResources.ts +++ b/quartz/plugins/emitters/componentResources.ts @@ -1,5 +1,8 @@ import { FullSlug, joinSegments } from "../../util/path" import { QuartzEmitterPlugin } from "../types" +import path from "path" +import fs from "node:fs/promises" +import { globby } from "globby" // @ts-ignore import spaRouterScript from "../../components/scripts/spa.inline" @@ -16,7 +19,7 @@ import { processGoogleFonts, } from "../../util/theme" import { Features, transform } from "lightningcss" -import { transform as transpile } from "esbuild" +import { transform as transpile, build as bundle } from "esbuild" import { write } from "./helpers" type ComponentResources = { @@ -357,7 +360,47 @@ export const ComponentResources: QuartzEmitterPlugin = () => { ext: ".js", content: postscript, }) + + // Bundle all worker files + const workerFiles = await globby(["quartz/**/*.worker.ts"]) + for (const src of workerFiles) { + const result = await bundle({ + entryPoints: [src], + bundle: true, + minify: true, + platform: "browser", + format: "esm", + write: false, + }) + const code = result.outputFiles[0].text + const name = path.basename(src).replace(/\.ts$/, "") + yield write({ ctx, slug: name as FullSlug, ext: ".js", content: code }) + } + }, + async *partialEmit(ctx, _content, _resources, changeEvents) { + // Handle worker file changes in incremental builds + for (const changeEvent of changeEvents) { + if (!/\.worker\.ts$/.test(changeEvent.path)) continue + if (changeEvent.type === "delete") { + const name = path.basename(changeEvent.path).replace(/\.ts$/, "") + const dest = joinSegments(ctx.argv.output, `${name}.js`) + try { + await fs.unlink(dest) + } catch {} + continue + } + const result = await bundle({ + entryPoints: [changeEvent.path], + bundle: true, + minify: true, + platform: "browser", + format: "esm", + write: false, + }) + const code = result.outputFiles[0].text + const name = path.basename(changeEvent.path).replace(/\.ts$/, "") + yield write({ ctx, slug: name as FullSlug, ext: ".js", content: code }) + } }, - async *partialEmit() {}, } } diff --git a/quartz/plugins/emitters/contentPage.tsx b/quartz/plugins/emitters/contentPage.tsx index c3410ecc3..b07635383 100644 --- a/quartz/plugins/emitters/contentPage.tsx +++ b/quartz/plugins/emitters/contentPage.tsx @@ -25,7 +25,7 @@ async function processContent( ) { const slug = fileData.slug! const cfg = ctx.cfg.configuration - const externalResources = pageResources(pathToRoot(slug), resources) + const externalResources = pageResources(pathToRoot(slug), resources, ctx.cfg.configuration) const componentData: QuartzComponentProps = { ctx, fileData, diff --git a/quartz/plugins/emitters/folderPage.tsx b/quartz/plugins/emitters/folderPage.tsx index f9b181dff..3cd288c05 100644 --- a/quartz/plugins/emitters/folderPage.tsx +++ b/quartz/plugins/emitters/folderPage.tsx @@ -38,7 +38,7 @@ async function* processFolderInfo( const slug = joinSegments(folder, "index") as FullSlug const [tree, file] = folderContent const cfg = ctx.cfg.configuration - const externalResources = pageResources(pathToRoot(slug), resources) + const externalResources = pageResources(pathToRoot(slug), resources, ctx.cfg.configuration) const componentData: QuartzComponentProps = { ctx, fileData: file.data, diff --git a/quartz/plugins/emitters/index.ts b/quartz/plugins/emitters/index.ts index d2de2ed1e..1471544ce 100644 --- a/quartz/plugins/emitters/index.ts +++ b/quartz/plugins/emitters/index.ts @@ -1,7 +1,7 @@ export { ContentPage } from "./contentPage" export { TagPage } from "./tagPage" export { FolderPage } from "./folderPage" -export { ContentIndex as ContentIndex } from "./contentIndex" +export { ContentIndex } from "./contentIndex" export { AliasRedirects } from "./aliases" export { Assets } from "./assets" export { Static } from "./static" @@ -10,3 +10,4 @@ export { ComponentResources } from "./componentResources" export { NotFoundPage } from "./404" export { CNAME } from "./cname" export { CustomOgImages } from "./ogImage" +export { SemanticIndex } from "./semantic" diff --git a/quartz/plugins/emitters/semantic.ts b/quartz/plugins/emitters/semantic.ts new file mode 100644 index 000000000..47442ea9a --- /dev/null +++ b/quartz/plugins/emitters/semantic.ts @@ -0,0 +1,235 @@ +import { write } from "./helpers" +import { QuartzEmitterPlugin } from "../types" +import { FilePath, FullSlug, joinSegments, QUARTZ } from "../../util/path" +import { ReadTimeResults } from "reading-time" +import { GlobalConfiguration } from "../../cfg" +import { spawn } from "child_process" + +const DEFAULT_MODEL_ID = "onnx-community/Qwen3-Embedding-0.6B-ONNX" + +const defaults: GlobalConfiguration["semanticSearch"] = { + enable: true, + model: DEFAULT_MODEL_ID, + aot: false, + dims: 1024, + dtype: "fp32", + shardSizeRows: 1024, + hnsw: { M: 16, efConstruction: 200 }, + chunking: { + chunkSize: 512, + chunkOverlap: 128, + noChunking: false, + }, + vllm: { + enable: false, + vllmUrl: + process.env.VLLM_URL || process.env.VLLM_EMBED_URL || "http://127.0.0.1:8000/v1/embeddings", + concurrency: parseInt(process.env.VLLM_CONCURRENCY || "8", 10), + batchSize: parseInt(process.env.VLLM_BATCH_SIZE || "64", 10), + }, +} + +type ContentDetails = { + slug: string + title: string + filePath: FilePath + content: string + readingTime?: Partial +} + +/** + * Check if uv is installed + */ +function checkUvInstalled(): Promise { + return new Promise((resolve) => { + const proc = spawn("uv", ["--version"], { shell: true }) + proc.on("error", () => resolve(false)) + proc.on("close", (code) => resolve(code === 0)) + }) +} + +/** + * Run the Python embedding build script using uv + * Script uses PEP 723 inline metadata for dependency management + */ +function runEmbedBuild( + jsonlPath: string, + outDir: string, + opts: { + model: string + dtype: string + dims: number + shardSizeRows: number + chunking: { chunkSize: number; chunkOverlap: number; noChunking: boolean } + vllm: { enable: boolean; vllmUrl?: string; concurrency: number; batchSize: number } + }, +): Promise { + return new Promise((resolve, reject) => { + const scriptPath = joinSegments(QUARTZ, "embed_build.py") + const args = [ + "run", + scriptPath, + "--jsonl", + jsonlPath, + "--model", + opts.model, + "--out", + outDir, + "--dtype", + opts.dtype, + "--dims", + String(opts.dims), + "--shard-size", + String(opts.shardSizeRows), + "--chunk-size", + String(opts.chunking.chunkSize), + "--chunk-overlap", + String(opts.chunking.chunkOverlap), + ] + + if (opts.chunking.noChunking) { + args.push("--no-chunking") + } + + if (opts.vllm.enable) { + args.push("--use-vllm") + if (opts.vllm.vllmUrl) { + args.push("--vllm-url", opts.vllm.vllmUrl) + } + args.push("--concurrency", String(opts.vllm.concurrency)) + args.push("--batch-size", String(opts.vllm.batchSize)) + } + + console.log("\nRunning embedding generation:") + console.log(` uv ${args.join(" ")}`) + + const env = { ...process.env } + if (opts.vllm.enable && !env.USE_VLLM) { + env.USE_VLLM = "1" + } + + const proc = spawn("uv", args, { + stdio: "inherit", + shell: true, + env, + }) + + proc.on("error", (err) => { + reject(new Error(`Failed to spawn uv: ${err.message}`)) + }) + + proc.on("close", (code) => { + if (code === 0) { + console.log("Embedding generation completed successfully") + resolve() + } else { + reject(new Error(`embed_build.py exited with code ${code}`)) + } + }) + }) +} + +export const SemanticIndex: QuartzEmitterPlugin> = ( + opts, +) => { + const merged = { ...defaults, ...opts } + const o = { + enable: merged.enable!, + model: merged.model!, + aot: merged.aot!, + dims: merged.dims!, + dtype: merged.dtype!, + shardSizeRows: merged.shardSizeRows!, + hnsw: { + M: merged.hnsw?.M ?? defaults.hnsw!.M!, + efConstruction: merged.hnsw?.efConstruction ?? defaults.hnsw!.efConstruction!, + efSearch: merged.hnsw?.efSearch, + }, + chunking: { + chunkSize: merged.chunking?.chunkSize ?? defaults.chunking!.chunkSize!, + chunkOverlap: merged.chunking?.chunkOverlap ?? defaults.chunking!.chunkOverlap!, + noChunking: merged.chunking?.noChunking ?? defaults.chunking!.noChunking!, + }, + vllm: { + enable: merged.vllm?.enable ?? defaults.vllm!.enable!, + vllmUrl: merged.vllm?.vllmUrl ?? defaults.vllm!.vllmUrl, + concurrency: merged.vllm?.concurrency ?? defaults.vllm!.concurrency!, + batchSize: merged.vllm?.batchSize ?? defaults.vllm!.batchSize!, + }, + } + + if (!o.model) { + throw new Error("Semantic search requires a model identifier") + } + + return { + name: "SemanticIndex", + getQuartzComponents() { + return [] + }, + async *partialEmit() {}, + async *emit(ctx, content, _resources) { + if (!o.enable) return + + const docs: ContentDetails[] = [] + for (const [_, file] of content) { + const slug = file.data.slug! + const title = file.data.frontmatter?.title ?? slug + const text = file.data.text + if (text) { + docs.push({ + slug, + title, + filePath: file.data.filePath!, + content: text, + readingTime: file.data.readingTime, + }) + } + } + + // Emit JSONL with the exact text used for embeddings + const jsonl = docs + .map((d) => ({ slug: d.slug, title: d.title, text: d.content })) + .map((o) => JSON.stringify(o)) + .join("\n") + + const jsonlSlug = "embeddings-text" as FullSlug + yield write({ + ctx, + slug: jsonlSlug, + ext: ".jsonl", + content: jsonl, + }) + + // If aot is false, run the embedding generation script + if (!o.aot) { + console.log("\nGenerating embeddings (aot=false)...") + + // Check for uv + const hasUv = await checkUvInstalled() + if (!hasUv) { + throw new Error( + "uv is required for embedding generation. Install it from https://docs.astral.sh/uv/", + ) + } + + const jsonlPath = joinSegments(ctx.argv.output, "embeddings-text.jsonl") + const outDir = joinSegments(ctx.argv.output, "embeddings") + + try { + await runEmbedBuild(jsonlPath, outDir, o) + } catch (err) { + const message = err instanceof Error ? err.message : String(err) + throw new Error(`Embedding generation failed: ${message}`) + } + } else { + console.log( + "\nSkipping embedding generation (aot=true). Expecting pre-generated embeddings in public/embeddings/", + ) + } + }, + externalResources(_ctx) { + return {} + }, + } +} diff --git a/quartz/plugins/emitters/tagPage.tsx b/quartz/plugins/emitters/tagPage.tsx index 5f238932d..d0ab59295 100644 --- a/quartz/plugins/emitters/tagPage.tsx +++ b/quartz/plugins/emitters/tagPage.tsx @@ -73,7 +73,7 @@ async function processTagPage( const slug = joinSegments("tags", tag) as FullSlug const [tree, file] = tagContent const cfg = ctx.cfg.configuration - const externalResources = pageResources(pathToRoot(slug), resources) + const externalResources = pageResources(pathToRoot(slug), resources, ctx.cfg.configuration) const componentData: QuartzComponentProps = { ctx, fileData: file.data, diff --git a/quartz/workers/semantic.worker.ts b/quartz/workers/semantic.worker.ts new file mode 100644 index 000000000..2d8e46477 --- /dev/null +++ b/quartz/workers/semantic.worker.ts @@ -0,0 +1,548 @@ +// Unified semantic search worker: handles data loading and query execution +import { env, pipeline } from "@huggingface/transformers" +import "onnxruntime-web/webgpu" +import "onnxruntime-web/wasm" + +export {} + +type VectorShardMeta = { + path: string + rows: number + rowOffset: number + byteLength: number + sha256?: string + byteStride: number +} + +type LevelSection = { + level: number + indptr: { offset: number; elements: number; byteLength: number } + indices: { offset: number; elements: number; byteLength: number } +} + +type ChunkMetadata = { + parentSlug: string + chunkId: number +} + +type Manifest = { + version: number + dims: number + dtype: string + normalized: boolean + rows: number + shardSizeRows: number + vectors: { + dtype: string + rows: number + dims: number + shards: VectorShardMeta[] + } + ids: string[] + titles?: string[] + chunkMetadata?: Record + hnsw: { + M: number + efConstruction: number + entryPoint: number + maxLevel: number + graph: { + path: string + sha256?: string + levels: LevelSection[] + } + } +} + +type InitMessage = { + type: "init" + cfg: any + manifestUrl: string + baseUrl?: string + disableCache?: boolean +} + +type SearchMessage = { type: "search"; text: string; k: number; seq: number } +type ResetMessage = { type: "reset" } + +type WorkerMessage = InitMessage | SearchMessage | ResetMessage + +type ReadyMessage = { type: "ready" } + +type ProgressMessage = { + type: "progress" + loadedRows: number + totalRows: number +} + +type SearchHit = { id: number; score: number } + +type SearchResultMessage = { + type: "search-result" + seq: number + semantic: SearchHit[] +} + +type ErrorMessage = { type: "error"; seq?: number; message: string } + +type WorkerState = "idle" | "loading" | "ready" | "error" + +// IndexedDB configuration +const DB_NAME = "semantic-search-cache" +const STORE_NAME = "assets" +const DB_VERSION = 1 +const hasIndexedDB = typeof indexedDB !== "undefined" +const supportsSharedArrayBuffer = typeof SharedArrayBuffer !== "undefined" + +// State +let state: WorkerState = "idle" +let manifest: Manifest | null = null +let cfg: any = null +let vectorsView: Float32Array | null = null +let dims = 0 +let rows = 0 +let classifier: any = null +let envConfigured = false +let entryPoint = -1 +let maxLevel = 0 +let efDefault = 128 +let levelGraph: { indptr: Uint32Array; indices: Uint32Array }[] = [] +let abortController: AbortController | null = null +let dbPromise: Promise | null = null + +// IndexedDB helpers +function openDatabase(): Promise { + if (!hasIndexedDB) { + return Promise.reject(new Error("indexedDB unavailable")) + } + if (!dbPromise) { + dbPromise = new Promise((resolve, reject) => { + const req = indexedDB.open(DB_NAME, DB_VERSION) + req.onupgradeneeded = () => { + const db = req.result + if (!db.objectStoreNames.contains(STORE_NAME)) { + db.createObjectStore(STORE_NAME) + } + } + req.onsuccess = () => resolve(req.result) + req.onerror = () => reject(req.error ?? new Error("failed to open cache store")) + }) + } + return dbPromise +} + +async function readAsset(hash: string): Promise { + if (!hasIndexedDB) { + return null + } + const db = await openDatabase() + return new Promise((resolve, reject) => { + const tx = db.transaction(STORE_NAME, "readonly") + const store = tx.objectStore(STORE_NAME) + const req = store.get(hash) + req.onsuccess = () => { + const value = req.result + if (value instanceof ArrayBuffer) { + resolve(value) + } else if (value && value.buffer instanceof ArrayBuffer) { + resolve(value.buffer as ArrayBuffer) + } else { + resolve(null) + } + } + req.onerror = () => reject(req.error ?? new Error("failed to read cached asset")) + }) +} + +async function writeAsset(hash: string, buffer: ArrayBuffer): Promise { + if (!hasIndexedDB) { + return + } + const db = await openDatabase() + await new Promise((resolve, reject) => { + const tx = db.transaction(STORE_NAME, "readwrite") + const store = tx.objectStore(STORE_NAME) + const req = store.put(buffer, hash) + req.onsuccess = () => resolve() + req.onerror = () => reject(req.error ?? new Error("failed to cache asset")) + }) +} + +function toAbsolute(path: string, baseUrl?: string): string { + if (path.startsWith("http://") || path.startsWith("https://")) { + return path + } + const base = baseUrl ?? self.location.origin + return new URL(path, base).toString() +} + +async function fetchBinary( + path: string, + disableCache: boolean, + sha?: string, +): Promise { + if (!disableCache && sha && hasIndexedDB) { + try { + const cached = await readAsset(sha) + if (cached) { + return cached + } + } catch { + // fall through to network fetch on cache errors + } + } + const res = await fetch(path, { signal: abortController?.signal ?? undefined }) + if (!res.ok) { + throw new Error(`failed to fetch ${path}: ${res.status} ${res.statusText}`) + } + const payload = await res.arrayBuffer() + if (!disableCache && sha && hasIndexedDB) { + try { + await writeAsset(sha, payload) + } catch { + // ignore cache write failures + } + } + return payload +} + +async function populateVectors( + manifest: Manifest, + baseUrl: string | undefined, + disableCache: boolean | undefined, +): Promise<{ buffer: Float32Array; rowsLoaded: number }> { + if (manifest.vectors.dtype !== "fp32") { + throw new Error(`unsupported embedding dtype '${manifest.vectors.dtype}', regenerate with fp32`) + } + const rows = manifest.rows + const dims = manifest.dims + const totalBytes = rows * dims * Float32Array.BYTES_PER_ELEMENT + const buffer = supportsSharedArrayBuffer + ? new Float32Array(new SharedArrayBuffer(totalBytes)) + : new Float32Array(totalBytes) + let loadedRows = 0 + for (const shard of manifest.vectors.shards) { + const absolute = toAbsolute(shard.path, baseUrl) + const payload = await fetchBinary(absolute, Boolean(disableCache), shard.sha256) + const view = new Float32Array(payload) + if (view.length !== shard.rows * dims) { + throw new Error( + `shard ${shard.path} has mismatched length (expected ${shard.rows * dims}, got ${view.length})`, + ) + } + buffer.set(view, shard.rowOffset * dims) + loadedRows = Math.min(rows, shard.rowOffset + shard.rows) + const progress: ProgressMessage = { + type: "progress", + loadedRows, + totalRows: rows, + } + self.postMessage(progress) + } + return { buffer, rowsLoaded: loadedRows } +} + +async function populateGraph( + manifest: Manifest, + baseUrl: string | undefined, + disableCache: boolean | undefined, +): Promise { + const graphMeta = manifest.hnsw.graph + const absolute = toAbsolute(graphMeta.path, baseUrl) + return await fetchBinary(absolute, Boolean(disableCache), graphMeta.sha256) +} + +function configureRuntimeEnv() { + if (envConfigured) return + env.allowLocalModels = false + env.allowRemoteModels = true + const wasmBackend = env.backends?.onnx?.wasm + if (!wasmBackend) { + throw new Error("transformers.js ONNX runtime backend unavailable") + } + const cdnBase = `https://cdn.jsdelivr.net/npm/@huggingface/transformers@${env.version}/dist/` + wasmBackend.wasmPaths = cdnBase + envConfigured = true +} + +async function ensureEncoder() { + if (classifier) return + if (!cfg?.model) { + throw new Error("semantic worker missing model identifier") + } + configureRuntimeEnv() + const dtype = typeof cfg?.dtype === "string" && cfg.dtype.length > 0 ? cfg.dtype : "fp32" + const pipelineOpts: Record = { + device: "wasm", + dtype, + local_files_only: false, + } + classifier = await pipeline("feature-extraction", cfg.model, pipelineOpts) + cfg.dtype = dtype +} + +function vectorSlice(id: number): Float32Array { + if (!vectorsView) { + throw new Error("vector buffer not configured") + } + const start = id * dims + const end = start + dims + return vectorsView.subarray(start, end) +} + +function dot(a: Float32Array, b: Float32Array): number { + let s = 0 + for (let i = 0; i < dims; i++) { + s += a[i] * b[i] + } + return s +} + +function neighborsFor(level: number, node: number): Uint32Array { + const meta = levelGraph[level] + if (!meta) return new Uint32Array() + const { indptr, indices } = meta + if (node < 0 || node + 1 >= indptr.length) return new Uint32Array() + const start = indptr[node] + const end = indptr[node + 1] + return indices.subarray(start, end) +} + +function insertSortedDescending(arr: SearchHit[], item: SearchHit) { + let idx = arr.length + while (idx > 0 && arr[idx - 1].score < item.score) { + idx -= 1 + } + arr.splice(idx, 0, item) +} + +function bruteForceSearch(query: Float32Array, k: number): SearchHit[] { + if (!vectorsView) return [] + const hits: SearchHit[] = [] + for (let id = 0; id < rows; id++) { + const score = dot(query, vectorSlice(id)) + if (hits.length < k) { + insertSortedDescending(hits, { id, score }) + } else if (score > hits[hits.length - 1].score) { + insertSortedDescending(hits, { id, score }) + hits.length = k + } + } + return hits +} + +function hnswSearch(query: Float32Array, k: number): SearchHit[] { + if (!manifest || !vectorsView || entryPoint < 0 || levelGraph.length === 0) { + return bruteForceSearch(query, k) + } + const ef = Math.max(efDefault, k * 10) + let ep = entryPoint + let epScore = dot(query, vectorSlice(ep)) + for (let level = maxLevel; level > 0; level--) { + let changed = true + while (changed) { + changed = false + const neigh = neighborsFor(level, ep) + for (let i = 0; i < neigh.length; i++) { + const candidate = neigh[i] + if (candidate >= rows) continue + const score = dot(query, vectorSlice(candidate)) + if (score > epScore) { + epScore = score + ep = candidate + changed = true + } + } + } + } + + const visited = new Set() + const candidateQueue: SearchHit[] = [] + const best: SearchHit[] = [] + insertSortedDescending(candidateQueue, { id: ep, score: epScore }) + insertSortedDescending(best, { id: ep, score: epScore }) + visited.add(ep) + + while (candidateQueue.length > 0) { + const current = candidateQueue.shift()! + const worstBest = best.length >= ef ? best[best.length - 1].score : -Infinity + if (current.score < worstBest && best.length >= ef) { + break + } + const neigh = neighborsFor(0, current.id) + for (let i = 0; i < neigh.length; i++) { + const candidate = neigh[i] + if (candidate >= rows || visited.has(candidate)) continue + visited.add(candidate) + const score = dot(query, vectorSlice(candidate)) + const hit = { id: candidate, score } + insertSortedDescending(candidateQueue, hit) + if (best.length < ef || score > best[best.length - 1].score) { + insertSortedDescending(best, hit) + if (best.length > ef) { + best.pop() + } + } + } + } + + best.sort((a, b) => b.score - a.score) + return best.slice(0, k) +} + +async function embed(text: string, isQuery: boolean = false): Promise { + await ensureEncoder() + // Apply model-specific prefixes for asymmetric search + let prefixedText = text + if (cfg?.model) { + const modelName = cfg.model.toLowerCase() + switch (true) { + case modelName.includes("e5"): { + // E5 models require query: or passage: prefix + prefixedText = isQuery ? `query: ${text}` : `passage: ${text}` + break + } + case modelName.includes("qwen") && modelName.includes("embedding"): { + // Qwen3-Embedding requires task instruction for queries only + if (isQuery) { + const task = "Given a web search query, retrieve relevant passages that answer the query" + prefixedText = `Instruct: ${task}\nQuery: ${text}` + } + // Documents use plain text (no prefix) + break + } + case modelName.includes("embeddinggemma"): { + // embeddinggemma requires specific prefixes + prefixedText = isQuery + ? `task: search result | query: ${text}` + : `title: none | text: ${text}` + break + } + default: + break + } + } + const out = await classifier(prefixedText, { pooling: "mean", normalize: true }) + const data = Array.from(out?.data ?? out) as number[] + const vec = new Float32Array(dims) + for (let i = 0; i < dims; i++) vec[i] = data[i] ?? 0 + return vec +} + +async function handleInit(msg: InitMessage) { + if (state === "loading" || state === "ready") { + throw new Error("worker already initialized or loading") + } + + state = "loading" + abortController?.abort() + abortController = new AbortController() + + try { + cfg = msg.cfg + + const manifestUrl = toAbsolute(msg.manifestUrl, msg.baseUrl) + const response = await fetch(manifestUrl, { signal: abortController.signal }) + if (!response.ok) { + throw new Error( + `failed to fetch manifest ${manifestUrl}: ${response.status} ${response.statusText}`, + ) + } + manifest = (await response.json()) as Manifest + + if (manifest.vectors.dtype !== "fp32") { + throw new Error( + `unsupported embedding dtype '${manifest.vectors.dtype}', regenerate with fp32`, + ) + } + + dims = manifest.dims + rows = manifest.rows + + const { buffer: vectorBuffer } = await populateVectors(manifest, msg.baseUrl, msg.disableCache) + vectorsView = vectorBuffer + + const graphBuffer = await populateGraph(manifest, msg.baseUrl, msg.disableCache) + + entryPoint = manifest.hnsw.entryPoint + maxLevel = manifest.hnsw.maxLevel + efDefault = Math.max(64, manifest.hnsw.M * 4) + levelGraph = manifest.hnsw.graph.levels.map((level) => { + const indptr = new Uint32Array(graphBuffer, level.indptr.offset, level.indptr.elements) + const indices = new Uint32Array(graphBuffer, level.indices.offset, level.indices.elements) + return { indptr, indices } + }) + + state = "ready" + const ready: ReadyMessage = { type: "ready" } + self.postMessage(ready) + } catch (err) { + state = "error" + throw err + } +} + +async function handleSearch(msg: SearchMessage) { + if (state !== "ready") { + throw new Error("worker not ready for search") + } + if (!manifest || !vectorsView) { + throw new Error("semantic worker not configured") + } + + const queryVec = await embed(msg.text, true) + const semanticHits = hnswSearch(queryVec, Math.max(1, msg.k)) + const message: SearchResultMessage = { + type: "search-result", + seq: msg.seq, + semantic: semanticHits, + } + self.postMessage(message) +} + +function handleReset() { + abortController?.abort() + abortController = null + state = "idle" + manifest = null + cfg = null + vectorsView = null + dims = 0 + rows = 0 + classifier = null + envConfigured = false + levelGraph = [] + entryPoint = -1 + maxLevel = 0 +} + +self.onmessage = (event: MessageEvent) => { + const data = event.data + + if (data.type === "reset") { + handleReset() + return + } + + if (data.type === "init") { + void handleInit(data).catch((err: unknown) => { + const message: ErrorMessage = { + type: "error", + message: err instanceof Error ? err.message : String(err), + } + self.postMessage(message) + }) + return + } + + if (data.type === "search") { + void handleSearch(data).catch((err: unknown) => { + const message: ErrorMessage = { + type: "error", + seq: data.seq, + message: err instanceof Error ? err.message : String(err), + } + self.postMessage(message) + }) + } +}