jbilcke-hf HF staff commited on
Commit
879455c
1 Parent(s): 274b152

update env variables

Browse files
.env CHANGED
@@ -8,47 +8,65 @@ RENDERING_ENGINE="INFERENCE_API"
8
  # Supported values:
9
  # - INFERENCE_ENDPOINT
10
  # - INFERENCE_API
 
11
  LLM_ENGINE="INFERENCE_API"
12
 
13
  # ------------- PROVIDER AUTH ------------
 
14
 
15
- # Hugging Face token, if you plan to use the Inference API or Inference Endpoint
16
- # for the LLM or SDXL generation
17
- HF_API_TOKEN=
18
 
19
- # Replicate token, if you wish to use them as a provider for SDXL
20
- REPLICATE_API_TOKEN=
21
 
22
- # OpenAI is not supported yet
23
- OPENAI_TOKEN=
24
 
25
- # VideoChain is a custom API used for SDXL but you don't need it for the base features
26
- VIDEOCHAIN_API_TOKEN=
27
 
28
  # ------------- RENDERING API CONFIG --------------
29
 
30
- RENDERING_VIDEOCHAIN_API_URL="http://localhost:7860"
31
-
32
  RENDERING_REPLICATE_API_MODEL="stabilityai/sdxl"
33
  RENDERING_REPLICATE_API_MODEL_VERSION="da77bc59ee60423279fd632efb4795ab731d9e3ca9705ef3341091fb989b7eaf"
34
 
35
- RENDERING_HF_INFERENCE_ENDPOINT_URL="https://XXXXXXXXXX.endpoints.huggingface.cloud"
36
- RENDERING_HF_INFERENCE_API_MODEL="stabilityai/stable-diffusion-xl-base-1.0"
 
 
 
 
 
 
37
 
38
  # ------------- LLM API CONFIG ----------------
39
 
40
- # URL to a custom text-generation Inference Endpoint of your choice
41
- # -> You can leave it empty if you decide to use an Inference API Model instead
42
- LLM_HF_INFERENCE_ENDPOINT_URL=
43
 
44
- # You can also use a model from the Inference API (not a custom inference endpoint)
45
- # -> You can leave it empty if you decide to use an Inference Endpoint URL instead
 
 
46
  LLM_HF_INFERENCE_API_MODEL="codellama/CodeLlama-7b-hf"
47
 
48
  # ----------- COMMUNITY SHARING (OPTIONAL) -----------
49
- NEXT_PUBLIC_ENABLE_COMMUNITY_SHARING="false"
50
  # You don't need those community sharing options to run the AI Comic Factory
51
  # locally or on your own server (they are meant to be used by the Hugging Face team)
 
52
  COMMUNITY_API_URL=
53
  COMMUNITY_API_TOKEN=
54
  COMMUNITY_API_ID=
 
 
 
 
 
 
 
 
 
 
 
8
  # Supported values:
9
  # - INFERENCE_ENDPOINT
10
  # - INFERENCE_API
11
+ # - OPENAI
12
  LLM_ENGINE="INFERENCE_API"
13
 
14
  # ------------- PROVIDER AUTH ------------
15
+ # You only need to configure the access token(s) for the provider(s) you want to use
16
 
17
+ # HuggingFace.co token: available for the LLM engine and the RENDERING engine
18
+ AUTH_HF_API_TOKEN=
 
19
 
20
+ # Replicate.com token: available for the RENDERING engine
21
+ AUTH_REPLICATE_API_TOKEN=
22
 
23
+ # OpenAI.dom token: available for the LLM engine and the RENDERING engine
24
+ AUTH_OPENAI_TOKEN=
25
 
26
+ # An experimental RENDERING engine (sorry it is not very documented yet, so you can use one of the other engines)
27
+ AUTH_VIDEOCHAIN_API_TOKEN=
28
 
29
  # ------------- RENDERING API CONFIG --------------
30
 
31
+ # If you decided to use Replicate for the RENDERING engine
 
32
  RENDERING_REPLICATE_API_MODEL="stabilityai/sdxl"
33
  RENDERING_REPLICATE_API_MODEL_VERSION="da77bc59ee60423279fd632efb4795ab731d9e3ca9705ef3341091fb989b7eaf"
34
 
35
+ # If you decided to use a private Hugging Face Inference Endpoint for the RENDERING engine
36
+ RENDERING_HF_RENDERING_INFERENCE_ENDPOINT_URL="https://XXXXXXXXXX.endpoints.huggingface.cloud"
37
+
38
+ # If you decided to use a Hugging Face Inference API model for the RENDERING engine
39
+ RENDERING_HF_RENDERING_INFERENCE_API_MODEL="stabilityai/stable-diffusion-xl-base-1.0"
40
+
41
+ # An experimental RENDERING engine (sorry it is not very documented yet, so you can use one of the other engines)
42
+ RENDERING_VIDEOCHAIN_API_URL="http://localhost:7860"
43
 
44
  # ------------- LLM API CONFIG ----------------
45
 
46
+ # If you decided to use OpenAI for the LLM engine
47
+ LLM_OPENAI_API_BASE_URL="https://api.openai.com/v1"
48
+ LLM_OPENAI_API_MODEL="gpt-3.5-turbo"
49
 
50
+ # If you decided to use a private Hugging Face Inference Endpoint for the LLM engine
51
+ LLM_HF_INFERENCE_ENDPOINT_URL=""
52
+
53
+ # If you decided to use a Hugging Face Inference API model for the LLM engine
54
  LLM_HF_INFERENCE_API_MODEL="codellama/CodeLlama-7b-hf"
55
 
56
  # ----------- COMMUNITY SHARING (OPTIONAL) -----------
 
57
  # You don't need those community sharing options to run the AI Comic Factory
58
  # locally or on your own server (they are meant to be used by the Hugging Face team)
59
+ NEXT_PUBLIC_ENABLE_COMMUNITY_SHARING="false"
60
  COMMUNITY_API_URL=
61
  COMMUNITY_API_TOKEN=
62
  COMMUNITY_API_ID=
63
+
64
+ # ----------- CENSORSHIP (OPTIONAL) -----------
65
+ # censorship is currently disabled, but will be required when we create a "community roll"
66
+ # (a public repositoruy of user-generated comic strips)
67
+ ENABLE_CENSORSHIP="false"
68
+
69
+ # Due to the sensitive nature of some of keywords we want to ban (users try all kind of crazy illegal things)
70
+ # the words are are not put in clear in the source code, but behind an encryption key
71
+ # (I don't want the project to be flagged by an AI robot police on GitHub or something)
72
+ SECRET_FINGERPRINT=""
CONTRIBUTORS.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ This project was developed Julian Bilcke (@jbilcke-hf), as part of his work at Hugging Face.
2
+
3
+ ------------------------------------------
4
+
5
+ A huge thanks to external developers for their contributions!
6
+
7
+ 艾逗笔 (@idoubi):
8
+ - Added support for OpenAI: https://github.com/jbilcke-hf/ai-comic-factory/pull/6
9
+
README.md CHANGED
@@ -20,13 +20,14 @@ it requires various components to run for the frontend, backend, LLM, SDXL etc.
20
  If you try to duplicate the project, open the `.env` you will see it requires some variables.
21
 
22
  Provider config:
23
- - `LLM_ENGINE`: can be either "INFERENCE_API" or "INFERENCE_ENDPOINT"
24
- - `RENDERING_ENGINE`: can only be "VIDEOCHAIN" or "REPLICATE" for now, unless you code your custom solution
25
 
26
  Auth config:
27
- - `HF_API_TOKEN`: necessary if you decide to use an inference api model or a custom inference endpoint
28
- - `VIDEOCHAIN_API_TOKEN`: secret token to access the VideoChain API server
29
- - `REPLICATE_API_TOKEN`: in case you want to use Replicate.com
 
30
 
31
  Rendering config:
32
  - `RENDERING_HF_INFERENCE_ENDPOINT_URL`: necessary if you decide to use a custom inference endpoint
 
20
  If you try to duplicate the project, open the `.env` you will see it requires some variables.
21
 
22
  Provider config:
23
+ - `LLM_ENGINE`: can be one of: "INFERENCE_API", "INFERENCE_ENDPOINT", "OPENAI"
24
+ - `RENDERING_ENGINE`: can be one of: "INFERENCE_API", "INFERENCE_ENDPOINT", "REPLICATE", "VIDEOCHAIN" for now, unless you code your custom solution
25
 
26
  Auth config:
27
+ - `AUTH_HF_API_TOKEN`: only if you decide to use OpenAI for the LLM engine necessary if you decide to use an inference api model or a custom inference endpoint
28
+ - `AUTH_OPENAI_TOKEN`: only if you decide to use OpenAI for the LLM engine
29
+ - `AITH_VIDEOCHAIN_API_TOKEN`: secret token to access the VideoChain API server
30
+ - `AUTH_REPLICATE_API_TOKEN`: in case you want to use Replicate.com
31
 
32
  Rendering config:
33
  - `RENDERING_HF_INFERENCE_ENDPOINT_URL`: necessary if you decide to use a custom inference endpoint
