mirror of
https://github.com/ggerganov/llama.cpp.git
synced 2024-12-26 14:20:31 +01:00
server: (UI) add syntax highlighting and latex math rendering (#10808)
* add code highlighting and math formatting
* code cleanup
* build public/index.html
* rebuild public/index.html
* fixed coding style
* fixed coding style
* style fixes
* highlight: smaller bundle size, fix light & dark theme
* remove katex
* add bundle size check
* add more languages
* add php
* reuse some langs
* use gzip
* Revert "remove katex"
This reverts commit c0e5046acc
.
* use better maintained @vscode/markdown-it-katex
* fix gzip non deterministic
* ability to add a demo conversation for dev
* fix latex rendering
* add comment
* latex codeblock as code
---------
Co-authored-by: Xuan Son Nguyen <son@huggingface.co>
This commit is contained in:
parent
b5ae1ddff9
commit
5478bbcd17
@ -15,7 +15,7 @@ set(TARGET_SRCS
|
|||||||
httplib.h
|
httplib.h
|
||||||
)
|
)
|
||||||
set(PUBLIC_ASSETS
|
set(PUBLIC_ASSETS
|
||||||
index.html
|
index.html.gz
|
||||||
loading.html
|
loading.html
|
||||||
)
|
)
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
BIN
examples/server/public/index.html.gz
Normal file
BIN
examples/server/public/index.html.gz
Normal file
Binary file not shown.
@ -15,7 +15,7 @@
|
|||||||
#define MIMETYPE_JSON "application/json; charset=utf-8"
|
#define MIMETYPE_JSON "application/json; charset=utf-8"
|
||||||
|
|
||||||
// auto generated files (update with ./deps.sh)
|
// auto generated files (update with ./deps.sh)
|
||||||
#include "index.html.hpp"
|
#include "index.html.gz.hpp"
|
||||||
#include "loading.html.hpp"
|
#include "loading.html.hpp"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
@ -3828,8 +3828,13 @@ int main(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// using embedded static index.html
|
// using embedded static index.html
|
||||||
svr->Get("/", [](const httplib::Request &, httplib::Response & res) {
|
svr->Get("/", [](const httplib::Request & req, httplib::Response & res) {
|
||||||
res.set_content(reinterpret_cast<const char*>(index_html), index_html_len, "text/html; charset=utf-8");
|
if (req.get_header_value("Accept-Encoding").find("gzip") == std::string::npos) {
|
||||||
|
res.set_content("Error: gzip is not supported by this browser", "text/plain");
|
||||||
|
} else {
|
||||||
|
res.set_header("Content-Encoding", "gzip");
|
||||||
|
res.set_content(reinterpret_cast<const char*>(index_html_gz), index_html_gz_len, "text/html; charset=utf-8");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,10 @@
|
|||||||
<details class="collapse collapse-arrow bg-base-200 mb-2 overflow-visible">
|
<details class="collapse collapse-arrow bg-base-200 mb-2 overflow-visible">
|
||||||
<summary class="collapse-title font-bold">Advanced config</summary>
|
<summary class="collapse-title font-bold">Advanced config</summary>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
|
<div class="flex flex-row items-center mb-2" v-if="isDev">
|
||||||
|
<!-- this button only shows in dev mode, used to import a demo conversation to test message rendering -->
|
||||||
|
<button class="btn" @click="debugImportDemoConv()">(debug) Import demo conversation</button>
|
||||||
|
</div>
|
||||||
<div class="flex flex-row items-center mb-2">
|
<div class="flex flex-row items-center mb-2">
|
||||||
<input type="checkbox" class="checkbox" v-model="config.showTokensPerSecond" />
|
<input type="checkbox" class="checkbox" v-model="config.showTokensPerSecond" />
|
||||||
<span class="ml-4">Show tokens per second</span>
|
<span class="ml-4">Show tokens per second</span>
|
||||||
|
512
examples/server/webui/package-lock.json
generated
512
examples/server/webui/package-lock.json
generated
@ -8,8 +8,11 @@
|
|||||||
"name": "webui",
|
"name": "webui",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vscode/markdown-it-katex": "^1.1.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"daisyui": "^4.12.14",
|
"daisyui": "^4.12.14",
|
||||||
|
"highlight.js": "^11.10.0",
|
||||||
|
"katex": "^0.16.15",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"tailwindcss": "^3.4.15",
|
"tailwindcss": "^3.4.15",
|
||||||
@ -18,6 +21,7 @@
|
|||||||
"vue": "^3.5.13"
|
"vue": "^3.5.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"sass-embedded": "^1.83.0",
|
||||||
"vite": "^5.4.10"
|
"vite": "^5.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -33,6 +37,13 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@bufbuild/protobuf": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||||
@ -606,6 +617,15 @@
|
|||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@vscode/markdown-it-katex": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vscode/markdown-it-katex/-/markdown-it-katex-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-3KTlbsRBPJQLE2YmLL7K6nunTlU+W9T5+FjfNdWuIUKgxSS6HWLQHaO3L4MkJi7z7MpIPpY+g4N+cWNBPE/MSA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"katex": "^0.16.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@vue/compiler-dom": {
|
"node_modules/@vue/compiler-dom": {
|
||||||
"version": "3.5.13",
|
"version": "3.5.13",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
|
||||||
@ -1004,6 +1024,13 @@
|
|||||||
"browserslist": ">= 4.21.0"
|
"browserslist": ">= 4.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-builder": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT/X11"
|
||||||
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001684",
|
"version": "1.0.30001684",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz",
|
||||||
@ -1166,6 +1193,22 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/colorjs.io": {
|
||||||
|
"version": "0.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
|
||||||
|
"integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/css-selector-tokenizer": {
|
"node_modules/css-selector-tokenizer": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
|
||||||
@ -1473,6 +1516,31 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/highlight.js": {
|
||||||
|
"version": "11.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz",
|
||||||
|
"integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/immutable": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-glob": {
|
"node_modules/is-glob": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
@ -1503,6 +1571,22 @@
|
|||||||
"jiti": "bin/jiti.js"
|
"jiti": "bin/jiti.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.16.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.15.tgz",
|
||||||
|
"integrity": "sha512-yE9YJIEAk2aZ+FL/G8r+UGw0CTUzEA8ZFy6E+8tc3spHUKq3qBnzCkI1CQwGoI9atJhVyFPEypQsTY7mJ1Pi9w==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||||
@ -2022,6 +2106,381 @@
|
|||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/rxjs": {
|
||||||
|
"version": "7.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-/8cYZeL39evUqe0o//193na51Q1VWZ61qhxioQvLJwOtWIrX+PgNhCyD8RSuTtmzc4+6+waFZf899bfp/MCUwA==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@bufbuild/protobuf": "^2.0.0",
|
||||||
|
"buffer-builder": "^0.2.0",
|
||||||
|
"colorjs.io": "^0.5.0",
|
||||||
|
"immutable": "^5.0.2",
|
||||||
|
"rxjs": "^7.4.0",
|
||||||
|
"supports-color": "^8.1.1",
|
||||||
|
"sync-child-process": "^1.0.2",
|
||||||
|
"varint": "^6.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"sass": "dist/bin/sass.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"sass-embedded-android-arm": "1.83.0",
|
||||||
|
"sass-embedded-android-arm64": "1.83.0",
|
||||||
|
"sass-embedded-android-ia32": "1.83.0",
|
||||||
|
"sass-embedded-android-riscv64": "1.83.0",
|
||||||
|
"sass-embedded-android-x64": "1.83.0",
|
||||||
|
"sass-embedded-darwin-arm64": "1.83.0",
|
||||||
|
"sass-embedded-darwin-x64": "1.83.0",
|
||||||
|
"sass-embedded-linux-arm": "1.83.0",
|
||||||
|
"sass-embedded-linux-arm64": "1.83.0",
|
||||||
|
"sass-embedded-linux-ia32": "1.83.0",
|
||||||
|
"sass-embedded-linux-musl-arm": "1.83.0",
|
||||||
|
"sass-embedded-linux-musl-arm64": "1.83.0",
|
||||||
|
"sass-embedded-linux-musl-ia32": "1.83.0",
|
||||||
|
"sass-embedded-linux-musl-riscv64": "1.83.0",
|
||||||
|
"sass-embedded-linux-musl-x64": "1.83.0",
|
||||||
|
"sass-embedded-linux-riscv64": "1.83.0",
|
||||||
|
"sass-embedded-linux-x64": "1.83.0",
|
||||||
|
"sass-embedded-win32-arm64": "1.83.0",
|
||||||
|
"sass-embedded-win32-ia32": "1.83.0",
|
||||||
|
"sass-embedded-win32-x64": "1.83.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-android-arm": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-uwFSXzJlfbd4Px189xE5l+cxN8+TQpXdQgJec7TIrb4HEY7imabtpYufpVdqUVwT1/uiis5V4+qIEC4Vl5XObQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-android-arm64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-GBiCvM4a2rkWBLdYDxI6XYnprfk5U5c81g69RC2X6kqPuzxzx8qTArQ9M6keFK4+iDQ5N9QTwFCr0KbZTn+ZNQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-android-ia32": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-5ATPdGo2SICqAhiJl/Z8KQ23zH4sGgobGgux0TnrNtt83uHZ+r+To/ubVJ7xTkZxed+KJZnIpolGD8dQyQqoTg==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-android-riscv64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-aveknUOB8GZewOzVn2Uwk+DKcncTR50Q6vtzslNMGbYnxtgQNHzy8A1qVEviNUruex+pHofppeMK4iMPFAbiEQ==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-android-x64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-WqIay/72ncyf9Ph4vS742J3a73wZihWmzFUwpn1OD6lme1Aj4eWzWIve5IVnlTEJgcZcDHu6ECID9IZgehJKoA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-darwin-arm64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-XQl9QqgxFFIPm/CzHhmppse5o9ocxrbaAdC2/DAnlAqvYWBBtgFqPjGoYlej13h9SzfvNoogx+y9r+Ap+e+hYg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-darwin-x64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-ERQ7Tvp1kFOW3ux4VDFIxb7tkYXHYc+zJpcrbs0hzcIO5ilIRU2tIOK1OrNwrFO6Qxyf7AUuBwYKLAtIU/Nz7g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-arm": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-baG9RYBJxUFmqwDNC9h9ZFElgJoyO3jgHGjzEZ1wHhIS9anpG+zZQvO8bHx3dBpKEImX+DBeLX+CxsFR9n81gQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-arm64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-syEAVTJt4qhaMLxrSwOWa46zdqHJdnqJkLUK+t9aCr8xqBZLPxSUeIGji76uOehQZ1C+KGFj6n9xstHN6wzOJw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-ia32": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-RRBxQxMpoxu5+XcSSc6QR/o9asEwUzR8AbCS83RaXcdTIHTa/CccQsiAoDDoPlRsMTLqnzs0LKL4CfOsf7zBbA==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-musl-arm": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-Yc7u2TelCfBab+PRob9/MNJFh3EooMiz4urvhejXkihTiKSHGCv5YqDdtWzvyb9tY2Jb7YtYREVuHwfdVn3dTQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-musl-arm64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-Y7juhPHClUO2H5O+u+StRy6SEAcwZ+hTEk5WJdEmo1Bb1gDtfHvJaWB/iFZJ2tW0W1e865AZeUrC4OcOFjyAQA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-musl-ia32": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-arQeYwGmwXV8byx5G1PtSzZWW1jbkfR5qrIHMEbTFSAvAxpqjgSvCvrHMOFd73FcMxVaYh4BX9LQNbKinkbEdg==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-musl-riscv64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-E6uzlIWz59rut+Z3XR6mLG915zNzv07ISvj3GUNZENdHM7dF8GQ//ANoIpl5PljMQKp89GnYdvo6kj2gnaBf/g==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-musl-x64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-eAMK6tyGqvqr21r9g8BnR3fQc1rYFj85RGduSQ3xkITZ6jOAnOhuU94N5fwRS852Hpws0lXhET+7JHXgg3U18w==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-riscv64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-Ojpi78pTv02sy2fUYirRGXHLY3fPnV/bvwuC2i5LwPQw2LpCcFyFTtN0c5h4LJDk9P6wr+/ZB/JXU8tHIOlK+Q==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-linux-x64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-3iLjlXdoPfgZRtX4odhRvka1BQs5mAXqfCtDIQBgh/o0JnGPzJIWWl9bYLpHxK8qb+uyVBxXYgXpI0sCzArBOw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-win32-arm64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-iOHw/8/t2dlTW3lOFwG5eUbiwhEyGWawivlKWJ8lkXH7fjMpVx2VO9zCFAm8RvY9xOHJ9sf1L7g5bx3EnNP9BQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-win32-ia32": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-2PxNXJ8Pad4geVcTXY4rkyTr5AwbF8nfrCTDv0ulbTvPhzX2mMKEGcBZUXWn5BeHZTBc6whNMfS7d5fQXR9dDQ==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass-embedded-win32-x64": {
|
||||||
|
"version": "1.83.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.83.0.tgz",
|
||||||
|
"integrity": "sha512-muBXkFngM6eLTNqOV0FQi7Dv9s+YRQ42Yem26mosdan/GmJQc81deto6uDTgrYn+bzFNmiXcOdfm+0MkTWK3OQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sucrase": {
|
"node_modules/sucrase": {
|
||||||
"version": "3.35.0",
|
"version": "3.35.0",
|
||||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
|
||||||
@ -2641,6 +3100,45 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "8.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||||
|
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sync-child-process": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sync-message-port": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sync-message-port": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "3.4.15",
|
"version": "3.4.15",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
|
||||||
@ -2684,12 +3182,26 @@
|
|||||||
"integrity": "sha512-iBHbi7BQxrFmwZUQJsT0SjNzlLLsXhvW/kg7EyOMVMBIrlnj/qYofwo1LVLZi+3GbUEo96Iu2eqToI2+lZoAEQ==",
|
"integrity": "sha512-iBHbi7BQxrFmwZUQJsT0SjNzlLLsXhvW/kg7EyOMVMBIrlnj/qYofwo1LVLZi+3GbUEo96Iu2eqToI2+lZoAEQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
"node_modules/uc.micro": {
|
"node_modules/uc.micro": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||||
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
|
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/varint": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.11",
|
"version": "5.4.11",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
|
||||||
|
@ -6,14 +6,19 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"analyze": "ANALYZE=1 npx vite-bundle-visualizer"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"sass-embedded": "^1.83.0",
|
||||||
"vite": "^5.4.10"
|
"vite": "^5.4.10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vscode/markdown-it-katex": "^1.1.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"daisyui": "^4.12.14",
|
"daisyui": "^4.12.14",
|
||||||
|
"highlight.js": "^11.10.0",
|
||||||
|
"katex": "^0.16.15",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"tailwindcss": "^3.4.15",
|
"tailwindcss": "^3.4.15",
|
||||||
|
33
examples/server/webui/public/demo-conversation.json
Normal file
33
examples/server/webui/public/demo-conversation.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"demo": true,
|
||||||
|
"id": "conv-1734086746930",
|
||||||
|
"lastModified": 1734087548943,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"id": 1734086764521,
|
||||||
|
"role": "user",
|
||||||
|
"content": "this is a demo conversation, used in dev mode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1734087548327,
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "This is the formula:\n\n$\\frac{e^{x_i}}{\\sum_{j=1}^{n}e^{x_j}}$\n\nGiven an input vector \\(\\mathbf{x} = [x_1, x_2, \\ldots, x_n]\\)\n\n\\[\ny_i = \\frac{e^{x_i}}{\\sum_{j=1}^n e^{x_j}}\n\\]\n\nCode block latex:\n```latex\n\\frac{e^{x_i}}{\\sum_{j=1}^{n}e^{x_j}}\n```\n\nTest dollar sign: $1234 $4567\n\nInvalid latex syntax: $E = mc^$ and $$E = mc^$$",
|
||||||
|
"timings": {
|
||||||
|
"prompt_n": 1,
|
||||||
|
"prompt_ms": 28.923,
|
||||||
|
"predicted_n": 25,
|
||||||
|
"predicted_ms": 573.016
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1734087548328,
|
||||||
|
"role": "user",
|
||||||
|
"content": "this is a demo conversation, used in dev mode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1734087548329,
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "Code block:\n```js\nconsole.log('hello world')\n```\n```sh\nls -la /dev\n```"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
60
examples/server/webui/src/highlight-config.js
Normal file
60
examples/server/webui/src/highlight-config.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import hljs from 'highlight.js/lib/core';
|
||||||
|
|
||||||
|
// only import commonly used languages to reduce bundle size
|
||||||
|
|
||||||
|
import python from 'highlight.js/lib/languages/python';
|
||||||
|
import javascript from 'highlight.js/lib/languages/javascript';
|
||||||
|
import json from 'highlight.js/lib/languages/json';
|
||||||
|
import bash from 'highlight.js/lib/languages/bash';
|
||||||
|
import yaml from 'highlight.js/lib/languages/yaml';
|
||||||
|
import markdown from 'highlight.js/lib/languages/markdown';
|
||||||
|
import scss from 'highlight.js/lib/languages/scss';
|
||||||
|
import xml from 'highlight.js/lib/languages/xml';
|
||||||
|
import ruby from 'highlight.js/lib/languages/ruby';
|
||||||
|
import go from 'highlight.js/lib/languages/go';
|
||||||
|
import java from 'highlight.js/lib/languages/java';
|
||||||
|
import rust from 'highlight.js/lib/languages/rust';
|
||||||
|
import scala from 'highlight.js/lib/languages/scala';
|
||||||
|
import cpp from 'highlight.js/lib/languages/cpp';
|
||||||
|
import csharp from 'highlight.js/lib/languages/csharp';
|
||||||
|
import swift from 'highlight.js/lib/languages/swift';
|
||||||
|
import dart from 'highlight.js/lib/languages/dart';
|
||||||
|
import elixir from 'highlight.js/lib/languages/elixir';
|
||||||
|
import kotlin from 'highlight.js/lib/languages/kotlin';
|
||||||
|
import lua from 'highlight.js/lib/languages/lua';
|
||||||
|
import php from 'highlight.js/lib/languages/php';
|
||||||
|
import latex from 'highlight.js/lib/languages/latex';
|
||||||
|
|
||||||
|
hljs.registerLanguage('python', python);
|
||||||
|
hljs.registerLanguage('javascript', javascript);
|
||||||
|
hljs.registerLanguage('json', json);
|
||||||
|
hljs.registerLanguage('yaml', yaml);
|
||||||
|
hljs.registerLanguage('markdown', markdown);
|
||||||
|
hljs.registerLanguage('xml', xml);
|
||||||
|
hljs.registerLanguage('ruby', ruby);
|
||||||
|
hljs.registerLanguage('go', go);
|
||||||
|
hljs.registerLanguage('java', java);
|
||||||
|
hljs.registerLanguage('rust', rust);
|
||||||
|
hljs.registerLanguage('scala', scala);
|
||||||
|
hljs.registerLanguage('csharp', csharp);
|
||||||
|
hljs.registerLanguage('swift', swift);
|
||||||
|
hljs.registerLanguage('dart', dart);
|
||||||
|
hljs.registerLanguage('elixir', elixir);
|
||||||
|
hljs.registerLanguage('kotlin', kotlin);
|
||||||
|
hljs.registerLanguage('lua', lua);
|
||||||
|
hljs.registerLanguage('php', php);
|
||||||
|
hljs.registerLanguage('latex', latex);
|
||||||
|
|
||||||
|
// reuse some languages to further reduce bundle size
|
||||||
|
|
||||||
|
hljs.registerLanguage('shell', bash);
|
||||||
|
hljs.registerLanguage('bash', bash);
|
||||||
|
hljs.registerLanguage('sh', bash);
|
||||||
|
|
||||||
|
hljs.registerLanguage('css', scss);
|
||||||
|
hljs.registerLanguage('scss', scss);
|
||||||
|
|
||||||
|
hljs.registerLanguage('c', cpp);
|
||||||
|
hljs.registerLanguage('cpp', cpp);
|
||||||
|
|
||||||
|
export default hljs;
|
66
examples/server/webui/src/katex-gpt.js
Normal file
66
examples/server/webui/src/katex-gpt.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import katex from 'katex';
|
||||||
|
|
||||||
|
// Adapted from https://github.com/SchneeHertz/markdown-it-katex-gpt
|
||||||
|
// MIT license
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
delimiters: [
|
||||||
|
{ left: '\\[', right: '\\]', display: true },
|
||||||
|
{ left: '\\(', right: '\\)', display: false },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function renderLatexHTML(content, display = false) {
|
||||||
|
return katex.renderToString(content, {
|
||||||
|
throwOnError: false,
|
||||||
|
output: 'mathml',
|
||||||
|
displayMode: display,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapedBracketRule(options) {
|
||||||
|
return (state, silent) => {
|
||||||
|
const max = state.posMax;
|
||||||
|
const start = state.pos;
|
||||||
|
|
||||||
|
for (const { left, right, display } of options.delimiters) {
|
||||||
|
|
||||||
|
// Check if it starts with the left delimiter
|
||||||
|
if (!state.src.slice(start).startsWith(left)) continue;
|
||||||
|
|
||||||
|
// Skip the length of the left delimiter
|
||||||
|
let pos = start + left.length;
|
||||||
|
|
||||||
|
// Find the matching right delimiter
|
||||||
|
while (pos < max) {
|
||||||
|
if (state.src.slice(pos).startsWith(right)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matching right delimiter found, skip to the next match
|
||||||
|
if (pos >= max) continue;
|
||||||
|
|
||||||
|
// If not in silent mode, convert LaTeX formula to MathML
|
||||||
|
if (!silent) {
|
||||||
|
const content = state.src.slice(start + left.length, pos);
|
||||||
|
try {
|
||||||
|
const renderedContent = renderLatexHTML(content, display);
|
||||||
|
const token = state.push('html_inline', '', 0);
|
||||||
|
token.content = renderedContent;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position, skip the length of the right delimiter
|
||||||
|
state.pos = pos + right.length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (md, options = defaultOptions) {
|
||||||
|
md.inline.ruler.after('text', 'escaped_bracket', escapedBracketRule(options));
|
||||||
|
}
|
@ -1,8 +1,17 @@
|
|||||||
import './styles.css';
|
import './styles.scss';
|
||||||
import { createApp, defineComponent, shallowRef, computed, h } from 'vue/dist/vue.esm-bundler.js';
|
import { createApp, defineComponent, shallowRef, computed, h } from 'vue/dist/vue.esm-bundler.js';
|
||||||
import MarkdownIt from 'markdown-it';
|
import MarkdownIt from 'markdown-it';
|
||||||
import TextLineStream from 'textlinestream';
|
import TextLineStream from 'textlinestream';
|
||||||
|
|
||||||
|
// math formula rendering
|
||||||
|
import 'katex/dist/katex.min.css';
|
||||||
|
import markdownItKatexGpt, { renderLatexHTML } from './katex-gpt';
|
||||||
|
import markdownItKatexNormal from '@vscode/markdown-it-katex';
|
||||||
|
|
||||||
|
// code highlighting
|
||||||
|
import hljs from './highlight-config';
|
||||||
|
import daisyuiThemes from 'daisyui/src/theming/themes';
|
||||||
|
|
||||||
const isDev = import.meta.env.MODE === 'development';
|
const isDev = import.meta.env.MODE === 'development';
|
||||||
|
|
||||||
// utility functions
|
// utility functions
|
||||||
@ -13,8 +22,11 @@ const escapeAttr = (str) => str.replace(/>/g, '>').replace(/"/g, '"');
|
|||||||
const copyStr = (str) => navigator.clipboard.writeText(str);
|
const copyStr = (str) => navigator.clipboard.writeText(str);
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
const BASE_URL = localStorage.getItem('base') // for debugging
|
const BASE_URL = isDev
|
||||||
|| (new URL('.', document.baseURI).href).toString().replace(/\/$/, ''); // for production
|
? (localStorage.getItem('base') || 'https://localhost:8080') // for debugging
|
||||||
|
: (new URL('.', document.baseURI).href).toString().replace(/\/$/, ''); // for production
|
||||||
|
console.log({ BASE_URL });
|
||||||
|
|
||||||
const CONFIG_DEFAULT = {
|
const CONFIG_DEFAULT = {
|
||||||
// Note: in order not to introduce breaking changes, please keep the same data type (number, string, etc) if you want to change the default value. Do not use null or undefined for default value.
|
// Note: in order not to introduce breaking changes, please keep the same data type (number, string, etc) if you want to change the default value. Do not use null or undefined for default value.
|
||||||
apiKey: '',
|
apiKey: '',
|
||||||
@ -69,12 +81,39 @@ const CONFIG_INFO = {
|
|||||||
// config keys having numeric value (i.e. temperature, top_k, top_p, etc)
|
// config keys having numeric value (i.e. temperature, top_k, top_p, etc)
|
||||||
const CONFIG_NUMERIC_KEYS = Object.entries(CONFIG_DEFAULT).filter(e => isNumeric(e[1])).map(e => e[0]);
|
const CONFIG_NUMERIC_KEYS = Object.entries(CONFIG_DEFAULT).filter(e => isNumeric(e[1])).map(e => e[0]);
|
||||||
// list of themes supported by daisyui
|
// list of themes supported by daisyui
|
||||||
const THEMES = ['light', 'dark', 'cupcake', 'bumblebee', 'emerald', 'corporate', 'synthwave', 'retro', 'cyberpunk', 'valentine', 'halloween', 'garden', 'forest', 'aqua', 'lofi', 'pastel', 'fantasy', 'wireframe', 'black', 'luxury', 'dracula', 'cmyk', 'autumn', 'business', 'acid', 'lemonade', 'night', 'coffee', 'winter', 'dim', 'nord', 'sunset'];
|
const THEMES = ['light', 'dark']
|
||||||
|
// make sure light & dark are always at the beginning
|
||||||
|
.concat(Object.keys(daisyuiThemes).filter(t => t !== 'light' && t !== 'dark'));
|
||||||
|
|
||||||
// markdown support
|
// markdown support
|
||||||
const VueMarkdown = defineComponent(
|
const VueMarkdown = defineComponent(
|
||||||
(props) => {
|
(props) => {
|
||||||
const md = shallowRef(new MarkdownIt({ breaks: true }));
|
const md = shallowRef(new MarkdownIt({
|
||||||
|
breaks: true,
|
||||||
|
highlight: function (str, lang) { // Add highlight.js
|
||||||
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
|
try {
|
||||||
|
return '<pre><code class="hljs">' +
|
||||||
|
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
||||||
|
'</code></pre>';
|
||||||
|
} catch (__) {}
|
||||||
|
}
|
||||||
|
return '<pre><code class="hljs">' + md.value.utils.escapeHtml(str) + '</code></pre>';
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
// support latex with double dollar sign and square brackets
|
||||||
|
md.value.use(markdownItKatexGpt, {
|
||||||
|
delimiters: [
|
||||||
|
{ left: '\\[', right: '\\]', display: true },
|
||||||
|
{ left: '\\(', right: '\\)', display: false },
|
||||||
|
{ left: '$$', right: '$$', display: false },
|
||||||
|
// do not add single dollar sign here, other wise it will confused with dollar used for money symbol
|
||||||
|
],
|
||||||
|
throwOnError: false,
|
||||||
|
});
|
||||||
|
// support latex with single dollar sign
|
||||||
|
md.value.use(markdownItKatexNormal, { throwOnError: false });
|
||||||
|
// add copy button to code blocks
|
||||||
const origFenchRenderer = md.value.renderer.rules.fence;
|
const origFenchRenderer = md.value.renderer.rules.fence;
|
||||||
md.value.renderer.rules.fence = (tokens, idx, ...args) => {
|
md.value.renderer.rules.fence = (tokens, idx, ...args) => {
|
||||||
const content = tokens[idx].content;
|
const content = tokens[idx].content;
|
||||||
@ -278,6 +317,7 @@ const mainApp = createApp({
|
|||||||
themes: THEMES,
|
themes: THEMES,
|
||||||
configDefault: {...CONFIG_DEFAULT},
|
configDefault: {...CONFIG_DEFAULT},
|
||||||
configInfo: {...CONFIG_INFO},
|
configInfo: {...CONFIG_INFO},
|
||||||
|
isDev,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
@ -289,6 +329,7 @@ const mainApp = createApp({
|
|||||||
if (this.isGenerating) chatScrollToBottom(true);
|
if (this.isGenerating) chatScrollToBottom(true);
|
||||||
});
|
});
|
||||||
resizeObserver.observe(pendingMsgElem);
|
resizeObserver.observe(pendingMsgElem);
|
||||||
|
this.setSelectedTheme(this.selectedTheme);
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
viewingConvId: function(val, oldVal) {
|
viewingConvId: function(val, oldVal) {
|
||||||
@ -305,6 +346,8 @@ const mainApp = createApp({
|
|||||||
},
|
},
|
||||||
setSelectedTheme(theme) {
|
setSelectedTheme(theme) {
|
||||||
this.selectedTheme = theme;
|
this.selectedTheme = theme;
|
||||||
|
document.body.setAttribute('data-theme', theme);
|
||||||
|
document.body.setAttribute('data-color-scheme', daisyuiThemes[theme]?.['color-scheme'] ?? 'auto');
|
||||||
StorageUtils.setTheme(theme);
|
StorageUtils.setTheme(theme);
|
||||||
},
|
},
|
||||||
newConversation() {
|
newConversation() {
|
||||||
@ -513,6 +556,17 @@ const mainApp = createApp({
|
|||||||
fetchMessages() {
|
fetchMessages() {
|
||||||
this.messages = StorageUtils.getOneConversation(this.viewingConvId)?.messages ?? [];
|
this.messages = StorageUtils.getOneConversation(this.viewingConvId)?.messages ?? [];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// debug functions
|
||||||
|
async debugImportDemoConv() {
|
||||||
|
const res = await fetch('/demo-conversation.json');
|
||||||
|
const demoConv = await res.json();
|
||||||
|
StorageUtils.remove(demoConv.id);
|
||||||
|
for (const msg of demoConv.messages) {
|
||||||
|
StorageUtils.appendMsg(demoConv.id, msg);
|
||||||
|
}
|
||||||
|
this.fetchConversation();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
mainApp.config.errorHandler = alert;
|
mainApp.config.errorHandler = alert;
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
.markdown {
|
|
||||||
h1, h2, h3, h4, h5, h6, ul, ol, li { all: revert; }
|
|
||||||
pre {
|
|
||||||
@apply whitespace-pre-wrap rounded-lg p-2;
|
|
||||||
border: 1px solid currentColor;
|
|
||||||
}
|
|
||||||
/* TODO: fix markdown table */
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-on-hover {
|
|
||||||
@apply md:opacity-0 md:group-hover:opacity-100;
|
|
||||||
}
|
|
||||||
.btn-mini {
|
|
||||||
@apply cursor-pointer hover:shadow-md;
|
|
||||||
}
|
|
||||||
.chat-screen { max-width: 900px; }
|
|
||||||
|
|
||||||
.chat-bubble-base-300 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
@apply bg-base-300 text-base-content;
|
|
||||||
}
|
|
48
examples/server/webui/src/styles.scss
Normal file
48
examples/server/webui/src/styles.scss
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
@use "sass:meta";
|
||||||
|
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
.markdown {
|
||||||
|
h1, h2, h3, h4, h5, h6, ul, ol, li { all: revert; }
|
||||||
|
pre {
|
||||||
|
@apply whitespace-pre-wrap rounded-lg p-2;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
}
|
||||||
|
/* TODO: fix markdown table */
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-on-hover {
|
||||||
|
@apply md:opacity-0 md:group-hover:opacity-100;
|
||||||
|
}
|
||||||
|
.btn-mini {
|
||||||
|
@apply cursor-pointer hover:shadow-md;
|
||||||
|
}
|
||||||
|
.chat-screen { max-width: 900px; }
|
||||||
|
|
||||||
|
.chat-bubble-base-300 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
@apply bg-base-300 text-base-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlight.js */
|
||||||
|
[data-color-scheme='light'] {
|
||||||
|
@include meta.load-css('highlight.js/styles/stackoverflow-light');
|
||||||
|
}
|
||||||
|
[data-color-scheme='dark'] {
|
||||||
|
@include meta.load-css('highlight.js/styles/stackoverflow-dark');
|
||||||
|
}
|
||||||
|
[data-color-scheme='auto'] {
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
@include meta.load-css('highlight.js/styles/stackoverflow-light');
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
@include meta.load-css('highlight.js/styles/stackoverflow-dark');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hljs {
|
||||||
|
background: transparent !important;
|
||||||
|
padding: 0.5em !important;
|
||||||
|
}
|
@ -2,6 +2,9 @@
|
|||||||
import { viteSingleFile } from 'vite-plugin-singlefile';
|
import { viteSingleFile } from 'vite-plugin-singlefile';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import zlib from 'zlib';
|
||||||
|
|
||||||
|
const MAX_BUNDLE_SIZE = 1.5 * 1024 * 1024; // only increase when absolutely necessary
|
||||||
|
|
||||||
const GUIDE_FOR_FRONTEND = `
|
const GUIDE_FOR_FRONTEND = `
|
||||||
<!--
|
<!--
|
||||||
@ -12,8 +15,7 @@ const GUIDE_FOR_FRONTEND = `
|
|||||||
-->
|
-->
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
export default {
|
const BUILD_PLUGINS = [
|
||||||
plugins: [
|
|
||||||
viteSingleFile(),
|
viteSingleFile(),
|
||||||
(function llamaCppPlugin() {
|
(function llamaCppPlugin() {
|
||||||
let config;
|
let config;
|
||||||
@ -25,12 +27,33 @@ export default {
|
|||||||
},
|
},
|
||||||
writeBundle() {
|
writeBundle() {
|
||||||
const outputIndexHtml = path.join(config.build.outDir, 'index.html');
|
const outputIndexHtml = path.join(config.build.outDir, 'index.html');
|
||||||
const content = fs.readFileSync(outputIndexHtml, 'utf-8');
|
const content = GUIDE_FOR_FRONTEND + '\n' + fs.readFileSync(outputIndexHtml, 'utf-8');
|
||||||
|
const compressed = zlib.gzipSync(Buffer.from(content, 'utf-8'), { level: 9 });
|
||||||
|
|
||||||
const targetOutputFile = path.join(config.build.outDir, '../../public/index.html');
|
// because gzip header contains machine-specific info, we must remove these data from the header
|
||||||
fs.writeFileSync(targetOutputFile, GUIDE_FOR_FRONTEND + '\n' + content);
|
// timestamp
|
||||||
|
compressed[0x4] = 0;
|
||||||
|
compressed[0x5] = 0;
|
||||||
|
compressed[0x6] = 0;
|
||||||
|
compressed[0x7] = 0;
|
||||||
|
// OS
|
||||||
|
compressed[0x9] = 0;
|
||||||
|
|
||||||
|
if (compressed.byteLength > MAX_BUNDLE_SIZE) {
|
||||||
|
throw new Error(
|
||||||
|
`Bundle size is too large (${Math.ceil(compressed.byteLength / 1024)} KB).\n` +
|
||||||
|
`Please reduce the size of the frontend or increase MAX_BUNDLE_SIZE in vite.config.js.\n`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetOutputFile = path.join(config.build.outDir, '../../public/index.html.gz');
|
||||||
|
fs.writeFileSync(targetOutputFile, compressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
],
|
];
|
||||||
|
|
||||||
|
/** @type {import('vite').UserConfig} */
|
||||||
|
export default {
|
||||||
|
plugins: process.env.ANALYZE ? [] : BUILD_PLUGINS,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user