[FEAT] Implement auto detect URL for KoboldCPP (#1860)

* implement auto detect url for koboldcpp

* remove unneeded import

* border-none inputs and buttons

---------

Co-authored-by: timothycarambat <rambat1010@gmail.com>
This commit is contained in:
Sean Hatfield 2024-07-15 11:39:48 -07:00 committed by GitHub
parent f367d82ebd
commit f553f07ec5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 139 additions and 47 deletions

View File

@ -1,47 +1,116 @@
import { useState, useEffect } from "react"; import { useEffect, useState } from "react";
import System from "@/models/system"; import System from "@/models/system";
import PreLoader from "@/components/Preloader";
import { KOBOLDCPP_COMMON_URLS } from "@/utils/constants";
import { CaretDown, CaretUp } from "@phosphor-icons/react";
import useProviderEndpointAutoDiscovery from "@/hooks/useProviderEndpointAutoDiscovery";
export default function KoboldCPPOptions({ settings }) { export default function KoboldCPPOptions({ settings }) {
const [basePathValue, setBasePathValue] = useState( const {
settings?.KoboldCPPBasePath autoDetecting: loading,
basePath,
basePathValue,
showAdvancedControls,
setShowAdvancedControls,
handleAutoDetectClick,
} = useProviderEndpointAutoDiscovery({
provider: "koboldcpp",
initialBasePath: settings?.KoboldCPPBasePath,
ENDPOINTS: KOBOLDCPP_COMMON_URLS,
});
const [tokenLimit, setTokenLimit] = useState(
settings?.KoboldCPPTokenLimit || 4096
); );
const [basePath, setBasePath] = useState(settings?.KoboldCPPBasePath);
const handleTokenLimitChange = (e) => {
setTokenLimit(Number(e.target.value));
};
return ( return (
<div className="flex gap-[36px] mt-1.5 flex-wrap"> <div className="w-full flex flex-col gap-y-7">
<div className="flex flex-col w-60"> <div className="w-full flex items-start gap-[36px] mt-1.5">
<label className="text-white text-sm font-semibold block mb-3"> <KoboldCPPModelSelection
Base URL settings={settings}
</label> basePath={basePath.value}
<input
type="url"
name="KoboldCPPBasePath"
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="http://127.0.0.1:5000/v1"
defaultValue={settings?.KoboldCPPBasePath}
required={true}
autoComplete="off"
spellCheck={false}
onChange={(e) => setBasePathValue(e.target.value)}
onBlur={() => setBasePath(basePathValue)}
/> />
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-2">
Token context window
</label>
<input
type="number"
name="KoboldCPPTokenLimit"
className="border-none bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="4096"
min={1}
value={tokenLimit}
onChange={handleTokenLimitChange}
onScroll={(e) => e.target.blur()}
required={true}
autoComplete="off"
/>
<p className="text-xs leading-[18px] font-base text-white text-opacity-60 mt-2">
Maximum number of tokens for context and response.
</p>
</div>
</div> </div>
<KoboldCPPModelSelection settings={settings} basePath={basePath} /> <div className="flex justify-start mt-4">
<div className="flex flex-col w-60"> <button
<label className="text-white text-sm font-semibold block mb-3"> onClick={(e) => {
Token context window e.preventDefault();
</label> setShowAdvancedControls(!showAdvancedControls);
<input }}
type="number" className="border-none text-white hover:text-white/70 flex items-center text-sm"
name="KoboldCPPTokenLimit" >
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" {showAdvancedControls ? "Hide" : "Show"} Manual Endpoint Input
placeholder="4096" {showAdvancedControls ? (
min={1} <CaretUp size={14} className="ml-1" />
onScroll={(e) => e.target.blur()} ) : (
defaultValue={settings?.KoboldCPPTokenLimit} <CaretDown size={14} className="ml-1" />
required={true} )}
autoComplete="off" </button>
/> </div>
<div hidden={!showAdvancedControls}>
<div className="w-full flex items-start gap-4">
<div className="flex flex-col w-60">
<div className="flex justify-between items-center mb-2">
<label className="text-white text-sm font-semibold">
KoboldCPP Base URL
</label>
{loading ? (
<PreLoader size="6" />
) : (
<>
{!basePathValue.value && (
<button
onClick={handleAutoDetectClick}
className="border-none bg-primary-button text-xs font-medium px-2 py-1 rounded-lg hover:bg-secondary hover:text-white shadow-[0_4px_14px_rgba(0,0,0,0.25)]"
>
Auto-Detect
</button>
)}
</>
)}
</div>
<input
type="url"
name="KoboldCPPBasePath"
className="border-none bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="http://127.0.0.1:5000/v1"
value={basePathValue.value}
required={true}
autoComplete="off"
spellCheck={false}
onChange={basePath.onChange}
onBlur={basePath.onBlur}
/>
<p className="text-xs leading-[18px] font-base text-white text-opacity-60 mt-2">
Enter the URL where KoboldCPP is running.
</p>
</div>
</div>
</div> </div>
</div> </div>
); );
@ -59,8 +128,17 @@ function KoboldCPPModelSelection({ settings, basePath = null }) {
return; return;
} }
setLoading(true); setLoading(true);
const { models } = await System.customModels("koboldcpp", null, basePath); try {
setCustomModels(models || []); const { models } = await System.customModels(
"koboldcpp",
null,
basePath
);
setCustomModels(models || []);
} catch (error) {
console.error("Failed to fetch custom models:", error);
setCustomModels([]);
}
setLoading(false); setLoading(false);
} }
findCustomModels(); findCustomModels();
@ -69,44 +147,51 @@ function KoboldCPPModelSelection({ settings, basePath = null }) {
if (loading || customModels.length === 0) { if (loading || customModels.length === 0) {
return ( return (
<div className="flex flex-col w-60"> <div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3"> <label className="text-white text-sm font-semibold block mb-2">
Chat Model Selection KoboldCPP Model
</label> </label>
<select <select
name="KoboldCPPModelPref" name="KoboldCPPModelPref"
disabled={true} disabled={true}
className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5" className="border-none bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
> >
<option disabled={true} selected={true}> <option disabled={true} selected={true}>
{basePath?.includes("/v1") {basePath?.includes("/v1")
? "-- loading available models --" ? "--loading available models--"
: "-- waiting for URL --"} : "Enter KoboldCPP URL first"}
</option> </option>
</select> </select>
<p className="text-xs leading-[18px] font-base text-white text-opacity-60 mt-2">
Select the KoboldCPP model you want to use. Models will load after
entering a valid KoboldCPP URL.
</p>
</div> </div>
); );
} }
return ( return (
<div className="flex flex-col w-60"> <div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3"> <label className="text-white text-sm font-semibold block mb-2">
Chat Model Selection KoboldCPP Model
</label> </label>
<select <select
name="KoboldCPPModelPref" name="KoboldCPPModelPref"
required={true} required={true}
className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5" className="border-none bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5"
> >
{customModels.map((model) => ( {customModels.map((model) => (
<option <option
key={model.id} key={model.id}
value={model.id} value={model.id}
selected={settings?.KoboldCPPModelPref === model.id} selected={settings.KoboldCPPModelPref === model.id}
> >
{model.id} {model.id}
</option> </option>
))} ))}
</select> </select>
<p className="text-xs leading-[18px] font-base text-white text-opacity-60 mt-2">
Choose the KoboldCPP model you want to use for your conversations.
</p>
</div> </div>
); );
} }

View File

@ -23,6 +23,13 @@ export const LMSTUDIO_COMMON_URLS = [
"http://172.17.0.1:1234/v1", "http://172.17.0.1:1234/v1",
]; ];
export const KOBOLDCPP_COMMON_URLS = [
"http://127.0.0.1:5000/v1",
"http://localhost:5000/v1",
"http://host.docker.internal:5000/v1",
"http://172.17.0.1:5000/v1",
];
export function fullApiUrl() { export function fullApiUrl() {
if (API_BASE !== "/api") return API_BASE; if (API_BASE !== "/api") return API_BASE;
return `${window.location.origin}/api`; return `${window.location.origin}/api`;