Julian Bilcke
		
	commited on
		
		
					Commit 
							
							·
						
						879455c
	
1
								Parent(s):
							
							274b152
								
update env variables
Browse files- .env +37 -19
 - CONTRIBUTORS.md +9 -0
 - README.md +6 -5
 - package-lock.json +240 -0
 - package.json +1 -0
 - src/app/engine/caption.ts +1 -1
 - src/app/engine/censorship.ts +175 -30
 - src/app/engine/render.ts +21 -62
 - src/app/queries/getStory.ts +4 -4
 - src/app/queries/getStyle.ts +4 -4
 - src/app/queries/predict.ts +3 -135
 - src/app/queries/predictWithHuggingFace.ts +90 -0
 - src/app/queries/predictWithOpenAI.ts +33 -0
 
    	
        .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 | 
         
            -
            #  
     | 
| 16 | 
         
            -
             
     | 
| 17 | 
         
            -
            HF_API_TOKEN=
         
     | 
| 18 | 
         | 
| 19 | 
         
            -
            # Replicate token 
     | 
| 20 | 
         
            -
             
     | 
| 21 | 
         | 
| 22 | 
         
            -
            # OpenAI  
     | 
| 23 | 
         
            -
             
     | 
| 24 | 
         | 
| 25 | 
         
            -
            #  
     | 
| 26 | 
         
            -
             
     | 
| 27 | 
         | 
| 28 | 
         
             
            # ------------- RENDERING API CONFIG --------------
         
     | 
| 29 | 
         | 
| 30 | 
         
            -
             
     | 
| 31 | 
         
            -
             
     | 
| 32 | 
         
             
            RENDERING_REPLICATE_API_MODEL="stabilityai/sdxl"
         
     | 
| 33 | 
         
             
            RENDERING_REPLICATE_API_MODEL_VERSION="da77bc59ee60423279fd632efb4795ab731d9e3ca9705ef3341091fb989b7eaf"
         
     | 
| 34 | 
         | 
| 35 | 
         
            -
             
     | 
| 36 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 37 | 
         | 
| 38 | 
         
             
            # ------------- LLM API CONFIG ----------------
         
     | 
| 39 | 
         | 
| 40 | 
         
            -
            #  
     | 
| 41 | 
         
            -
             
     | 
| 42 | 
         
            -
             
     | 
| 43 | 
         | 
| 44 | 
         
            -
            #  
     | 
| 45 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 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  
     | 
| 24 | 
         
            -
            - `RENDERING_ENGINE`: can  
     | 
| 25 | 
         | 
| 26 | 
         
             
            Auth config:
         
     | 
| 27 | 
         
            -
            - ` 
     | 
| 28 | 
         
            -
            - ` 
     | 
| 29 | 
         
            -
            - ` 
     | 
| 
         | 
|
| 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 ${ 
     | 
| 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 | 
         
            -
             
     | 
| 13 | 
         
            -
             
     | 
| 14 | 
         
            -
             
     | 
| 15 | 
         
            -
             
     | 
| 16 | 
         
            -
             
     | 
| 17 | 
         
            -
             
     | 
| 18 | 
         
            -
              " 
     | 
| 19 | 
         
            -
              " 
     | 
| 20 | 
         
            -
              " 
     | 
| 21 | 
         
            -
              " 
     | 
| 22 | 
         
            -
              " 
     | 
| 23 | 
         
            -
              " 
     | 
| 24 | 
         
            -
              " 
     | 
| 25 | 
         
            -
             
     | 
| 26 | 
         
            -
             
     | 
| 27 | 
         
            -
             
     | 
| 28 | 
         
            -
              " 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 29 | 
         
             
            ]
         
     | 
| 30 | 
         | 
| 31 | 
         
            -
             
     | 
| 32 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 33 | 
         
             
            export const filterOutBadWords = (sentence: string) => {
         
     | 
| 34 | 
         
            -
               
     | 
| 35 | 
         
            -
             
     | 
| 36 | 
         
            -
             
     | 
| 37 | 
         
            -
             
     | 
| 38 | 
         
            -
               
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 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 | 
         
            -
             
     | 
| 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. 
     | 
| 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 | 
         
            -
                 
     | 
| 36 | 
         
            -
                 
     | 
| 
         | 
|
| 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 
     | 
| 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 ${ 
     | 
| 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 | 
         
            -
                 
     | 
| 208 | 
         
            -
                 
     | 
| 
         | 
|
| 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  
     | 
| 225 | 
         
             
                  }
         
     | 
| 226 | 
         
             
                  if (!replicateModel) {
         
     | 
| 227 | 
         
            -
                    throw new Error(`you need to configure your  
     | 
| 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 ${ 
     | 
| 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 | 
         
            -
                 
     | 
| 316 | 
         
            -
                 
     | 
| 
         | 
|
| 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 ${ 
     | 
| 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. 
     | 
| 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. 
     | 
| 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. 
     | 
| 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. 
     | 
| 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  
     | 
| 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 | 
         
            -
             
     | 
| 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 | 
         
            +
            }
         
     |