Add auto provider
Browse files- server.js +15 -8
 - src/components/ask-ai/ask-ai.tsx +1 -1
 - src/components/settings/settings.tsx +42 -24
 - utils/providers.js +10 -10
 
    	
        server.js
    CHANGED
    
    | 
         @@ -213,15 +213,19 @@ app.post("/api/ask-ai", async (req, res) => { 
     | 
|
| 213 | 
         
             
              const client = new InferenceClient(token);
         
     | 
| 214 | 
         
             
              let completeResponse = "";
         
     | 
| 215 | 
         | 
| 216 | 
         
            -
              const selectedProvider =
         
     | 
| 217 | 
         
            -
                PROVIDERS.find((providerItem) => providerItem.id === provider) ??
         
     | 
| 218 | 
         
            -
                PROVIDERS[0];
         
     | 
| 219 | 
         
            -
             
     | 
| 220 | 
         
             
              let TOKENS_USED = prompt?.length;
         
     | 
| 221 | 
         
             
              if (previousPrompt) TOKENS_USED += previousPrompt.length;
         
     | 
| 222 | 
         
             
              if (html) TOKENS_USED += html.length;
         
     | 
| 223 | 
         | 
| 224 | 
         
            -
               
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 225 | 
         
             
                return res.status(400).send({
         
     | 
| 226 | 
         
             
                  ok: false,
         
     | 
| 227 | 
         
             
                  openSelectProvider: true,
         
     | 
| 
         @@ -236,8 +240,7 @@ app.post("/api/ask-ai", async (req, res) => { 
     | 
|
| 236 | 
         
             
                  messages: [
         
     | 
| 237 | 
         
             
                    {
         
     | 
| 238 | 
         
             
                      role: "system",
         
     | 
| 239 | 
         
            -
                      content:
         
     | 
| 240 | 
         
            -
                        "ONLY USE HTML, CSS AND JAVASCRIPT. If you want to use ICON make sure to import the library first. Try to create the best UI possible by using only HTML, CSS and JAVASCRIPT. Also, try to ellaborate as much as you can, to create something unique. ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE",
         
     | 
| 241 | 
         
             
                    },
         
     | 
| 242 | 
         
             
                    ...(previousPrompt
         
     | 
| 243 | 
         
             
                      ? [
         
     | 
| 
         @@ -260,7 +263,11 @@ app.post("/api/ask-ai", async (req, res) => { 
     | 
|
| 260 | 
         
             
                      content: prompt,
         
     | 
| 261 | 
         
             
                    },
         
     | 
| 262 | 
         
             
                  ],
         
     | 
| 263 | 
         
            -
                   
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 264 | 
         
             
                });
         
     | 
| 265 | 
         | 
| 266 | 
         
             
                while (true) {
         
     | 
| 
         | 
|
| 213 | 
         
             
              const client = new InferenceClient(token);
         
     | 
| 214 | 
         
             
              let completeResponse = "";
         
     | 
| 215 | 
         | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 216 | 
         
             
              let TOKENS_USED = prompt?.length;
         
     | 
| 217 | 
         
             
              if (previousPrompt) TOKENS_USED += previousPrompt.length;
         
     | 
| 218 | 
         
             
              if (html) TOKENS_USED += html.length;
         
     | 
| 219 | 
         | 
| 220 | 
         
            +
              const DEFAULT_PROVIDER = PROVIDERS["fireworks-ai"];
         
     | 
| 221 | 
         
            +
              const selectedProvider =
         
     | 
| 222 | 
         
            +
                provider === "auto"
         
     | 
| 223 | 
         
            +
                  ? TOKENS_USED < PROVIDERS.sambanova.max_tokens
         
     | 
| 224 | 
         
            +
                    ? PROVIDERS.sambanova
         
     | 
| 225 | 
         
            +
                    : DEFAULT_PROVIDER
         
     | 
| 226 | 
         
            +
                  : PROVIDERS[provider] ?? DEFAULT_PROVIDER;
         
     | 
| 227 | 
         
            +
             
     | 
| 228 | 
         
            +
              if (provider !== "auto" && TOKENS_USED >= selectedProvider.max_tokens) {
         
     | 
| 229 | 
         
             
                return res.status(400).send({
         
     | 
| 230 | 
         
             
                  ok: false,
         
     | 
| 231 | 
         
             
                  openSelectProvider: true,
         
     | 
| 
         | 
|
| 240 | 
         
             
                  messages: [
         
     | 
| 241 | 
         
             
                    {
         
     | 
| 242 | 
         
             
                      role: "system",
         
     | 
| 243 | 
         
            +
                      content: `ONLY USE HTML, CSS AND JAVASCRIPT. If you want to use ICON make sure to import the library first. Try to create the best UI possible by using only HTML, CSS and JAVASCRIPT. Use as much as you can TailwindCSS for the CSS, if you can't do something with TailwindCSS, then use custom CSS (make sure to import <script src="https://cdn.tailwindcss.com"></script> in the head). Also, try to ellaborate as much as you can, to create something unique. ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE`,
         
     | 
| 
         | 
|
| 244 | 
         
             
                    },
         
     | 
| 245 | 
         
             
                    ...(previousPrompt
         
     | 
| 246 | 
         
             
                      ? [
         
     | 
| 
         | 
|
| 263 | 
         
             
                      content: prompt,
         
     | 
| 264 | 
         
             
                    },
         
     | 
| 265 | 
         
             
                  ],
         
     | 
| 266 | 
         
            +
                  ...(selectedProvider.id !== "sambanova"
         
     | 
| 267 | 
         
            +
                    ? {
         
     | 
| 268 | 
         
            +
                        max_tokens: selectedProvider.max_tokens,
         
     | 
| 269 | 
         
            +
                      }
         
     | 
| 270 | 
         
            +
                    : {}),
         
     | 
| 271 | 
         
             
                });
         
     | 
| 272 | 
         | 
| 273 | 
         
             
                while (true) {
         
     | 
    	
        src/components/ask-ai/ask-ai.tsx
    CHANGED
    
    | 
         @@ -27,7 +27,7 @@ function AskAI({ 
     | 
|
| 27 | 
         
             
              const [prompt, setPrompt] = useState("");
         
     | 
| 28 | 
         
             
              const [hasAsked, setHasAsked] = useState(false);
         
     | 
| 29 | 
         
             
              const [previousPrompt, setPreviousPrompt] = useState("");
         
     | 
| 30 | 
         
            -
              const [provider, setProvider] = useLocalStorage("provider", " 
     | 
| 31 | 
         
             
              const [openProvider, setOpenProvider] = useState(false);
         
     | 
| 32 | 
         
             
              const [providerError, setProviderError] = useState("");
         
     | 
| 33 | 
         | 
| 
         | 
|
| 27 | 
         
             
              const [prompt, setPrompt] = useState("");
         
     | 
| 28 | 
         
             
              const [hasAsked, setHasAsked] = useState(false);
         
     | 
| 29 | 
         
             
              const [previousPrompt, setPreviousPrompt] = useState("");
         
     | 
| 30 | 
         
            +
              const [provider, setProvider] = useLocalStorage("provider", "auto");
         
     | 
| 31 | 
         
             
              const [openProvider, setOpenProvider] = useState(false);
         
     | 
| 32 | 
         
             
              const [providerError, setProviderError] = useState("");
         
     | 
| 33 | 
         | 
    	
        src/components/settings/settings.tsx
    CHANGED
    
    | 
         @@ -51,55 +51,73 @@ function Settings({ 
     | 
|
| 51 | 
         
             
                      </span>
         
     | 
| 52 | 
         
             
                      Customize Settings
         
     | 
| 53 | 
         
             
                    </header>
         
     | 
| 54 | 
         
            -
                    <main className="px-4 pt-3 pb-4 space-y- 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 55 | 
         
             
                      {error !== "" && (
         
     | 
| 56 | 
         
             
                        <p className="text-red-500 text-sm font-medium mb-2 flex items-center justify-between bg-red-500/10 p-2 rounded-md">
         
     | 
| 57 | 
         
             
                          {error}
         
     | 
| 58 | 
         
             
                        </p>
         
     | 
| 59 | 
         
             
                      )}
         
     | 
| 60 | 
         
             
                      <label className="block">
         
     | 
| 61 | 
         
            -
                        <p className="text-gray- 
     | 
| 62 | 
         
             
                          Inference Provider
         
     | 
| 63 | 
         
             
                        </p>
         
     | 
| 64 | 
         
             
                        <div className="grid grid-cols-2 gap-1.5">
         
     | 
| 65 | 
         
            -
                          {PROVIDERS.map(( 
     | 
| 66 | 
         
             
                            <div
         
     | 
| 67 | 
         
            -
                              key={ 
     | 
| 68 | 
         
             
                              className={classNames(
         
     | 
| 69 | 
         
             
                                "text-gray-600 text-sm font-medium cursor-pointer border p-2 rounded-md flex items-center justify-start gap-2",
         
     | 
| 70 | 
         
             
                                {
         
     | 
| 71 | 
         
             
                                  "bg-blue-500/10 border-blue-500/15 text-blue-500":
         
     | 
| 72 | 
         
            -
                                     
     | 
| 73 | 
         
            -
                                  "hover:bg-gray-100 border-gray-100":  
     | 
| 74 | 
         
             
                                }
         
     | 
| 75 | 
         
             
                              )}
         
     | 
| 76 | 
         
             
                              onClick={() => {
         
     | 
| 77 | 
         
            -
                                onChange( 
     | 
| 78 | 
         
             
                              }}
         
     | 
| 79 | 
         
             
                            >
         
     | 
| 80 | 
         
             
                              <img
         
     | 
| 81 | 
         
            -
                                src={`/providers/${ 
     | 
| 82 | 
         
            -
                                alt={ 
     | 
| 83 | 
         
             
                                className="size-5"
         
     | 
| 84 | 
         
             
                              />
         
     | 
| 85 | 
         
            -
                              { 
     | 
| 86 | 
         
             
                            </div>
         
     | 
| 87 | 
         
             
                          ))}
         
     | 
| 88 | 
         
             
                        </div>
         
     | 
| 89 | 
         
            -
                        {/* <input
         
     | 
| 90 | 
         
            -
                          type="password"
         
     | 
| 91 | 
         
            -
                          autoComplete="off"
         
     | 
| 92 | 
         
            -
                          className="mr-2 border rounded-md px-3 py-1.5 border-gray-300 w-full text-sm"
         
     | 
| 93 | 
         
            -
                          placeholder="hf_******"
         
     | 
| 94 | 
         
            -
                          value={tokenStorage[0] as string}
         
     | 
| 95 | 
         
            -
                          onChange={(e) => {
         
     | 
| 96 | 
         
            -
                            if (e.target.value.length > 0) {
         
     | 
| 97 | 
         
            -
                              tokenStorage[1](e.target.value);
         
     | 
| 98 | 
         
            -
                            } else {
         
     | 
| 99 | 
         
            -
                              tokenStorage[2]();
         
     | 
| 100 | 
         
            -
                            }
         
     | 
| 101 | 
         
            -
                          }}
         
     | 
| 102 | 
         
            -
                        /> */}
         
     | 
| 103 | 
         
             
                      </label>
         
     | 
| 104 | 
         
             
                    </main>
         
     | 
| 105 | 
         
             
                  </div>
         
     | 
| 
         | 
|
| 51 | 
         
             
                      </span>
         
     | 
| 52 | 
         
             
                      Customize Settings
         
     | 
| 53 | 
         
             
                    </header>
         
     | 
| 54 | 
         
            +
                    <main className="px-4 pt-3 pb-4 space-y-4">
         
     | 
| 55 | 
         
            +
                      {/* toggle using tailwind css */}
         
     | 
| 56 | 
         
            +
                      <div>
         
     | 
| 57 | 
         
            +
                        <div className="flex items-center justify-between">
         
     | 
| 58 | 
         
            +
                          <p className="text-gray-800 text-sm font-medium flex items-center justify-between">
         
     | 
| 59 | 
         
            +
                            Use auto-provider
         
     | 
| 60 | 
         
            +
                          </p>
         
     | 
| 61 | 
         
            +
                          <div
         
     | 
| 62 | 
         
            +
                            className={classNames(
         
     | 
| 63 | 
         
            +
                              "bg-gray-200 rounded-full w-10 h-6 flex items-center justify-between p-1 cursor-pointer transition-all duration-200",
         
     | 
| 64 | 
         
            +
                              {
         
     | 
| 65 | 
         
            +
                                "!bg-blue-500": provider === "auto",
         
     | 
| 66 | 
         
            +
                              }
         
     | 
| 67 | 
         
            +
                            )}
         
     | 
| 68 | 
         
            +
                            onClick={() => {
         
     | 
| 69 | 
         
            +
                              onChange(provider === "auto" ? "fireworks-ai" : "auto");
         
     | 
| 70 | 
         
            +
                            }}
         
     | 
| 71 | 
         
            +
                          >
         
     | 
| 72 | 
         
            +
                            <div
         
     | 
| 73 | 
         
            +
                              className={classNames(
         
     | 
| 74 | 
         
            +
                                "w-4 h-4 rounded-full shadow-md transition-all duration-200 bg-white",
         
     | 
| 75 | 
         
            +
                                {
         
     | 
| 76 | 
         
            +
                                  "translate-x-4": provider !== "auto",
         
     | 
| 77 | 
         
            +
                                }
         
     | 
| 78 | 
         
            +
                              )}
         
     | 
| 79 | 
         
            +
                            />
         
     | 
| 80 | 
         
            +
                          </div>
         
     | 
| 81 | 
         
            +
                        </div>
         
     | 
| 82 | 
         
            +
                        <p className="text-xs text-gray-500 mt-2">
         
     | 
| 83 | 
         
            +
                          We'll automatically select the best provider for you based on your
         
     | 
| 84 | 
         
            +
                          prompt.
         
     | 
| 85 | 
         
            +
                        </p>
         
     | 
| 86 | 
         
            +
                      </div>
         
     | 
| 87 | 
         
             
                      {error !== "" && (
         
     | 
| 88 | 
         
             
                        <p className="text-red-500 text-sm font-medium mb-2 flex items-center justify-between bg-red-500/10 p-2 rounded-md">
         
     | 
| 89 | 
         
             
                          {error}
         
     | 
| 90 | 
         
             
                        </p>
         
     | 
| 91 | 
         
             
                      )}
         
     | 
| 92 | 
         
             
                      <label className="block">
         
     | 
| 93 | 
         
            +
                        <p className="text-gray-800 text-sm font-medium mb-2 flex items-center justify-between">
         
     | 
| 94 | 
         
             
                          Inference Provider
         
     | 
| 95 | 
         
             
                        </p>
         
     | 
| 96 | 
         
             
                        <div className="grid grid-cols-2 gap-1.5">
         
     | 
| 97 | 
         
            +
                          {Object.keys(PROVIDERS).map((id: string) => (
         
     | 
| 98 | 
         
             
                            <div
         
     | 
| 99 | 
         
            +
                              key={id}
         
     | 
| 100 | 
         
             
                              className={classNames(
         
     | 
| 101 | 
         
             
                                "text-gray-600 text-sm font-medium cursor-pointer border p-2 rounded-md flex items-center justify-start gap-2",
         
     | 
| 102 | 
         
             
                                {
         
     | 
| 103 | 
         
             
                                  "bg-blue-500/10 border-blue-500/15 text-blue-500":
         
     | 
| 104 | 
         
            +
                                    id === provider,
         
     | 
| 105 | 
         
            +
                                  "hover:bg-gray-100 border-gray-100": id !== provider,
         
     | 
| 106 | 
         
             
                                }
         
     | 
| 107 | 
         
             
                              )}
         
     | 
| 108 | 
         
             
                              onClick={() => {
         
     | 
| 109 | 
         
            +
                                onChange(id);
         
     | 
| 110 | 
         
             
                              }}
         
     | 
| 111 | 
         
             
                            >
         
     | 
| 112 | 
         
             
                              <img
         
     | 
| 113 | 
         
            +
                                src={`/providers/${id}.svg`}
         
     | 
| 114 | 
         
            +
                                alt={PROVIDERS[id].name}
         
     | 
| 115 | 
         
             
                                className="size-5"
         
     | 
| 116 | 
         
             
                              />
         
     | 
| 117 | 
         
            +
                              {PROVIDERS[id].name}
         
     | 
| 118 | 
         
             
                            </div>
         
     | 
| 119 | 
         
             
                          ))}
         
     | 
| 120 | 
         
             
                        </div>
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 121 | 
         
             
                      </label>
         
     | 
| 122 | 
         
             
                    </main>
         
     | 
| 123 | 
         
             
                  </div>
         
     | 
    	
        utils/providers.js
    CHANGED
    
    | 
         @@ -1,22 +1,22 @@ 
     | 
|
| 1 | 
         
            -
            export const PROVIDERS =  
     | 
| 2 | 
         
            -
              {
         
     | 
| 3 | 
         
             
                name: "Fireworks AI",
         
     | 
| 4 | 
         
            -
                id: "fireworks-ai",
         
     | 
| 5 | 
         
             
                max_tokens: 131_000,
         
     | 
| 
         | 
|
| 6 | 
         
             
              },
         
     | 
| 7 | 
         
            -
              {
         
     | 
| 8 | 
         
             
                name: "Nebius AI Studio",
         
     | 
| 9 | 
         
            -
                id: "nebius",
         
     | 
| 10 | 
         
             
                max_tokens: 131_000,
         
     | 
| 
         | 
|
| 11 | 
         
             
              },
         
     | 
| 12 | 
         
            -
              {
         
     | 
| 13 | 
         
             
                name: "SambaNova",
         
     | 
| 14 | 
         
            -
                id: "sambanova",
         
     | 
| 15 | 
         
             
                max_tokens: 8_000,
         
     | 
| 
         | 
|
| 16 | 
         
             
              },
         
     | 
| 17 | 
         
            -
              {
         
     | 
| 18 | 
         
             
                name: "Hyperbolic",
         
     | 
| 19 | 
         
            -
                id: "hyperbolic",
         
     | 
| 20 | 
         
             
                max_tokens: 131_000,
         
     | 
| 
         | 
|
| 21 | 
         
             
              },
         
     | 
| 22 | 
         
            -
             
     | 
| 
         | 
|
| 1 | 
         
            +
            export const PROVIDERS = {
         
     | 
| 2 | 
         
            +
              "fireworks-ai": {
         
     | 
| 3 | 
         
             
                name: "Fireworks AI",
         
     | 
| 
         | 
|
| 4 | 
         
             
                max_tokens: 131_000,
         
     | 
| 5 | 
         
            +
                id: "fireworks-ai",
         
     | 
| 6 | 
         
             
              },
         
     | 
| 7 | 
         
            +
              nebius: {
         
     | 
| 8 | 
         
             
                name: "Nebius AI Studio",
         
     | 
| 
         | 
|
| 9 | 
         
             
                max_tokens: 131_000,
         
     | 
| 10 | 
         
            +
                id: "nebius",
         
     | 
| 11 | 
         
             
              },
         
     | 
| 12 | 
         
            +
              sambanova: {
         
     | 
| 13 | 
         
             
                name: "SambaNova",
         
     | 
| 
         | 
|
| 14 | 
         
             
                max_tokens: 8_000,
         
     | 
| 15 | 
         
            +
                id: "sambanova",
         
     | 
| 16 | 
         
             
              },
         
     | 
| 17 | 
         
            +
              hyperbolic: {
         
     | 
| 18 | 
         
             
                name: "Hyperbolic",
         
     | 
| 
         | 
|
| 19 | 
         
             
                max_tokens: 131_000,
         
     | 
| 20 | 
         
            +
                id: "hyperbolic",
         
     | 
| 21 | 
         
             
              },
         
     | 
| 22 | 
         
            +
            };
         
     |