Spaces:
Sleeping
Sleeping
Mishig
commited on
Revert "Generic Multimodal Support" (#1146)
Browse filesRevert "Generic Multimodal Support (#1021)"
This reverts commit 57f89346cc6d953246d0f1705e342e2e66fce386.
- README.md +2 -25
- package-lock.json +161 -238
- package.json +3 -4
- src/lib/components/chat/ChatMessage.svelte +4 -4
- src/lib/components/chat/ChatWindow.svelte +3 -5
- src/lib/server/endpoints/anthropic/endpointAnthropic.ts +13 -17
- src/lib/server/endpoints/anthropic/endpointAnthropicVertex.ts +12 -16
- src/lib/server/endpoints/anthropic/utils.ts +0 -44
- src/lib/server/endpoints/endpoints.ts +1 -3
- src/lib/server/endpoints/images.ts +0 -211
- src/lib/server/endpoints/openai/endpointOai.ts +6 -74
- src/lib/server/endpoints/preprocessMessages.ts +0 -56
- src/lib/server/endpoints/tgi/endpointTgi.ts +4 -46
- src/lib/server/files/downloadFile.ts +3 -4
- src/lib/server/files/uploadFile.ts +5 -11
- src/lib/server/generateFromDefaultEndpoint.ts +2 -2
- src/lib/server/models.ts +1 -1
- src/lib/server/preprocessMessages.ts +61 -0
- src/lib/server/summarize.ts +2 -2
- src/lib/server/websearch/search/generateQuery.ts +1 -2
- src/lib/types/Message.ts +1 -11
- src/lib/utils/messageUpdates.ts +1 -2
- src/routes/conversation/[id]/+page.svelte +18 -13
- src/routes/conversation/[id]/+server.ts +36 -38
- src/routes/conversation/[id]/output/[sha256]/+server.ts +2 -2
README.md
CHANGED
|
@@ -230,7 +230,7 @@ The following is the default `chatPromptTemplate`, although newlines and indenti
|
|
| 230 |
|
| 231 |
#### Multi modal model
|
| 232 |
|
| 233 |
-
We currently support
|
| 234 |
|
| 235 |
```env
|
| 236 |
{
|
|
@@ -465,34 +465,14 @@ MODELS=`[
|
|
| 465 |
|
| 466 |
#### Anthropic
|
| 467 |
|
| 468 |
-
We also support Anthropic models
|
| 469 |
|
| 470 |
```
|
| 471 |
MODELS=`[
|
| 472 |
-
{
|
| 473 |
-
"name": "claude-3-haiku-20240307",
|
| 474 |
-
"displayName": "Claude 3 Haiku",
|
| 475 |
-
"description": "Fastest and most compact model for near-instant responsiveness",
|
| 476 |
-
"multimodal": true,
|
| 477 |
-
"parameters": {
|
| 478 |
-
"max_new_tokens": 4096,
|
| 479 |
-
},
|
| 480 |
-
"endpoints": [
|
| 481 |
-
{
|
| 482 |
-
"type": "anthropic",
|
| 483 |
-
// optionals
|
| 484 |
-
"apiKey": "sk-ant-...",
|
| 485 |
-
"baseURL": "https://api.anthropic.com",
|
| 486 |
-
"defaultHeaders": {},
|
| 487 |
-
"defaultQuery": {}
|
| 488 |
-
}
|
| 489 |
-
]
|
| 490 |
-
},
|
| 491 |
{
|
| 492 |
"name": "claude-3-sonnet-20240229",
|
| 493 |
"displayName": "Claude 3 Sonnet",
|
| 494 |
"description": "Ideal balance of intelligence and speed",
|
| 495 |
-
"multimodal": true,
|
| 496 |
"parameters": {
|
| 497 |
"max_new_tokens": 4096,
|
| 498 |
},
|
|
@@ -511,7 +491,6 @@ MODELS=`[
|
|
| 511 |
"name": "claude-3-opus-20240229",
|
| 512 |
"displayName": "Claude 3 Opus",
|
| 513 |
"description": "Most powerful model for highly complex tasks",
|
| 514 |
-
"multimodal": true,
|
| 515 |
"parameters": {
|
| 516 |
"max_new_tokens": 4096
|
| 517 |
},
|
|
@@ -537,7 +516,6 @@ MODELS=`[
|
|
| 537 |
"name": "claude-3-sonnet@20240229",
|
| 538 |
"displayName": "Claude 3 Sonnet",
|
| 539 |
"description": "Ideal balance of intelligence and speed",
|
| 540 |
-
"multimodal": true,
|
| 541 |
"parameters": {
|
| 542 |
"max_new_tokens": 4096,
|
| 543 |
},
|
|
@@ -556,7 +534,6 @@ MODELS=`[
|
|
| 556 |
"name": "claude-3-haiku@20240307",
|
| 557 |
"displayName": "Claude 3 Haiku",
|
| 558 |
"description": "Fastest, most compact model for near-instant responsiveness",
|
| 559 |
-
"multimodal": true,
|
| 560 |
"parameters": {
|
| 561 |
"max_new_tokens": 4096
|
| 562 |
},
|
|
|
|
| 230 |
|
| 231 |
#### Multi modal model
|
| 232 |
|
| 233 |
+
We currently only support IDEFICS as a multimodal model, hosted on TGI. You can enable it by using the following config (if you have a PRO HF Api token):
|
| 234 |
|
| 235 |
```env
|
| 236 |
{
|
|
|
|
| 465 |
|
| 466 |
#### Anthropic
|
| 467 |
|
| 468 |
+
We also support Anthropic models through the official SDK. You may provide your API key via the `ANTHROPIC_API_KEY` env variable, or alternatively, through the `endpoints.apiKey` as per the following example.
|
| 469 |
|
| 470 |
```
|
| 471 |
MODELS=`[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 472 |
{
|
| 473 |
"name": "claude-3-sonnet-20240229",
|
| 474 |
"displayName": "Claude 3 Sonnet",
|
| 475 |
"description": "Ideal balance of intelligence and speed",
|
|
|
|
| 476 |
"parameters": {
|
| 477 |
"max_new_tokens": 4096,
|
| 478 |
},
|
|
|
|
| 491 |
"name": "claude-3-opus-20240229",
|
| 492 |
"displayName": "Claude 3 Opus",
|
| 493 |
"description": "Most powerful model for highly complex tasks",
|
|
|
|
| 494 |
"parameters": {
|
| 495 |
"max_new_tokens": 4096
|
| 496 |
},
|
|
|
|
| 516 |
"name": "claude-3-sonnet@20240229",
|
| 517 |
"displayName": "Claude 3 Sonnet",
|
| 518 |
"description": "Ideal balance of intelligence and speed",
|
|
|
|
| 519 |
"parameters": {
|
| 520 |
"max_new_tokens": 4096,
|
| 521 |
},
|
|
|
|
| 534 |
"name": "claude-3-haiku@20240307",
|
| 535 |
"displayName": "Claude 3 Haiku",
|
| 536 |
"description": "Fastest, most compact model for near-instant responsiveness",
|
|
|
|
| 537 |
"parameters": {
|
| 538 |
"max_new_tokens": 4096
|
| 539 |
},
|
package-lock.json
CHANGED
|
@@ -13,14 +13,13 @@
|
|
| 13 |
"@huggingface/inference": "^2.6.3",
|
| 14 |
"@iconify-json/bi": "^1.1.21",
|
| 15 |
"@playwright/browser-chromium": "^1.43.1",
|
| 16 |
-
"@resvg/resvg-js": "^2.6.
|
| 17 |
"@xenova/transformers": "^2.16.1",
|
| 18 |
"autoprefixer": "^10.4.14",
|
| 19 |
"browser-image-resizer": "^2.4.1",
|
| 20 |
"date-fns": "^2.29.3",
|
| 21 |
"dotenv": "^16.0.3",
|
| 22 |
"express": "^4.19.2",
|
| 23 |
-
"file-type": "^19.0.0",
|
| 24 |
"handlebars": "^4.7.8",
|
| 25 |
"highlight.js": "^11.7.0",
|
| 26 |
"image-size": "^1.0.2",
|
|
@@ -42,7 +41,7 @@
|
|
| 42 |
"satori-html": "^0.3.2",
|
| 43 |
"sbd": "^1.0.19",
|
| 44 |
"serpapi": "^1.1.1",
|
| 45 |
-
"sharp": "^0.33.
|
| 46 |
"tailwind-scrollbar": "^3.0.0",
|
| 47 |
"tailwindcss": "^3.4.0",
|
| 48 |
"uuid": "^9.0.1",
|
|
@@ -89,7 +88,7 @@
|
|
| 89 |
"@google-cloud/vertexai": "^1.1.0",
|
| 90 |
"aws4fetch": "^1.0.17",
|
| 91 |
"cohere-ai": "^7.9.0",
|
| 92 |
-
"openai": "^4.
|
| 93 |
}
|
| 94 |
},
|
| 95 |
"node_modules/@alloc/quick-lru": {
|
|
@@ -238,9 +237,9 @@
|
|
| 238 |
}
|
| 239 |
},
|
| 240 |
"node_modules/@emnapi/runtime": {
|
| 241 |
-
"version": "
|
| 242 |
-
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-
|
| 243 |
-
"integrity": "sha512-
|
| 244 |
"optional": true,
|
| 245 |
"dependencies": {
|
| 246 |
"tslib": "^2.4.0"
|
|
@@ -812,9 +811,9 @@
|
|
| 812 |
}
|
| 813 |
},
|
| 814 |
"node_modules/@img/sharp-darwin-arm64": {
|
| 815 |
-
"version": "0.33.
|
| 816 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.
|
| 817 |
-
"integrity": "sha512-
|
| 818 |
"cpu": [
|
| 819 |
"arm64"
|
| 820 |
],
|
|
@@ -833,13 +832,13 @@
|
|
| 833 |
"url": "https://opencollective.com/libvips"
|
| 834 |
},
|
| 835 |
"optionalDependencies": {
|
| 836 |
-
"@img/sharp-libvips-darwin-arm64": "1.0.
|
| 837 |
}
|
| 838 |
},
|
| 839 |
"node_modules/@img/sharp-darwin-x64": {
|
| 840 |
-
"version": "0.33.
|
| 841 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.
|
| 842 |
-
"integrity": "sha512
|
| 843 |
"cpu": [
|
| 844 |
"x64"
|
| 845 |
],
|
|
@@ -858,13 +857,13 @@
|
|
| 858 |
"url": "https://opencollective.com/libvips"
|
| 859 |
},
|
| 860 |
"optionalDependencies": {
|
| 861 |
-
"@img/sharp-libvips-darwin-x64": "1.0.
|
| 862 |
}
|
| 863 |
},
|
| 864 |
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
| 865 |
-
"version": "1.0.
|
| 866 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.
|
| 867 |
-
"integrity": "sha512-
|
| 868 |
"cpu": [
|
| 869 |
"arm64"
|
| 870 |
],
|
|
@@ -883,9 +882,9 @@
|
|
| 883 |
}
|
| 884 |
},
|
| 885 |
"node_modules/@img/sharp-libvips-darwin-x64": {
|
| 886 |
-
"version": "1.0.
|
| 887 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.
|
| 888 |
-
"integrity": "sha512-
|
| 889 |
"cpu": [
|
| 890 |
"x64"
|
| 891 |
],
|
|
@@ -904,9 +903,9 @@
|
|
| 904 |
}
|
| 905 |
},
|
| 906 |
"node_modules/@img/sharp-libvips-linux-arm": {
|
| 907 |
-
"version": "1.0.
|
| 908 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.
|
| 909 |
-
"integrity": "sha512-
|
| 910 |
"cpu": [
|
| 911 |
"arm"
|
| 912 |
],
|
|
@@ -925,9 +924,9 @@
|
|
| 925 |
}
|
| 926 |
},
|
| 927 |
"node_modules/@img/sharp-libvips-linux-arm64": {
|
| 928 |
-
"version": "1.0.
|
| 929 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.
|
| 930 |
-
"integrity": "sha512-
|
| 931 |
"cpu": [
|
| 932 |
"arm64"
|
| 933 |
],
|
|
@@ -946,9 +945,9 @@
|
|
| 946 |
}
|
| 947 |
},
|
| 948 |
"node_modules/@img/sharp-libvips-linux-s390x": {
|
| 949 |
-
"version": "1.0.
|
| 950 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.
|
| 951 |
-
"integrity": "sha512-
|
| 952 |
"cpu": [
|
| 953 |
"s390x"
|
| 954 |
],
|
|
@@ -967,9 +966,9 @@
|
|
| 967 |
}
|
| 968 |
},
|
| 969 |
"node_modules/@img/sharp-libvips-linux-x64": {
|
| 970 |
-
"version": "1.0.
|
| 971 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.
|
| 972 |
-
"integrity": "sha512-
|
| 973 |
"cpu": [
|
| 974 |
"x64"
|
| 975 |
],
|
|
@@ -988,9 +987,9 @@
|
|
| 988 |
}
|
| 989 |
},
|
| 990 |
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
| 991 |
-
"version": "1.0.
|
| 992 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.
|
| 993 |
-
"integrity": "sha512-
|
| 994 |
"cpu": [
|
| 995 |
"arm64"
|
| 996 |
],
|
|
@@ -1009,9 +1008,9 @@
|
|
| 1009 |
}
|
| 1010 |
},
|
| 1011 |
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
| 1012 |
-
"version": "1.0.
|
| 1013 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.
|
| 1014 |
-
"integrity": "sha512-
|
| 1015 |
"cpu": [
|
| 1016 |
"x64"
|
| 1017 |
],
|
|
@@ -1030,9 +1029,9 @@
|
|
| 1030 |
}
|
| 1031 |
},
|
| 1032 |
"node_modules/@img/sharp-linux-arm": {
|
| 1033 |
-
"version": "0.33.
|
| 1034 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.
|
| 1035 |
-
"integrity": "sha512-
|
| 1036 |
"cpu": [
|
| 1037 |
"arm"
|
| 1038 |
],
|
|
@@ -1051,13 +1050,13 @@
|
|
| 1051 |
"url": "https://opencollective.com/libvips"
|
| 1052 |
},
|
| 1053 |
"optionalDependencies": {
|
| 1054 |
-
"@img/sharp-libvips-linux-arm": "1.0.
|
| 1055 |
}
|
| 1056 |
},
|
| 1057 |
"node_modules/@img/sharp-linux-arm64": {
|
| 1058 |
-
"version": "0.33.
|
| 1059 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.
|
| 1060 |
-
"integrity": "sha512-
|
| 1061 |
"cpu": [
|
| 1062 |
"arm64"
|
| 1063 |
],
|
|
@@ -1076,13 +1075,13 @@
|
|
| 1076 |
"url": "https://opencollective.com/libvips"
|
| 1077 |
},
|
| 1078 |
"optionalDependencies": {
|
| 1079 |
-
"@img/sharp-libvips-linux-arm64": "1.0.
|
| 1080 |
}
|
| 1081 |
},
|
| 1082 |
"node_modules/@img/sharp-linux-s390x": {
|
| 1083 |
-
"version": "0.33.
|
| 1084 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.
|
| 1085 |
-
"integrity": "sha512-
|
| 1086 |
"cpu": [
|
| 1087 |
"s390x"
|
| 1088 |
],
|
|
@@ -1101,13 +1100,13 @@
|
|
| 1101 |
"url": "https://opencollective.com/libvips"
|
| 1102 |
},
|
| 1103 |
"optionalDependencies": {
|
| 1104 |
-
"@img/sharp-libvips-linux-s390x": "1.0.
|
| 1105 |
}
|
| 1106 |
},
|
| 1107 |
"node_modules/@img/sharp-linux-x64": {
|
| 1108 |
-
"version": "0.33.
|
| 1109 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.
|
| 1110 |
-
"integrity": "sha512-
|
| 1111 |
"cpu": [
|
| 1112 |
"x64"
|
| 1113 |
],
|
|
@@ -1126,13 +1125,13 @@
|
|
| 1126 |
"url": "https://opencollective.com/libvips"
|
| 1127 |
},
|
| 1128 |
"optionalDependencies": {
|
| 1129 |
-
"@img/sharp-libvips-linux-x64": "1.0.
|
| 1130 |
}
|
| 1131 |
},
|
| 1132 |
"node_modules/@img/sharp-linuxmusl-arm64": {
|
| 1133 |
-
"version": "0.33.
|
| 1134 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.
|
| 1135 |
-
"integrity": "sha512-
|
| 1136 |
"cpu": [
|
| 1137 |
"arm64"
|
| 1138 |
],
|
|
@@ -1151,13 +1150,13 @@
|
|
| 1151 |
"url": "https://opencollective.com/libvips"
|
| 1152 |
},
|
| 1153 |
"optionalDependencies": {
|
| 1154 |
-
"@img/sharp-libvips-linuxmusl-arm64": "1.0.
|
| 1155 |
}
|
| 1156 |
},
|
| 1157 |
"node_modules/@img/sharp-linuxmusl-x64": {
|
| 1158 |
-
"version": "0.33.
|
| 1159 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.
|
| 1160 |
-
"integrity": "sha512
|
| 1161 |
"cpu": [
|
| 1162 |
"x64"
|
| 1163 |
],
|
|
@@ -1176,19 +1175,19 @@
|
|
| 1176 |
"url": "https://opencollective.com/libvips"
|
| 1177 |
},
|
| 1178 |
"optionalDependencies": {
|
| 1179 |
-
"@img/sharp-libvips-linuxmusl-x64": "1.0.
|
| 1180 |
}
|
| 1181 |
},
|
| 1182 |
"node_modules/@img/sharp-wasm32": {
|
| 1183 |
-
"version": "0.33.
|
| 1184 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.
|
| 1185 |
-
"integrity": "sha512-
|
| 1186 |
"cpu": [
|
| 1187 |
"wasm32"
|
| 1188 |
],
|
| 1189 |
"optional": true,
|
| 1190 |
"dependencies": {
|
| 1191 |
-
"@emnapi/runtime": "^
|
| 1192 |
},
|
| 1193 |
"engines": {
|
| 1194 |
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
|
|
@@ -1201,9 +1200,9 @@
|
|
| 1201 |
}
|
| 1202 |
},
|
| 1203 |
"node_modules/@img/sharp-win32-ia32": {
|
| 1204 |
-
"version": "0.33.
|
| 1205 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.
|
| 1206 |
-
"integrity": "sha512-
|
| 1207 |
"cpu": [
|
| 1208 |
"ia32"
|
| 1209 |
],
|
|
@@ -1222,9 +1221,9 @@
|
|
| 1222 |
}
|
| 1223 |
},
|
| 1224 |
"node_modules/@img/sharp-win32-x64": {
|
| 1225 |
-
"version": "0.33.
|
| 1226 |
-
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.
|
| 1227 |
-
"integrity": "sha512-
|
| 1228 |
"cpu": [
|
| 1229 |
"x64"
|
| 1230 |
],
|
|
@@ -1445,31 +1444,31 @@
|
|
| 1445 |
"integrity": "sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q=="
|
| 1446 |
},
|
| 1447 |
"node_modules/@resvg/resvg-js": {
|
| 1448 |
-
"version": "2.6.
|
| 1449 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.
|
| 1450 |
-
"integrity": "sha512-
|
| 1451 |
"engines": {
|
| 1452 |
"node": ">= 10"
|
| 1453 |
},
|
| 1454 |
"optionalDependencies": {
|
| 1455 |
-
"@resvg/resvg-js-android-arm-eabi": "2.6.
|
| 1456 |
-
"@resvg/resvg-js-android-arm64": "2.6.
|
| 1457 |
-
"@resvg/resvg-js-darwin-arm64": "2.6.
|
| 1458 |
-
"@resvg/resvg-js-darwin-x64": "2.6.
|
| 1459 |
-
"@resvg/resvg-js-linux-arm-gnueabihf": "2.6.
|
| 1460 |
-
"@resvg/resvg-js-linux-arm64-gnu": "2.6.
|
| 1461 |
-
"@resvg/resvg-js-linux-arm64-musl": "2.6.
|
| 1462 |
-
"@resvg/resvg-js-linux-x64-gnu": "2.6.
|
| 1463 |
-
"@resvg/resvg-js-linux-x64-musl": "2.6.
|
| 1464 |
-
"@resvg/resvg-js-win32-arm64-msvc": "2.6.
|
| 1465 |
-
"@resvg/resvg-js-win32-ia32-msvc": "2.6.
|
| 1466 |
-
"@resvg/resvg-js-win32-x64-msvc": "2.6.
|
| 1467 |
}
|
| 1468 |
},
|
| 1469 |
"node_modules/@resvg/resvg-js-android-arm-eabi": {
|
| 1470 |
-
"version": "2.6.
|
| 1471 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.
|
| 1472 |
-
"integrity": "sha512-
|
| 1473 |
"cpu": [
|
| 1474 |
"arm"
|
| 1475 |
],
|
|
@@ -1482,9 +1481,9 @@
|
|
| 1482 |
}
|
| 1483 |
},
|
| 1484 |
"node_modules/@resvg/resvg-js-android-arm64": {
|
| 1485 |
-
"version": "2.6.
|
| 1486 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm64/-/resvg-js-android-arm64-2.6.
|
| 1487 |
-
"integrity": "sha512-
|
| 1488 |
"cpu": [
|
| 1489 |
"arm64"
|
| 1490 |
],
|
|
@@ -1497,9 +1496,9 @@
|
|
| 1497 |
}
|
| 1498 |
},
|
| 1499 |
"node_modules/@resvg/resvg-js-darwin-arm64": {
|
| 1500 |
-
"version": "2.6.
|
| 1501 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-arm64/-/resvg-js-darwin-arm64-2.6.
|
| 1502 |
-
"integrity": "sha512-
|
| 1503 |
"cpu": [
|
| 1504 |
"arm64"
|
| 1505 |
],
|
|
@@ -1512,9 +1511,9 @@
|
|
| 1512 |
}
|
| 1513 |
},
|
| 1514 |
"node_modules/@resvg/resvg-js-darwin-x64": {
|
| 1515 |
-
"version": "2.6.
|
| 1516 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-x64/-/resvg-js-darwin-x64-2.6.
|
| 1517 |
-
"integrity": "sha512-
|
| 1518 |
"cpu": [
|
| 1519 |
"x64"
|
| 1520 |
],
|
|
@@ -1527,9 +1526,9 @@
|
|
| 1527 |
}
|
| 1528 |
},
|
| 1529 |
"node_modules/@resvg/resvg-js-linux-arm-gnueabihf": {
|
| 1530 |
-
"version": "2.6.
|
| 1531 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm-gnueabihf/-/resvg-js-linux-arm-gnueabihf-2.6.
|
| 1532 |
-
"integrity": "sha512-
|
| 1533 |
"cpu": [
|
| 1534 |
"arm"
|
| 1535 |
],
|
|
@@ -1542,9 +1541,9 @@
|
|
| 1542 |
}
|
| 1543 |
},
|
| 1544 |
"node_modules/@resvg/resvg-js-linux-arm64-gnu": {
|
| 1545 |
-
"version": "2.6.
|
| 1546 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-gnu/-/resvg-js-linux-arm64-gnu-2.6.
|
| 1547 |
-
"integrity": "sha512-
|
| 1548 |
"cpu": [
|
| 1549 |
"arm64"
|
| 1550 |
],
|
|
@@ -1557,9 +1556,9 @@
|
|
| 1557 |
}
|
| 1558 |
},
|
| 1559 |
"node_modules/@resvg/resvg-js-linux-arm64-musl": {
|
| 1560 |
-
"version": "2.6.
|
| 1561 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-musl/-/resvg-js-linux-arm64-musl-2.6.
|
| 1562 |
-
"integrity": "sha512-
|
| 1563 |
"cpu": [
|
| 1564 |
"arm64"
|
| 1565 |
],
|
|
@@ -1572,9 +1571,9 @@
|
|
| 1572 |
}
|
| 1573 |
},
|
| 1574 |
"node_modules/@resvg/resvg-js-linux-x64-gnu": {
|
| 1575 |
-
"version": "2.6.
|
| 1576 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-gnu/-/resvg-js-linux-x64-gnu-2.6.
|
| 1577 |
-
"integrity": "sha512-
|
| 1578 |
"cpu": [
|
| 1579 |
"x64"
|
| 1580 |
],
|
|
@@ -1587,9 +1586,9 @@
|
|
| 1587 |
}
|
| 1588 |
},
|
| 1589 |
"node_modules/@resvg/resvg-js-linux-x64-musl": {
|
| 1590 |
-
"version": "2.6.
|
| 1591 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-musl/-/resvg-js-linux-x64-musl-2.6.
|
| 1592 |
-
"integrity": "sha512-
|
| 1593 |
"cpu": [
|
| 1594 |
"x64"
|
| 1595 |
],
|
|
@@ -1602,9 +1601,9 @@
|
|
| 1602 |
}
|
| 1603 |
},
|
| 1604 |
"node_modules/@resvg/resvg-js-win32-arm64-msvc": {
|
| 1605 |
-
"version": "2.6.
|
| 1606 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-arm64-msvc/-/resvg-js-win32-arm64-msvc-2.6.
|
| 1607 |
-
"integrity": "sha512-
|
| 1608 |
"cpu": [
|
| 1609 |
"arm64"
|
| 1610 |
],
|
|
@@ -1617,9 +1616,9 @@
|
|
| 1617 |
}
|
| 1618 |
},
|
| 1619 |
"node_modules/@resvg/resvg-js-win32-ia32-msvc": {
|
| 1620 |
-
"version": "2.6.
|
| 1621 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-ia32-msvc/-/resvg-js-win32-ia32-msvc-2.6.
|
| 1622 |
-
"integrity": "sha512-
|
| 1623 |
"cpu": [
|
| 1624 |
"ia32"
|
| 1625 |
],
|
|
@@ -1632,9 +1631,9 @@
|
|
| 1632 |
}
|
| 1633 |
},
|
| 1634 |
"node_modules/@resvg/resvg-js-win32-x64-msvc": {
|
| 1635 |
-
"version": "2.6.
|
| 1636 |
-
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-x64-msvc/-/resvg-js-win32-x64-msvc-2.6.
|
| 1637 |
-
"integrity": "sha512-
|
| 1638 |
"cpu": [
|
| 1639 |
"x64"
|
| 1640 |
],
|
|
@@ -2076,11 +2075,6 @@
|
|
| 2076 |
"node": ">=4"
|
| 2077 |
}
|
| 2078 |
},
|
| 2079 |
-
"node_modules/@tokenizer/token": {
|
| 2080 |
-
"version": "0.3.0",
|
| 2081 |
-
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
| 2082 |
-
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
|
| 2083 |
-
},
|
| 2084 |
"node_modules/@tootallnate/once": {
|
| 2085 |
"version": "2.0.0",
|
| 2086 |
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
|
@@ -3837,9 +3831,9 @@
|
|
| 3837 |
}
|
| 3838 |
},
|
| 3839 |
"node_modules/detect-libc": {
|
| 3840 |
-
"version": "2.0.
|
| 3841 |
-
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.
|
| 3842 |
-
"integrity": "sha512-
|
| 3843 |
"engines": {
|
| 3844 |
"node": ">=8"
|
| 3845 |
}
|
|
@@ -4562,22 +4556,6 @@
|
|
| 4562 |
"node": "^10.12.0 || >=12.0.0"
|
| 4563 |
}
|
| 4564 |
},
|
| 4565 |
-
"node_modules/file-type": {
|
| 4566 |
-
"version": "19.0.0",
|
| 4567 |
-
"resolved": "https://registry.npmjs.org/file-type/-/file-type-19.0.0.tgz",
|
| 4568 |
-
"integrity": "sha512-s7cxa7/leUWLiXO78DVVfBVse+milos9FitauDLG1pI7lNaJ2+5lzPnr2N24ym+84HVwJL6hVuGfgVE+ALvU8Q==",
|
| 4569 |
-
"dependencies": {
|
| 4570 |
-
"readable-web-to-node-stream": "^3.0.2",
|
| 4571 |
-
"strtok3": "^7.0.0",
|
| 4572 |
-
"token-types": "^5.0.1"
|
| 4573 |
-
},
|
| 4574 |
-
"engines": {
|
| 4575 |
-
"node": ">=18"
|
| 4576 |
-
},
|
| 4577 |
-
"funding": {
|
| 4578 |
-
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
| 4579 |
-
}
|
| 4580 |
-
},
|
| 4581 |
"node_modules/fill-range": {
|
| 4582 |
"version": "7.0.1",
|
| 4583 |
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
|
@@ -6407,15 +6385,16 @@
|
|
| 6407 |
}
|
| 6408 |
},
|
| 6409 |
"node_modules/openai": {
|
| 6410 |
-
"version": "4.
|
| 6411 |
-
"resolved": "https://registry.npmjs.org/openai/-/openai-4.
|
| 6412 |
-
"integrity": "sha512-
|
| 6413 |
"optional": true,
|
| 6414 |
"dependencies": {
|
| 6415 |
"@types/node": "^18.11.18",
|
| 6416 |
"@types/node-fetch": "^2.6.4",
|
| 6417 |
"abort-controller": "^3.0.0",
|
| 6418 |
"agentkeepalive": "^4.2.1",
|
|
|
|
| 6419 |
"form-data-encoder": "1.7.2",
|
| 6420 |
"formdata-node": "^4.3.2",
|
| 6421 |
"node-fetch": "^2.6.7",
|
|
@@ -6641,18 +6620,6 @@
|
|
| 6641 |
"node": "*"
|
| 6642 |
}
|
| 6643 |
},
|
| 6644 |
-
"node_modules/peek-readable": {
|
| 6645 |
-
"version": "5.0.0",
|
| 6646 |
-
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
|
| 6647 |
-
"integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==",
|
| 6648 |
-
"engines": {
|
| 6649 |
-
"node": ">=14.16"
|
| 6650 |
-
},
|
| 6651 |
-
"funding": {
|
| 6652 |
-
"type": "github",
|
| 6653 |
-
"url": "https://github.com/sponsors/Borewit"
|
| 6654 |
-
}
|
| 6655 |
-
},
|
| 6656 |
"node_modules/periscopic": {
|
| 6657 |
"version": "3.1.0",
|
| 6658 |
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
|
|
@@ -7508,21 +7475,6 @@
|
|
| 7508 |
"node": ">= 6"
|
| 7509 |
}
|
| 7510 |
},
|
| 7511 |
-
"node_modules/readable-web-to-node-stream": {
|
| 7512 |
-
"version": "3.0.2",
|
| 7513 |
-
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
| 7514 |
-
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
| 7515 |
-
"dependencies": {
|
| 7516 |
-
"readable-stream": "^3.6.0"
|
| 7517 |
-
},
|
| 7518 |
-
"engines": {
|
| 7519 |
-
"node": ">=8"
|
| 7520 |
-
},
|
| 7521 |
-
"funding": {
|
| 7522 |
-
"type": "github",
|
| 7523 |
-
"url": "https://github.com/sponsors/Borewit"
|
| 7524 |
-
}
|
| 7525 |
-
},
|
| 7526 |
"node_modules/readdirp": {
|
| 7527 |
"version": "3.6.0",
|
| 7528 |
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
|
@@ -7784,9 +7736,12 @@
|
|
| 7784 |
"integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="
|
| 7785 |
},
|
| 7786 |
"node_modules/semver": {
|
| 7787 |
-
"version": "7.
|
| 7788 |
-
"resolved": "https://registry.npmjs.org/semver/-/semver-7.
|
| 7789 |
-
"integrity": "sha512-
|
|
|
|
|
|
|
|
|
|
| 7790 |
"bin": {
|
| 7791 |
"semver": "bin/semver.js"
|
| 7792 |
},
|
|
@@ -7885,42 +7840,42 @@
|
|
| 7885 |
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
| 7886 |
},
|
| 7887 |
"node_modules/sharp": {
|
| 7888 |
-
"version": "0.33.
|
| 7889 |
-
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.
|
| 7890 |
-
"integrity": "sha512-
|
| 7891 |
"hasInstallScript": true,
|
| 7892 |
"dependencies": {
|
| 7893 |
"color": "^4.2.3",
|
| 7894 |
-
"detect-libc": "^2.0.
|
| 7895 |
-
"semver": "^7.
|
| 7896 |
},
|
| 7897 |
"engines": {
|
| 7898 |
-
"libvips": ">=8.15.
|
| 7899 |
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 7900 |
},
|
| 7901 |
"funding": {
|
| 7902 |
"url": "https://opencollective.com/libvips"
|
| 7903 |
},
|
| 7904 |
"optionalDependencies": {
|
| 7905 |
-
"@img/sharp-darwin-arm64": "0.33.
|
| 7906 |
-
"@img/sharp-darwin-x64": "0.33.
|
| 7907 |
-
"@img/sharp-libvips-darwin-arm64": "1.0.
|
| 7908 |
-
"@img/sharp-libvips-darwin-x64": "1.0.
|
| 7909 |
-
"@img/sharp-libvips-linux-arm": "1.0.
|
| 7910 |
-
"@img/sharp-libvips-linux-arm64": "1.0.
|
| 7911 |
-
"@img/sharp-libvips-linux-s390x": "1.0.
|
| 7912 |
-
"@img/sharp-libvips-linux-x64": "1.0.
|
| 7913 |
-
"@img/sharp-libvips-linuxmusl-arm64": "1.0.
|
| 7914 |
-
"@img/sharp-libvips-linuxmusl-x64": "1.0.
|
| 7915 |
-
"@img/sharp-linux-arm": "0.33.
|
| 7916 |
-
"@img/sharp-linux-arm64": "0.33.
|
| 7917 |
-
"@img/sharp-linux-s390x": "0.33.
|
| 7918 |
-
"@img/sharp-linux-x64": "0.33.
|
| 7919 |
-
"@img/sharp-linuxmusl-arm64": "0.33.
|
| 7920 |
-
"@img/sharp-linuxmusl-x64": "0.33.
|
| 7921 |
-
"@img/sharp-wasm32": "0.33.
|
| 7922 |
-
"@img/sharp-win32-ia32": "0.33.
|
| 7923 |
-
"@img/sharp-win32-x64": "0.33.
|
| 7924 |
}
|
| 7925 |
},
|
| 7926 |
"node_modules/shebang-command": {
|
|
@@ -8232,22 +8187,6 @@
|
|
| 8232 |
"url": "https://github.com/sponsors/antfu"
|
| 8233 |
}
|
| 8234 |
},
|
| 8235 |
-
"node_modules/strtok3": {
|
| 8236 |
-
"version": "7.0.0",
|
| 8237 |
-
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz",
|
| 8238 |
-
"integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==",
|
| 8239 |
-
"dependencies": {
|
| 8240 |
-
"@tokenizer/token": "^0.3.0",
|
| 8241 |
-
"peek-readable": "^5.0.0"
|
| 8242 |
-
},
|
| 8243 |
-
"engines": {
|
| 8244 |
-
"node": ">=14.16"
|
| 8245 |
-
},
|
| 8246 |
-
"funding": {
|
| 8247 |
-
"type": "github",
|
| 8248 |
-
"url": "https://github.com/sponsors/Borewit"
|
| 8249 |
-
}
|
| 8250 |
-
},
|
| 8251 |
"node_modules/sucrase": {
|
| 8252 |
"version": "3.32.0",
|
| 8253 |
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz",
|
|
@@ -8770,22 +8709,6 @@
|
|
| 8770 |
"node": ">=0.6"
|
| 8771 |
}
|
| 8772 |
},
|
| 8773 |
-
"node_modules/token-types": {
|
| 8774 |
-
"version": "5.0.1",
|
| 8775 |
-
"resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz",
|
| 8776 |
-
"integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==",
|
| 8777 |
-
"dependencies": {
|
| 8778 |
-
"@tokenizer/token": "^0.3.0",
|
| 8779 |
-
"ieee754": "^1.2.1"
|
| 8780 |
-
},
|
| 8781 |
-
"engines": {
|
| 8782 |
-
"node": ">=14.16"
|
| 8783 |
-
},
|
| 8784 |
-
"funding": {
|
| 8785 |
-
"type": "github",
|
| 8786 |
-
"url": "https://github.com/sponsors/Borewit"
|
| 8787 |
-
}
|
| 8788 |
-
},
|
| 8789 |
"node_modules/totalist": {
|
| 8790 |
"version": "3.0.0",
|
| 8791 |
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
|
|
|
|
| 13 |
"@huggingface/inference": "^2.6.3",
|
| 14 |
"@iconify-json/bi": "^1.1.21",
|
| 15 |
"@playwright/browser-chromium": "^1.43.1",
|
| 16 |
+
"@resvg/resvg-js": "^2.6.0",
|
| 17 |
"@xenova/transformers": "^2.16.1",
|
| 18 |
"autoprefixer": "^10.4.14",
|
| 19 |
"browser-image-resizer": "^2.4.1",
|
| 20 |
"date-fns": "^2.29.3",
|
| 21 |
"dotenv": "^16.0.3",
|
| 22 |
"express": "^4.19.2",
|
|
|
|
| 23 |
"handlebars": "^4.7.8",
|
| 24 |
"highlight.js": "^11.7.0",
|
| 25 |
"image-size": "^1.0.2",
|
|
|
|
| 41 |
"satori-html": "^0.3.2",
|
| 42 |
"sbd": "^1.0.19",
|
| 43 |
"serpapi": "^1.1.1",
|
| 44 |
+
"sharp": "^0.33.2",
|
| 45 |
"tailwind-scrollbar": "^3.0.0",
|
| 46 |
"tailwindcss": "^3.4.0",
|
| 47 |
"uuid": "^9.0.1",
|
|
|
|
| 88 |
"@google-cloud/vertexai": "^1.1.0",
|
| 89 |
"aws4fetch": "^1.0.17",
|
| 90 |
"cohere-ai": "^7.9.0",
|
| 91 |
+
"openai": "^4.14.2"
|
| 92 |
}
|
| 93 |
},
|
| 94 |
"node_modules/@alloc/quick-lru": {
|
|
|
|
| 237 |
}
|
| 238 |
},
|
| 239 |
"node_modules/@emnapi/runtime": {
|
| 240 |
+
"version": "0.45.0",
|
| 241 |
+
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz",
|
| 242 |
+
"integrity": "sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==",
|
| 243 |
"optional": true,
|
| 244 |
"dependencies": {
|
| 245 |
"tslib": "^2.4.0"
|
|
|
|
| 811 |
}
|
| 812 |
},
|
| 813 |
"node_modules/@img/sharp-darwin-arm64": {
|
| 814 |
+
"version": "0.33.2",
|
| 815 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.2.tgz",
|
| 816 |
+
"integrity": "sha512-itHBs1rPmsmGF9p4qRe++CzCgd+kFYktnsoR1sbIAfsRMrJZau0Tt1AH9KVnufc2/tU02Gf6Ibujx+15qRE03w==",
|
| 817 |
"cpu": [
|
| 818 |
"arm64"
|
| 819 |
],
|
|
|
|
| 832 |
"url": "https://opencollective.com/libvips"
|
| 833 |
},
|
| 834 |
"optionalDependencies": {
|
| 835 |
+
"@img/sharp-libvips-darwin-arm64": "1.0.1"
|
| 836 |
}
|
| 837 |
},
|
| 838 |
"node_modules/@img/sharp-darwin-x64": {
|
| 839 |
+
"version": "0.33.2",
|
| 840 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.2.tgz",
|
| 841 |
+
"integrity": "sha512-/rK/69Rrp9x5kaWBjVN07KixZanRr+W1OiyKdXcbjQD6KbW+obaTeBBtLUAtbBsnlTTmWthw99xqoOS7SsySDg==",
|
| 842 |
"cpu": [
|
| 843 |
"x64"
|
| 844 |
],
|
|
|
|
| 857 |
"url": "https://opencollective.com/libvips"
|
| 858 |
},
|
| 859 |
"optionalDependencies": {
|
| 860 |
+
"@img/sharp-libvips-darwin-x64": "1.0.1"
|
| 861 |
}
|
| 862 |
},
|
| 863 |
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
| 864 |
+
"version": "1.0.1",
|
| 865 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.1.tgz",
|
| 866 |
+
"integrity": "sha512-kQyrSNd6lmBV7O0BUiyu/OEw9yeNGFbQhbxswS1i6rMDwBBSX+e+rPzu3S+MwAiGU3HdLze3PanQ4Xkfemgzcw==",
|
| 867 |
"cpu": [
|
| 868 |
"arm64"
|
| 869 |
],
|
|
|
|
| 882 |
}
|
| 883 |
},
|
| 884 |
"node_modules/@img/sharp-libvips-darwin-x64": {
|
| 885 |
+
"version": "1.0.1",
|
| 886 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.1.tgz",
|
| 887 |
+
"integrity": "sha512-eVU/JYLPVjhhrd8Tk6gosl5pVlvsqiFlt50wotCvdkFGf+mDNBJxMh+bvav+Wt3EBnNZWq8Sp2I7XfSjm8siog==",
|
| 888 |
"cpu": [
|
| 889 |
"x64"
|
| 890 |
],
|
|
|
|
| 903 |
}
|
| 904 |
},
|
| 905 |
"node_modules/@img/sharp-libvips-linux-arm": {
|
| 906 |
+
"version": "1.0.1",
|
| 907 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.1.tgz",
|
| 908 |
+
"integrity": "sha512-FtdMvR4R99FTsD53IA3LxYGghQ82t3yt0ZQ93WMZ2xV3dqrb0E8zq4VHaTOuLEAuA83oDawHV3fd+BsAPadHIQ==",
|
| 909 |
"cpu": [
|
| 910 |
"arm"
|
| 911 |
],
|
|
|
|
| 924 |
}
|
| 925 |
},
|
| 926 |
"node_modules/@img/sharp-libvips-linux-arm64": {
|
| 927 |
+
"version": "1.0.1",
|
| 928 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.1.tgz",
|
| 929 |
+
"integrity": "sha512-bnGG+MJjdX70mAQcSLxgeJco11G+MxTz+ebxlz8Y3dxyeb3Nkl7LgLI0mXupoO+u1wRNx/iRj5yHtzA4sde1yA==",
|
| 930 |
"cpu": [
|
| 931 |
"arm64"
|
| 932 |
],
|
|
|
|
| 945 |
}
|
| 946 |
},
|
| 947 |
"node_modules/@img/sharp-libvips-linux-s390x": {
|
| 948 |
+
"version": "1.0.1",
|
| 949 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.1.tgz",
|
| 950 |
+
"integrity": "sha512-3+rzfAR1YpMOeA2zZNp+aYEzGNWK4zF3+sdMxuCS3ey9HhDbJ66w6hDSHDMoap32DueFwhhs3vwooAB2MaK4XQ==",
|
| 951 |
"cpu": [
|
| 952 |
"s390x"
|
| 953 |
],
|
|
|
|
| 966 |
}
|
| 967 |
},
|
| 968 |
"node_modules/@img/sharp-libvips-linux-x64": {
|
| 969 |
+
"version": "1.0.1",
|
| 970 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.1.tgz",
|
| 971 |
+
"integrity": "sha512-3NR1mxFsaSgMMzz1bAnnKbSAI+lHXVTqAHgc1bgzjHuXjo4hlscpUxc0vFSAPKI3yuzdzcZOkq7nDPrP2F8Jgw==",
|
| 972 |
"cpu": [
|
| 973 |
"x64"
|
| 974 |
],
|
|
|
|
| 987 |
}
|
| 988 |
},
|
| 989 |
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
| 990 |
+
"version": "1.0.1",
|
| 991 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.1.tgz",
|
| 992 |
+
"integrity": "sha512-5aBRcjHDG/T6jwC3Edl3lP8nl9U2Yo8+oTl5drd1dh9Z1EBfzUKAJFUDTDisDjUwc7N4AjnPGfCA3jl3hY8uDg==",
|
| 993 |
"cpu": [
|
| 994 |
"arm64"
|
| 995 |
],
|
|
|
|
| 1008 |
}
|
| 1009 |
},
|
| 1010 |
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
| 1011 |
+
"version": "1.0.1",
|
| 1012 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.1.tgz",
|
| 1013 |
+
"integrity": "sha512-dcT7inI9DBFK6ovfeWRe3hG30h51cBAP5JXlZfx6pzc/Mnf9HFCQDLtYf4MCBjxaaTfjCCjkBxcy3XzOAo5txw==",
|
| 1014 |
"cpu": [
|
| 1015 |
"x64"
|
| 1016 |
],
|
|
|
|
| 1029 |
}
|
| 1030 |
},
|
| 1031 |
"node_modules/@img/sharp-linux-arm": {
|
| 1032 |
+
"version": "0.33.2",
|
| 1033 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.2.tgz",
|
| 1034 |
+
"integrity": "sha512-Fndk/4Zq3vAc4G/qyfXASbS3HBZbKrlnKZLEJzPLrXoJuipFNNwTes71+Ki1hwYW5lch26niRYoZFAtZVf3EGA==",
|
| 1035 |
"cpu": [
|
| 1036 |
"arm"
|
| 1037 |
],
|
|
|
|
| 1050 |
"url": "https://opencollective.com/libvips"
|
| 1051 |
},
|
| 1052 |
"optionalDependencies": {
|
| 1053 |
+
"@img/sharp-libvips-linux-arm": "1.0.1"
|
| 1054 |
}
|
| 1055 |
},
|
| 1056 |
"node_modules/@img/sharp-linux-arm64": {
|
| 1057 |
+
"version": "0.33.2",
|
| 1058 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.2.tgz",
|
| 1059 |
+
"integrity": "sha512-pz0NNo882vVfqJ0yNInuG9YH71smP4gRSdeL09ukC2YLE6ZyZePAlWKEHgAzJGTiOh8Qkaov6mMIMlEhmLdKew==",
|
| 1060 |
"cpu": [
|
| 1061 |
"arm64"
|
| 1062 |
],
|
|
|
|
| 1075 |
"url": "https://opencollective.com/libvips"
|
| 1076 |
},
|
| 1077 |
"optionalDependencies": {
|
| 1078 |
+
"@img/sharp-libvips-linux-arm64": "1.0.1"
|
| 1079 |
}
|
| 1080 |
},
|
| 1081 |
"node_modules/@img/sharp-linux-s390x": {
|
| 1082 |
+
"version": "0.33.2",
|
| 1083 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.2.tgz",
|
| 1084 |
+
"integrity": "sha512-MBoInDXDppMfhSzbMmOQtGfloVAflS2rP1qPcUIiITMi36Mm5YR7r0ASND99razjQUpHTzjrU1flO76hKvP5RA==",
|
| 1085 |
"cpu": [
|
| 1086 |
"s390x"
|
| 1087 |
],
|
|
|
|
| 1100 |
"url": "https://opencollective.com/libvips"
|
| 1101 |
},
|
| 1102 |
"optionalDependencies": {
|
| 1103 |
+
"@img/sharp-libvips-linux-s390x": "1.0.1"
|
| 1104 |
}
|
| 1105 |
},
|
| 1106 |
"node_modules/@img/sharp-linux-x64": {
|
| 1107 |
+
"version": "0.33.2",
|
| 1108 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.2.tgz",
|
| 1109 |
+
"integrity": "sha512-xUT82H5IbXewKkeF5aiooajoO1tQV4PnKfS/OZtb5DDdxS/FCI/uXTVZ35GQ97RZXsycojz/AJ0asoz6p2/H/A==",
|
| 1110 |
"cpu": [
|
| 1111 |
"x64"
|
| 1112 |
],
|
|
|
|
| 1125 |
"url": "https://opencollective.com/libvips"
|
| 1126 |
},
|
| 1127 |
"optionalDependencies": {
|
| 1128 |
+
"@img/sharp-libvips-linux-x64": "1.0.1"
|
| 1129 |
}
|
| 1130 |
},
|
| 1131 |
"node_modules/@img/sharp-linuxmusl-arm64": {
|
| 1132 |
+
"version": "0.33.2",
|
| 1133 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.2.tgz",
|
| 1134 |
+
"integrity": "sha512-F+0z8JCu/UnMzg8IYW1TMeiViIWBVg7IWP6nE0p5S5EPQxlLd76c8jYemG21X99UzFwgkRo5yz2DS+zbrnxZeA==",
|
| 1135 |
"cpu": [
|
| 1136 |
"arm64"
|
| 1137 |
],
|
|
|
|
| 1150 |
"url": "https://opencollective.com/libvips"
|
| 1151 |
},
|
| 1152 |
"optionalDependencies": {
|
| 1153 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.0.1"
|
| 1154 |
}
|
| 1155 |
},
|
| 1156 |
"node_modules/@img/sharp-linuxmusl-x64": {
|
| 1157 |
+
"version": "0.33.2",
|
| 1158 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.2.tgz",
|
| 1159 |
+
"integrity": "sha512-+ZLE3SQmSL+Fn1gmSaM8uFusW5Y3J9VOf+wMGNnTtJUMUxFhv+P4UPaYEYT8tqnyYVaOVGgMN/zsOxn9pSsO2A==",
|
| 1160 |
"cpu": [
|
| 1161 |
"x64"
|
| 1162 |
],
|
|
|
|
| 1175 |
"url": "https://opencollective.com/libvips"
|
| 1176 |
},
|
| 1177 |
"optionalDependencies": {
|
| 1178 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.0.1"
|
| 1179 |
}
|
| 1180 |
},
|
| 1181 |
"node_modules/@img/sharp-wasm32": {
|
| 1182 |
+
"version": "0.33.2",
|
| 1183 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.2.tgz",
|
| 1184 |
+
"integrity": "sha512-fLbTaESVKuQcpm8ffgBD7jLb/CQLcATju/jxtTXR1XCLwbOQt+OL5zPHSDMmp2JZIeq82e18yE0Vv7zh6+6BfQ==",
|
| 1185 |
"cpu": [
|
| 1186 |
"wasm32"
|
| 1187 |
],
|
| 1188 |
"optional": true,
|
| 1189 |
"dependencies": {
|
| 1190 |
+
"@emnapi/runtime": "^0.45.0"
|
| 1191 |
},
|
| 1192 |
"engines": {
|
| 1193 |
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
|
|
|
|
| 1200 |
}
|
| 1201 |
},
|
| 1202 |
"node_modules/@img/sharp-win32-ia32": {
|
| 1203 |
+
"version": "0.33.2",
|
| 1204 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.2.tgz",
|
| 1205 |
+
"integrity": "sha512-okBpql96hIGuZ4lN3+nsAjGeggxKm7hIRu9zyec0lnfB8E7Z6p95BuRZzDDXZOl2e8UmR4RhYt631i7mfmKU8g==",
|
| 1206 |
"cpu": [
|
| 1207 |
"ia32"
|
| 1208 |
],
|
|
|
|
| 1221 |
}
|
| 1222 |
},
|
| 1223 |
"node_modules/@img/sharp-win32-x64": {
|
| 1224 |
+
"version": "0.33.2",
|
| 1225 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.2.tgz",
|
| 1226 |
+
"integrity": "sha512-E4magOks77DK47FwHUIGH0RYWSgRBfGdK56kIHSVeB9uIS4pPFr4N2kIVsXdQQo4LzOsENKV5KAhRlRL7eMAdg==",
|
| 1227 |
"cpu": [
|
| 1228 |
"x64"
|
| 1229 |
],
|
|
|
|
| 1444 |
"integrity": "sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q=="
|
| 1445 |
},
|
| 1446 |
"node_modules/@resvg/resvg-js": {
|
| 1447 |
+
"version": "2.6.0",
|
| 1448 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.0.tgz",
|
| 1449 |
+
"integrity": "sha512-Tf3YpbBKcQn991KKcw/vg7vZf98v01seSv6CVxZBbRkL/xyjnoYB6KgrFL6zskT1A4dWC/vg77KyNOW+ePaNlA==",
|
| 1450 |
"engines": {
|
| 1451 |
"node": ">= 10"
|
| 1452 |
},
|
| 1453 |
"optionalDependencies": {
|
| 1454 |
+
"@resvg/resvg-js-android-arm-eabi": "2.6.0",
|
| 1455 |
+
"@resvg/resvg-js-android-arm64": "2.6.0",
|
| 1456 |
+
"@resvg/resvg-js-darwin-arm64": "2.6.0",
|
| 1457 |
+
"@resvg/resvg-js-darwin-x64": "2.6.0",
|
| 1458 |
+
"@resvg/resvg-js-linux-arm-gnueabihf": "2.6.0",
|
| 1459 |
+
"@resvg/resvg-js-linux-arm64-gnu": "2.6.0",
|
| 1460 |
+
"@resvg/resvg-js-linux-arm64-musl": "2.6.0",
|
| 1461 |
+
"@resvg/resvg-js-linux-x64-gnu": "2.6.0",
|
| 1462 |
+
"@resvg/resvg-js-linux-x64-musl": "2.6.0",
|
| 1463 |
+
"@resvg/resvg-js-win32-arm64-msvc": "2.6.0",
|
| 1464 |
+
"@resvg/resvg-js-win32-ia32-msvc": "2.6.0",
|
| 1465 |
+
"@resvg/resvg-js-win32-x64-msvc": "2.6.0"
|
| 1466 |
}
|
| 1467 |
},
|
| 1468 |
"node_modules/@resvg/resvg-js-android-arm-eabi": {
|
| 1469 |
+
"version": "2.6.0",
|
| 1470 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.0.tgz",
|
| 1471 |
+
"integrity": "sha512-lJnZ/2P5aMocrFMW7HWhVne5gH82I8xH6zsfH75MYr4+/JOaVcGCTEQ06XFohGMdYRP3v05SSPLPvTM/RHjxfA==",
|
| 1472 |
"cpu": [
|
| 1473 |
"arm"
|
| 1474 |
],
|
|
|
|
| 1481 |
}
|
| 1482 |
},
|
| 1483 |
"node_modules/@resvg/resvg-js-android-arm64": {
|
| 1484 |
+
"version": "2.6.0",
|
| 1485 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm64/-/resvg-js-android-arm64-2.6.0.tgz",
|
| 1486 |
+
"integrity": "sha512-N527f529bjMwYWShZYfBD60dXA4Fux+D695QsHQ93BDYZSHUoOh1CUGUyICevnTxs7VgEl98XpArmUWBZQVMfQ==",
|
| 1487 |
"cpu": [
|
| 1488 |
"arm64"
|
| 1489 |
],
|
|
|
|
| 1496 |
}
|
| 1497 |
},
|
| 1498 |
"node_modules/@resvg/resvg-js-darwin-arm64": {
|
| 1499 |
+
"version": "2.6.0",
|
| 1500 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-arm64/-/resvg-js-darwin-arm64-2.6.0.tgz",
|
| 1501 |
+
"integrity": "sha512-MabUKLVayEwlPo0mIqAmMt+qESN8LltCvv5+GLgVga1avpUrkxj/fkU1TKm8kQegutUjbP/B0QuMuUr0uhF8ew==",
|
| 1502 |
"cpu": [
|
| 1503 |
"arm64"
|
| 1504 |
],
|
|
|
|
| 1511 |
}
|
| 1512 |
},
|
| 1513 |
"node_modules/@resvg/resvg-js-darwin-x64": {
|
| 1514 |
+
"version": "2.6.0",
|
| 1515 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-x64/-/resvg-js-darwin-x64-2.6.0.tgz",
|
| 1516 |
+
"integrity": "sha512-zrFetdnSw/suXjmyxSjfDV7i61hahv6DDG6kM7BYN2yJ3Es5+BZtqYZTcIWogPJedYKmzN1YTMWGd/3f0ubFiA==",
|
| 1517 |
"cpu": [
|
| 1518 |
"x64"
|
| 1519 |
],
|
|
|
|
| 1526 |
}
|
| 1527 |
},
|
| 1528 |
"node_modules/@resvg/resvg-js-linux-arm-gnueabihf": {
|
| 1529 |
+
"version": "2.6.0",
|
| 1530 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm-gnueabihf/-/resvg-js-linux-arm-gnueabihf-2.6.0.tgz",
|
| 1531 |
+
"integrity": "sha512-sH4gxXt7v7dGwjGyzLwn7SFGvwZG6DQqLaZ11MmzbCwd9Zosy1TnmrMJfn6TJ7RHezmQMgBPi18bl55FZ1AT4A==",
|
| 1532 |
"cpu": [
|
| 1533 |
"arm"
|
| 1534 |
],
|
|
|
|
| 1541 |
}
|
| 1542 |
},
|
| 1543 |
"node_modules/@resvg/resvg-js-linux-arm64-gnu": {
|
| 1544 |
+
"version": "2.6.0",
|
| 1545 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-gnu/-/resvg-js-linux-arm64-gnu-2.6.0.tgz",
|
| 1546 |
+
"integrity": "sha512-fCyMncqCJtrlANADIduYF4IfnWQ295UKib7DAxFXQhBsM9PLDTpizr0qemZcCNadcwSVHnAIzL4tliZhCM8P6A==",
|
| 1547 |
"cpu": [
|
| 1548 |
"arm64"
|
| 1549 |
],
|
|
|
|
| 1556 |
}
|
| 1557 |
},
|
| 1558 |
"node_modules/@resvg/resvg-js-linux-arm64-musl": {
|
| 1559 |
+
"version": "2.6.0",
|
| 1560 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-musl/-/resvg-js-linux-arm64-musl-2.6.0.tgz",
|
| 1561 |
+
"integrity": "sha512-ouLjTgBQHQyxLht4FdMPTvuY8xzJigM9EM2Tlu0llWkN1mKyTQrvYWi6TA6XnKdzDJHy7ZLpWpjZi7F5+Pg+Vg==",
|
| 1562 |
"cpu": [
|
| 1563 |
"arm64"
|
| 1564 |
],
|
|
|
|
| 1571 |
}
|
| 1572 |
},
|
| 1573 |
"node_modules/@resvg/resvg-js-linux-x64-gnu": {
|
| 1574 |
+
"version": "2.6.0",
|
| 1575 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-gnu/-/resvg-js-linux-x64-gnu-2.6.0.tgz",
|
| 1576 |
+
"integrity": "sha512-n3zC8DWsvxC1AwxpKFclIPapDFibs5XdIRoV/mcIlxlh0vseW1F49b97F33BtJQRmlntsqqN6GMMqx8byB7B+Q==",
|
| 1577 |
"cpu": [
|
| 1578 |
"x64"
|
| 1579 |
],
|
|
|
|
| 1586 |
}
|
| 1587 |
},
|
| 1588 |
"node_modules/@resvg/resvg-js-linux-x64-musl": {
|
| 1589 |
+
"version": "2.6.0",
|
| 1590 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-musl/-/resvg-js-linux-x64-musl-2.6.0.tgz",
|
| 1591 |
+
"integrity": "sha512-n4tasK1HOlAxdTEROgYA1aCfsEKk0UOFDNd/AQTTZlTmCbHKXPq+O8npaaKlwXquxlVK8vrkcWbksbiGqbCAcw==",
|
| 1592 |
"cpu": [
|
| 1593 |
"x64"
|
| 1594 |
],
|
|
|
|
| 1601 |
}
|
| 1602 |
},
|
| 1603 |
"node_modules/@resvg/resvg-js-win32-arm64-msvc": {
|
| 1604 |
+
"version": "2.6.0",
|
| 1605 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-arm64-msvc/-/resvg-js-win32-arm64-msvc-2.6.0.tgz",
|
| 1606 |
+
"integrity": "sha512-X2+EoBJFwDI5LDVb51Sk7ldnVLitMGr9WwU/i21i3fAeAXZb3hM16k67DeTy16OYkT2dk/RfU1tP1wG+rWbz2Q==",
|
| 1607 |
"cpu": [
|
| 1608 |
"arm64"
|
| 1609 |
],
|
|
|
|
| 1616 |
}
|
| 1617 |
},
|
| 1618 |
"node_modules/@resvg/resvg-js-win32-ia32-msvc": {
|
| 1619 |
+
"version": "2.6.0",
|
| 1620 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-ia32-msvc/-/resvg-js-win32-ia32-msvc-2.6.0.tgz",
|
| 1621 |
+
"integrity": "sha512-L7oevWjQoUgK5W1fCKn0euSVemhDXVhrjtwqpc7MwBKKimYeiOshO1Li1pa8bBt5PESahenhWgdB6lav9O0fEg==",
|
| 1622 |
"cpu": [
|
| 1623 |
"ia32"
|
| 1624 |
],
|
|
|
|
| 1631 |
}
|
| 1632 |
},
|
| 1633 |
"node_modules/@resvg/resvg-js-win32-x64-msvc": {
|
| 1634 |
+
"version": "2.6.0",
|
| 1635 |
+
"resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-x64-msvc/-/resvg-js-win32-x64-msvc-2.6.0.tgz",
|
| 1636 |
+
"integrity": "sha512-8lJlghb+Unki5AyKgsnFbRJwkEj9r1NpwyuBG8yEJiG1W9eEGl03R3I7bsVa3haof/3J1NlWf0rzSa1G++A2iw==",
|
| 1637 |
"cpu": [
|
| 1638 |
"x64"
|
| 1639 |
],
|
|
|
|
| 2075 |
"node": ">=4"
|
| 2076 |
}
|
| 2077 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2078 |
"node_modules/@tootallnate/once": {
|
| 2079 |
"version": "2.0.0",
|
| 2080 |
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
|
|
|
| 3831 |
}
|
| 3832 |
},
|
| 3833 |
"node_modules/detect-libc": {
|
| 3834 |
+
"version": "2.0.2",
|
| 3835 |
+
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
|
| 3836 |
+
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
|
| 3837 |
"engines": {
|
| 3838 |
"node": ">=8"
|
| 3839 |
}
|
|
|
|
| 4556 |
"node": "^10.12.0 || >=12.0.0"
|
| 4557 |
}
|
| 4558 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4559 |
"node_modules/fill-range": {
|
| 4560 |
"version": "7.0.1",
|
| 4561 |
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
|
|
|
| 6385 |
}
|
| 6386 |
},
|
| 6387 |
"node_modules/openai": {
|
| 6388 |
+
"version": "4.14.2",
|
| 6389 |
+
"resolved": "https://registry.npmjs.org/openai/-/openai-4.14.2.tgz",
|
| 6390 |
+
"integrity": "sha512-JGlm7mMC7J+cyQZnQMOH7daD9cBqqWqLtlBsejElEkgoehPrYfdyxSxIGICz5xk4YimbwI5FlLATSVojLtCKXQ==",
|
| 6391 |
"optional": true,
|
| 6392 |
"dependencies": {
|
| 6393 |
"@types/node": "^18.11.18",
|
| 6394 |
"@types/node-fetch": "^2.6.4",
|
| 6395 |
"abort-controller": "^3.0.0",
|
| 6396 |
"agentkeepalive": "^4.2.1",
|
| 6397 |
+
"digest-fetch": "^1.3.0",
|
| 6398 |
"form-data-encoder": "1.7.2",
|
| 6399 |
"formdata-node": "^4.3.2",
|
| 6400 |
"node-fetch": "^2.6.7",
|
|
|
|
| 6620 |
"node": "*"
|
| 6621 |
}
|
| 6622 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6623 |
"node_modules/periscopic": {
|
| 6624 |
"version": "3.1.0",
|
| 6625 |
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
|
|
|
|
| 7475 |
"node": ">= 6"
|
| 7476 |
}
|
| 7477 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7478 |
"node_modules/readdirp": {
|
| 7479 |
"version": "3.6.0",
|
| 7480 |
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
|
|
|
| 7736 |
"integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="
|
| 7737 |
},
|
| 7738 |
"node_modules/semver": {
|
| 7739 |
+
"version": "7.5.4",
|
| 7740 |
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
| 7741 |
+
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
| 7742 |
+
"dependencies": {
|
| 7743 |
+
"lru-cache": "^6.0.0"
|
| 7744 |
+
},
|
| 7745 |
"bin": {
|
| 7746 |
"semver": "bin/semver.js"
|
| 7747 |
},
|
|
|
|
| 7840 |
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
| 7841 |
},
|
| 7842 |
"node_modules/sharp": {
|
| 7843 |
+
"version": "0.33.2",
|
| 7844 |
+
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.2.tgz",
|
| 7845 |
+
"integrity": "sha512-WlYOPyyPDiiM07j/UO+E720ju6gtNtHjEGg5vovUk1Lgxyjm2LFO+37Nt/UI3MMh2l6hxTWQWi7qk3cXJTutcQ==",
|
| 7846 |
"hasInstallScript": true,
|
| 7847 |
"dependencies": {
|
| 7848 |
"color": "^4.2.3",
|
| 7849 |
+
"detect-libc": "^2.0.2",
|
| 7850 |
+
"semver": "^7.5.4"
|
| 7851 |
},
|
| 7852 |
"engines": {
|
| 7853 |
+
"libvips": ">=8.15.1",
|
| 7854 |
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 7855 |
},
|
| 7856 |
"funding": {
|
| 7857 |
"url": "https://opencollective.com/libvips"
|
| 7858 |
},
|
| 7859 |
"optionalDependencies": {
|
| 7860 |
+
"@img/sharp-darwin-arm64": "0.33.2",
|
| 7861 |
+
"@img/sharp-darwin-x64": "0.33.2",
|
| 7862 |
+
"@img/sharp-libvips-darwin-arm64": "1.0.1",
|
| 7863 |
+
"@img/sharp-libvips-darwin-x64": "1.0.1",
|
| 7864 |
+
"@img/sharp-libvips-linux-arm": "1.0.1",
|
| 7865 |
+
"@img/sharp-libvips-linux-arm64": "1.0.1",
|
| 7866 |
+
"@img/sharp-libvips-linux-s390x": "1.0.1",
|
| 7867 |
+
"@img/sharp-libvips-linux-x64": "1.0.1",
|
| 7868 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.0.1",
|
| 7869 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.0.1",
|
| 7870 |
+
"@img/sharp-linux-arm": "0.33.2",
|
| 7871 |
+
"@img/sharp-linux-arm64": "0.33.2",
|
| 7872 |
+
"@img/sharp-linux-s390x": "0.33.2",
|
| 7873 |
+
"@img/sharp-linux-x64": "0.33.2",
|
| 7874 |
+
"@img/sharp-linuxmusl-arm64": "0.33.2",
|
| 7875 |
+
"@img/sharp-linuxmusl-x64": "0.33.2",
|
| 7876 |
+
"@img/sharp-wasm32": "0.33.2",
|
| 7877 |
+
"@img/sharp-win32-ia32": "0.33.2",
|
| 7878 |
+
"@img/sharp-win32-x64": "0.33.2"
|
| 7879 |
}
|
| 7880 |
},
|
| 7881 |
"node_modules/shebang-command": {
|
|
|
|
| 8187 |
"url": "https://github.com/sponsors/antfu"
|
| 8188 |
}
|
| 8189 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8190 |
"node_modules/sucrase": {
|
| 8191 |
"version": "3.32.0",
|
| 8192 |
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz",
|
|
|
|
| 8709 |
"node": ">=0.6"
|
| 8710 |
}
|
| 8711 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8712 |
"node_modules/totalist": {
|
| 8713 |
"version": "3.0.0",
|
| 8714 |
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
|
package.json
CHANGED
|
@@ -57,15 +57,14 @@
|
|
| 57 |
"@huggingface/hub": "^0.5.1",
|
| 58 |
"@huggingface/inference": "^2.6.3",
|
| 59 |
"@iconify-json/bi": "^1.1.21",
|
| 60 |
-
"@resvg/resvg-js": "^2.6.2",
|
| 61 |
"@playwright/browser-chromium": "^1.43.1",
|
|
|
|
| 62 |
"@xenova/transformers": "^2.16.1",
|
| 63 |
"autoprefixer": "^10.4.14",
|
| 64 |
"browser-image-resizer": "^2.4.1",
|
| 65 |
"date-fns": "^2.29.3",
|
| 66 |
"dotenv": "^16.0.3",
|
| 67 |
"express": "^4.19.2",
|
| 68 |
-
"file-type": "^19.0.0",
|
| 69 |
"handlebars": "^4.7.8",
|
| 70 |
"highlight.js": "^11.7.0",
|
| 71 |
"image-size": "^1.0.2",
|
|
@@ -87,7 +86,7 @@
|
|
| 87 |
"satori-html": "^0.3.2",
|
| 88 |
"sbd": "^1.0.19",
|
| 89 |
"serpapi": "^1.1.1",
|
| 90 |
-
"sharp": "^0.33.
|
| 91 |
"tailwind-scrollbar": "^3.0.0",
|
| 92 |
"tailwindcss": "^3.4.0",
|
| 93 |
"uuid": "^9.0.1",
|
|
@@ -99,6 +98,6 @@
|
|
| 99 |
"@google-cloud/vertexai": "^1.1.0",
|
| 100 |
"aws4fetch": "^1.0.17",
|
| 101 |
"cohere-ai": "^7.9.0",
|
| 102 |
-
"openai": "^4.
|
| 103 |
}
|
| 104 |
}
|
|
|
|
| 57 |
"@huggingface/hub": "^0.5.1",
|
| 58 |
"@huggingface/inference": "^2.6.3",
|
| 59 |
"@iconify-json/bi": "^1.1.21",
|
|
|
|
| 60 |
"@playwright/browser-chromium": "^1.43.1",
|
| 61 |
+
"@resvg/resvg-js": "^2.6.0",
|
| 62 |
"@xenova/transformers": "^2.16.1",
|
| 63 |
"autoprefixer": "^10.4.14",
|
| 64 |
"browser-image-resizer": "^2.4.1",
|
| 65 |
"date-fns": "^2.29.3",
|
| 66 |
"dotenv": "^16.0.3",
|
| 67 |
"express": "^4.19.2",
|
|
|
|
| 68 |
"handlebars": "^4.7.8",
|
| 69 |
"highlight.js": "^11.7.0",
|
| 70 |
"image-size": "^1.0.2",
|
|
|
|
| 86 |
"satori-html": "^0.3.2",
|
| 87 |
"sbd": "^1.0.19",
|
| 88 |
"serpapi": "^1.1.1",
|
| 89 |
+
"sharp": "^0.33.2",
|
| 90 |
"tailwind-scrollbar": "^3.0.0",
|
| 91 |
"tailwindcss": "^3.4.0",
|
| 92 |
"uuid": "^9.0.1",
|
|
|
|
| 98 |
"@google-cloud/vertexai": "^1.1.0",
|
| 99 |
"aws4fetch": "^1.0.17",
|
| 100 |
"cohere-ai": "^7.9.0",
|
| 101 |
+
"openai": "^4.14.2"
|
| 102 |
}
|
| 103 |
}
|
src/lib/components/chat/ChatMessage.svelte
CHANGED
|
@@ -308,17 +308,17 @@
|
|
| 308 |
{#if message.files && message.files.length > 0}
|
| 309 |
<div class="mx-auto grid w-fit grid-cols-2 gap-5 px-5">
|
| 310 |
{#each message.files as file}
|
| 311 |
-
<!-- handle the case where this is a hash that points to an image in the db -->
|
| 312 |
-
{#if file.
|
| 313 |
<img
|
| 314 |
-
src={$page.url.pathname + "/output/" + file
|
| 315 |
alt="input from user"
|
| 316 |
class="my-2 aspect-auto max-h-48 rounded-lg shadow-lg"
|
| 317 |
/>
|
| 318 |
{:else}
|
| 319 |
<!-- handle the case where this is a base64 encoded image -->
|
| 320 |
<img
|
| 321 |
-
src={
|
| 322 |
alt="input from user"
|
| 323 |
class="my-2 aspect-auto max-h-48 rounded-lg shadow-lg"
|
| 324 |
/>
|
|
|
|
| 308 |
{#if message.files && message.files.length > 0}
|
| 309 |
<div class="mx-auto grid w-fit grid-cols-2 gap-5 px-5">
|
| 310 |
{#each message.files as file}
|
| 311 |
+
<!-- handle the case where this is a hash that points to an image in the db, hash is always 64 char long -->
|
| 312 |
+
{#if file.length === 64}
|
| 313 |
<img
|
| 314 |
+
src={$page.url.pathname + "/output/" + file}
|
| 315 |
alt="input from user"
|
| 316 |
class="my-2 aspect-auto max-h-48 rounded-lg shadow-lg"
|
| 317 |
/>
|
| 318 |
{:else}
|
| 319 |
<!-- handle the case where this is a base64 encoded image -->
|
| 320 |
<img
|
| 321 |
+
src={"data:image/*;base64," + file}
|
| 322 |
alt="input from user"
|
| 323 |
class="my-2 aspect-auto max-h-48 rounded-lg shadow-lg"
|
| 324 |
/>
|
src/lib/components/chat/ChatWindow.svelte
CHANGED
|
@@ -92,9 +92,7 @@
|
|
| 92 |
(lastMessage.from === "user" ||
|
| 93 |
lastMessage.updates?.findIndex((u) => u.type === "status" && u.status === "error") !== -1);
|
| 94 |
|
| 95 |
-
$: sources = files
|
| 96 |
-
file2base64(file).then((value) => ({ type: "base64", value, mime: file.type }))
|
| 97 |
-
);
|
| 98 |
|
| 99 |
function onShare() {
|
| 100 |
dispatch("share");
|
|
@@ -231,13 +229,13 @@
|
|
| 231 |
<div
|
| 232 |
class="dark:via-gray-80 pointer-events-none absolute inset-x-0 bottom-0 z-0 mx-auto flex w-full max-w-3xl flex-col items-center justify-center bg-gradient-to-t from-white via-white/80 to-white/0 px-3.5 py-4 max-md:border-t max-md:bg-white sm:px-5 md:py-8 xl:max-w-4xl dark:border-gray-800 dark:from-gray-900 dark:to-gray-900/0 max-md:dark:bg-gray-900 [&>*]:pointer-events-auto"
|
| 233 |
>
|
| 234 |
-
{#if sources
|
| 235 |
<div class="flex flex-row flex-wrap justify-center gap-2.5 max-md:pb-3">
|
| 236 |
{#each sources as source, index}
|
| 237 |
{#await source then src}
|
| 238 |
<div class="relative h-16 w-16 overflow-hidden rounded-lg shadow-lg">
|
| 239 |
<img
|
| 240 |
-
src={`data
|
| 241 |
alt="input content"
|
| 242 |
class="h-full w-full rounded-lg bg-gray-400 object-cover dark:bg-gray-900"
|
| 243 |
/>
|
|
|
|
| 92 |
(lastMessage.from === "user" ||
|
| 93 |
lastMessage.updates?.findIndex((u) => u.type === "status" && u.status === "error") !== -1);
|
| 94 |
|
| 95 |
+
$: sources = files.map((file) => file2base64(file));
|
|
|
|
|
|
|
| 96 |
|
| 97 |
function onShare() {
|
| 98 |
dispatch("share");
|
|
|
|
| 229 |
<div
|
| 230 |
class="dark:via-gray-80 pointer-events-none absolute inset-x-0 bottom-0 z-0 mx-auto flex w-full max-w-3xl flex-col items-center justify-center bg-gradient-to-t from-white via-white/80 to-white/0 px-3.5 py-4 max-md:border-t max-md:bg-white sm:px-5 md:py-8 xl:max-w-4xl dark:border-gray-800 dark:from-gray-900 dark:to-gray-900/0 max-md:dark:bg-gray-900 [&>*]:pointer-events-auto"
|
| 231 |
>
|
| 232 |
+
{#if sources.length}
|
| 233 |
<div class="flex flex-row flex-wrap justify-center gap-2.5 max-md:pb-3">
|
| 234 |
{#each sources as source, index}
|
| 235 |
{#await source then src}
|
| 236 |
<div class="relative h-16 w-16 overflow-hidden rounded-lg shadow-lg">
|
| 237 |
<img
|
| 238 |
+
src={`data:image/*;base64,${src}`}
|
| 239 |
alt="input content"
|
| 240 |
class="h-full w-full rounded-lg bg-gray-400 object-cover dark:bg-gray-900"
|
| 241 |
/>
|
src/lib/server/endpoints/anthropic/endpointAnthropic.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
| 1 |
import { z } from "zod";
|
| 2 |
-
import type { Endpoint } from "../endpoints";
|
| 3 |
import { env } from "$env/dynamic/private";
|
|
|
|
| 4 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
| 5 |
-
import { createImageProcessorOptionsValidator } from "../images";
|
| 6 |
-
import { endpointMessagesToAnthropicMessages } from "./utils";
|
| 7 |
|
| 8 |
export const endpointAnthropicParametersSchema = z.object({
|
| 9 |
weight: z.number().int().positive().default(1),
|
|
@@ -13,24 +11,12 @@ export const endpointAnthropicParametersSchema = z.object({
|
|
| 13 |
apiKey: z.string().default(env.ANTHROPIC_API_KEY ?? "sk-"),
|
| 14 |
defaultHeaders: z.record(z.string()).optional(),
|
| 15 |
defaultQuery: z.record(z.string()).optional(),
|
| 16 |
-
multimodal: z
|
| 17 |
-
.object({
|
| 18 |
-
image: createImageProcessorOptionsValidator({
|
| 19 |
-
supportedMimeTypes: ["image/png", "image/jpeg", "image/webp"],
|
| 20 |
-
preferredMimeType: "image/webp",
|
| 21 |
-
// The 4 / 3 compensates for the 33% increase in size when converting to base64
|
| 22 |
-
maxSizeInMB: (5 / 4) * 3,
|
| 23 |
-
maxWidth: 4096,
|
| 24 |
-
maxHeight: 4096,
|
| 25 |
-
}),
|
| 26 |
-
})
|
| 27 |
-
.default({}),
|
| 28 |
});
|
| 29 |
|
| 30 |
export async function endpointAnthropic(
|
| 31 |
input: z.input<typeof endpointAnthropicParametersSchema>
|
| 32 |
): Promise<Endpoint> {
|
| 33 |
-
const { baseURL, apiKey, model, defaultHeaders, defaultQuery
|
| 34 |
endpointAnthropicParametersSchema.parse(input);
|
| 35 |
let Anthropic;
|
| 36 |
try {
|
|
@@ -52,6 +38,16 @@ export async function endpointAnthropic(
|
|
| 52 |
system = messages[0].content;
|
| 53 |
}
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
let tokenId = 0;
|
| 56 |
|
| 57 |
const parameters = { ...model.parameters, ...generateSettings };
|
|
@@ -59,7 +55,7 @@ export async function endpointAnthropic(
|
|
| 59 |
return (async function* () {
|
| 60 |
const stream = anthropic.messages.stream({
|
| 61 |
model: model.id ?? model.name,
|
| 62 |
-
messages:
|
| 63 |
max_tokens: parameters?.max_new_tokens,
|
| 64 |
temperature: parameters?.temperature,
|
| 65 |
top_p: parameters?.top_p,
|
|
|
|
| 1 |
import { z } from "zod";
|
|
|
|
| 2 |
import { env } from "$env/dynamic/private";
|
| 3 |
+
import type { Endpoint } from "../endpoints";
|
| 4 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
|
|
|
|
|
|
| 5 |
|
| 6 |
export const endpointAnthropicParametersSchema = z.object({
|
| 7 |
weight: z.number().int().positive().default(1),
|
|
|
|
| 11 |
apiKey: z.string().default(env.ANTHROPIC_API_KEY ?? "sk-"),
|
| 12 |
defaultHeaders: z.record(z.string()).optional(),
|
| 13 |
defaultQuery: z.record(z.string()).optional(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
});
|
| 15 |
|
| 16 |
export async function endpointAnthropic(
|
| 17 |
input: z.input<typeof endpointAnthropicParametersSchema>
|
| 18 |
): Promise<Endpoint> {
|
| 19 |
+
const { baseURL, apiKey, model, defaultHeaders, defaultQuery } =
|
| 20 |
endpointAnthropicParametersSchema.parse(input);
|
| 21 |
let Anthropic;
|
| 22 |
try {
|
|
|
|
| 38 |
system = messages[0].content;
|
| 39 |
}
|
| 40 |
|
| 41 |
+
const messagesFormatted = messages
|
| 42 |
+
.filter((message) => message.from !== "system")
|
| 43 |
+
.map((message) => ({
|
| 44 |
+
role: message.from,
|
| 45 |
+
content: message.content,
|
| 46 |
+
})) as unknown as {
|
| 47 |
+
role: "user" | "assistant";
|
| 48 |
+
content: string;
|
| 49 |
+
}[];
|
| 50 |
+
|
| 51 |
let tokenId = 0;
|
| 52 |
|
| 53 |
const parameters = { ...model.parameters, ...generateSettings };
|
|
|
|
| 55 |
return (async function* () {
|
| 56 |
const stream = anthropic.messages.stream({
|
| 57 |
model: model.id ?? model.name,
|
| 58 |
+
messages: messagesFormatted,
|
| 59 |
max_tokens: parameters?.max_new_tokens,
|
| 60 |
temperature: parameters?.temperature,
|
| 61 |
top_p: parameters?.top_p,
|
src/lib/server/endpoints/anthropic/endpointAnthropicVertex.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
import { z } from "zod";
|
| 2 |
import type { Endpoint } from "../endpoints";
|
| 3 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
| 4 |
-
import { createImageProcessorOptionsValidator } from "../images";
|
| 5 |
-
import { endpointMessagesToAnthropicMessages } from "./utils";
|
| 6 |
|
| 7 |
export const endpointAnthropicVertexParametersSchema = z.object({
|
| 8 |
weight: z.number().int().positive().default(1),
|
|
@@ -12,24 +10,12 @@ export const endpointAnthropicVertexParametersSchema = z.object({
|
|
| 12 |
projectId: z.string(),
|
| 13 |
defaultHeaders: z.record(z.string()).optional(),
|
| 14 |
defaultQuery: z.record(z.string()).optional(),
|
| 15 |
-
multimodal: z
|
| 16 |
-
.object({
|
| 17 |
-
image: createImageProcessorOptionsValidator({
|
| 18 |
-
supportedMimeTypes: ["image/png", "image/jpeg", "image/webp"],
|
| 19 |
-
preferredMimeType: "image/webp",
|
| 20 |
-
// The 4 / 3 compensates for the 33% increase in size when converting to base64
|
| 21 |
-
maxSizeInMB: (5 / 4) * 3,
|
| 22 |
-
maxWidth: 4096,
|
| 23 |
-
maxHeight: 4096,
|
| 24 |
-
}),
|
| 25 |
-
})
|
| 26 |
-
.default({}),
|
| 27 |
});
|
| 28 |
|
| 29 |
export async function endpointAnthropicVertex(
|
| 30 |
input: z.input<typeof endpointAnthropicVertexParametersSchema>
|
| 31 |
): Promise<Endpoint> {
|
| 32 |
-
const { region, projectId, model, defaultHeaders, defaultQuery
|
| 33 |
endpointAnthropicVertexParametersSchema.parse(input);
|
| 34 |
let AnthropicVertex;
|
| 35 |
try {
|
|
@@ -52,11 +38,21 @@ export async function endpointAnthropicVertex(
|
|
| 52 |
system = messages[0].content;
|
| 53 |
}
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
let tokenId = 0;
|
| 56 |
return (async function* () {
|
| 57 |
const stream = anthropic.messages.stream({
|
| 58 |
model: model.id ?? model.name,
|
| 59 |
-
messages:
|
| 60 |
max_tokens: model.parameters?.max_new_tokens,
|
| 61 |
temperature: model.parameters?.temperature,
|
| 62 |
top_p: model.parameters?.top_p,
|
|
|
|
| 1 |
import { z } from "zod";
|
| 2 |
import type { Endpoint } from "../endpoints";
|
| 3 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
|
|
|
|
|
|
| 4 |
|
| 5 |
export const endpointAnthropicVertexParametersSchema = z.object({
|
| 6 |
weight: z.number().int().positive().default(1),
|
|
|
|
| 10 |
projectId: z.string(),
|
| 11 |
defaultHeaders: z.record(z.string()).optional(),
|
| 12 |
defaultQuery: z.record(z.string()).optional(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
});
|
| 14 |
|
| 15 |
export async function endpointAnthropicVertex(
|
| 16 |
input: z.input<typeof endpointAnthropicVertexParametersSchema>
|
| 17 |
): Promise<Endpoint> {
|
| 18 |
+
const { region, projectId, model, defaultHeaders, defaultQuery } =
|
| 19 |
endpointAnthropicVertexParametersSchema.parse(input);
|
| 20 |
let AnthropicVertex;
|
| 21 |
try {
|
|
|
|
| 38 |
system = messages[0].content;
|
| 39 |
}
|
| 40 |
|
| 41 |
+
const messagesFormatted = messages
|
| 42 |
+
.filter((message) => message.from !== "system")
|
| 43 |
+
.map((message) => ({
|
| 44 |
+
role: message.from,
|
| 45 |
+
content: message.content,
|
| 46 |
+
})) as unknown as {
|
| 47 |
+
role: "user" | "assistant";
|
| 48 |
+
content: string;
|
| 49 |
+
}[];
|
| 50 |
+
|
| 51 |
let tokenId = 0;
|
| 52 |
return (async function* () {
|
| 53 |
const stream = anthropic.messages.stream({
|
| 54 |
model: model.id ?? model.name,
|
| 55 |
+
messages: messagesFormatted,
|
| 56 |
max_tokens: model.parameters?.max_new_tokens,
|
| 57 |
temperature: model.parameters?.temperature,
|
| 58 |
top_p: model.parameters?.top_p,
|
src/lib/server/endpoints/anthropic/utils.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
| 1 |
-
import type { ImageBlockParam, MessageParam } from "@anthropic-ai/sdk/resources";
|
| 2 |
-
import { makeImageProcessor, type ImageProcessorOptions } from "../images";
|
| 3 |
-
import type { EndpointMessage } from "../endpoints";
|
| 4 |
-
import type { MessageFile } from "$lib/types/Message";
|
| 5 |
-
|
| 6 |
-
export async function fileToImageBlock(
|
| 7 |
-
file: MessageFile,
|
| 8 |
-
opts: ImageProcessorOptions<"image/png" | "image/jpeg" | "image/webp">
|
| 9 |
-
): Promise<ImageBlockParam> {
|
| 10 |
-
const processor = makeImageProcessor(opts);
|
| 11 |
-
const { image, mime } = await processor(file);
|
| 12 |
-
|
| 13 |
-
return {
|
| 14 |
-
type: "image",
|
| 15 |
-
source: {
|
| 16 |
-
type: "base64",
|
| 17 |
-
media_type: mime,
|
| 18 |
-
data: image.toString("base64"),
|
| 19 |
-
},
|
| 20 |
-
};
|
| 21 |
-
}
|
| 22 |
-
|
| 23 |
-
type NonSystemMessage = EndpointMessage & { from: "user" | "assistant" };
|
| 24 |
-
|
| 25 |
-
export async function endpointMessagesToAnthropicMessages(
|
| 26 |
-
messages: EndpointMessage[],
|
| 27 |
-
multimodal: { image: ImageProcessorOptions<"image/png" | "image/jpeg" | "image/webp"> }
|
| 28 |
-
): Promise<MessageParam[]> {
|
| 29 |
-
return await Promise.all(
|
| 30 |
-
messages
|
| 31 |
-
.filter((message): message is NonSystemMessage => message.from !== "system")
|
| 32 |
-
.map<Promise<MessageParam>>(async (message) => {
|
| 33 |
-
return {
|
| 34 |
-
role: message.from,
|
| 35 |
-
content: [
|
| 36 |
-
...(await Promise.all(
|
| 37 |
-
(message.files ?? []).map((file) => fileToImageBlock(file, multimodal.image))
|
| 38 |
-
)),
|
| 39 |
-
{ type: "text", text: message.content },
|
| 40 |
-
],
|
| 41 |
-
};
|
| 42 |
-
})
|
| 43 |
-
);
|
| 44 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/server/endpoints/endpoints.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
import type { Conversation } from "$lib/types/Conversation";
|
| 2 |
-
import type { Message } from "$lib/types/Message";
|
| 3 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
| 4 |
import { endpointTgi, endpointTgiParametersSchema } from "./tgi/endpointTgi";
|
| 5 |
import { z } from "zod";
|
|
@@ -26,10 +25,9 @@ import endpointLangserve, {
|
|
| 26 |
endpointLangserveParametersSchema,
|
| 27 |
} from "./langserve/endpointLangserve";
|
| 28 |
|
| 29 |
-
export type EndpointMessage = Omit<Message, "id">;
|
| 30 |
// parameters passed when generating text
|
| 31 |
export interface EndpointParameters {
|
| 32 |
-
messages:
|
| 33 |
preprompt?: Conversation["preprompt"];
|
| 34 |
continueMessage?: boolean; // used to signal that the last message will be extended
|
| 35 |
generateSettings?: Partial<Model["parameters"]>;
|
|
|
|
| 1 |
import type { Conversation } from "$lib/types/Conversation";
|
|
|
|
| 2 |
import type { TextGenerationStreamOutput } from "@huggingface/inference";
|
| 3 |
import { endpointTgi, endpointTgiParametersSchema } from "./tgi/endpointTgi";
|
| 4 |
import { z } from "zod";
|
|
|
|
| 25 |
endpointLangserveParametersSchema,
|
| 26 |
} from "./langserve/endpointLangserve";
|
| 27 |
|
|
|
|
| 28 |
// parameters passed when generating text
|
| 29 |
export interface EndpointParameters {
|
| 30 |
+
messages: Omit<Conversation["messages"][0], "id">[];
|
| 31 |
preprompt?: Conversation["preprompt"];
|
| 32 |
continueMessage?: boolean; // used to signal that the last message will be extended
|
| 33 |
generateSettings?: Partial<Model["parameters"]>;
|
src/lib/server/endpoints/images.ts
DELETED
|
@@ -1,211 +0,0 @@
|
|
| 1 |
-
import type { Sharp } from "sharp";
|
| 2 |
-
import sharp from "sharp";
|
| 3 |
-
import type { MessageFile } from "$lib/types/Message";
|
| 4 |
-
import { z, type util } from "zod";
|
| 5 |
-
|
| 6 |
-
export interface ImageProcessorOptions<TMimeType extends string = string> {
|
| 7 |
-
supportedMimeTypes: TMimeType[];
|
| 8 |
-
preferredMimeType: TMimeType;
|
| 9 |
-
maxSizeInMB: number;
|
| 10 |
-
maxWidth: number;
|
| 11 |
-
maxHeight: number;
|
| 12 |
-
}
|
| 13 |
-
export type ImageProcessor<TMimeType extends string = string> = (file: MessageFile) => Promise<{
|
| 14 |
-
image: Buffer;
|
| 15 |
-
mime: TMimeType;
|
| 16 |
-
}>;
|
| 17 |
-
|
| 18 |
-
export function createImageProcessorOptionsValidator<TMimeType extends string = string>(
|
| 19 |
-
defaults: ImageProcessorOptions<TMimeType>
|
| 20 |
-
) {
|
| 21 |
-
return z
|
| 22 |
-
.object({
|
| 23 |
-
supportedMimeTypes: z
|
| 24 |
-
.array(
|
| 25 |
-
z.enum<string, [TMimeType, ...TMimeType[]]>([
|
| 26 |
-
defaults.supportedMimeTypes[0],
|
| 27 |
-
...defaults.supportedMimeTypes.slice(1),
|
| 28 |
-
])
|
| 29 |
-
)
|
| 30 |
-
.default(defaults.supportedMimeTypes),
|
| 31 |
-
preferredMimeType: z
|
| 32 |
-
.enum([defaults.supportedMimeTypes[0], ...defaults.supportedMimeTypes.slice(1)])
|
| 33 |
-
.default(defaults.preferredMimeType as util.noUndefined<TMimeType>),
|
| 34 |
-
maxSizeInMB: z.number().positive().default(defaults.maxSizeInMB),
|
| 35 |
-
maxWidth: z.number().int().positive().default(defaults.maxWidth),
|
| 36 |
-
maxHeight: z.number().int().positive().default(defaults.maxHeight),
|
| 37 |
-
})
|
| 38 |
-
.default(defaults);
|
| 39 |
-
}
|
| 40 |
-
|
| 41 |
-
export function makeImageProcessor<TMimeType extends string = string>(
|
| 42 |
-
options: ImageProcessorOptions<TMimeType>
|
| 43 |
-
): ImageProcessor<TMimeType> {
|
| 44 |
-
return async (file) => {
|
| 45 |
-
const { supportedMimeTypes, preferredMimeType, maxSizeInMB, maxWidth, maxHeight } = options;
|
| 46 |
-
const { mime, value } = file;
|
| 47 |
-
|
| 48 |
-
const buffer = Buffer.from(value, "base64");
|
| 49 |
-
let sharpInst = sharp(buffer);
|
| 50 |
-
|
| 51 |
-
const metadata = await sharpInst.metadata();
|
| 52 |
-
if (!metadata) throw Error("Failed to read image metadata");
|
| 53 |
-
const { width, height } = metadata;
|
| 54 |
-
if (width === undefined || height === undefined) throw Error("Failed to read image size");
|
| 55 |
-
|
| 56 |
-
const tooLargeInSize = width > maxWidth || height > maxHeight;
|
| 57 |
-
const tooLargeInBytes = buffer.byteLength > maxSizeInMB * 1000 * 1000;
|
| 58 |
-
|
| 59 |
-
const outputMime = chooseMimeType(supportedMimeTypes, preferredMimeType, mime, {
|
| 60 |
-
preferSizeReduction: tooLargeInBytes,
|
| 61 |
-
});
|
| 62 |
-
|
| 63 |
-
// Resize if necessary
|
| 64 |
-
if (tooLargeInSize || tooLargeInBytes) {
|
| 65 |
-
const size = chooseImageSize({
|
| 66 |
-
mime: outputMime,
|
| 67 |
-
width,
|
| 68 |
-
height,
|
| 69 |
-
maxWidth,
|
| 70 |
-
maxHeight,
|
| 71 |
-
maxSizeInMB,
|
| 72 |
-
});
|
| 73 |
-
if (size.width !== width || size.height !== height) {
|
| 74 |
-
sharpInst = resizeImage(sharpInst, size.width, size.height);
|
| 75 |
-
}
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
// Convert format if necessary
|
| 79 |
-
// We always want to convert the image when the file was too large in bytes
|
| 80 |
-
// so we can guarantee that ideal options are used, which are expected when
|
| 81 |
-
// choosing the image size
|
| 82 |
-
if (outputMime !== mime || tooLargeInBytes) {
|
| 83 |
-
sharpInst = convertImage(sharpInst, outputMime);
|
| 84 |
-
}
|
| 85 |
-
|
| 86 |
-
const processedImage = await sharpInst.toBuffer();
|
| 87 |
-
return { image: processedImage, mime: outputMime };
|
| 88 |
-
};
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
const outputFormats = ["png", "jpeg", "webp", "avif", "tiff", "gif"] as const;
|
| 92 |
-
type OutputImgFormat = (typeof outputFormats)[number];
|
| 93 |
-
const isOutputFormat = (format: string): format is (typeof outputFormats)[number] =>
|
| 94 |
-
outputFormats.includes(format as OutputImgFormat);
|
| 95 |
-
|
| 96 |
-
export function convertImage(sharpInst: Sharp, outputMime: string): Sharp {
|
| 97 |
-
const [type, format] = outputMime.split("/");
|
| 98 |
-
if (type !== "image") throw Error(`Requested non-image mime type: ${outputMime}`);
|
| 99 |
-
if (!isOutputFormat(format)) {
|
| 100 |
-
throw Error(`Requested to convert to an unsupported format: ${format}`);
|
| 101 |
-
}
|
| 102 |
-
|
| 103 |
-
return sharpInst[format]();
|
| 104 |
-
}
|
| 105 |
-
|
| 106 |
-
// heic/heif requires proprietary license
|
| 107 |
-
// TODO: blocking heif may be incorrect considering it also supports av1, so we should instead
|
| 108 |
-
// detect the compression method used via sharp().metadata().compression
|
| 109 |
-
// TODO: consider what to do about animated formats: apng, gif, animated webp, ...
|
| 110 |
-
const blocklistedMimes = ["image/heic", "image/heif"];
|
| 111 |
-
|
| 112 |
-
/** Sorted from largest to smallest */
|
| 113 |
-
const mimesBySizeDesc = [
|
| 114 |
-
"image/png",
|
| 115 |
-
"image/tiff",
|
| 116 |
-
"image/gif",
|
| 117 |
-
"image/jpeg",
|
| 118 |
-
"image/webp",
|
| 119 |
-
"image/avif",
|
| 120 |
-
];
|
| 121 |
-
|
| 122 |
-
/**
|
| 123 |
-
* Defaults to preferred format or uses existing mime if supported
|
| 124 |
-
* When preferSizeReduction is true, it will choose the smallest format that is supported
|
| 125 |
-
**/
|
| 126 |
-
function chooseMimeType<T extends readonly string[]>(
|
| 127 |
-
supportedMimes: T,
|
| 128 |
-
preferredMime: string,
|
| 129 |
-
mime: string,
|
| 130 |
-
{ preferSizeReduction }: { preferSizeReduction: boolean }
|
| 131 |
-
): T[number] {
|
| 132 |
-
if (!supportedMimes.includes(preferredMime)) {
|
| 133 |
-
const supportedMimesStr = supportedMimes.join(", ");
|
| 134 |
-
throw Error(
|
| 135 |
-
`Preferred format "${preferredMime}" not found in supported mimes: ${supportedMimesStr}`
|
| 136 |
-
);
|
| 137 |
-
}
|
| 138 |
-
|
| 139 |
-
const [type] = mime.split("/");
|
| 140 |
-
if (type !== "image") throw Error(`Received non-image mime type: ${mime}`);
|
| 141 |
-
|
| 142 |
-
if (supportedMimes.includes(mime) && !preferSizeReduction) return mime;
|
| 143 |
-
|
| 144 |
-
if (blocklistedMimes.includes(mime)) throw Error(`Received blocklisted mime type: ${mime}`);
|
| 145 |
-
|
| 146 |
-
const smallestMime = mimesBySizeDesc.findLast((m) => supportedMimes.includes(m));
|
| 147 |
-
return smallestMime ?? preferredMime;
|
| 148 |
-
}
|
| 149 |
-
|
| 150 |
-
interface ImageSizeOptions {
|
| 151 |
-
mime: string;
|
| 152 |
-
width: number;
|
| 153 |
-
height: number;
|
| 154 |
-
maxWidth: number;
|
| 155 |
-
maxHeight: number;
|
| 156 |
-
maxSizeInMB: number;
|
| 157 |
-
}
|
| 158 |
-
|
| 159 |
-
/** Resizes the image to fit within the specified size in MB by guessing the output size */
|
| 160 |
-
export function chooseImageSize({
|
| 161 |
-
mime,
|
| 162 |
-
width,
|
| 163 |
-
height,
|
| 164 |
-
maxWidth,
|
| 165 |
-
maxHeight,
|
| 166 |
-
maxSizeInMB,
|
| 167 |
-
}: ImageSizeOptions): { width: number; height: number } {
|
| 168 |
-
const biggestDiscrepency = Math.max(1, width / maxWidth, height / maxHeight);
|
| 169 |
-
|
| 170 |
-
let selectedWidth = Math.ceil(width / biggestDiscrepency);
|
| 171 |
-
let selectedHeight = Math.ceil(height / biggestDiscrepency);
|
| 172 |
-
|
| 173 |
-
do {
|
| 174 |
-
const estimatedSize = estimateImageSizeInBytes(mime, selectedWidth, selectedHeight);
|
| 175 |
-
if (estimatedSize < maxSizeInMB * 1024 * 1024) {
|
| 176 |
-
return { width: selectedWidth, height: selectedHeight };
|
| 177 |
-
}
|
| 178 |
-
selectedWidth = Math.floor(selectedWidth / 1.1);
|
| 179 |
-
selectedHeight = Math.floor(selectedHeight / 1.1);
|
| 180 |
-
} while (selectedWidth > 1 && selectedHeight > 1);
|
| 181 |
-
|
| 182 |
-
throw Error(`Failed to resize image to fit within ${maxSizeInMB}MB`);
|
| 183 |
-
}
|
| 184 |
-
|
| 185 |
-
const mimeToCompressionRatio: Record<string, number> = {
|
| 186 |
-
"image/png": 1 / 2,
|
| 187 |
-
"image/jpeg": 1 / 10,
|
| 188 |
-
"image/webp": 1 / 4,
|
| 189 |
-
"image/avif": 1 / 5,
|
| 190 |
-
"image/tiff": 1,
|
| 191 |
-
"image/gif": 1 / 5,
|
| 192 |
-
};
|
| 193 |
-
|
| 194 |
-
/**
|
| 195 |
-
* Guesses the side of an image in MB based on its format and dimensions
|
| 196 |
-
* Should guess the worst case
|
| 197 |
-
**/
|
| 198 |
-
function estimateImageSizeInBytes(mime: string, width: number, height: number): number {
|
| 199 |
-
const compressionRatio = mimeToCompressionRatio[mime];
|
| 200 |
-
if (!compressionRatio) throw Error(`Unsupported image format: ${mime}`);
|
| 201 |
-
|
| 202 |
-
const bitsPerPixel = 32; // Assuming 32-bit color depth for 8-bit R G B A
|
| 203 |
-
const bytesPerPixel = bitsPerPixel / 8;
|
| 204 |
-
const uncompressedSize = width * height * bytesPerPixel;
|
| 205 |
-
|
| 206 |
-
return uncompressedSize * compressionRatio;
|
| 207 |
-
}
|
| 208 |
-
|
| 209 |
-
export function resizeImage(sharpInst: Sharp, maxWidth: number, maxHeight: number): Sharp {
|
| 210 |
-
return sharpInst.resize({ width: maxWidth, height: maxHeight, fit: "inside" });
|
| 211 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/server/endpoints/openai/endpointOai.ts
CHANGED
|
@@ -6,10 +6,6 @@ import type { ChatCompletionCreateParamsStreaming } from "openai/resources/chat/
|
|
| 6 |
import { buildPrompt } from "$lib/buildPrompt";
|
| 7 |
import { env } from "$env/dynamic/private";
|
| 8 |
import type { Endpoint } from "../endpoints";
|
| 9 |
-
import type OpenAI from "openai";
|
| 10 |
-
import { createImageProcessorOptionsValidator, makeImageProcessor } from "../images";
|
| 11 |
-
import type { MessageFile } from "$lib/types/Message";
|
| 12 |
-
import type { EndpointMessage } from "../endpoints";
|
| 13 |
|
| 14 |
export const endpointOAIParametersSchema = z.object({
|
| 15 |
weight: z.number().int().positive().default(1),
|
|
@@ -23,41 +19,13 @@ export const endpointOAIParametersSchema = z.object({
|
|
| 23 |
defaultHeaders: z.record(z.string()).optional(),
|
| 24 |
defaultQuery: z.record(z.string()).optional(),
|
| 25 |
extraBody: z.record(z.any()).optional(),
|
| 26 |
-
multimodal: z
|
| 27 |
-
.object({
|
| 28 |
-
image: createImageProcessorOptionsValidator({
|
| 29 |
-
supportedMimeTypes: [
|
| 30 |
-
"image/png",
|
| 31 |
-
"image/jpeg",
|
| 32 |
-
"image/webp",
|
| 33 |
-
"image/avif",
|
| 34 |
-
"image/tiff",
|
| 35 |
-
"image/gif",
|
| 36 |
-
],
|
| 37 |
-
preferredMimeType: "image/webp",
|
| 38 |
-
maxSizeInMB: Infinity,
|
| 39 |
-
maxWidth: 4096,
|
| 40 |
-
maxHeight: 4096,
|
| 41 |
-
}),
|
| 42 |
-
})
|
| 43 |
-
.default({}),
|
| 44 |
});
|
| 45 |
|
| 46 |
export async function endpointOai(
|
| 47 |
input: z.input<typeof endpointOAIParametersSchema>
|
| 48 |
): Promise<Endpoint> {
|
| 49 |
-
const {
|
| 50 |
-
|
| 51 |
-
apiKey,
|
| 52 |
-
completion,
|
| 53 |
-
model,
|
| 54 |
-
defaultHeaders,
|
| 55 |
-
defaultQuery,
|
| 56 |
-
multimodal,
|
| 57 |
-
extraBody,
|
| 58 |
-
} = endpointOAIParametersSchema.parse(input);
|
| 59 |
-
|
| 60 |
-
/* eslint-disable-next-line no-shadow */
|
| 61 |
let OpenAI;
|
| 62 |
try {
|
| 63 |
OpenAI = (await import("openai")).OpenAI;
|
|
@@ -72,8 +40,6 @@ export async function endpointOai(
|
|
| 72 |
defaultQuery,
|
| 73 |
});
|
| 74 |
|
| 75 |
-
const imageProcessor = makeImageProcessor(multimodal.image);
|
| 76 |
-
|
| 77 |
if (completion === "completions") {
|
| 78 |
return async ({ messages, preprompt, continueMessage, generateSettings }) => {
|
| 79 |
const prompt = await buildPrompt({
|
|
@@ -103,8 +69,10 @@ export async function endpointOai(
|
|
| 103 |
};
|
| 104 |
} else if (completion === "chat_completions") {
|
| 105 |
return async ({ messages, preprompt, generateSettings }) => {
|
| 106 |
-
let messagesOpenAI
|
| 107 |
-
|
|
|
|
|
|
|
| 108 |
|
| 109 |
if (messagesOpenAI?.[0]?.role !== "system") {
|
| 110 |
messagesOpenAI = [{ role: "system", content: "" }, ...messagesOpenAI];
|
|
@@ -136,39 +104,3 @@ export async function endpointOai(
|
|
| 136 |
throw new Error("Invalid completion type");
|
| 137 |
}
|
| 138 |
}
|
| 139 |
-
|
| 140 |
-
async function prepareMessages(
|
| 141 |
-
messages: EndpointMessage[],
|
| 142 |
-
imageProcessor: ReturnType<typeof makeImageProcessor>
|
| 143 |
-
): Promise<OpenAI.Chat.Completions.ChatCompletionMessageParam[]> {
|
| 144 |
-
return Promise.all(
|
| 145 |
-
messages.map(async (message) => {
|
| 146 |
-
if (message.from === "user") {
|
| 147 |
-
return {
|
| 148 |
-
role: message.from,
|
| 149 |
-
content: [
|
| 150 |
-
...(await prepareFiles(imageProcessor, message.files ?? [])),
|
| 151 |
-
{ type: "text", text: message.content },
|
| 152 |
-
],
|
| 153 |
-
};
|
| 154 |
-
}
|
| 155 |
-
return {
|
| 156 |
-
role: message.from,
|
| 157 |
-
content: message.content,
|
| 158 |
-
};
|
| 159 |
-
})
|
| 160 |
-
);
|
| 161 |
-
}
|
| 162 |
-
|
| 163 |
-
async function prepareFiles(
|
| 164 |
-
imageProcessor: ReturnType<typeof makeImageProcessor>,
|
| 165 |
-
files: MessageFile[]
|
| 166 |
-
): Promise<OpenAI.Chat.Completions.ChatCompletionContentPartImage[]> {
|
| 167 |
-
const processedFiles = await Promise.all(files.map(imageProcessor));
|
| 168 |
-
return processedFiles.map((file) => ({
|
| 169 |
-
type: "image_url" as const,
|
| 170 |
-
image_url: {
|
| 171 |
-
url: `data:${file.mime};base64,${file.image.toString("base64")}`,
|
| 172 |
-
},
|
| 173 |
-
}));
|
| 174 |
-
}
|
|
|
|
| 6 |
import { buildPrompt } from "$lib/buildPrompt";
|
| 7 |
import { env } from "$env/dynamic/private";
|
| 8 |
import type { Endpoint } from "../endpoints";
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
export const endpointOAIParametersSchema = z.object({
|
| 11 |
weight: z.number().int().positive().default(1),
|
|
|
|
| 19 |
defaultHeaders: z.record(z.string()).optional(),
|
| 20 |
defaultQuery: z.record(z.string()).optional(),
|
| 21 |
extraBody: z.record(z.any()).optional(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
});
|
| 23 |
|
| 24 |
export async function endpointOai(
|
| 25 |
input: z.input<typeof endpointOAIParametersSchema>
|
| 26 |
): Promise<Endpoint> {
|
| 27 |
+
const { baseURL, apiKey, completion, model, defaultHeaders, defaultQuery, extraBody } =
|
| 28 |
+
endpointOAIParametersSchema.parse(input);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
let OpenAI;
|
| 30 |
try {
|
| 31 |
OpenAI = (await import("openai")).OpenAI;
|
|
|
|
| 40 |
defaultQuery,
|
| 41 |
});
|
| 42 |
|
|
|
|
|
|
|
| 43 |
if (completion === "completions") {
|
| 44 |
return async ({ messages, preprompt, continueMessage, generateSettings }) => {
|
| 45 |
const prompt = await buildPrompt({
|
|
|
|
| 69 |
};
|
| 70 |
} else if (completion === "chat_completions") {
|
| 71 |
return async ({ messages, preprompt, generateSettings }) => {
|
| 72 |
+
let messagesOpenAI = messages.map((message) => ({
|
| 73 |
+
role: message.from,
|
| 74 |
+
content: message.content,
|
| 75 |
+
}));
|
| 76 |
|
| 77 |
if (messagesOpenAI?.[0]?.role !== "system") {
|
| 78 |
messagesOpenAI = [{ role: "system", content: "" }, ...messagesOpenAI];
|
|
|
|
| 104 |
throw new Error("Invalid completion type");
|
| 105 |
}
|
| 106 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/server/endpoints/preprocessMessages.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
| 1 |
-
import type { Message } from "$lib/types/Message";
|
| 2 |
-
import { format } from "date-fns";
|
| 3 |
-
import type { EndpointMessage } from "./endpoints";
|
| 4 |
-
import { downloadFile } from "../files/downloadFile";
|
| 5 |
-
import type { ObjectId } from "mongodb";
|
| 6 |
-
|
| 7 |
-
export async function preprocessMessages(
|
| 8 |
-
messages: Message[],
|
| 9 |
-
webSearch: Message["webSearch"],
|
| 10 |
-
convId: ObjectId
|
| 11 |
-
): Promise<EndpointMessage[]> {
|
| 12 |
-
return Promise.resolve(messages)
|
| 13 |
-
.then((msgs) => addWebSearchContext(msgs, webSearch))
|
| 14 |
-
.then((msgs) => downloadFiles(msgs, convId));
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
function addWebSearchContext(messages: Message[], webSearch: Message["webSearch"]) {
|
| 18 |
-
const webSearchContext = webSearch?.contextSources
|
| 19 |
-
.map(({ context }) => context.trim())
|
| 20 |
-
.join("\n\n----------\n\n");
|
| 21 |
-
|
| 22 |
-
// No web search context available, skip
|
| 23 |
-
if (!webSearch || !webSearchContext?.trim()) return messages;
|
| 24 |
-
// No messages available, skip
|
| 25 |
-
if (messages.length === 0) return messages;
|
| 26 |
-
|
| 27 |
-
const lastQuestion = messages.findLast((el) => el.from === "user")?.content ?? "";
|
| 28 |
-
const previousQuestions = messages
|
| 29 |
-
.filter((el) => el.from === "user")
|
| 30 |
-
.slice(0, -1)
|
| 31 |
-
.map((el) => el.content);
|
| 32 |
-
const currentDate = format(new Date(), "MMMM d, yyyy");
|
| 33 |
-
|
| 34 |
-
const finalMessage = {
|
| 35 |
-
...messages[messages.length - 1],
|
| 36 |
-
content: `I searched the web using the query: ${webSearch.searchQuery}.
|
| 37 |
-
Today is ${currentDate} and here are the results:
|
| 38 |
-
=====================
|
| 39 |
-
${webSearchContext}
|
| 40 |
-
=====================
|
| 41 |
-
${previousQuestions.length > 0 ? `Previous questions: \n- ${previousQuestions.join("\n- ")}` : ""}
|
| 42 |
-
Answer the question: ${lastQuestion}`,
|
| 43 |
-
};
|
| 44 |
-
|
| 45 |
-
return [...messages.slice(0, -1), finalMessage];
|
| 46 |
-
}
|
| 47 |
-
|
| 48 |
-
async function downloadFiles(messages: Message[], convId: ObjectId): Promise<EndpointMessage[]> {
|
| 49 |
-
return Promise.all(
|
| 50 |
-
messages.map<Promise<EndpointMessage>>((message) =>
|
| 51 |
-
Promise.all((message.files ?? []).map((file) => downloadFile(file.value, convId))).then(
|
| 52 |
-
(files) => ({ ...message, files })
|
| 53 |
-
)
|
| 54 |
-
)
|
| 55 |
-
);
|
| 56 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/server/endpoints/tgi/endpointTgi.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
| 1 |
import { env } from "$env/dynamic/private";
|
| 2 |
import { buildPrompt } from "$lib/buildPrompt";
|
| 3 |
import { textGenerationStream } from "@huggingface/inference";
|
| 4 |
-
import type { Endpoint
|
| 5 |
import { z } from "zod";
|
| 6 |
-
import {
|
| 7 |
-
createImageProcessorOptionsValidator,
|
| 8 |
-
makeImageProcessor,
|
| 9 |
-
type ImageProcessor,
|
| 10 |
-
} from "../images";
|
| 11 |
|
| 12 |
export const endpointTgiParametersSchema = z.object({
|
| 13 |
weight: z.number().int().positive().default(1),
|
|
@@ -16,32 +11,14 @@ export const endpointTgiParametersSchema = z.object({
|
|
| 16 |
url: z.string().url(),
|
| 17 |
accessToken: z.string().default(env.HF_TOKEN ?? env.HF_ACCESS_TOKEN),
|
| 18 |
authorization: z.string().optional(),
|
| 19 |
-
multimodal: z
|
| 20 |
-
.object({
|
| 21 |
-
// Assumes IDEFICS
|
| 22 |
-
image: createImageProcessorOptionsValidator({
|
| 23 |
-
supportedMimeTypes: ["image/jpeg", "image/webp"],
|
| 24 |
-
preferredMimeType: "image/webp",
|
| 25 |
-
maxSizeInMB: 5,
|
| 26 |
-
maxWidth: 224,
|
| 27 |
-
maxHeight: 224,
|
| 28 |
-
}),
|
| 29 |
-
})
|
| 30 |
-
.default({}),
|
| 31 |
});
|
| 32 |
|
| 33 |
export function endpointTgi(input: z.input<typeof endpointTgiParametersSchema>): Endpoint {
|
| 34 |
-
const { url, accessToken, model, authorization
|
| 35 |
-
endpointTgiParametersSchema.parse(input);
|
| 36 |
-
const imageProcessor = makeImageProcessor(multimodal.image);
|
| 37 |
|
| 38 |
return async ({ messages, preprompt, continueMessage, generateSettings }) => {
|
| 39 |
-
const messagesWithResizedFiles = await Promise.all(
|
| 40 |
-
messages.map((message) => prepareMessage(message, imageProcessor))
|
| 41 |
-
);
|
| 42 |
-
|
| 43 |
const prompt = await buildPrompt({
|
| 44 |
-
messages
|
| 45 |
preprompt,
|
| 46 |
model,
|
| 47 |
continueMessage,
|
|
@@ -71,23 +48,4 @@ export function endpointTgi(input: z.input<typeof endpointTgiParametersSchema>):
|
|
| 71 |
};
|
| 72 |
}
|
| 73 |
|
| 74 |
-
|
| 75 |
-
mime: "image/png",
|
| 76 |
-
image: Buffer.from(
|
| 77 |
-
"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAAQABADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKACgD/2Q==",
|
| 78 |
-
"base64"
|
| 79 |
-
),
|
| 80 |
-
};
|
| 81 |
-
|
| 82 |
-
async function prepareMessage(
|
| 83 |
-
message: EndpointMessage,
|
| 84 |
-
imageProcessor: ImageProcessor
|
| 85 |
-
): Promise<EndpointMessage> {
|
| 86 |
-
const files = await Promise.all(message.files?.map(imageProcessor) ?? [whiteImage]);
|
| 87 |
-
const markdowns = files.map(
|
| 88 |
-
(file) => `})`
|
| 89 |
-
);
|
| 90 |
-
const content = message.content + "\n" + markdowns.join("\n ");
|
| 91 |
-
|
| 92 |
-
return { ...message, content };
|
| 93 |
-
}
|
|
|
|
| 1 |
import { env } from "$env/dynamic/private";
|
| 2 |
import { buildPrompt } from "$lib/buildPrompt";
|
| 3 |
import { textGenerationStream } from "@huggingface/inference";
|
| 4 |
+
import type { Endpoint } from "../endpoints";
|
| 5 |
import { z } from "zod";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
export const endpointTgiParametersSchema = z.object({
|
| 8 |
weight: z.number().int().positive().default(1),
|
|
|
|
| 11 |
url: z.string().url(),
|
| 12 |
accessToken: z.string().default(env.HF_TOKEN ?? env.HF_ACCESS_TOKEN),
|
| 13 |
authorization: z.string().optional(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
});
|
| 15 |
|
| 16 |
export function endpointTgi(input: z.input<typeof endpointTgiParametersSchema>): Endpoint {
|
| 17 |
+
const { url, accessToken, model, authorization } = endpointTgiParametersSchema.parse(input);
|
|
|
|
|
|
|
| 18 |
|
| 19 |
return async ({ messages, preprompt, continueMessage, generateSettings }) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
const prompt = await buildPrompt({
|
| 21 |
+
messages,
|
| 22 |
preprompt,
|
| 23 |
model,
|
| 24 |
continueMessage,
|
|
|
|
| 48 |
};
|
| 49 |
}
|
| 50 |
|
| 51 |
+
export default endpointTgi;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/server/files/downloadFile.ts
CHANGED
|
@@ -2,16 +2,15 @@ import { error } from "@sveltejs/kit";
|
|
| 2 |
import { collections } from "$lib/server/database";
|
| 3 |
import type { Conversation } from "$lib/types/Conversation";
|
| 4 |
import type { SharedConversation } from "$lib/types/SharedConversation";
|
| 5 |
-
import type { MessageFile } from "$lib/types/Message";
|
| 6 |
|
| 7 |
export async function downloadFile(
|
| 8 |
sha256: string,
|
| 9 |
convId: Conversation["_id"] | SharedConversation["_id"]
|
| 10 |
-
)
|
| 11 |
const fileId = collections.bucket.find({ filename: `${convId.toString()}-${sha256}` });
|
| 12 |
let mime = "";
|
| 13 |
|
| 14 |
-
const
|
| 15 |
if (!file) {
|
| 16 |
throw error(404, "File not found");
|
| 17 |
}
|
|
@@ -33,5 +32,5 @@ export async function downloadFile(
|
|
| 33 |
return fileBuffer;
|
| 34 |
});
|
| 35 |
|
| 36 |
-
return {
|
| 37 |
}
|
|
|
|
| 2 |
import { collections } from "$lib/server/database";
|
| 3 |
import type { Conversation } from "$lib/types/Conversation";
|
| 4 |
import type { SharedConversation } from "$lib/types/SharedConversation";
|
|
|
|
| 5 |
|
| 6 |
export async function downloadFile(
|
| 7 |
sha256: string,
|
| 8 |
convId: Conversation["_id"] | SharedConversation["_id"]
|
| 9 |
+
) {
|
| 10 |
const fileId = collections.bucket.find({ filename: `${convId.toString()}-${sha256}` });
|
| 11 |
let mime = "";
|
| 12 |
|
| 13 |
+
const content = await fileId.next().then(async (file) => {
|
| 14 |
if (!file) {
|
| 15 |
throw error(404, "File not found");
|
| 16 |
}
|
|
|
|
| 32 |
return fileBuffer;
|
| 33 |
});
|
| 34 |
|
| 35 |
+
return { content, mime };
|
| 36 |
}
|
src/lib/server/files/uploadFile.ts
CHANGED
|
@@ -1,27 +1,21 @@
|
|
| 1 |
import type { Conversation } from "$lib/types/Conversation";
|
| 2 |
-
import type { MessageFile } from "$lib/types/Message";
|
| 3 |
import { sha256 } from "$lib/utils/sha256";
|
| 4 |
-
import { fileTypeFromBuffer } from "file-type";
|
| 5 |
import { collections } from "$lib/server/database";
|
| 6 |
|
| 7 |
-
export async function uploadFile(file:
|
| 8 |
const sha = await sha256(await file.text());
|
| 9 |
-
const buffer = await file.arrayBuffer();
|
| 10 |
-
|
| 11 |
-
// Attempt to detect the mime type of the file, fallback to the uploaded mime
|
| 12 |
-
const mime = await fileTypeFromBuffer(buffer).then((fileType) => fileType?.mime ?? file.type);
|
| 13 |
|
| 14 |
const upload = collections.bucket.openUploadStream(`${conv._id}-${sha}`, {
|
| 15 |
-
metadata: { conversation: conv._id.toString(), mime },
|
| 16 |
});
|
| 17 |
|
| 18 |
upload.write((await file.arrayBuffer()) as unknown as Buffer);
|
| 19 |
upload.end();
|
| 20 |
|
| 21 |
-
// only return the filename when upload throws a finish event or a
|
| 22 |
return new Promise((resolve, reject) => {
|
| 23 |
-
upload.once("finish", () => resolve(
|
| 24 |
upload.once("error", reject);
|
| 25 |
-
setTimeout(() => reject(new Error("Upload timed out")),
|
| 26 |
});
|
| 27 |
}
|
|
|
|
| 1 |
import type { Conversation } from "$lib/types/Conversation";
|
|
|
|
| 2 |
import { sha256 } from "$lib/utils/sha256";
|
|
|
|
| 3 |
import { collections } from "$lib/server/database";
|
| 4 |
|
| 5 |
+
export async function uploadFile(file: Blob, conv: Conversation): Promise<string> {
|
| 6 |
const sha = await sha256(await file.text());
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
const upload = collections.bucket.openUploadStream(`${conv._id}-${sha}`, {
|
| 9 |
+
metadata: { conversation: conv._id.toString(), mime: "image/jpeg" },
|
| 10 |
});
|
| 11 |
|
| 12 |
upload.write((await file.arrayBuffer()) as unknown as Buffer);
|
| 13 |
upload.end();
|
| 14 |
|
| 15 |
+
// only return the filename when upload throws a finish event or a 10s time out occurs
|
| 16 |
return new Promise((resolve, reject) => {
|
| 17 |
+
upload.once("finish", () => resolve(sha));
|
| 18 |
upload.once("error", reject);
|
| 19 |
+
setTimeout(() => reject(new Error("Upload timed out")), 10000);
|
| 20 |
});
|
| 21 |
}
|
src/lib/server/generateFromDefaultEndpoint.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
import { smallModel } from "$lib/server/models";
|
| 2 |
-
import type {
|
| 3 |
|
| 4 |
export async function generateFromDefaultEndpoint({
|
| 5 |
messages,
|
| 6 |
preprompt,
|
| 7 |
generateSettings,
|
| 8 |
}: {
|
| 9 |
-
messages:
|
| 10 |
preprompt?: string;
|
| 11 |
generateSettings?: Record<string, unknown>;
|
| 12 |
}): Promise<string> {
|
|
|
|
| 1 |
import { smallModel } from "$lib/server/models";
|
| 2 |
+
import type { Conversation } from "$lib/types/Conversation";
|
| 3 |
|
| 4 |
export async function generateFromDefaultEndpoint({
|
| 5 |
messages,
|
| 6 |
preprompt,
|
| 7 |
generateSettings,
|
| 8 |
}: {
|
| 9 |
+
messages: Omit<Conversation["messages"][0], "id">[];
|
| 10 |
preprompt?: string;
|
| 11 |
generateSettings?: Record<string, unknown>;
|
| 12 |
}): Promise<string> {
|
src/lib/server/models.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { ChatTemplateInput } from "$lib/types/Template";
|
|
| 3 |
import { compileTemplate } from "$lib/utils/template";
|
| 4 |
import { z } from "zod";
|
| 5 |
import endpoints, { endpointSchema, type Endpoint } from "./endpoints/endpoints";
|
| 6 |
-
import
|
| 7 |
import { sum } from "$lib/utils/sum";
|
| 8 |
import { embeddingModels, validateEmbeddingModelByName } from "./embeddingModels";
|
| 9 |
|
|
|
|
| 3 |
import { compileTemplate } from "$lib/utils/template";
|
| 4 |
import { z } from "zod";
|
| 5 |
import endpoints, { endpointSchema, type Endpoint } from "./endpoints/endpoints";
|
| 6 |
+
import endpointTgi from "./endpoints/tgi/endpointTgi";
|
| 7 |
import { sum } from "$lib/utils/sum";
|
| 8 |
import { embeddingModels, validateEmbeddingModelByName } from "./embeddingModels";
|
| 9 |
|
src/lib/server/preprocessMessages.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { Conversation } from "$lib/types/Conversation";
|
| 2 |
+
import type { Message } from "$lib/types/Message";
|
| 3 |
+
import { format } from "date-fns";
|
| 4 |
+
import { downloadFile } from "./files/downloadFile";
|
| 5 |
+
import { logger } from "$lib/server/logger";
|
| 6 |
+
|
| 7 |
+
export async function preprocessMessages(
|
| 8 |
+
messages: Message[],
|
| 9 |
+
webSearch: Message["webSearch"],
|
| 10 |
+
multimodal: boolean,
|
| 11 |
+
id: Conversation["_id"]
|
| 12 |
+
): Promise<Message[]> {
|
| 13 |
+
return await Promise.all(
|
| 14 |
+
structuredClone(messages).map(async (message, idx) => {
|
| 15 |
+
const webSearchContext = webSearch?.contextSources
|
| 16 |
+
.map(({ context }) => context.trim())
|
| 17 |
+
.join("\n\n----------\n\n");
|
| 18 |
+
|
| 19 |
+
// start by adding websearch to the last message
|
| 20 |
+
if (idx === messages.length - 1 && webSearch && webSearchContext?.trim()) {
|
| 21 |
+
const lastQuestion = messages.findLast((el) => el.from === "user")?.content ?? "";
|
| 22 |
+
const previousQuestions = messages
|
| 23 |
+
.filter((el) => el.from === "user")
|
| 24 |
+
.slice(0, -1)
|
| 25 |
+
.map((el) => el.content);
|
| 26 |
+
const currentDate = format(new Date(), "MMMM d, yyyy");
|
| 27 |
+
|
| 28 |
+
message.content = `I searched the web using the query: ${webSearch.searchQuery}.
|
| 29 |
+
Today is ${currentDate} and here are the results:
|
| 30 |
+
=====================
|
| 31 |
+
${webSearchContext}
|
| 32 |
+
=====================
|
| 33 |
+
${previousQuestions.length > 0 ? `Previous questions: \n- ${previousQuestions.join("\n- ")}` : ""}
|
| 34 |
+
Answer the question: ${lastQuestion}`;
|
| 35 |
+
}
|
| 36 |
+
// handle files if model is multimodal
|
| 37 |
+
if (multimodal) {
|
| 38 |
+
if (message.files && message.files.length > 0) {
|
| 39 |
+
const markdowns = await Promise.all(
|
| 40 |
+
message.files.map(async (hash) => {
|
| 41 |
+
try {
|
| 42 |
+
const { content: image, mime } = await downloadFile(hash, id);
|
| 43 |
+
const b64 = image.toString("base64");
|
| 44 |
+
return `})`;
|
| 45 |
+
} catch (e) {
|
| 46 |
+
logger.error(e);
|
| 47 |
+
}
|
| 48 |
+
})
|
| 49 |
+
);
|
| 50 |
+
message.content += markdowns.join("\n ");
|
| 51 |
+
} else {
|
| 52 |
+
// if no image, append an empty white image
|
| 53 |
+
message.content +=
|
| 54 |
+
"\n";
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
return message;
|
| 59 |
+
})
|
| 60 |
+
);
|
| 61 |
+
}
|
src/lib/server/summarize.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import { env } from "$env/dynamic/private";
|
| 2 |
import { generateFromDefaultEndpoint } from "$lib/server/generateFromDefaultEndpoint";
|
| 3 |
-
import type {
|
| 4 |
import { logger } from "$lib/server/logger";
|
| 5 |
|
| 6 |
export async function summarize(prompt: string) {
|
|
@@ -8,7 +8,7 @@ export async function summarize(prompt: string) {
|
|
| 8 |
return prompt.split(/\s+/g).slice(0, 5).join(" ");
|
| 9 |
}
|
| 10 |
|
| 11 |
-
const messages: Array<
|
| 12 |
{ from: "user", content: "Who is the president of Gabon?" },
|
| 13 |
{ from: "assistant", content: "🇬🇦 President of Gabon" },
|
| 14 |
{ from: "user", content: "Who is Julien Chaumond?" },
|
|
|
|
| 1 |
import { env } from "$env/dynamic/private";
|
| 2 |
import { generateFromDefaultEndpoint } from "$lib/server/generateFromDefaultEndpoint";
|
| 3 |
+
import type { Message } from "$lib/types/Message";
|
| 4 |
import { logger } from "$lib/server/logger";
|
| 5 |
|
| 6 |
export async function summarize(prompt: string) {
|
|
|
|
| 8 |
return prompt.split(/\s+/g).slice(0, 5).join(" ");
|
| 9 |
}
|
| 10 |
|
| 11 |
+
const messages: Array<Omit<Message, "id">> = [
|
| 12 |
{ from: "user", content: "Who is the president of Gabon?" },
|
| 13 |
{ from: "assistant", content: "🇬🇦 President of Gabon" },
|
| 14 |
{ from: "user", content: "Who is Julien Chaumond?" },
|
src/lib/server/websearch/search/generateQuery.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
import type { Message } from "$lib/types/Message";
|
| 2 |
import { format } from "date-fns";
|
| 3 |
-
import type { EndpointMessage } from "../../endpoints/endpoints";
|
| 4 |
import { generateFromDefaultEndpoint } from "../../generateFromDefaultEndpoint";
|
| 5 |
|
| 6 |
export async function generateQuery(messages: Message[]) {
|
|
@@ -10,7 +9,7 @@ export async function generateQuery(messages: Message[]) {
|
|
| 10 |
|
| 11 |
const lastMessage = userMessages.slice(-1)[0];
|
| 12 |
|
| 13 |
-
const convQuery: Array<
|
| 14 |
{
|
| 15 |
from: "user",
|
| 16 |
content: `Previous Questions:
|
|
|
|
| 1 |
import type { Message } from "$lib/types/Message";
|
| 2 |
import { format } from "date-fns";
|
|
|
|
| 3 |
import { generateFromDefaultEndpoint } from "../../generateFromDefaultEndpoint";
|
| 4 |
|
| 5 |
export async function generateQuery(messages: Message[]) {
|
|
|
|
| 9 |
|
| 10 |
const lastMessage = userMessages.slice(-1)[0];
|
| 11 |
|
| 12 |
+
const convQuery: Array<Omit<Message, "id">> = [
|
| 13 |
{
|
| 14 |
from: "user",
|
| 15 |
content: `Previous Questions:
|
src/lib/types/Message.ts
CHANGED
|
@@ -11,11 +11,7 @@ export type Message = Partial<Timestamps> & {
|
|
| 11 |
webSearchId?: WebSearch["_id"]; // legacy version
|
| 12 |
webSearch?: WebSearch;
|
| 13 |
score?: -1 | 0 | 1;
|
| 14 |
-
|
| 15 |
-
* Either contains the base64 encoded image data
|
| 16 |
-
* or the hash of the file stored on the server
|
| 17 |
-
**/
|
| 18 |
-
files?: MessageFile[];
|
| 19 |
interrupted?: boolean;
|
| 20 |
|
| 21 |
// needed for conversation trees
|
|
@@ -24,9 +20,3 @@ export type Message = Partial<Timestamps> & {
|
|
| 24 |
// goes one level deep
|
| 25 |
children?: Message["id"][];
|
| 26 |
};
|
| 27 |
-
|
| 28 |
-
export type MessageFile = {
|
| 29 |
-
type: "hash" | "base64";
|
| 30 |
-
value: string;
|
| 31 |
-
mime: string;
|
| 32 |
-
};
|
|
|
|
| 11 |
webSearchId?: WebSearch["_id"]; // legacy version
|
| 12 |
webSearch?: WebSearch;
|
| 13 |
score?: -1 | 0 | 1;
|
| 14 |
+
files?: string[]; // can contain either the hash of the file or the b64 encoded image data on the client side when uploading
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
interrupted?: boolean;
|
| 16 |
|
| 17 |
// needed for conversation trees
|
|
|
|
| 20 |
// goes one level deep
|
| 21 |
children?: Message["id"][];
|
| 22 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/utils/messageUpdates.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
import type { MessageFile } from "$lib/types/Message";
|
| 2 |
import type { MessageUpdate, TextStreamUpdate } from "$lib/types/MessageUpdate";
|
| 3 |
|
| 4 |
type MessageUpdateRequestOptions = {
|
|
@@ -8,7 +7,7 @@ type MessageUpdateRequestOptions = {
|
|
| 8 |
isRetry: boolean;
|
| 9 |
isContinue: boolean;
|
| 10 |
webSearch: boolean;
|
| 11 |
-
files?:
|
| 12 |
};
|
| 13 |
export async function fetchMessageUpdates(
|
| 14 |
conversationId: string,
|
|
|
|
|
|
|
| 1 |
import type { MessageUpdate, TextStreamUpdate } from "$lib/types/MessageUpdate";
|
| 2 |
|
| 3 |
type MessageUpdateRequestOptions = {
|
|
|
|
| 7 |
isRetry: boolean;
|
| 8 |
isContinue: boolean;
|
| 9 |
webSearch: boolean;
|
| 10 |
+
files?: string[];
|
| 11 |
};
|
| 12 |
export async function fetchMessageUpdates(
|
| 13 |
conversationId: string,
|
src/routes/conversation/[id]/+page.svelte
CHANGED
|
@@ -75,10 +75,20 @@
|
|
| 75 |
loading = true;
|
| 76 |
pending = true;
|
| 77 |
|
| 78 |
-
const
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
);
|
| 83 |
|
| 84 |
let messageToWriteToId: Message["id"] | undefined = undefined;
|
|
@@ -110,11 +120,7 @@
|
|
| 110 |
messages,
|
| 111 |
rootMessageId: data.rootMessageId,
|
| 112 |
},
|
| 113 |
-
{
|
| 114 |
-
from: "user",
|
| 115 |
-
content: prompt,
|
| 116 |
-
files: messageToRetry.files,
|
| 117 |
-
},
|
| 118 |
messageId
|
| 119 |
);
|
| 120 |
messageToWriteToId = addChildren(
|
|
@@ -122,7 +128,7 @@
|
|
| 122 |
messages,
|
| 123 |
rootMessageId: data.rootMessageId,
|
| 124 |
},
|
| 125 |
-
{ from: "assistant", content: "" },
|
| 126 |
newUserMessageId
|
| 127 |
);
|
| 128 |
} else if (messageToRetry?.from === "assistant") {
|
|
@@ -148,7 +154,7 @@
|
|
| 148 |
{
|
| 149 |
from: "user",
|
| 150 |
content: prompt ?? "",
|
| 151 |
-
files:
|
| 152 |
createdAt: new Date(),
|
| 153 |
updatedAt: new Date(),
|
| 154 |
},
|
|
@@ -175,7 +181,6 @@
|
|
| 175 |
}
|
| 176 |
|
| 177 |
messages = [...messages];
|
| 178 |
-
const userMessage = messages.find((message) => message.id === messageId);
|
| 179 |
const messageToWriteTo = messages.find((message) => message.id === messageToWriteToId);
|
| 180 |
if (!messageToWriteTo) {
|
| 181 |
throw new Error("Message to write to not found");
|
|
@@ -193,7 +198,7 @@
|
|
| 193 |
isRetry,
|
| 194 |
isContinue,
|
| 195 |
webSearch: !hasAssistant && $webSearchParameters.useSearch,
|
| 196 |
-
files: isRetry ?
|
| 197 |
},
|
| 198 |
messageUpdatesAbortController.signal
|
| 199 |
).catch((err) => {
|
|
|
|
| 75 |
loading = true;
|
| 76 |
pending = true;
|
| 77 |
|
| 78 |
+
const module = await import("browser-image-resizer");
|
| 79 |
+
// currently, only IDEFICS is supported by TGI
|
| 80 |
+
// the size of images is hardcoded to 224x224 in TGI
|
| 81 |
+
// this will need to be configurable when support for more models is added
|
| 82 |
+
const resizedImages = await Promise.all(
|
| 83 |
+
files.map(async (file) => {
|
| 84 |
+
return await module
|
| 85 |
+
.readAndCompressImage(file, {
|
| 86 |
+
maxHeight: 224,
|
| 87 |
+
maxWidth: 224,
|
| 88 |
+
quality: 1,
|
| 89 |
+
})
|
| 90 |
+
.then(async (el) => await file2base64(el as File));
|
| 91 |
+
})
|
| 92 |
);
|
| 93 |
|
| 94 |
let messageToWriteToId: Message["id"] | undefined = undefined;
|
|
|
|
| 120 |
messages,
|
| 121 |
rootMessageId: data.rootMessageId,
|
| 122 |
},
|
| 123 |
+
{ from: "user", content: prompt },
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
messageId
|
| 125 |
);
|
| 126 |
messageToWriteToId = addChildren(
|
|
|
|
| 128 |
messages,
|
| 129 |
rootMessageId: data.rootMessageId,
|
| 130 |
},
|
| 131 |
+
{ from: "assistant", content: "", files: resizedImages },
|
| 132 |
newUserMessageId
|
| 133 |
);
|
| 134 |
} else if (messageToRetry?.from === "assistant") {
|
|
|
|
| 154 |
{
|
| 155 |
from: "user",
|
| 156 |
content: prompt ?? "",
|
| 157 |
+
files: resizedImages,
|
| 158 |
createdAt: new Date(),
|
| 159 |
updatedAt: new Date(),
|
| 160 |
},
|
|
|
|
| 181 |
}
|
| 182 |
|
| 183 |
messages = [...messages];
|
|
|
|
| 184 |
const messageToWriteTo = messages.find((message) => message.id === messageToWriteToId);
|
| 185 |
if (!messageToWriteTo) {
|
| 186 |
throw new Error("Message to write to not found");
|
|
|
|
| 198 |
isRetry,
|
| 199 |
isContinue,
|
| 200 |
webSearch: !hasAssistant && $webSearchParameters.useSearch,
|
| 201 |
+
files: isRetry ? undefined : resizedImages,
|
| 202 |
},
|
| 203 |
messageUpdatesAbortController.signal
|
| 204 |
).catch((err) => {
|
src/routes/conversation/[id]/+server.ts
CHANGED
|
@@ -13,13 +13,14 @@ import { runWebSearch } from "$lib/server/websearch/runWebSearch";
|
|
| 13 |
import { AbortedGenerations } from "$lib/server/abortedGenerations";
|
| 14 |
import { summarize } from "$lib/server/summarize";
|
| 15 |
import { uploadFile } from "$lib/server/files/uploadFile";
|
|
|
|
| 16 |
import type { Assistant } from "$lib/types/Assistant";
|
| 17 |
import { convertLegacyConversation } from "$lib/utils/tree/convertLegacyConversation";
|
| 18 |
import { isMessageId } from "$lib/utils/tree/isMessageId";
|
| 19 |
import { buildSubtree } from "$lib/utils/tree/buildSubtree.js";
|
| 20 |
import { addChildren } from "$lib/utils/tree/addChildren.js";
|
| 21 |
import { addSibling } from "$lib/utils/tree/addSibling.js";
|
| 22 |
-
import { preprocessMessages } from "$lib/server/
|
| 23 |
import { usageLimits } from "$lib/server/usageLimits";
|
| 24 |
import { isURLLocal } from "$lib/server/isURLLocal.js";
|
| 25 |
import { logger } from "$lib/server/logger.js";
|
|
@@ -133,7 +134,7 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 133 |
is_retry: isRetry,
|
| 134 |
is_continue: isContinue,
|
| 135 |
web_search: webSearch,
|
| 136 |
-
files:
|
| 137 |
} = z
|
| 138 |
.object({
|
| 139 |
id: z.string().uuid().refine(isMessageId).optional(), // parent message id to append to for a normal message, or the message id for a retry/continue
|
|
@@ -146,43 +147,44 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 146 |
is_retry: z.optional(z.boolean()),
|
| 147 |
is_continue: z.optional(z.boolean()),
|
| 148 |
web_search: z.optional(z.boolean()),
|
| 149 |
-
files: z.optional(
|
| 150 |
-
z.array(
|
| 151 |
-
z.object({
|
| 152 |
-
type: z.literal("base64").or(z.literal("hash")),
|
| 153 |
-
value: z.string(),
|
| 154 |
-
mime: z.string(),
|
| 155 |
-
})
|
| 156 |
-
)
|
| 157 |
-
),
|
| 158 |
})
|
| 159 |
.parse(json);
|
| 160 |
|
| 161 |
if (usageLimits?.messageLength && (newPrompt?.length ?? 0) > usageLimits.messageLength) {
|
| 162 |
throw error(400, "Message too long.");
|
| 163 |
}
|
|
|
|
|
|
|
| 164 |
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
const b64Files =
|
| 170 |
-
inputFiles
|
| 171 |
-
?.filter((file) => file.type !== "hash")
|
| 172 |
-
.map((file) => {
|
| 173 |
-
const blob = Buffer.from(file.value, "base64");
|
| 174 |
-
return new File([blob], "file", { type: file.mime });
|
| 175 |
-
}) ?? [];
|
| 176 |
|
| 177 |
// check sizes
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
}
|
| 182 |
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
)
|
|
|
|
|
|
|
| 186 |
|
| 187 |
// we will append tokens to the content of this message
|
| 188 |
let messageToWriteToId: Message["id"] | undefined = undefined;
|
|
@@ -214,13 +216,7 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 214 |
// add a children to that sibling, where we can write to
|
| 215 |
const newUserMessageId = addSibling(
|
| 216 |
conv,
|
| 217 |
-
{
|
| 218 |
-
from: "user",
|
| 219 |
-
content: newPrompt,
|
| 220 |
-
files: uploadedFiles,
|
| 221 |
-
createdAt: new Date(),
|
| 222 |
-
updatedAt: new Date(),
|
| 223 |
-
},
|
| 224 |
messageId
|
| 225 |
);
|
| 226 |
messageToWriteToId = addChildren(
|
|
@@ -228,6 +224,7 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 228 |
{
|
| 229 |
from: "assistant",
|
| 230 |
content: "",
|
|
|
|
| 231 |
createdAt: new Date(),
|
| 232 |
updatedAt: new Date(),
|
| 233 |
},
|
|
@@ -253,7 +250,7 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 253 |
{
|
| 254 |
from: "user",
|
| 255 |
content: newPrompt ?? "",
|
| 256 |
-
files:
|
| 257 |
createdAt: new Date(),
|
| 258 |
updatedAt: new Date(),
|
| 259 |
},
|
|
@@ -414,9 +411,10 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 414 |
}
|
| 415 |
|
| 416 |
// inject websearch result & optionally images into the messages
|
| 417 |
-
const processedMessages = preprocessMessages(
|
| 418 |
messagesForPrompt,
|
| 419 |
messageToWriteTo.webSearch,
|
|
|
|
| 420 |
convId
|
| 421 |
);
|
| 422 |
|
|
@@ -431,7 +429,7 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 431 |
try {
|
| 432 |
const endpoint = await model.getEndpoint();
|
| 433 |
for await (const output of await endpoint({
|
| 434 |
-
messages:
|
| 435 |
preprompt,
|
| 436 |
continueMessage: isContinue,
|
| 437 |
generateSettings: assistant?.generateSettings,
|
|
|
|
| 13 |
import { AbortedGenerations } from "$lib/server/abortedGenerations";
|
| 14 |
import { summarize } from "$lib/server/summarize";
|
| 15 |
import { uploadFile } from "$lib/server/files/uploadFile";
|
| 16 |
+
import sizeof from "image-size";
|
| 17 |
import type { Assistant } from "$lib/types/Assistant";
|
| 18 |
import { convertLegacyConversation } from "$lib/utils/tree/convertLegacyConversation";
|
| 19 |
import { isMessageId } from "$lib/utils/tree/isMessageId";
|
| 20 |
import { buildSubtree } from "$lib/utils/tree/buildSubtree.js";
|
| 21 |
import { addChildren } from "$lib/utils/tree/addChildren.js";
|
| 22 |
import { addSibling } from "$lib/utils/tree/addSibling.js";
|
| 23 |
+
import { preprocessMessages } from "$lib/server/preprocessMessages.js";
|
| 24 |
import { usageLimits } from "$lib/server/usageLimits";
|
| 25 |
import { isURLLocal } from "$lib/server/isURLLocal.js";
|
| 26 |
import { logger } from "$lib/server/logger.js";
|
|
|
|
| 134 |
is_retry: isRetry,
|
| 135 |
is_continue: isContinue,
|
| 136 |
web_search: webSearch,
|
| 137 |
+
files: b64files,
|
| 138 |
} = z
|
| 139 |
.object({
|
| 140 |
id: z.string().uuid().refine(isMessageId).optional(), // parent message id to append to for a normal message, or the message id for a retry/continue
|
|
|
|
| 147 |
is_retry: z.optional(z.boolean()),
|
| 148 |
is_continue: z.optional(z.boolean()),
|
| 149 |
web_search: z.optional(z.boolean()),
|
| 150 |
+
files: z.optional(z.array(z.string())),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
})
|
| 152 |
.parse(json);
|
| 153 |
|
| 154 |
if (usageLimits?.messageLength && (newPrompt?.length ?? 0) > usageLimits.messageLength) {
|
| 155 |
throw error(400, "Message too long.");
|
| 156 |
}
|
| 157 |
+
// files is an array of base64 strings encoding Blob objects
|
| 158 |
+
// we need to convert this array to an array of File objects
|
| 159 |
|
| 160 |
+
const files = b64files?.map((file) => {
|
| 161 |
+
const blob = Buffer.from(file, "base64");
|
| 162 |
+
return new File([blob], "image.png");
|
| 163 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
// check sizes
|
| 166 |
+
if (files) {
|
| 167 |
+
const filechecks = await Promise.all(
|
| 168 |
+
files.map(async (file) => {
|
| 169 |
+
const dimensions = sizeof(Buffer.from(await file.arrayBuffer()));
|
| 170 |
+
return (
|
| 171 |
+
file.size > 2 * 1024 * 1024 ||
|
| 172 |
+
(dimensions.width ?? 0) > 224 ||
|
| 173 |
+
(dimensions.height ?? 0) > 224
|
| 174 |
+
);
|
| 175 |
+
})
|
| 176 |
+
);
|
| 177 |
+
|
| 178 |
+
if (filechecks.some((check) => check)) {
|
| 179 |
+
throw error(413, "File too large, should be <2MB and 224x224 max.");
|
| 180 |
+
}
|
| 181 |
}
|
| 182 |
|
| 183 |
+
let hashes: undefined | string[];
|
| 184 |
+
|
| 185 |
+
if (files) {
|
| 186 |
+
hashes = await Promise.all(files.map(async (file) => await uploadFile(file, conv)));
|
| 187 |
+
}
|
| 188 |
|
| 189 |
// we will append tokens to the content of this message
|
| 190 |
let messageToWriteToId: Message["id"] | undefined = undefined;
|
|
|
|
| 216 |
// add a children to that sibling, where we can write to
|
| 217 |
const newUserMessageId = addSibling(
|
| 218 |
conv,
|
| 219 |
+
{ from: "user", content: newPrompt, createdAt: new Date(), updatedAt: new Date() },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
messageId
|
| 221 |
);
|
| 222 |
messageToWriteToId = addChildren(
|
|
|
|
| 224 |
{
|
| 225 |
from: "assistant",
|
| 226 |
content: "",
|
| 227 |
+
files: hashes,
|
| 228 |
createdAt: new Date(),
|
| 229 |
updatedAt: new Date(),
|
| 230 |
},
|
|
|
|
| 250 |
{
|
| 251 |
from: "user",
|
| 252 |
content: newPrompt ?? "",
|
| 253 |
+
files: hashes,
|
| 254 |
createdAt: new Date(),
|
| 255 |
updatedAt: new Date(),
|
| 256 |
},
|
|
|
|
| 411 |
}
|
| 412 |
|
| 413 |
// inject websearch result & optionally images into the messages
|
| 414 |
+
const processedMessages = await preprocessMessages(
|
| 415 |
messagesForPrompt,
|
| 416 |
messageToWriteTo.webSearch,
|
| 417 |
+
model.multimodal,
|
| 418 |
convId
|
| 419 |
);
|
| 420 |
|
|
|
|
| 429 |
try {
|
| 430 |
const endpoint = await model.getEndpoint();
|
| 431 |
for await (const output of await endpoint({
|
| 432 |
+
messages: processedMessages,
|
| 433 |
preprompt,
|
| 434 |
continueMessage: isContinue,
|
| 435 |
generateSettings: assistant?.generateSettings,
|
src/routes/conversation/[id]/output/[sha256]/+server.ts
CHANGED
|
@@ -39,9 +39,9 @@ export const GET: RequestHandler = async ({ locals, params }) => {
|
|
| 39 |
}
|
| 40 |
}
|
| 41 |
|
| 42 |
-
const {
|
| 43 |
|
| 44 |
-
return new Response(
|
| 45 |
headers: {
|
| 46 |
"Content-Type": mime ?? "application/octet-stream",
|
| 47 |
},
|
|
|
|
| 39 |
}
|
| 40 |
}
|
| 41 |
|
| 42 |
+
const { content, mime } = await downloadFile(sha256, params.id);
|
| 43 |
|
| 44 |
+
return new Response(content, {
|
| 45 |
headers: {
|
| 46 |
"Content-Type": mime ?? "application/octet-stream",
|
| 47 |
},
|