package-lock.json CHANGED
@@ -37,11 +37,13 @@
37
  "cmdk": "^0.2.0",
38
  "cookies-next": "^2.1.2",
39
  "date-fns": "^2.30.0",
 
40
  "eslint": "8.45.0",
41
  "eslint-config-next": "13.4.10",
42
  "html2canvas": "^1.4.1",
43
  "lucide-react": "^0.260.0",
44
  "next": "13.4.10",
 
45
  "pick": "^0.0.1",
46
  "postcss": "8.4.26",
47
  "react": "18.2.0",
@@ -3691,6 +3693,15 @@
3691
  "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
3692
  "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw=="
3693
  },
 
 
 
 
 
 
 
 
 
3694
  "node_modules/@types/prop-types": {
3695
  "version": "15.7.5",
3696
  "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@@ -3847,6 +3858,17 @@
3847
  "url": "https://opencollective.com/typescript-eslint"
3848
  }
3849
  },
 
 
 
 
 
 
 
 
 
 
 
3850
  "node_modules/abs-svg-path": {
3851
  "version": "0.1.1",
3852
  "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz",
@@ -3879,6 +3901,17 @@
3879
  "node": ">=0.4.0"
3880
  }
3881
  },
 
 
 
 
 
 
 
 
 
 
 
3882
  "node_modules/ajv": {
3883
  "version": "6.12.6",
3884
  "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -4096,6 +4129,11 @@
4096
  "has-symbols": "^1.0.3"
4097
  }
4098
  },
 
 
 
 
 
4099
  "node_modules/autoprefixer": {
4100
  "version": "10.4.14",
4101
  "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
@@ -4209,6 +4247,11 @@
4209
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
4210
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
4211
  },
 
 
 
 
 
4212
  "node_modules/base64-arraybuffer": {
4213
  "version": "1.0.2",
4214
  "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
@@ -4430,6 +4473,14 @@
4430
  "url": "https://github.com/chalk/chalk?sponsor=1"
4431
  }
4432
  },
 
 
 
 
 
 
 
 
4433
  "node_modules/chokidar": {
4434
  "version": "3.5.3",
4435
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -4795,6 +4846,17 @@
4795
  "simple-swizzle": "^0.2.2"
4796
  }
4797
  },
 
 
 
 
 
 
 
 
 
 
 
4798
  "node_modules/command-score": {
4799
  "version": "0.1.2",
4800
  "resolved": "https://registry.npmjs.org/command-score/-/command-score-0.1.2.tgz",
@@ -4879,6 +4941,14 @@
4879
  "node": ">= 8"
4880
  }
4881
  },
 
 
 
 
 
 
 
 
4882
  "node_modules/crypto-js": {
4883
  "version": "4.1.1",
4884
  "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
@@ -5012,6 +5082,14 @@
5012
  "url": "https://github.com/sponsors/ljharb"
5013
  }
5014
  },
 
 
 
 
 
 
 
 
5015
  "node_modules/dequal": {
5016
  "version": "2.0.3",
5017
  "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -5051,6 +5129,15 @@
5051
  "node": ">=0.3.1"
5052
  }
5053
  },
 
 
 
 
 
 
 
 
 
5054
  "node_modules/dir-glob": {
5055
  "version": "3.0.1",
5056
  "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -5139,6 +5226,14 @@
5139
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz",
5140
  "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA=="
5141
  },
 
 
 
 
 
 
 
 
5142
  "node_modules/end-of-stream": {
5143
  "version": "1.4.4",
5144
  "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -5697,6 +5792,14 @@
5697
  "node": ">=0.10.0"
5698
  }
5699
  },
 
 
 
 
 
 
 
 
5700
  "node_modules/events": {
5701
  "version": "3.3.0",
5702
  "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@@ -5846,6 +5949,36 @@
5846
  "is-callable": "^1.1.3"
5847
  }
5848
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5849
  "node_modules/fraction.js": {
5850
  "version": "4.2.1",
5851
  "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz",
@@ -6197,11 +6330,30 @@
6197
  "entities": "^4.4.0"
6198
  }
6199
  },
 
 
 
 
 
 
 
 
6200
  "node_modules/hyphen": {
6201
  "version": "1.6.6",
6202
  "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.6.6.tgz",
6203
  "integrity": "sha512-XtqmnT+b9n5MX+MsqluFAVTIenbtC25iskW0Z+jLd+awfhA+ZbWKWQMIvLJccGoa2bM1R6juWJ27cZxIFOmkWw=="
6204
  },
 
 
 
 
 
 
 
 
 
 
 
6205
  "node_modules/idb-keyval": {
6206
  "version": "6.2.1",
6207
  "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
@@ -6366,6 +6518,11 @@
6366
  "url": "https://github.com/sponsors/ljharb"
6367
  }
6368
  },
 
 
 
 
 
6369
  "node_modules/is-callable": {
6370
  "version": "1.2.7",
6371
  "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -6851,6 +7008,16 @@
6851
  "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
6852
  "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
6853
  },
 
 
 
 
 
 
 
 
 
 
6854
  "node_modules/media-engine": {
6855
  "version": "1.0.3",
6856
  "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz",
@@ -6876,6 +7043,25 @@
6876
  "node": ">=8.6"
6877
  }
6878
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6879
  "node_modules/mimic-response": {
6880
  "version": "3.1.0",
6881
  "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
@@ -7050,6 +7236,24 @@
7050
  "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
7051
  "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
7052
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7053
  "node_modules/node-fetch": {
7054
  "version": "2.7.0",
7055
  "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@@ -7223,6 +7427,29 @@
7223
  "wrappy": "1"
7224
  }
7225
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7226
  "node_modules/opencollective-postinstall": {
7227
  "version": "2.0.3",
7228
  "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
@@ -8043,6 +8270,11 @@
8043
  "url": "https://github.com/sponsors/ljharb"
8044
  }
8045
  },
 
 
 
 
 
8046
  "node_modules/sanitize-html": {
8047
  "version": "2.11.0",
8048
  "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
@@ -9067,6 +9299,14 @@
9067
  "node": ">=10.13.0"
9068
  }
9069
  },
 
 
 
 
 
 
 
 
9070
  "node_modules/webidl-conversions": {
9071
  "version": "3.0.1",
9072
  "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
 
37
  "cmdk": "^0.2.0",
38
  "cookies-next": "^2.1.2",
39
  "date-fns": "^2.30.0",
40
+ "encoding": "^0.1.13",
41
  "eslint": "8.45.0",
42
  "eslint-config-next": "13.4.10",
43
  "html2canvas": "^1.4.1",
44
  "lucide-react": "^0.260.0",
45
  "next": "13.4.10",
46
+ "openai": "^4.10.0",
47
  "pick": "^0.0.1",
48
  "postcss": "8.4.26",
49
  "react": "18.2.0",
 
3693
  "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
3694
  "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw=="
3695
  },
3696
+ "node_modules/@types/node-fetch": {
3697
+ "version": "2.6.6",
3698
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz",
3699
+ "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==",
3700
+ "dependencies": {
3701
+ "@types/node": "*",
3702
+ "form-data": "^4.0.0"
3703
+ }
3704
+ },
3705
  "node_modules/@types/prop-types": {
3706
  "version": "15.7.5",
3707
  "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
 
3858
  "url": "https://opencollective.com/typescript-eslint"
3859
  }
3860
  },
3861
+ "node_modules/abort-controller": {
3862
+ "version": "3.0.0",
3863
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
3864
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
3865
+ "dependencies": {
3866
+ "event-target-shim": "^5.0.0"
3867
+ },
3868
+ "engines": {
3869
+ "node": ">=6.5"
3870
+ }
3871
+ },
3872
  "node_modules/abs-svg-path": {
3873
  "version": "0.1.1",
3874
  "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz",
 
3901
  "node": ">=0.4.0"
3902
  }
3903
  },
3904
+ "node_modules/agentkeepalive": {
3905
+ "version": "4.5.0",
3906
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
3907
+ "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
3908
+ "dependencies": {
3909
+ "humanize-ms": "^1.2.1"
3910
+ },
3911
+ "engines": {
3912
+ "node": ">= 8.0.0"
3913
+ }
3914
+ },
3915
  "node_modules/ajv": {
3916
  "version": "6.12.6",
3917
  "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
 
4129
  "has-symbols": "^1.0.3"
4130
  }
4131
  },
4132
+ "node_modules/asynckit": {
4133
+ "version": "0.4.0",
4134
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
4135
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
4136
+ },
4137
  "node_modules/autoprefixer": {
4138
  "version": "10.4.14",
4139
  "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
 
4247
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
4248
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
4249
  },
4250
+ "node_modules/base-64": {
4251
+ "version": "0.1.0",
4252
+ "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
4253
+ "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
4254
+ },
4255
  "node_modules/base64-arraybuffer": {
4256
  "version": "1.0.2",
4257
  "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
 
4473
  "url": "https://github.com/chalk/chalk?sponsor=1"
4474
  }
4475
  },
4476
+ "node_modules/charenc": {
4477
+ "version": "0.0.2",
4478
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
4479
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
4480
+ "engines": {
4481
+ "node": "*"
4482
+ }
4483
+ },
4484
  "node_modules/chokidar": {
4485
  "version": "3.5.3",
4486
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
 
4846
  "simple-swizzle": "^0.2.2"
4847
  }
