2023-10-30 15:44:03 -07:00
|
|
|
import React, { memo, useEffect, useState } from "react";
|
|
|
|
import OpenAiLogo from "../../../../../media/llmprovider/openai.png";
|
|
|
|
import AzureOpenAiLogo from "../../../../../media/llmprovider/azure.png";
|
2023-11-14 22:49:31 +01:00
|
|
|
import LocalAiLogo from "../../../../../media/llmprovider/localai.png";
|
2023-10-30 15:44:03 -07:00
|
|
|
import System from "../../../../../models/system";
|
|
|
|
import PreLoader from "../../../../../components/Preloader";
|
2023-10-31 11:38:28 -07:00
|
|
|
import LLMProviderOption from "../../../../../components/LLMSelection/LLMProviderOption";
|
2023-10-30 15:44:03 -07:00
|
|
|
|
2023-11-08 19:00:12 -08:00
|
|
|
function EmbeddingSelection({ nextStep, prevStep, currentStep }) {
|
2023-10-30 15:44:03 -07:00
|
|
|
const [embeddingChoice, setEmbeddingChoice] = useState("openai");
|
|
|
|
const [settings, setSettings] = useState(null);
|
|
|
|
const [loading, setLoading] = useState(true);
|
2023-11-14 22:49:31 +01:00
|
|
|
const [basePathValue, setBasePathValue] = useState("");
|
|
|
|
const [basePath, setBasePath] = useState("");
|
2023-10-30 15:44:03 -07:00
|
|
|
|
|
|
|
const updateChoice = (selection) => {
|
|
|
|
setEmbeddingChoice(selection);
|
|
|
|
};
|
|
|
|
|
2023-11-14 22:49:31 +01:00
|
|
|
function updateBasePath() {
|
|
|
|
setBasePath(basePathValue);
|
|
|
|
}
|
|
|
|
|
2023-10-30 15:44:03 -07:00
|
|
|
useEffect(() => {
|
|
|
|
async function fetchKeys() {
|
|
|
|
const _settings = await System.keys();
|
|
|
|
setSettings(_settings);
|
|
|
|
setEmbeddingChoice(_settings?.EmbeddingEngine || "openai");
|
2023-11-14 22:49:31 +01:00
|
|
|
setBasePathValue(_settings?.EmbeddingBasePath || "");
|
2023-10-30 15:44:03 -07:00
|
|
|
setLoading(false);
|
|
|
|
}
|
|
|
|
fetchKeys();
|
|
|
|
}, [currentStep]);
|
|
|
|
|
|
|
|
const handleSubmit = async (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
const form = e.target;
|
|
|
|
const data = {};
|
|
|
|
const formData = new FormData(form);
|
|
|
|
for (var [key, value] of formData.entries()) data[key] = value;
|
|
|
|
const { error } = await System.updateSystem(data);
|
|
|
|
if (error) {
|
|
|
|
alert(`Failed to save LLM settings: ${error}`, "error");
|
|
|
|
return;
|
|
|
|
}
|
2023-11-08 19:00:12 -08:00
|
|
|
nextStep("vector_database");
|
2023-10-30 15:44:03 -07:00
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (loading)
|
|
|
|
return (
|
|
|
|
<div className="w-full h-full flex justify-center items-center p-20">
|
|
|
|
<PreLoader />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="w-full">
|
|
|
|
<form onSubmit={handleSubmit} className="flex flex-col w-full">
|
|
|
|
<div className="flex flex-col w-full px-1 md:px-8 py-12">
|
|
|
|
<div className="text-white text-sm font-medium pb-4">
|
|
|
|
Embedding Provider
|
|
|
|
</div>
|
|
|
|
<div className="w-full flex md:flex-wrap overflow-x-scroll gap-4 max-w-[900px]">
|
|
|
|
<input
|
|
|
|
hidden={true}
|
|
|
|
name="EmbeddingEngine"
|
|
|
|
value={embeddingChoice}
|
|
|
|
/>
|
|
|
|
<LLMProviderOption
|
|
|
|
name="OpenAI"
|
|
|
|
value="openai"
|
|
|
|
link="openai.com"
|
|
|
|
description="The standard option for most non-commercial use. Provides both chat and embedding."
|
|
|
|
checked={embeddingChoice === "openai"}
|
|
|
|
image={OpenAiLogo}
|
|
|
|
onClick={updateChoice}
|
|
|
|
/>
|
|
|
|
<LLMProviderOption
|
|
|
|
name="Azure OpenAI"
|
|
|
|
value="azure"
|
|
|
|
link="azure.microsoft.com"
|
|
|
|
description="The enterprise option of OpenAI hosted on Azure services. Provides both chat and embedding."
|
|
|
|
checked={embeddingChoice === "azure"}
|
|
|
|
image={AzureOpenAiLogo}
|
|
|
|
onClick={updateChoice}
|
|
|
|
/>
|
2023-11-14 22:49:31 +01:00
|
|
|
<LLMProviderOption
|
|
|
|
name="LocalAI"
|
|
|
|
value="localai"
|
|
|
|
link="localai.io"
|
|
|
|
description="Self hosted LocalAI embedding engine."
|
|
|
|
checked={embeddingChoice === "localai"}
|
|
|
|
image={LocalAiLogo}
|
|
|
|
onClick={updateChoice}
|
|
|
|
/>
|
2023-10-30 15:44:03 -07:00
|
|
|
</div>
|
|
|
|
<div className="mt-10 flex flex-wrap gap-4 max-w-[800px]">
|
|
|
|
{embeddingChoice === "openai" && (
|
|
|
|
<>
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
API Key
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="password"
|
|
|
|
name="OpenAiKey"
|
|
|
|
className="bg-zinc-900 text-white placeholder-white placeholder-opacity-60 text-sm rounded-lg focus:border-white block w-full p-2.5"
|
|
|
|
placeholder="OpenAI API Key"
|
|
|
|
defaultValue={settings?.OpenAiKey ? "*".repeat(20) : ""}
|
|
|
|
required={true}
|
|
|
|
autoComplete="off"
|
|
|
|
spellCheck={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{embeddingChoice === "azure" && (
|
|
|
|
<>
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
Azure Service Endpoint
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="url"
|
|
|
|
name="AzureOpenAiEndpoint"
|
|
|
|
className="bg-zinc-900 text-white placeholder-white placeholder-opacity-60 text-sm rounded-lg focus:border-white block w-full p-2.5"
|
|
|
|
placeholder="https://my-azure.openai.azure.com"
|
|
|
|
defaultValue={settings?.AzureOpenAiEndpoint}
|
|
|
|
required={true}
|
|
|
|
autoComplete="off"
|
|
|
|
spellCheck={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
API Key
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="password"
|
|
|
|
name="AzureOpenAiKey"
|
|
|
|
className="bg-zinc-900 text-white placeholder-white placeholder-opacity-60 text-sm rounded-lg focus:border-white block w-full p-2.5"
|
|
|
|
placeholder="Azure OpenAI API Key"
|
|
|
|
defaultValue={
|
|
|
|
settings?.AzureOpenAiKey ? "*".repeat(20) : ""
|
|
|
|
}
|
|
|
|
required={true}
|
|
|
|
autoComplete="off"
|
|
|
|
spellCheck={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
Embedding Deployment Name
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
name="AzureOpenAiEmbeddingModelPref"
|
|
|
|
className="bg-zinc-900 text-white placeholder-white placeholder-opacity-60 text-sm rounded-lg focus:border-white block w-full p-2.5"
|
|
|
|
placeholder="Azure OpenAI embedding model deployment name"
|
|
|
|
defaultValue={settings?.AzureOpenAiEmbeddingModelPref}
|
|
|
|
required={true}
|
|
|
|
autoComplete="off"
|
|
|
|
spellCheck={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
2023-11-14 22:49:31 +01:00
|
|
|
|
|
|
|
{embeddingChoice === "localai" && (
|
|
|
|
<>
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
LocalAI Base URL
|
|
|
|
</label>
|
|
|
|
<input
|
|
|
|
type="url"
|
|
|
|
name="EmbeddingBasePath"
|
|
|
|
className="bg-zinc-900 text-white placeholder-white placeholder-opacity-60 text-sm rounded-lg focus:border-white block w-full p-2.5"
|
|
|
|
placeholder="http://localhost:8080/v1"
|
|
|
|
defaultValue={settings?.EmbeddingBasePath}
|
|
|
|
onChange={(e) => setBasePathValue(e.target.value)}
|
|
|
|
onBlur={updateBasePath}
|
|
|
|
required={true}
|
|
|
|
autoComplete="off"
|
|
|
|
spellCheck={false}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<LocalAIModelSelection
|
|
|
|
settings={settings}
|
|
|
|
basePath={basePath}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
)}
|
2023-10-30 15:44:03 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex w-full justify-between items-center p-6 space-x-2 border-t rounded-b border-gray-500/50">
|
|
|
|
<button
|
2023-11-08 19:00:12 -08:00
|
|
|
onClick={prevStep}
|
2023-10-30 15:44:03 -07:00
|
|
|
type="button"
|
|
|
|
className="px-4 py-2 rounded-lg text-white hover:bg-sidebar"
|
|
|
|
>
|
|
|
|
Back
|
|
|
|
</button>
|
|
|
|
<button
|
|
|
|
type="submit"
|
|
|
|
className="border border-slate-200 px-4 py-2 rounded-lg text-slate-800 bg-slate-200 text-sm items-center flex gap-x-2 hover:text-white hover:bg-transparent focus:ring-gray-800 font-semibold shadow"
|
|
|
|
>
|
|
|
|
Continue
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-11-14 22:49:31 +01:00
|
|
|
function LocalAIModelSelection({ settings, basePath = null }) {
|
|
|
|
const [customModels, setCustomModels] = useState([]);
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
async function findCustomModels() {
|
|
|
|
if (!basePath || !basePath.includes("/v1")) {
|
|
|
|
setCustomModels([]);
|
|
|
|
setLoading(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setLoading(true);
|
|
|
|
const { models } = await System.customModels("localai", null, basePath);
|
|
|
|
setCustomModels(models || []);
|
|
|
|
setLoading(false);
|
|
|
|
}
|
|
|
|
findCustomModels();
|
|
|
|
}, [basePath]);
|
|
|
|
|
|
|
|
if (loading || customModels.length == 0) {
|
|
|
|
return (
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
Embedding Model Name
|
|
|
|
</label>
|
|
|
|
<select
|
|
|
|
name="EmbeddingModelPref"
|
|
|
|
disabled={true}
|
|
|
|
className="bg-zinc-900 border border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
|
|
|
|
>
|
|
|
|
<option disabled={true} selected={true}>
|
|
|
|
{basePath?.includes("/v1")
|
|
|
|
? "-- loading available models --"
|
|
|
|
: "-- waiting for URL --"}
|
|
|
|
</option>
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="flex flex-col w-60">
|
|
|
|
<label className="text-white text-sm font-semibold block mb-4">
|
|
|
|
Embedding Model Name
|
|
|
|
</label>
|
|
|
|
<select
|
|
|
|
name="EmbeddingModelPref"
|
|
|
|
required={true}
|
|
|
|
className="bg-zinc-900 border border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
|
|
|
|
>
|
|
|
|
{customModels.length > 0 && (
|
|
|
|
<optgroup label="Your loaded models">
|
|
|
|
{customModels.map((model) => {
|
|
|
|
return (
|
|
|
|
<option
|
|
|
|
key={model.id}
|
|
|
|
value={model.id}
|
|
|
|
selected={settings.EmbeddingModelPref === model.id}
|
|
|
|
>
|
|
|
|
{model.id}
|
|
|
|
</option>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</optgroup>
|
|
|
|
)}
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-10-30 15:44:03 -07:00
|
|
|
export default memo(EmbeddingSelection);
|