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 |
},
|