4848
  },
4849
+ "node_modules/combined-stream": {
4850
+ "version": "1.0.8",
4851
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
4852
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
4853
+ "dependencies": {
4854
+ "delayed-stream": "~1.0.0"
4855
+ },
4856
+ "engines": {
4857
+ "node": ">= 0.8"
4858
+ }
4859
+ },
4860
  "node_modules/command-score": {
4861
  "version": "0.1.2",
4862
  "resolved": "https://registry.npmjs.org/command-score/-/command-score-0.1.2.tgz",
 
4941
  "node": ">= 8"
4942
  }
4943
  },
4944
+ "node_modules/crypt": {
4945
+ "version": "0.0.2",
4946
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
4947
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
4948
+ "engines": {
4949
+ "node": "*"
4950
+ }
4951
+ },
4952
  "node_modules/crypto-js": {
4953
  "version": "4.1.1",
4954
  "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
 
5082
  "url": "https://github.com/sponsors/ljharb"
5083
  }
5084
  },
5085
+ "node_modules/delayed-stream": {
5086
+ "version": "1.0.0",
5087
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
5088
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
5089
+ "engines": {
5090
+ "node": ">=0.4.0"
5091
+ }
5092
+ },
5093
  "node_modules/dequal": {
5094
  "version": "2.0.3",
5095
  "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
 
5129
  "node": ">=0.3.1"
5130
  }
5131
  },
5132
+ "node_modules/digest-fetch": {
5133
+ "version": "1.3.0",
5134
+ "resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz",
5135
+ "integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==",
5136
+ "dependencies": {
5137
+ "base-64": "^0.1.0",
5138
+ "md5": "^2.3.0"
5139
+ }
5140
+ },
5141
  "node_modules/dir-glob": {
5142
  "version": "3.0.1",
5143
  "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
 
5226
  "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz",
5227
  "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA=="
5228
  },
5229
+ "node_modules/encoding": {
5230
+ "version": "0.1.13",
5231
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
5232
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
5233
+ "dependencies": {
5234
+ "iconv-lite": "^0.6.2"
5235
+ }
5236
+ },
5237
  "node_modules/end-of-stream": {
5238
  "version": "1.4.4",
5239
  "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
 
5792
  "node": ">=0.10.0"
5793
  }
5794
  },
5795
+ "node_modules/event-target-shim": {
5796
+ "version": "5.0.1",
5797
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
5798
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
5799
+ "engines": {
5800
+ "node": ">=6"
5801
+ }
5802
+ },
5803
  "node_modules/events": {
5804
  "version": "3.3.0",
5805
  "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
 
5949
  "is-callable": "^1.1.3"
5950
  }
5951
  },
5952
+ "node_modules/form-data": {
5953
+ "version": "4.0.0",
5954
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
5955
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
5956
+ "dependencies": {
5957
+ "asynckit": "^0.4.0",
5958
+ "combined-stream": "^1.0.8",
5959
+ "mime-types": "^2.1.12"
5960
+ },
5961
+ "engines": {
5962
+ "node": ">= 6"
5963
+ }
5964
+ },
5965
+ "node_modules/form-data-encoder": {
5966
+ "version": "1.7.2",
5967
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
5968
+ "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
5969
+ },
5970
+ "node_modules/formdata-node": {
5971
+ "version": "4.4.1",
5972
+ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
5973
+ "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
5974
+ "dependencies": {
5975
+ "node-domexception": "1.0.0",
5976
+ "web-streams-polyfill": "4.0.0-beta.3"
5977
+ },
5978
+ "engines": {
5979
+ "node": ">= 12.20"
5980
+ }
5981
+ },
5982
  "node_modules/fraction.js": {
5983
  "version": "4.2.1",
5984
  "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz",
 
6330
  "entities": "^4.4.0"
6331
  }
6332
  },
6333
+ "node_modules/humanize-ms": {
6334
+ "version": "1.2.1",
6335
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
6336
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
6337
+ "dependencies": {
6338
+ "ms": "^2.0.0"
6339
+ }
6340
+ },
6341
  "node_modules/hyphen": {
6342
  "version": "1.6.6",
6343
  "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.6.6.tgz",
6344
  "integrity": "sha512-XtqmnT+b9n5MX+MsqluFAVTIenbtC25iskW0Z+jLd+awfhA+ZbWKWQMIvLJccGoa2bM1R6juWJ27cZxIFOmkWw=="
6345
  },
6346
+ "node_modules/iconv-lite": {
6347
+ "version": "0.6.3",
6348
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
6349
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
6350
+ "dependencies": {
6351
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
6352
+ },
6353
+ "engines": {
6354
+ "node": ">=0.10.0"
6355
+ }
6356
+ },
6357
  "node_modules/idb-keyval": {
6358
  "version": "6.2.1",
6359
  "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
 
6518
  "url": "https://github.com/sponsors/ljharb"
6519
  }
6520
  },
6521
+ "node_modules/is-buffer": {
6522
+ "version": "1.1.6",
6523
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
6524
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
6525
+ },
6526
  "node_modules/is-callable": {
6527
  "version": "1.2.7",
6528
  "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
 
7008
  "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
7009
  "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
7010
  },
7011
+ "node_modules/md5": {
7012
+ "version": "2.3.0",
7013
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
7014
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
7015
+ "dependencies": {
7016
+ "charenc": "0.0.2",
7017
+ "crypt": "0.0.2",
7018
+ "is-buffer": "~1.1.6"
7019
+ }
7020
+ },
7021
  "node_modules/media-engine": {
7022
  "version": "1.0.3",
7023
  "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz",
 
7043
  "node": ">=8.6"
7044
  }
7045
  },
7046
+ "node_modules/mime-db": {
7047
+ "version": "1.52.0",
7048
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
7049
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
7050
+ "engines": {
7051
+ "node": ">= 0.6"
7052
+ }
7053
+ },
7054
+ "node_modules/mime-types": {
7055
+ "version": "2.1.35",
7056
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
7057
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
7058
+ "dependencies": {
7059
+ "mime-db": "1.52.0"
7060
+ },
7061
+ "engines": {
7062
+ "node": ">= 0.6"
7063
+ }
7064
+ },
7065
  "node_modules/mimic-response": {
7066
  "version": "3.1.0",
7067
  "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
 
7236
  "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
7237
  "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
7238
  },
7239
+ "node_modules/node-domexception": {
7240
+ "version": "1.0.0",
7241
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
7242
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
7243
+ "funding": [
7244
+ {
7245
+ "type": "github",
7246
+ "url": "https://github.com/sponsors/jimmywarting"
7247
+ },
7248
+ {
7249
+ "type": "github",
7250
+ "url": "https://paypal.me/jimmywarting"
7251
+ }
7252
+ ],
7253
+ "engines": {
7254
+ "node": ">=10.5.0"
7255
+ }
7256
+ },
7257
  "node_modules/node-fetch": {
7258
  "version": "2.7.0",
7259
  "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
 
7427
  "wrappy": "1"
7428
  }
7429
  },
7430
+ "node_modules/openai": {
7431
+ "version": "4.10.0",
7432
+ "resolved": "https://registry.npmjs.org/openai/-/openai-4.10.0.tgz",
7433
+ "integrity": "sha512-II4b5/7qzwYkqA9MSjgqdofCc798EW+dtF2h6qNaVLet+qO7FShAJTWnoyzb50J4ZH1rPxRFAsmDLIhY3PT6DQ==",
7434
+ "dependencies": {
7435
+ "@types/node": "^18.11.18",
7436
+ "@types/node-fetch": "^2.6.4",
7437
+ "abort-controller": "^3.0.0",
7438
+ "agentkeepalive": "^4.2.1",
7439
+ "digest-fetch": "^1.3.0",
7440
+ "form-data-encoder": "1.7.2",
7441
+ "formdata-node": "^4.3.2",
7442
+ "node-fetch": "^2.6.7"
7443
+ },
7444
+ "bin": {
7445
+ "openai": "bin/cli"
7446
+ }
7447
+ },
7448
+ "node_modules/openai/node_modules/@types/node": {
7449
+ "version": "18.17.19",
7450
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.19.tgz",
7451
+ "integrity": "sha512-+pMhShR3Or5GR0/sp4Da7FnhVmTalWm81M6MkEldbwjETSaPalw138Z4KdpQaistvqQxLB7Cy4xwYdxpbSOs9Q=="
7452
+ },
7453
  "node_modules/opencollective-postinstall": {
7454
  "version": "2.0.3",
7455
  "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
 
8270
  "url": "https://github.com/sponsors/ljharb"
8271
  }
8272
  },
8273
+ "node_modules/safer-buffer": {
8274
+ "version": "2.1.2",
8275
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
8276
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
8277
+ },
8278
  "node_modules/sanitize-html": {
8279
  "version": "2.11.0",
8280
  "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
 
9299
  "node": ">=10.13.0"
9300
  }
9301
  },
