From 826ef00da30738c458772ae93f8d4d7f10b9231c Mon Sep 17 00:00:00 2001 From: Sean Hatfield <seanhatfield5@gmail.com> Date: Thu, 16 May 2024 13:56:28 -0700 Subject: [PATCH] [FEAT] LiteLLM provider support (#1424) * litellm LLM provider support * fix lint error * change import orders fix issue with model retrieval --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com> --- README.md | 1 + docker/.env.example | 6 + .../LLMSelection/LiteLLMOptions/index.jsx | 148 +++++++++++++++ frontend/src/media/llmprovider/litellm.png | Bin 0 -> 50535 bytes .../GeneralSettings/LLMPreference/index.jsx | 14 +- .../Steps/DataHandling/index.jsx | 9 + .../Steps/LLMPreference/index.jsx | 14 +- server/.env.example | 6 + server/models/systemSettings.js | 6 + server/utils/AiProviders/liteLLM/index.js | 178 ++++++++++++++++++ server/utils/helpers/customModels.js | 22 +++ server/utils/helpers/index.js | 3 + server/utils/helpers/updateENV.js | 19 ++ 13 files changed, 422 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/LLMSelection/LiteLLMOptions/index.jsx create mode 100644 frontend/src/media/llmprovider/litellm.png create mode 100644 server/utils/AiProviders/liteLLM/index.js diff --git a/README.md b/README.md index e15f7ff65..bf50f209a 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Some cool features of AnythingLLM - [Groq](https://groq.com/) - [Cohere](https://cohere.com/) - [KoboldCPP](https://github.com/LostRuins/koboldcpp) +- [LiteLLM](https://github.com/BerriAI/litellm) - [Text Generation Web UI](https://github.com/oobabooga/text-generation-webui) **Embedder models:** diff --git a/docker/.env.example b/docker/.env.example index 70059ea51..7fedf944c 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -82,6 +82,12 @@ GID='1000' # GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT=4096 # GENERIC_OPEN_AI_API_KEY=sk-123abc +# LLM_PROVIDER='litellm' +# LITE_LLM_MODEL_PREF='gpt-3.5-turbo' +# LITE_LLM_MODEL_TOKEN_LIMIT=4096 +# LITE_LLM_BASE_PATH='http://127.0.0.1:4000' +# LITE_LLM_API_KEY='sk-123abc' + # LLM_PROVIDER='cohere' # COHERE_API_KEY= # COHERE_MODEL_PREF='command-r' diff --git a/frontend/src/components/LLMSelection/LiteLLMOptions/index.jsx b/frontend/src/components/LLMSelection/LiteLLMOptions/index.jsx new file mode 100644 index 000000000..6199ba26d --- /dev/null +++ b/frontend/src/components/LLMSelection/LiteLLMOptions/index.jsx @@ -0,0 +1,148 @@ +import { useEffect, useState } from "react"; +import System from "@/models/system"; + +export default function LiteLLMOptions({ settings }) { + const [basePathValue, setBasePathValue] = useState(settings?.LiteLLMBasePath); + const [basePath, setBasePath] = useState(settings?.LiteLLMBasePath); + const [apiKeyValue, setApiKeyValue] = useState(settings?.LiteLLMAPIKey); + const [apiKey, setApiKey] = useState(settings?.LiteLLMAPIKey); + + return ( + <div className="w-full flex flex-col gap-y-4"> + <div className="w-full flex items-center gap-4"> + <div className="flex flex-col w-60"> + <label className="text-white text-sm font-semibold block mb-4"> + Base URL + </label> + <input + type="url" + name="LiteLLMBasePath" + className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5" + placeholder="http://127.0.0.1:4000" + defaultValue={settings?.LiteLLMBasePath} + required={true} + autoComplete="off" + spellCheck={false} + onChange={(e) => setBasePathValue(e.target.value)} + onBlur={() => setBasePath(basePathValue)} + /> + </div> + <LiteLLMModelSelection + settings={settings} + basePath={basePath} + apiKey={apiKey} + /> + <div className="flex flex-col w-60"> + <label className="text-white text-sm font-semibold block mb-4"> + Token context window + </label> + <input + type="number" + name="LiteLLMTokenLimit" + className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5" + placeholder="4096" + min={1} + onScroll={(e) => e.target.blur()} + defaultValue={settings?.LiteLLMTokenLimit} + required={true} + autoComplete="off" + /> + </div> + </div> + <div className="w-full flex items-center gap-4"> + <div className="flex flex-col w-60"> + <div className="flex flex-col gap-y-1 mb-4"> + <label className="text-white text-sm font-semibold flex items-center gap-x-2"> + API Key <p className="!text-xs !italic !font-thin">optional</p> + </label> + </div> + <input + type="password" + name="LiteLLMAPIKey" + className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:border-white block w-full p-2.5" + placeholder="sk-mysecretkey" + defaultValue={settings?.LiteLLMAPIKey ? "*".repeat(20) : ""} + autoComplete="off" + spellCheck={false} + onChange={(e) => setApiKeyValue(e.target.value)} + onBlur={() => setApiKey(apiKeyValue)} + /> + </div> + </div> + </div> + ); +} + +function LiteLLMModelSelection({ settings, basePath = null, apiKey = null }) { + const [customModels, setCustomModels] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function findCustomModels() { + if (!basePath) { + setCustomModels([]); + setLoading(false); + return; + } + setLoading(true); + const { models } = await System.customModels( + "litellm", + typeof apiKey === "boolean" ? null : apiKey, + basePath + ); + setCustomModels(models || []); + setLoading(false); + } + findCustomModels(); + }, [basePath, apiKey]); + + if (loading || customModels.length == 0) { + return ( + <div className="flex flex-col w-60"> + <label className="text-white text-sm font-semibold block mb-4"> + Chat Model Selection + </label> + <select + name="LiteLLMModelPref" + disabled={true} + className="bg-zinc-900 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"> + Chat Model Selection + </label> + <select + name="LiteLLMModelPref" + required={true} + className="bg-zinc-900 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.LiteLLMModelPref === model.id} + > + {model.id} + </option> + ); + })} + </optgroup> + )} + </select> + </div> + ); +} diff --git a/frontend/src/media/llmprovider/litellm.png b/frontend/src/media/llmprovider/litellm.png new file mode 100644 index 0000000000000000000000000000000000000000..da4faf5b5ca6c812a73e3c1a74d93ea6f6afa682 GIT binary patch literal 50535 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 L{an^LB{Ts5taLn5 literal 0 HcmV?d00001 diff --git a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx index 4db201236..5c4b0b2f0 100644 --- a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx +++ b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx @@ -21,6 +21,7 @@ import GroqLogo from "@/media/llmprovider/groq.png"; import KoboldCPPLogo from "@/media/llmprovider/koboldcpp.png"; import TextGenWebUILogo from "@/media/llmprovider/text-generation-webui.png"; import CohereLogo from "@/media/llmprovider/cohere.png"; +import LiteLLMLogo from "@/media/llmprovider/litellm.png"; import PreLoader from "@/components/Preloader"; import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions"; import GenericOpenAiOptions from "@/components/LLMSelection/GenericOpenAiOptions"; @@ -38,12 +39,13 @@ import PerplexityOptions from "@/components/LLMSelection/PerplexityOptions"; import OpenRouterOptions from "@/components/LLMSelection/OpenRouterOptions"; import GroqAiOptions from "@/components/LLMSelection/GroqAiOptions"; import CohereAiOptions from "@/components/LLMSelection/CohereAiOptions"; +import KoboldCPPOptions from "@/components/LLMSelection/KoboldCPPOptions"; +import TextGenWebUIOptions from "@/components/LLMSelection/TextGenWebUIOptions"; +import LiteLLMOptions from "@/components/LLMSelection/LiteLLMOptions"; import LLMItem from "@/components/LLMSelection/LLMItem"; import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react"; import CTAButton from "@/components/lib/CTAButton"; -import KoboldCPPOptions from "@/components/LLMSelection/KoboldCPPOptions"; -import TextGenWebUIOptions from "@/components/LLMSelection/TextGenWebUIOptions"; export const AVAILABLE_LLM_PROVIDERS = [ { @@ -186,6 +188,14 @@ export const AVAILABLE_LLM_PROVIDERS = [ description: "Run Cohere's powerful Command models.", requiredConfig: ["CohereApiKey"], }, + { + name: "LiteLLM", + value: "litellm", + logo: LiteLLMLogo, + options: (settings) => <LiteLLMOptions settings={settings} />, + description: "Run LiteLLM's OpenAI compatible proxy for various LLMs.", + requiredConfig: ["LiteLLMBasePath"], + }, { name: "Generic OpenAI", value: "generic-openai", diff --git a/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx b/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx index 5c6b3798c..b6ae8cb20 100644 --- a/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx +++ b/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx @@ -17,6 +17,8 @@ import OpenRouterLogo from "@/media/llmprovider/openrouter.jpeg"; import GroqLogo from "@/media/llmprovider/groq.png"; import KoboldCPPLogo from "@/media/llmprovider/koboldcpp.png"; import TextGenWebUILogo from "@/media/llmprovider/text-generation-webui.png"; +import LiteLLMLogo from "@/media/llmprovider/litellm.png"; + import CohereLogo from "@/media/llmprovider/cohere.png"; import ZillizLogo from "@/media/vectordbs/zilliz.png"; import AstraDBLogo from "@/media/vectordbs/astraDB.png"; @@ -168,6 +170,13 @@ export const LLM_SELECTION_PRIVACY = { ], logo: CohereLogo, }, + litellm: { + name: "LiteLLM", + description: [ + "Your model and chats are only accessible on the server running LiteLLM", + ], + logo: LiteLLMLogo, + }, }; export const VECTOR_DB_PRIVACY = { diff --git a/frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx b/frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx index 966253f47..25b465229 100644 --- a/frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx +++ b/frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx @@ -17,6 +17,8 @@ import OpenRouterLogo from "@/media/llmprovider/openrouter.jpeg"; import GroqLogo from "@/media/llmprovider/groq.png"; import KoboldCPPLogo from "@/media/llmprovider/koboldcpp.png"; import TextGenWebUILogo from "@/media/llmprovider/text-generation-webui.png"; +import LiteLLMLogo from "@/media/llmprovider/litellm.png"; + import CohereLogo from "@/media/llmprovider/cohere.png"; import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions"; import GenericOpenAiOptions from "@/components/LLMSelection/GenericOpenAiOptions"; @@ -34,14 +36,15 @@ import PerplexityOptions from "@/components/LLMSelection/PerplexityOptions"; import OpenRouterOptions from "@/components/LLMSelection/OpenRouterOptions"; import GroqAiOptions from "@/components/LLMSelection/GroqAiOptions"; import CohereAiOptions from "@/components/LLMSelection/CohereAiOptions"; +import KoboldCPPOptions from "@/components/LLMSelection/KoboldCPPOptions"; +import TextGenWebUIOptions from "@/components/LLMSelection/TextGenWebUIOptions"; +import LiteLLMOptions from "@/components/LLMSelection/LiteLLMOptions"; import LLMItem from "@/components/LLMSelection/LLMItem"; import System from "@/models/system"; import paths from "@/utils/paths"; import showToast from "@/utils/toast"; import { useNavigate } from "react-router-dom"; -import KoboldCPPOptions from "@/components/LLMSelection/KoboldCPPOptions"; -import TextGenWebUIOptions from "@/components/LLMSelection/TextGenWebUIOptions"; const TITLE = "LLM Preference"; const DESCRIPTION = @@ -164,6 +167,13 @@ const LLMS = [ options: (settings) => <CohereAiOptions settings={settings} />, description: "Run Cohere's powerful Command models.", }, + { + name: "LiteLLM", + value: "litellm", + logo: LiteLLMLogo, + options: (settings) => <LiteLLMOptions settings={settings} />, + description: "Run LiteLLM's OpenAI compatible proxy for various LLMs.", + }, { name: "Generic OpenAI", value: "generic-openai", diff --git a/server/.env.example b/server/.env.example index 5e0233b7b..4be9ab75e 100644 --- a/server/.env.example +++ b/server/.env.example @@ -79,6 +79,12 @@ JWT_SECRET="my-random-string-for-seeding" # Please generate random string at lea # GENERIC_OPEN_AI_MODEL_TOKEN_LIMIT=4096 # GENERIC_OPEN_AI_API_KEY=sk-123abc +# LLM_PROVIDER='litellm' +# LITE_LLM_MODEL_PREF='gpt-3.5-turbo' +# LITE_LLM_MODEL_TOKEN_LIMIT=4096 +# LITE_LLM_BASE_PATH='http://127.0.0.1:4000' +# LITE_LLM_API_KEY='sk-123abc' + # LLM_PROVIDER='cohere' # COHERE_API_KEY= # COHERE_MODEL_PREF='command-r' diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js index 7b4f21eeb..68d1d0dde 100644 --- a/server/models/systemSettings.js +++ b/server/models/systemSettings.js @@ -408,6 +408,12 @@ const SystemSettings = { TextGenWebUITokenLimit: process.env.TEXT_GEN_WEB_UI_MODEL_TOKEN_LIMIT, TextGenWebUIAPIKey: !!process.env.TEXT_GEN_WEB_UI_API_KEY, + // LiteLLM Keys + LiteLLMModelPref: process.env.LITE_LLM_MODEL_PREF, + LiteLLMTokenLimit: process.env.LITE_LLM_MODEL_TOKEN_LIMIT, + LiteLLMBasePath: process.env.LITE_LLM_BASE_PATH, + LiteLLMApiKey: !!process.env.LITE_LLM_API_KEY, + // Generic OpenAI Keys GenericOpenAiBasePath: process.env.GENERIC_OPEN_AI_BASE_PATH, GenericOpenAiModelPref: process.env.GENERIC_OPEN_AI_MODEL_PREF, diff --git a/server/utils/AiProviders/liteLLM/index.js b/server/utils/AiProviders/liteLLM/index.js new file mode 100644 index 000000000..5973826cc --- /dev/null +++ b/server/utils/AiProviders/liteLLM/index.js @@ -0,0 +1,178 @@ +const { NativeEmbedder } = require("../../EmbeddingEngines/native"); +const { + writeResponseChunk, + clientAbortedHandler, +} = require("../../helpers/chat/responses"); + +class LiteLLM { + constructor(embedder = null, modelPreference = null) { + const { OpenAI: OpenAIApi } = require("openai"); + if (!process.env.LITE_LLM_BASE_PATH) + throw new Error( + "LiteLLM must have a valid base path to use for the api." + ); + + this.basePath = process.env.LITE_LLM_BASE_PATH; + this.openai = new OpenAIApi({ + baseURL: this.basePath, + apiKey: process.env.LITE_LLM_API_KEY ?? null, + }); + this.model = modelPreference ?? process.env.LITE_LLM_MODEL_PREF ?? null; + this.maxTokens = process.env.LITE_LLM_MODEL_TOKEN_LIMIT ?? 1024; + if (!this.model) throw new Error("LiteLLM must have a valid model set."); + this.limits = { + history: this.promptWindowLimit() * 0.15, + system: this.promptWindowLimit() * 0.15, + user: this.promptWindowLimit() * 0.7, + }; + + if (!embedder) + console.warn( + "No embedding provider defined for LiteLLM - falling back to NativeEmbedder for embedding!" + ); + this.embedder = !embedder ? new NativeEmbedder() : embedder; + this.defaultTemp = 0.7; + this.log(`Inference API: ${this.basePath} Model: ${this.model}`); + } + + log(text, ...args) { + console.log(`\x1b[36m[${this.constructor.name}]\x1b[0m ${text}`, ...args); + } + + #appendContext(contextTexts = []) { + if (!contextTexts || !contextTexts.length) return ""; + return ( + "\nContext:\n" + + contextTexts + .map((text, i) => { + return `[CONTEXT ${i}]:\n${text}\n[END CONTEXT ${i}]\n\n`; + }) + .join("") + ); + } + + streamingEnabled() { + return "streamGetChatCompletion" in this; + } + + // Ensure the user set a value for the token limit + // and if undefined - assume 4096 window. + promptWindowLimit() { + const limit = process.env.LITE_LLM_MODEL_TOKEN_LIMIT || 4096; + if (!limit || isNaN(Number(limit))) + throw new Error("No token context limit was set."); + return Number(limit); + } + + // Short circuit since we have no idea if the model is valid or not + // in pre-flight for generic endpoints + isValidChatCompletionModel(_modelName = "") { + return true; + } + + constructPrompt({ + systemPrompt = "", + contextTexts = [], + chatHistory = [], + userPrompt = "", + }) { + const prompt = { + role: "system", + content: `${systemPrompt}${this.#appendContext(contextTexts)}`, + }; + return [prompt, ...chatHistory, { role: "user", content: userPrompt }]; + } + + async isSafe(_input = "") { + // Not implemented so must be stubbed + return { safe: true, reasons: [] }; + } + + async getChatCompletion(messages = null, { temperature = 0.7 }) { + const result = await this.openai.chat.completions + .create({ + model: this.model, + messages, + temperature, + max_tokens: parseInt(this.maxTokens), // LiteLLM requires int + }) + .catch((e) => { + throw new Error(e.response.data.error.message); + }); + + if (!result.hasOwnProperty("choices") || result.choices.length === 0) + return null; + return result.choices[0].message.content; + } + + async streamGetChatCompletion(messages = null, { temperature = 0.7 }) { + const streamRequest = await this.openai.chat.completions.create({ + model: this.model, + stream: true, + messages, + temperature, + max_tokens: parseInt(this.maxTokens), // LiteLLM requires int + }); + return streamRequest; + } + + handleStream(response, stream, responseProps) { + const { uuid = uuidv4(), sources = [] } = responseProps; + + return new Promise(async (resolve) => { + let fullText = ""; + + const handleAbort = () => clientAbortedHandler(resolve, fullText); + response.on("close", handleAbort); + + for await (const chunk of stream) { + const message = chunk?.choices?.[0]; + const token = message?.delta?.content; + + if (token) { + fullText += token; + writeResponseChunk(response, { + uuid, + sources: [], + type: "textResponseChunk", + textResponse: token, + close: false, + error: false, + }); + } + + // LiteLLM does not give a finish reason in stream until the final chunk + if (message.finish_reason || message.finish_reason === "stop") { + writeResponseChunk(response, { + uuid, + sources, + type: "textResponseChunk", + textResponse: "", + close: true, + error: false, + }); + response.removeListener("close", handleAbort); + resolve(fullText); + } + } + }); + } + + // Simple wrapper for dynamic embedder & normalize interface for all LLM implementations + async embedTextInput(textInput) { + return await this.embedder.embedTextInput(textInput); + } + async embedChunks(textChunks = []) { + return await this.embedder.embedChunks(textChunks); + } + + async compressMessages(promptArgs = {}, rawHistory = []) { + const { messageArrayCompressor } = require("../../helpers/chat"); + const messageArray = this.constructPrompt(promptArgs); + return await messageArrayCompressor(this, messageArray, rawHistory); + } +} + +module.exports = { + LiteLLM, +}; diff --git a/server/utils/helpers/customModels.js b/server/utils/helpers/customModels.js index caf5a77c7..31a3eb2c0 100644 --- a/server/utils/helpers/customModels.js +++ b/server/utils/helpers/customModels.js @@ -16,6 +16,7 @@ const SUPPORT_CUSTOM_MODELS = [ "openrouter", "lmstudio", "koboldcpp", + "litellm", "elevenlabs-tts", ]; @@ -44,6 +45,8 @@ async function getCustomModels(provider = "", apiKey = null, basePath = null) { return await getLMStudioModels(basePath); case "koboldcpp": return await getKoboldCPPModels(basePath); + case "litellm": + return await liteLLMModels(basePath, apiKey); case "elevenlabs-tts": return await getElevenLabsModels(apiKey); default: @@ -164,6 +167,25 @@ async function localAIModels(basePath = null, apiKey = null) { return { models, error: null }; } +async function liteLLMModels(basePath = null, apiKey = null) { + const { OpenAI: OpenAIApi } = require("openai"); + const openai = new OpenAIApi({ + baseURL: basePath || process.env.LITE_LLM_BASE_PATH, + apiKey: apiKey || process.env.LITE_LLM_API_KEY || null, + }); + const models = await openai.models + .list() + .then((results) => results.data) + .catch((e) => { + console.error(`LiteLLM:listModels`, e.message); + return []; + }); + + // Api Key was successful so lets save it for future uses + if (models.length > 0 && !!apiKey) process.env.LITE_LLM_API_KEY = apiKey; + return { models, error: null }; +} + async function getLMStudioModels(basePath = null) { try { const { OpenAI: OpenAIApi } = require("openai"); diff --git a/server/utils/helpers/index.js b/server/utils/helpers/index.js index 72fbfc6e3..dde8d7ab4 100644 --- a/server/utils/helpers/index.js +++ b/server/utils/helpers/index.js @@ -86,6 +86,9 @@ function getLLMProvider({ provider = null, model = null } = {}) { case "cohere": const { CohereLLM } = require("../AiProviders/cohere"); return new CohereLLM(embedder, model); + case "litellm": + const { LiteLLM } = require("../AiProviders/liteLLM"); + return new LiteLLM(embedder, model); case "generic-openai": const { GenericOpenAiLLM } = require("../AiProviders/genericOpenAi"); return new GenericOpenAiLLM(embedder, model); diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js index e2b1d2e1c..8630d85a1 100644 --- a/server/utils/helpers/updateENV.js +++ b/server/utils/helpers/updateENV.js @@ -160,6 +160,24 @@ const KEY_MAPPING = { checks: [], }, + // LiteLLM Settings + LiteLLMModelPref: { + envKey: "LITE_LLM_MODEL_PREF", + checks: [isNotEmpty], + }, + LiteLLMTokenLimit: { + envKey: "LITE_LLM_MODEL_TOKEN_LIMIT", + checks: [nonZero], + }, + LiteLLMBasePath: { + envKey: "LITE_LLM_BASE_PATH", + checks: [isValidURL], + }, + LiteLLMApiKey: { + envKey: "LITE_LLM_API_KEY", + checks: [], + }, + // Generic OpenAI InferenceSettings GenericOpenAiBasePath: { envKey: "GENERIC_OPEN_AI_BASE_PATH", @@ -469,6 +487,7 @@ function supportedLLM(input = "") { "koboldcpp", "textgenwebui", "cohere", + "litellm", "generic-openai", ].includes(input); return validSelection ? null : `${input} is not a valid LLM provider.`; -- GitLab