9302
+ "node_modules/web-streams-polyfill": {
9303
+ "version": "4.0.0-beta.3",
9304
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
9305
+ "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
9306
+ "engines": {
9307
+ "node": ">= 14"
9308
+ }
9309
+ },
9310
  "node_modules/webidl-conversions": {
9311
  "version": "3.0.1",
9312
  "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
package.json CHANGED
@@ -38,6 +38,7 @@
38
  "cmdk": "^0.2.0",
39
  "cookies-next": "^2.1.2",
40
  "date-fns": "^2.30.0",
 
41
  "eslint": "8.45.0",
42
  "eslint-config-next": "13.4.10",
43
  "html2canvas": "^1.4.1",
 
38
  "cmdk": "^0.2.0",
39
  "cookies-next": "^2.1.2",
40
  "date-fns": "^2.30.0",
41
+ "encoding": "^0.1.13",
42
  "eslint": "8.45.0",
43
  "eslint-config-next": "13.4.10",
44
  "html2canvas": "^1.4.1",
src/app/engine/caption.ts CHANGED
@@ -33,7 +33,7 @@ export async function see({
33
  headers: {
34
  Accept: "application/json",
35
  "Content-Type": "application/json",
36
- // Authorization: `Bearer ${process.env.VIDEOCHAIN_API_TOKEN}`,
37
  },
38
  body: JSON.stringify(request),
39
  cache: 'no-store',
 
33
  headers: {
34
  Accept: "application/json",
35
  "Content-Type": "application/json",
36
+ // Authorization: `Bearer ${videochainApi}`,
37
  },
38
  body: JSON.stringify(request),
39
  cache: 'no-store',
src/app/engine/censorship.ts CHANGED
@@ -1,39 +1,184 @@
1
 
2
-
3
- // unfortunately due to abuse by some users, I have to add this NSFW filter
4
- const secretSalt = `${process.env.SECRET_CENSORSHIP_KEY || ""}`
5
-
6
- // TODO the censorship is not implement yet actually
7
-
8
  // I don't want to be banned by Replicate because bad actors are asking
9
  // for some naked anime stuff or whatever
10
  // I also want to avoid a PR scandal due to some bad user generated content
11
 
12
- const forbiddenWords = [
13
- // those keywords have been generated by looking at the logs of the AI Comic Factory
14
- // those are real requests some users tried to attempt.. :|
15
- "nazi",
16
- "hitler",
17
- "boob",
18
- "boobs",
19
- "boobies",
20
- "nipple",
21
- "nipples",
22
- "nude",
23
- "nudes",
24
- "naked",
25
- "pee",
26
- "peeing",
27
- "erotic",
28
- "sexy"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  ]
30
 
31
- // temporary utility to make sure Replicate doesn't ban my account
32
- // because of what users do in their prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  export const filterOutBadWords = (sentence: string) => {
34
- const words = sentence.split(" ")
35
- return words.filter(word => {
36
- const lowerCase = word.toLocaleLowerCase()
37
- return !forbiddenWords.includes(lowerCase)
38
- }).join(" ")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
 
1
 
 
 
 
 
 
 
2
  // I don't want to be banned by Replicate because bad actors are asking
3
  // for some naked anime stuff or whatever
4
  // I also want to avoid a PR scandal due to some bad user generated content
5
 
6
+ import { computeSecretFingerprint } from "@/lib/computeSecretFingerprint"
7
+
8
+ // those keywords have been generated by looking at the logs of the panorama and the AI Comic Factory
9
+ // those are real requests some users tried to attempt.. :|
10
+
11
+ const chickens = [
12
+ "fcb4dacbd99b21368c50f29c1d47071c87cf2225ab9192282c785460391cd365",
13
+ "68840b60ac27eacaa7afe17e898d3c4a2dc71acff8c74d6782c1bcaafd14963d",
14
+ "67f745224fd6e1a7a3a244514d5807fcc994cbb62ca4ec8fa44cd14244a515ae",
15
+ "681fea565117808c6dbe002520d2cfeeb3e5c67e68630afb4a453449a9da587b",
16
+ "2f3d913b3db9e15a930aac43eb2d6fe8817db8e4bcf37794bf0227b06b718d1b",
17
+ "922a700b807e4994df82eba2b48a6ac131fe8d8d1035d06b3592d622fb232161",
18
+ "cb69ee6774eafcc720adb1f689d28acbb9f47998cbea0299ec66a58dedf91c37"
19
+ ]
20
+
21
+ const ducks = [
22
+ "1c52cb20c0cbc76349fa63232b982bd394cf0850ebc17240dcf33c19fb15a26d",
23
+ "e1d4de9b8d464d7da07c276b63a42c1c9922224f0a6cab6b0826427ce4a7461a",
24
+ "0be3174bfb1a48a65875c2f035b1ae14fbc8f232f55785018de0cfe2132fa952",
25
+ "0f174769641b2e5d2c79b5a83e8ef91e004f6f3e62531cd70cfdff02159268cb",
26
+ "e9fb8ae8ff720acd91025229478a21e43e8e976e30119a76c293201adf572736",
27
+ "f65a0dc0e07b5d084ff24c69dcdb953f7b57101d2ebb716d4dfb5963076ef807",
28
+ "2bf38af1646489c2c086f811d082054cd29e23fa7bb5c525396bec01b3ab688e"
29
+ ]
30
+
31
+ const cats = [
32
+ "fcffc3e997d952007d1b902a9cf40b750ba4a410ac65bfd95475996bf51359e4",
33
+ "3172a5fa159754d703489dfba5af520b8ace107cdf170f4c4cb38a6797aa163f",
34
+ "500012dbff4498a9c4513369d6b9b373fab9330ffd2cb1e622294043cc21b610",
35
+ "84e3a8d34ee7d0c8e7a2926dd1acad46a0b66b9d27725b3a7e5053550f490301"
36
+ ]
37
+
38
+ const roasted = [
39
+ "a2bfbce0046c9a52a0eabf98f73e0f8e09959970431fc892ebdb4e1c97031b50",
40
+ "6eca1adf06851f99e9cdfbb496c27d46ff81106903d11f3346a146e96082b016",
41
+ "49a124c9ed6fbbad4105b3657dc25de369bcafb9d6787f610c08f584cd607d0f",
42
+ "c3afb59420c812cbc7c8f57ad3e8d79407f10106a99f829aa65316c99d0b29c4",
43
+ "2b808858836a5c205080f5b93201ef92e098cff931d8de6d9f20dc722997d077",
44
+ "07bef89d1a7d63c9c5ed64ba0f73d6cff689811847c2e20c8b3fbfb060e1d64e",
45
+ "baeb994922d5473f534aa54322d83effe74c6c4dac807e6b523a677d7acdc17b",
46
+ "ea4735a879edd5cc94ca7db26edd5a970df69a41f0009d3444486647e44175af",
47
+ "f2412249030454cd13ac6f7965871d924c16daacda0123de81892adb19ce49ac",
48
+ "9958c56e12bab8549cf752bcd8bec4ac36cf79c404b1faf5611f057bb71bc0e1",
49
+ "76cdade0b3d4caf0888f60318a5cbca00f830a3b0bf37735fc64fdaeb67c34d3",
50
+ "1bf53c97869e1ea89bda19da64a9173d48fe4ec823e949e2c898f8abb3fbf457",
51
+ "1bf53c97869e1ea89bda19da64a9173d48fe4ec823e949e2c898f8abb3fbf457",
52
+ "3d7f973fab8f4a19c0a3e59efe970ed7bd55a1cb795752d9cbe3c19e8a7d81ec"
53
  ]
54
 
55
+ const banned = [
56
+ "8a05d4869d9d6ce388c6cd2db13ca12b88097b90f9be027d5ffaaa467c7a6e5e",
57
+ "0c475212a608138244c5fc150b1563e5ef79c516234fd78dcd5993f726c359a0",
58
+ "df17388805f99f2ff3e5ae97a0f55e5c927eb47f17ca65822bf8c88f02bac3dd",
59
+ "86c3355d1bd581cdf7306729d8dd0ee9b7a317b9cfd6d7a6f5fad9c0dafe2167",
60
+ "23a2484cd420c9ffbfcc2c0075a9b330664450ced1fc64ab6a65e278086b8c6e",
61
+ "fb4cabe709b62eea1b4cc0030c76f5e4a43ee677ce19124e8e7bafa86c78ab66",
62
+ "d99c26daee85f7dc81c46c061a5874cff7179ed72d884d2316d664d36ffe7ab5",
63
+ "b93c38af5aa221d76c60ee3eb762efee0cdb0daf29ceb235b7dda6d46c06490d",
64
+ "8cf6c8765dc757319461dd9a785e77c201b8e5a604d36b817cd987c6a5e62500",
65
+ "f4a1cb290745717f86c3cee30fc324c0d80a9945fcbc7bbeb010579f58792f1e",
66
+ "7c87c47c42fc983119551342be9ddd5b32e530c0504ccdbbaa1e12b1d9f1bbcb",
67
+ "d04fad4f21d030da7a1301afbf480ef6246eb7bbf0f26e31865b2e015a25f747",
68
+ "d685ff22fb9da01ee949db212770729603989850864ef7a7085e1f086cfa7deb",
69
+ "533b90588d9ccf7967da54691f575e9fd4926c6e0b5fd94a47b932bcea270bee",
70
+ "9c2d61f28f5bb7f3f1dc9122be64cda8a428b46ce68b70120da4c41dba96ba4c",
71
+ "5d4b1a3eebe64dfa631d0e3b084bd96ee9364c3669269f838ca17a4900276264",
72
+ "d56f56413b9679fc0820a2c0237224ded8554c61fab8959c174123c8b68ba029",
73
+ "323a9ab60739726070d615ff3a05d7ff6bb6e3c4dd9ff16ce24f253ecd7b8851",
74
+ "975c6739de7d4999db15972f707f5f4e95649275f1c0c48e895b8c537e8638ec",
75
+ "67ee26eb9e1c1c7124797321b02bca90a19c18171782917cd4a487b722484dce",
76
+ "6df5aa7b72a4e6e3fb726489ff1437daa5752047507f4da912680b1d6647c7d6",
77
+ "b0864805364359e8c5810c233b1bf2c74dedce9055ae5f7680ba05b4e39db8e2",
78
+ "a8f841472ecffdd6266151148320c8e36847a24ead9d3338e0313b075c16649d",
79
+ "f9b127cd90e85b0ff68dd220361671663f0154b2b827f1f7ea797b020ca0018c",
80
+ "d5c20e9a1ecf01c82da24c514d867498b3e5f522adc1523ce29404a6563641d5",
81
+ "241022b49d7c0aba24a61eea1137a804f36e4bcb47af42950275baac9b4e7aac",
82
+ "fc99a70e17b6c86ef1b537654b0f50353567a7b59912c3ba955f3fca4d1ea696",
83
+ "255306e968009003d295cb2a7256f27bfcdb5d1743bf4d9f2aa4b8adf1a7734d",
84
+ "048c7b709763dd9c43794d241c369f0abcb079d546ddcbbba9968a1ed1da7ed7",
85
+ "520cbfeef3e4c405d79478eedccb97a4d476be585626dd2b1c53292797491bc7",
86
+ "f9f28a7ae7e8b1719b350a04dc087a4b8e33478d109ceeef6ba892b32d1105c9",
87
+ "d177f1bfe603647ef4c1c0e6f1a7172081fb9bbc2ea859705949f2c5aa5d4f22",
88
+ "302feef2c09247fbd23789581f7f5e2219f88ae0a937880954938573c2a52a84",
89
+ "99edd6f57b864873835f16f19c805dd94bed9da8967b84e3a62782f106d9ebcc",
90
+ "e75e5f01dcd8351c9553e89558085bd68e6feb295dee5d8da0c9b43ee303ce36",
91
+ "135e52a026aea9d2e12de358a85e05cf21121a18269269b7c62678c3bc846f5b",
92
+ "28e5b2d3eb5f1ef4cc7b570878b03acf303a6ca4ca95893591e0fb943b0beab0",
93
+ "a26b26340f8d0363633490556d20bcc250726d10e1431eb8c22d6b1ff3f2b14a",
94
+ "27e4ddde96ec6a1dbe1cf12d79448b3e72f144944c15b299629542d1b65fbabf",
95
+ "efd9c0a391ee93251046a58326d1b21b33fe21d71a3fb1855b9048ade53df77c",
96
+ "6d505fcce416c26a606878aab4d249a034ba2a9846cb1f883e0f9e3fb76ba6da",
97
+ "3a37b8a1b72f9bca51233536d50f9c8d33a787434684787871e0049c82347cda",
98
+ "16f9b451184a7c3148344c7d0315f5312ca20553d2271912ecaad91810d977e6",
99
+ "7406537eb74d1885bd05e191228de313b13702a64d90ae1736c6377b25ab579a",
100
+ "7e4d1395ae18980015cab16c85ffa20b4cb90a2db594126e893d0f7ac6eecaa8",
101
+ "ba813ee6c25698f0f68a07121d38bb47c9aa404c1ab0a6e767595cb75e1747b8",
102
+ "6586c93f3ece83e01ecc1eb84a7711e7975826a388d478a009468ea0ed9dc03e",
103
+ "8960174c74d86e03ae88fb6774580170e49952f2286d960be08c556bbd0dda95",
104
+ "4d611454369aa1a4e2b7eed1734fac5d480f08fb86b87a162967e416370f2a8e",
105
+ "59d48440f85eabf565fe8d3bc6b973ba64c70df3b36b0511e0e67ceca91762b3",
106
+ "cd926926e2af74e43d1a6a420a7e1933b78662320477a3c018b2711d8765e339",
107
+ "80e90057df6a59823f51aafac36ed5bc4e5ac26d675d9c1467501590c82f12d4",
108
+ "a9cf28b869b70e258adde5639a048f866ec86f8f3f3d53bfc960b86aa6da9239",
109
+ "cc2adbf8ac0cddeefa304d7b20f14a7e047a4b2299cc5e8f898f5c59660bd964",
110
+ "92a150a46146e9d3f84899cf15e12514af684e7ee18d7add782ddd4f4a15ef18",
111
+ "d9b2e84ef6dc0ce449357d52c9095f69b173a1b848ea2921199d33b0ec10024a",
112
+ "a9329a7e4d367a0135c1ca86c6ce5ecabcc26529235229d71b6bf991f7689e21",
113
+ "8f160c6fd8ccc3fb2a371a4b52748f0bd030766627c4322e2911fe82f6b10497",
114
+ "620e96eae4f3e88cbe0770292b33724c5df3866d83f39df6380441f7271c80e2",
115
+ "cafa3481fa3c45ed1e55cd0129c12b477eeab5aa3d6da20cae6d6292f19b0e6d",
116
+ "be07994e9a83aa3689e79b6e96123676ccc4fa29f523c28c750c6d60505531ee",
117
+ "f6498069768cd3aa79b2b0c91879694f05a259c8ee4a6bb343f0435f74eb1b53",
118
+ "c9b6b26cb3a694eb78fcac0a14ad18d46d50907186a9add41022d31d191b2b65"
119
+ ]
120
+
121
+ const young = [
122
+ "ffdf66787b4a33b78b18c18822e334cfe2c8406caf442851deef451bd43140a1",
123
+ "858f22219afc4b32a7ba9a27a213d7f495e77c3cceed8147eae5282bf3e23d39",
124
+ "8c3c46df84ace3d58d4ce0fbc513017986b33c6002ae369d9f7dd1f892a898cb",
125
+ "66caa22b9483fdf026ce67de61067d81535a7c9b3169cbc5c2a455ac8dcc7bec",
126
+ "76893047b1eff9fadc7be07b13adb5aaed9c73bcdeea46ee07098605e2c7ff76",
127
+ "526cb848754e2baaa17376a5693d90ba3f69f71fd2a866f22876ac8a075849a7",
128
+ "f59c38e31d0f64dc1bfcdf34451723bc1a65570e209e5496c8d1d7f6d3d649db",
129
+ "e013a67e275c62c1402ccbbb11ad14afb8b8a82318a44c07d67599ed5ac874de",
130
+ "3bef34219fb07f867ecbff4d6748f598d6cc0761e17dd0d431ee1f4ec3281374",
131
+ "8211bf5f613fac06cd5d074d34c16dfacc9367c8afaa6ad3aff99d145e5221be"
132
+ ]
133
+
134
+ const getFingerprint = (word: string) => {
135
+ return computeSecretFingerprint(
136
+ word.toLocaleLowerCase().replaceAll(/[^a-zA-Z0-9]/gi, "")
137
+ )
138
+ }
139
+
140
+ const encode = (list: string[]) => {
141
+ console.log(JSON.stringify(
142
+ list.sort((a, b) => (b.length - a.length))
143
+ .map(item => getFingerprint(item)), null, 2))
144
+ }
145
+
146
+ // encode([ "badword" ])
147
+
148
  export const filterOutBadWords = (sentence: string) => {
149
+ if (process.env.ENABLE_CENSORSHIP !== "true") { return sentence }
150
+
151
+ let requireCensorship = false
152
+
153
+ const words = sentence.replaceAll(/[^a-zA-Z0-9]/gi, " ").replaceAll(/\s+/gi, " ").trim().split(" ")
154
+
155
+ const sanitized = words.map(word => {
156
+ const fingerprint = getFingerprint(word)
157
+
158
+ let result: string = word
159
+ // some users want to play it smart and bypass our system so let's play too
160
+ if (chickens.includes(fingerprint)) {
161
+ result = "large chicken"
162
+ } else if (ducks.includes(fingerprint)) {
163
+ result = "big duck"
164
+ } else if (cats.includes(fingerprint)) {
165
+ result = "cat"
166
+ } else if (roasted.includes(fingerprint)) {
167
+ result = "roasted chicken"
168
+ } else if (young.includes(fingerprint)) {
169
+ result = "adult"
170
+ } else if (banned.includes(fingerprint)) {
171
+ result = "_BANNED_"
172
+ }
173
+
174
+ if (result !== word) {
175
+ requireCensorship = true
176
+ }
177
+ return result
178
+ }).filter(item => item !== "_BANNED_").join(" ")
179
+
180
+ // if the user didn't try to use a bad word, we leave it untouched
181
+ // he words array has been degraded by the replace operation, but it removes commas etc which isn't great
182
+ // so if the request was genuine and SFW, it's best to return the original prompt
183
+ return requireCensorship ? sanitized : sentence
184
  }
src/app/engine/render.ts CHANGED
@@ -9,16 +9,18 @@ import { sleep } from "@/lib/sleep"
9
 
10
  const renderingEngine = `${process.env.RENDERING_ENGINE || ""}` as RenderingEngine
11
 
12
- const videochainApiUrl = `${process.env.RENDERING_VIDEOCHAIN_API_URL || "" }`
13
-
14
- const huggingFaceToken = `${process.env.HF_API_TOKEN || ""}`
15
  const huggingFaceInferenceEndpointUrl = `${process.env.RENDERING_HF_INFERENCE_ENDPOINT_URL || ""}`
16
  const huggingFaceInferenceApiModel = `${process.env.RENDERING_HF_INFERENCE_API_MODEL || ""}`
17
 
18
- const replicateToken = `${process.env.RENDERING_REPLICATE_API_TOKEN || ""}`
19
  const replicateModel = `${process.env.RENDERING_REPLICATE_API_MODEL || ""}`
20
  const replicateModelVersion = `${process.env.RENDERING_REPLICATE_API_MODEL_VERSION || ""}`
21
 
 
 
 
22
  export async function newRender({
23
  prompt,
24
  // negativePrompt,
@@ -30,10 +32,10 @@ export async function newRender({
30
  width: number
31
  height: number
32
  }) {
33
- // console.log(`newRender(${prompt})`)
34
  if (!prompt) {
35
- console.error(`cannot call the rendering API without a prompt, aborting..`)
36
- throw new Error(`cannot call the rendering API without a prompt, aborting..`)
 
37
  }
38
 
39
  let defaulResult: RenderedScene = {
@@ -69,7 +71,7 @@ export async function newRender({
69
 
70
  // console.log("prediction:", prediction)
71
 
72
- // no need to reply straight away: good things take time
73
  // also our friends at Replicate won't like it if we spam them with requests
74
  await sleep(4000)
75
 
@@ -93,8 +95,6 @@ export async function newRender({
93
  throw new Error(`you need to configure your RENDERING_HF_INFERENCE_API_MODEL in order to use the INFERENCE_API rendering engine`)
94
  }
95
 
96
- const seed = generateSeed()
97
-
98
  const url = renderingEngine === "INFERENCE_ENDPOINT"
99
  ? huggingFaceInferenceEndpointUrl
100
  : `https://api-inference.huggingface.co/models/${huggingFaceInferenceApiModel}`
@@ -102,7 +102,6 @@ export async function newRender({
102
  const res = await fetch(url, {
103
  method: "POST",
104
  headers: {
105
- // Accept: "application/json",
106
  "Content-Type": "application/json",
107
  Authorization: `Bearer ${huggingFaceToken}`,
108
  },
@@ -148,13 +147,12 @@ export async function newRender({
148
  segments: []
149
  } as RenderedScene
150
  } else {
151
- // console.log(`calling POST ${apiUrl}/render with prompt: ${prompt}`)
152
  const res = await fetch(`${videochainApiUrl}/render`, {
153
  method: "POST",
154
  headers: {
155
  Accept: "application/json",
156
  "Content-Type": "application/json",
157
- Authorization: `Bearer ${process.env.VIDEOCHAIN_API_TOKEN}`,
158
  },
159
  body: JSON.stringify({
160
  prompt,
@@ -182,14 +180,7 @@ export async function newRender({
182
  // next: { revalidate: 1 }
183
  })
184
 
185
-
186
- // console.log("res:", res)
187
- // The return value is *not* serialized
188
- // You can return Date, Map, Set, etc.
189
-
190
- // Recommendation: handle errors
191
  if (res.status !== 200) {
192
- // This will activate the closest `error.js` Error Boundary
193
  throw new Error('Failed to fetch data')
194
  }
195
 
@@ -204,8 +195,9 @@ export async function newRender({
204
 
205
  export async function getRender(renderId: string) {
206
  if (!renderId) {
207
- console.error(`cannot call the rendering API without a renderId, aborting..`)
208
- throw new Error(`cannot call the rendering API without a renderId, aborting..`)
 
209
  }
210
 
211
  let defaulResult: RenderedScene = {
@@ -221,24 +213,15 @@ export async function getRender(renderId: string) {
221
  try {
222
  if (renderingEngine === "REPLICATE") {
223
  if (!replicateToken) {
224
- throw new Error(`you need to configure your REPLICATE_API_TOKEN in order to use the REPLICATE rendering engine`)
225
  }
226
  if (!replicateModel) {
227
- throw new Error(`you need to configure your REPLICATE_API_MODEL in order to use the REPLICATE rendering engine`)
228
  }
229
 
230
- // const replicate = new Replicate({ auth: replicateToken })
231
-
232
- // console.log("Calling replicate..")
233
- // const prediction = await replicate.predictions.get(renderId)
234
- // console.log("Prediction:", prediction)
235
-
236
- // console.log(`calling GET https://api.replicate.com/v1/predictions/${renderId}`)
237
  const res = await fetch(`https://api.replicate.com/v1/predictions/${renderId}`, {
238
  method: "GET",
239
  headers: {
240
- // Accept: "application/json",
241
- // "Content-Type": "application/json",
242
  Authorization: `Token ${replicateToken}`,
243
  },
244
  cache: 'no-store',
@@ -246,10 +229,6 @@ export async function getRender(renderId: string) {
246
  // next: { revalidate: 1 }
247
  })
248
 
249
- // console.log("res:", res)
250
- // The return value is *not* serialized
251
- // You can return Date, Map, Set, etc.
252
-
253
  // Recommendation: handle errors
254
  if (res.status !== 200) {
255
  // This will activate the closest `error.js` Error Boundary
@@ -257,7 +236,6 @@ export async function getRender(renderId: string) {
257
  }
258
 
259
  const response = (await res.json()) as any
260
- // console.log("response:", response)
261
 
262
  return {
263
  renderId,
@@ -275,36 +253,26 @@ export async function getRender(renderId: string) {
275
  headers: {
276
  Accept: "application/json",
277
  "Content-Type": "application/json",
278
- Authorization: `Bearer ${process.env.VIDEOCHAIN_API_TOKEN}`,
279
  },
280
  cache: 'no-store',
281
  // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
282
  // next: { revalidate: 1 }
283
  })
284
-
285
- // console.log("res:", res)
286
- // The return value is *not* serialized
287
- // You can return Date, Map, Set, etc.
288
 
289
- // Recommendation: handle errors
290
  if (res.status !== 200) {
291
- // This will activate the closest `error.js` Error Boundary
292
  throw new Error('Failed to fetch data')
293
  }
294
 
295
  const response = (await res.json()) as RenderedScene
296
- // console.log("response:", response)
297
  return response
298
  }
299
  } catch (err) {
300
  console.error(err)
301
  defaulResult.status = "error"
302
  defaulResult.error = `${err}`
303
- // Gorgon.clear(cacheKey)
304
  return defaulResult
305
  }
306
-
307
- // }, cacheDurationInSec * 1000)
308
  }
309
 
310
  export async function upscaleImage(image: string): Promise<{
@@ -312,8 +280,9 @@ export async function upscaleImage(image: string): Promise<{
312
  error: string
313
  }> {
314
  if (!image) {
315
- console.error(`cannot call the rendering API without an image, aborting..`)
316
- throw new Error(`cannot call the rendering API without an image, aborting..`)
 
317
  }
318
 
319
  let defaulResult = {
@@ -328,7 +297,7 @@ export async function upscaleImage(image: string): Promise<{
328
  headers: {
329
  Accept: "application/json",
330
  "Content-Type": "application/json",
331
- Authorization: `Bearer ${process.env.VIDEOCHAIN_API_TOKEN}`,
332
  },
333
  cache: 'no-store',
334
  body: JSON.stringify({ image, factor: 3 })
@@ -336,13 +305,7 @@ export async function upscaleImage(image: string): Promise<{
336
  // next: { revalidate: 1 }
337
  })
338
 
339
- // console.log("res:", res)
340
- // The return value is *not* serialized
341
- // You can return Date, Map, Set, etc.
342
-
343
- // Recommendation: handle errors
344
  if (res.status !== 200) {
345
- // This will activate the closest `error.js` Error Boundary
346
  throw new Error('Failed to fetch data')
347
  }
348
 
@@ -350,13 +313,9 @@ export async function upscaleImage(image: string): Promise<{
350
  assetUrl: string
351
  error: string
352
  }
353
- // console.log("response:", response)
354
  return response
355
  } catch (err) {
356
  console.error(err)
357
- // Gorgon.clear(cacheKey)
358
  return defaulResult
359
  }
360
-
361
- // }, cacheDurationInSec * 1000)
362
  }
 
9
 
10
  const renderingEngine = `${process.env.RENDERING_ENGINE || ""}` as RenderingEngine
11
 
12
+ // TODO: we should split Hugging Face and Replicate backends into separate files
13
+ const huggingFaceToken = `${process.env.AUTH_HF_API_TOKEN || ""}`
 
14
  const huggingFaceInferenceEndpointUrl = `${process.env.RENDERING_HF_INFERENCE_ENDPOINT_URL || ""}`
15
  const huggingFaceInferenceApiModel = `${process.env.RENDERING_HF_INFERENCE_API_MODEL || ""}`
16
 
17
+ const replicateToken = `${process.env.AUTH_REPLICATE_API_TOKEN || ""}`
18
  const replicateModel = `${process.env.RENDERING_REPLICATE_API_MODEL || ""}`
19
  const replicateModelVersion = `${process.env.RENDERING_REPLICATE_API_MODEL_VERSION || ""}`
20
 
21
+ const videochainToken = `${process.env.AUTH_VIDEOCHAIN_API_TOKEN || ""}`
22
+ const videochainApiUrl = `${process.env.RENDERING_VIDEOCHAIN_API_URL || ""}`
23
+
24
  export async function newRender({
25
  prompt,
26
  // negativePrompt,
 
32
  width: number
33
  height: number
34
  }) {
 
35
  if (!prompt) {
36
+ const error = `cannot call the rendering API without a prompt, aborting..`
37
+ console.error(error)
38
+ throw new Error(error)
39
  }
40
 
41
  let defaulResult: RenderedScene = {
 
71
 
72
  // console.log("prediction:", prediction)
73
 
74
+ // no need to reply straight away as images take time to generate, this isn't instantaneous
75
  // also our friends at Replicate won't like it if we spam them with requests
76
  await sleep(4000)
77
 
 
95
  throw new Error(`you need to configure your RENDERING_HF_INFERENCE_API_MODEL in order to use the INFERENCE_API rendering engine`)
96
  }
97
 
 
 
98
  const url = renderingEngine === "INFERENCE_ENDPOINT"
99
  ? huggingFaceInferenceEndpointUrl
100
  : `https://api-inference.huggingface.co/models/${huggingFaceInferenceApiModel}`
 
102
  const res = await fetch(url, {
103
  method: "POST",
104
  headers: {
 
105
  "Content-Type": "application/json",
106
  Authorization: `Bearer ${huggingFaceToken}`,
107
  },
 
147
  segments: []
148
  } as RenderedScene
149
  } else {
 
150
  const res = await fetch(`${videochainApiUrl}/render`, {
151
  method: "POST",
152
  headers: {
153
  Accept: "application/json",
154
  "Content-Type": "application/json",
155
+ Authorization: `Bearer ${videochainToken}`,
156
  },
157
  body: JSON.stringify({
158
  prompt,
 
180
  // next: { revalidate: 1 }
181
  })
182
 
 
 
 
 
 
 
183
  if (res.status !== 200) {
 
184
  throw new Error('Failed to fetch data')
185
  }
186
 
 
195
 
196
  export async function getRender(renderId: string) {
197
  if (!renderId) {
198
+ const error = `cannot call the rendering API without a renderId, aborting..`
199
+ console.error(error)
200
+ throw new Error(error)
201
  }
202
 
203
  let defaulResult: RenderedScene = {
 
213
  try {
214
  if (renderingEngine === "REPLICATE") {
215
  if (!replicateToken) {
216
+ throw new Error(`you need to configure your AUTH_REPLICATE_API_TOKEN in order to use the REPLICATE rendering engine`)
217
  }
218
  if (!replicateModel) {
219
+ throw new Error(`you need to configure your RENDERING_REPLICATE_API_MODEL in order to use the REPLICATE rendering engine`)
220
  }
221
 
 
 
 
 
 
 
 
222
  const res = await fetch(`https://api.replicate.com/v1/predictions/${renderId}`, {
223
  method: "GET",
224
  headers: {
 
 
225
  Authorization: `Token ${replicateToken}`,
226
  },
227
  cache: 'no-store',
 
229
  // next: { revalidate: 1 }
230
  })
231
 
 
 
 
 
232
  // Recommendation: handle errors
233
  if (res.status !== 200) {
234
  // This will activate the closest `error.js` Error Boundary
 
236
  }
237
 
238
  const response = (await res.json()) as any
 
239
 
240
  return {
241
  renderId,
 
253
  headers: {
254
  Accept: "application/json",
255
  "Content-Type": "application/json",
256
+ Authorization: `Bearer ${videochainToken}`,
257
  },
258
  cache: 'no-store',
259
  // we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
260
  // next: { revalidate: 1 }
261
  })
 
 
 
 
262
 
 
263
  if (res.status !== 200) {
 
264
  throw new Error('Failed to fetch data')
265
  }
266
 
267
  const response = (await res.json()) as RenderedScene
 
268
  return response
269
  }
270
  } catch (err) {
271
  console.error(err)
272
  defaulResult.status = "error"
273
  defaulResult.error = `${err}`
 
274
  return defaulResult
275
  }
 
 
276
  }
277
 
278
  export async function upscaleImage(image: string): Promise<{
 
280
  error: string
281
  }> {
282
  if (!image) {
283
+ const error = `cannot call the rendering API without an image, aborting..`
284
+ console.error(error)
285
+ throw new Error(error)
286
  }
287
 
288
  let defaulResult = {
 
297
  headers: {
298
  Accept: "application/json",
299
  "Content-Type": "application/json",
300
+ Authorization: `Bearer ${videochainToken}`,
301
  },
302
  cache: 'no-store',
303
  body: JSON.stringify({ image, factor: 3 })
 
305
  // next: { revalidate: 1 }
306
  })
307
 
 
 
 
 
 
308
  if (res.status !== 200) {
 
309
  throw new Error('Failed to fetch data')
310
  }
311
 
 
313
  assetUrl: string
314
  error: string
315
  }
 
316
  return response
317
  } catch (err) {
318
  console.error(err)
 
319
  return defaulResult
320
  }
 
 
321
  }
src/app/queries/getStory.ts CHANGED
@@ -37,15 +37,15 @@ export const getStory = async ({
37
  let result = ""
38
 
39
  try {
40
- result = await predict(query)
41
- if (!result.trim().length) {
42
  throw new Error("empty result!")
43
  }
44
  } catch (err) {
45
  console.log(`prediction of the story failed, trying again..`)
46
  try {
47
- result = await predict(query+".")
48
- if (!result.trim().length) {
49
  throw new Error("empty result!")
50
  }
51
  } catch (err) {
 
37
  let result = ""
38
 
39
  try {
40
+ result = `${await predict(query) || ""}`.trim()
41
+ if (!result.length) {
42
  throw new Error("empty result!")
43
  }
44
  } catch (err) {
45
  console.log(`prediction of the story failed, trying again..`)
46
  try {
47
+ result = `${await predict(query+".") || ""}`.trim()
48
+ if (!result.length) {
49
  throw new Error("empty result!")
50
  }
51
  } catch (err) {
src/app/queries/getStyle.ts CHANGED
@@ -30,15 +30,15 @@ export const getStory = async ({
30
 
31
  let result = ""
32
  try {
33
- result = await predict(query)
34
- if (!result.trim().length) {
35
  throw new Error("empty result!")
36
  }
37
  } catch (err) {
38
  console.log(`prediction of the story failed, trying again..`)
39
  try {
40
- result = await predict(query+".")
41
- if (!result.trim().length) {
42
  throw new Error("empty result!")
43
  }
44
  } catch (err) {
 
30
 
31
  let result = ""
32
  try {
33
+ result = `${await predict(query) || ""}`.trim()
34
+ if (!result.length) {
35
  throw new Error("empty result!")
36
  }
37
  } catch (err) {
38
  console.log(`prediction of the story failed, trying again..`)
39
  try {
40
+ result = `${await predict(query+".") || ""}`.trim()
41
+ if (!result.length) {
42
  throw new Error("empty result!")
43
  }
44
  } catch (err) {
src/app/queries/predict.ts CHANGED
@@ -1,141 +1,9 @@
1
  "use server"
2
 
3
- import { HfInference, HfInferenceEndpoint } from "@huggingface/inference"
4
-
5
- import type { ChatCompletionMessage } from "openai/resources/chat"
6
  import { LLMEngine } from "@/types"
7
- import OpenAI from "openai"
8
-
9
- const hf = new HfInference(process.env.HF_API_TOKEN)
10
 
11
-
12
- // note: we always try "inference endpoint" first
13
  const llmEngine = `${process.env.LLM_ENGINE || ""}` as LLMEngine
14
- const inferenceEndpoint = `${process.env.LLM_HF_INFERENCE_ENDPOINT_URL || ""}`
15
- const inferenceModel = `${process.env.LLM_HF_INFERENCE_API_MODEL || ""}`
16
- const openaiApiKey = `${process.env.LLM_OPENAI_API_KEY || ""}`
17
-
18
-
19
- let hfie: HfInferenceEndpoint
20
-
21
- switch (llmEngine) {
22
- case "INFERENCE_ENDPOINT":
23
- if (inferenceEndpoint) {
24
- console.log("Using a custom HF Inference Endpoint")
25
- hfie = hf.endpoint(inferenceEndpoint)
26
- } else {
27
- const error = "No Inference Endpoint URL defined"
28
- console.error(error)
29
- throw new Error(error)
30
- }
31
- break;
32
-
33
- case "INFERENCE_API":
34
- if (inferenceModel) {
35
- console.log("Using an HF Inference API Model")
36
- } else {
37
- const error = "No Inference API model defined"
38
- console.error(error)
39
- throw new Error(error)
40
- }
41
- break;
42
-
43
- case "OPENAI":
44
- if (openaiApiKey) {
45
- console.log("Using an OpenAI API Key")
46
- } else {
47
- const error = "No OpenAI API key defined"
48
- console.error(error)
49
- throw new Error(error)
50
- }
51
- break;
52
-
53
- default:
54
- const error = "No Inference Endpoint URL or Inference API Model defined"
55
- console.error(error)
56
- throw new Error(error)
57
- }
58
-
59
- export async function predict(inputs: string) {
60
-
61
- console.log(`predict: `, inputs)
62
-
63
- if (llmEngine==="OPENAI") {
64
- return predictWithOpenAI(inputs)
65
- }
66
-
67
- const api = llmEngine ==="INFERENCE_ENDPOINT" ? hfie : hf
68
-
69
- let instructions = ""
70
- try {
71
- for await (const output of api.textGenerationStream({
72
- model: llmEngine ==="INFERENCE_ENDPOINT" ? undefined : (inferenceModel || undefined),
73
- inputs,
74
- parameters: {
75
- do_sample: true,
76
- // we don't require a lot of token for our task
77
- // but to be safe, let's count ~110 tokens per panel
78
- max_new_tokens: 450, // 1150,
79
- return_full_text: false,
80
- }
81
- })) {
82
- instructions += output.token.text
83
- process.stdout.write(output.token.text)
84
- if (
85
- instructions.includes("</s>") ||
86
- instructions.includes("<s>") ||
87
- instructions.includes("[INST]") ||
88
- instructions.includes("[/INST]") ||
89
- instructions.includes("<SYS>") ||
90
- instructions.includes("</SYS>") ||
91
- instructions.includes("<|end|>") ||
92
- instructions.includes("<|assistant|>")
93
- ) {
94
- break
95
- }
96
- }
97
- } catch (err) {
98
- console.error(`error during generation: ${err}`)
99
- }
100
-
101
- // need to do some cleanup of the garbage the LLM might have gave us
102
- return (
103
- instructions
104
- .replaceAll("<|end|>", "")
105
- .replaceAll("<s>", "")
106
- .replaceAll("</s>", "")
107
- .replaceAll("[INST]", "")
108
- .replaceAll("[/INST]", "")
109
- .replaceAll("<SYS>", "")
110
- .replaceAll("</SYS>", "")
111
- .replaceAll("<|assistant|>", "")
112
- .replaceAll('""', '"')
113
- )
114
- }
115
-
116
- async function predictWithOpenAI(inputs: string) {
117
- const openaiApiBaseUrl = `${process.env.OPENAI_API_BASE_URL || "https://api.openai.com/v1"}`
118
- const openaiApiModel = `${process.env.OPENAI_API_MODEL || "gpt-3.5-turbo"}`
119
-
120
- const openai = new OpenAI({
121
- apiKey: openaiApiKey,
122
- baseURL: openaiApiBaseUrl,
123
- })
124
-
125
- const messages: ChatCompletionMessage[] = [
126
- { role: "system", content: inputs },
127
- ]
128
-
129
- try {
130
- const res = await openai.chat.completions.create({
131
- messages: messages,
132
- stream: false,
133
- model: openaiApiModel,
134
- temperature: 0.8
135
- })
136
 
137
- return res.choices[0].message.content
138
- } catch (err) {
139
- console.error(`error during generation: ${err}`)
140
- }
141
- }
 
1
  "use server"
2
 
 
 
 
3
  import { LLMEngine } from "@/types"
4
+ import { predictWithHuggingFace } from "./predictWithHuggingFace"
5
+ import { predictWithOpenAI } from "./predictWithOpenAI"
 
6
 
 
 
7
  const llmEngine = `${process.env.LLM_ENGINE || ""}` as LLMEngine
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ export const predict = llmEngine === "OPENAI" ? predictWithOpenAI : predictWithHuggingFace
 
 
 
 
src/app/queries/predictWithHuggingFace.ts ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use server"
2
+
3
+ import { HfInference, HfInferenceEndpoint } from "@huggingface/inference"
4
+ import { LLMEngine } from "@/types"
5
+
6
+ const hf = new HfInference(process.env.AUTH_HF_API_TOKEN)
7
+
8
+ const llmEngine = `${process.env.LLM_ENGINE || ""}` as LLMEngine
9
+ const inferenceEndpoint = `${process.env.LLM_HF_INFERENCE_ENDPOINT_URL || ""}`
10
+ const inferenceModel = `${process.env.LLM_HF_INFERENCE_API_MODEL || ""}`
11
+
12
+ let hfie: HfInferenceEndpoint = hf
13
+
14
+ switch (llmEngine) {
15
+ case "INFERENCE_ENDPOINT":
16
+ if (inferenceEndpoint) {
17
+ console.log("Using a custom HF Inference Endpoint")
18
+ hfie = hf.endpoint(inferenceEndpoint)
19
+ } else {
20
+ const error = "No Inference Endpoint URL defined"
21
+ console.error(error)
22
+ throw new Error(error)
23
+ }
24
+ break;
25
+
26
+ case "INFERENCE_API":
27
+ if (inferenceModel) {
28
+ console.log("Using an HF Inference API Model")
29
+ } else {
30
+ const error = "No Inference API model defined"
31
+ console.error(error)
32
+ throw new Error(error)
33
+ }
34
+ break;
35
+
36
+ default:
37
+ const error = "Please check your Hugging Face Inference API or Inference Endpoint settings"
38
+ console.error(error)
39
+ throw new Error(error)
40
+ }
41
+
42
+ const api = llmEngine === "INFERENCE_ENDPOINT" ? hfie : hf
43
+
44
+ export async function predictWithHuggingFace(inputs: string) {
45
+ let instructions = ""
46
+ try {
47
+ for await (const output of api.textGenerationStream({
48
+ model: llmEngine === "INFERENCE_ENDPOINT" ? undefined : (inferenceModel || undefined),
49
+ inputs,
50
+ parameters: {
51
+ do_sample: true,
52
+ // we don't require a lot of token for our task
53
+ // but to be safe, let's count ~110 tokens per panel
54
+ max_new_tokens: 450, // 1150,
55
+ return_full_text: false,
56
+ }
57
+ })) {
58
+ instructions += output.token.text
59
+ process.stdout.write(output.token.text)
60
+ if (
61
+ instructions.includes("</s>") ||
62
+ instructions.includes("<s>") ||
63
+ instructions.includes("[INST]") ||
64
+ instructions.includes("[/INST]") ||
65
+ instructions.includes("<SYS>") ||
66
+ instructions.includes("</SYS>") ||
67
+ instructions.includes("<|end|>") ||
68
+ instructions.includes("<|assistant|>")
69
+ ) {
70
+ break
71
+ }
72
+ }
73
+ } catch (err) {
74
+ console.error(`error during generation: ${err}`)
75
+ }
76
+
77
+ // need to do some cleanup of the garbage the LLM might have gave us
78
+ return (
79
+ instructions
80
+ .replaceAll("<|end|>", "")
81
+ .replaceAll("<s>", "")
82
+ .replaceAll("</s>", "")
83
+ .replaceAll("[INST]", "")
84
+ .replaceAll("[/INST]", "")
85
+ .replaceAll("<SYS>", "")
86
+ .replaceAll("</SYS>", "")
87
+ .replaceAll("<|assistant|>", "")
88
+ .replaceAll('""', '"')
89
+ )
90
+ }
src/app/queries/predictWithOpenAI.ts ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use server"
2
+
3
+ import type { ChatCompletionMessage } from "openai/resources/chat"
4
+ import OpenAI from "openai"
5
+
6
+ const openaiApiKey = `${process.env.AUTH_OPENAI_API_KEY || ""}`
7
+
8
+ export async function predictWithOpenAI(inputs: string) {
9
+ const openaiApiBaseUrl = `${process.env.LLM_OPENAI_API_BASE_URL || "https://api.openai.com/v1"}`
10
+ const openaiApiModel = `${process.env.LLM_OPENAI_API_MODEL || "gpt-3.5-turbo"}`
11
+
12
+ const openai = new OpenAI({
13
+ apiKey: openaiApiKey,
14
+ baseURL: openaiApiBaseUrl,
15
+ })
16
+
17
+ const messages: ChatCompletionMessage[] = [
18
+ { role: "system", content: inputs },
19
+ ]
20
+
21
+ try {
22
+ const res = await openai.chat.completions.create({
23
+ messages: messages,
24
+ stream: false,
25
+ model: openaiApiModel,
26
+ temperature: 0.8
27
+ })
28
+
29
+ return res.choices[0].message.content
30
+ } catch (err) {
31
+ console.error(`error during generation: ${err}`)
32
+ }
33
+ }