1351 lines
39 KiB
JavaScript
1351 lines
39 KiB
JavaScript
const { fetchOpenRouterModels } = require("../AiProviders/openRouter");
|
|
const {
|
|
fetchOpenRouterEmbeddingModels,
|
|
} = require("../EmbeddingEngines/openRouter");
|
|
const { fetchApiPieModels } = require("../AiProviders/apipie");
|
|
const { perplexityModels } = require("../AiProviders/perplexity");
|
|
const { fireworksAiModels } = require("../AiProviders/fireworksAi");
|
|
const { ElevenLabsTTS } = require("../TextToSpeech/elevenLabs");
|
|
const { fetchNovitaModels } = require("../AiProviders/novita");
|
|
const { parseLMStudioBasePath } = require("../AiProviders/lmStudio");
|
|
const { parseNvidiaNimBasePath } = require("../AiProviders/nvidiaNim");
|
|
const { fetchPPIOModels } = require("../AiProviders/ppio");
|
|
const { GeminiLLM } = require("../AiProviders/gemini");
|
|
const { fetchCometApiModels } = require("../AiProviders/cometapi");
|
|
const { parseFoundryBasePath } = require("../AiProviders/foundry");
|
|
const { getDockerModels } = require("../AiProviders/dockerModelRunner");
|
|
const { getAllLemonadeModels } = require("../AiProviders/lemonade");
|
|
|
|
const SUPPORT_CUSTOM_MODELS = [
|
|
"openai",
|
|
"anthropic",
|
|
"localai",
|
|
"ollama",
|
|
"togetherai",
|
|
"fireworksai",
|
|
"nvidia-nim",
|
|
"mistral",
|
|
"perplexity",
|
|
"openrouter",
|
|
"lmstudio",
|
|
"koboldcpp",
|
|
"litellm",
|
|
"elevenlabs-tts",
|
|
"groq",
|
|
"deepseek",
|
|
"apipie",
|
|
"novita",
|
|
"cometapi",
|
|
"xai",
|
|
"gemini",
|
|
"ppio",
|
|
"moonshotai",
|
|
"foundry",
|
|
"cohere",
|
|
"zai",
|
|
"giteeai",
|
|
"docker-model-runner",
|
|
"privatemode",
|
|
"sambanova",
|
|
"lemonade",
|
|
"minimax",
|
|
"cerebras",
|
|
"bedrock",
|
|
"generic-openai",
|
|
// Embedding Engines
|
|
"native-embedder",
|
|
"cohere-embedder",
|
|
"openrouter-embedder",
|
|
"lemonade-embedder",
|
|
// STT Engines
|
|
"openai-stt",
|
|
"deepgram-stt",
|
|
"lemonade-stt",
|
|
"groq-stt",
|
|
// TTS Engines
|
|
"kokoro-tts",
|
|
];
|
|
|
|
async function getCustomModels(
|
|
provider = "",
|
|
apiKey = null,
|
|
basePath = null,
|
|
options = {}
|
|
) {
|
|
if (!SUPPORT_CUSTOM_MODELS.includes(provider))
|
|
return { models: [], error: "Invalid provider for custom models" };
|
|
|
|
switch (provider) {
|
|
case "openai":
|
|
return await openAiModels(apiKey);
|
|
case "openai-stt":
|
|
return await openAiSttModels(apiKey);
|
|
case "anthropic":
|
|
return await anthropicModels(apiKey);
|
|
case "localai":
|
|
return await localAIModels(basePath, apiKey);
|
|
case "ollama":
|
|
return await ollamaAIModels(basePath, apiKey);
|
|
case "togetherai":
|
|
return await getTogetherAiModels(apiKey);
|
|
case "fireworksai":
|
|
return await getFireworksAiModels(apiKey);
|
|
case "mistral":
|
|
return await getMistralModels(apiKey);
|
|
case "perplexity":
|
|
return await getPerplexityModels();
|
|
case "openrouter":
|
|
return await getOpenRouterModels();
|
|
case "lmstudio":
|
|
return await getLMStudioModels(basePath, apiKey);
|
|
case "koboldcpp":
|
|
return await getKoboldCPPModels(basePath);
|
|
case "litellm":
|
|
return await liteLLMModels(basePath, apiKey);
|
|
case "elevenlabs-tts":
|
|
return await getElevenLabsModels(apiKey);
|
|
case "groq":
|
|
return await getGroqAiModels(apiKey);
|
|
case "deepseek":
|
|
return await getDeepSeekModels(apiKey);
|
|
case "apipie":
|
|
return await getAPIPieModels(apiKey);
|
|
case "novita":
|
|
return await getNovitaModels();
|
|
case "cometapi":
|
|
return await getCometApiModels();
|
|
case "xai":
|
|
return await getXAIModels(apiKey);
|
|
case "nvidia-nim":
|
|
return await getNvidiaNimModels(basePath);
|
|
case "gemini":
|
|
return await getGeminiModels(apiKey);
|
|
case "ppio":
|
|
return await getPPIOModels(apiKey);
|
|
case "moonshotai":
|
|
return await getMoonshotAiModels(apiKey);
|
|
case "foundry":
|
|
return await getFoundryModels(basePath);
|
|
case "cohere":
|
|
return await getCohereModels(apiKey, "chat");
|
|
case "zai":
|
|
return await getZAiModels(apiKey);
|
|
case "native-embedder":
|
|
return await getNativeEmbedderModels();
|
|
case "cohere-embedder":
|
|
return await getCohereModels(apiKey, "embed");
|
|
case "openrouter-embedder":
|
|
return await getOpenRouterEmbeddingModels();
|
|
case "giteeai":
|
|
return await getGiteeAIModels(apiKey);
|
|
case "docker-model-runner":
|
|
return await getDockerModelRunnerModels(basePath);
|
|
case "privatemode":
|
|
return await getPrivatemodeModels(basePath, "generate");
|
|
case "sambanova":
|
|
return await getSambaNovaModels(apiKey);
|
|
case "lemonade":
|
|
return await getLemonadeModels(basePath);
|
|
case "lemonade-stt":
|
|
return await getLemonadeSTTModels(basePath);
|
|
case "lemonade-embedder":
|
|
return await getLemonadeModels(basePath, "embedding");
|
|
case "minimax":
|
|
return await getMinimaxModels(apiKey);
|
|
case "cerebras":
|
|
return await getCerebrasModels();
|
|
case "bedrock":
|
|
return await getBedrockModels(apiKey, options);
|
|
case "generic-openai":
|
|
return await getGenericOpenAiModels(basePath, apiKey);
|
|
case "deepgram-stt":
|
|
return await getDeepgramSTTModels(apiKey);
|
|
case "groq-stt":
|
|
return await getGroqSTTModels(apiKey);
|
|
case "kokoro-tts":
|
|
return await kokoroTtsVoices(basePath, apiKey);
|
|
default:
|
|
return { models: [], error: "Invalid provider for custom models" };
|
|
}
|
|
}
|
|
|
|
async function openAiModels(apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
apiKey: apiKey || process.env.OPEN_AI_KEY,
|
|
});
|
|
const allModels = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`OpenAI:listModels`, e.message);
|
|
return [
|
|
{
|
|
name: "gpt-3.5-turbo",
|
|
id: "gpt-3.5-turbo",
|
|
object: "model",
|
|
created: 1677610602,
|
|
owned_by: "openai",
|
|
organization: "OpenAi",
|
|
},
|
|
{
|
|
name: "gpt-4o",
|
|
id: "gpt-4o",
|
|
object: "model",
|
|
created: 1677610602,
|
|
owned_by: "openai",
|
|
organization: "OpenAi",
|
|
},
|
|
{
|
|
name: "gpt-4",
|
|
id: "gpt-4",
|
|
object: "model",
|
|
created: 1687882411,
|
|
owned_by: "openai",
|
|
organization: "OpenAi",
|
|
},
|
|
{
|
|
name: "gpt-4-turbo",
|
|
id: "gpt-4-turbo",
|
|
object: "model",
|
|
created: 1712361441,
|
|
owned_by: "system",
|
|
organization: "OpenAi",
|
|
},
|
|
{
|
|
name: "gpt-4-32k",
|
|
id: "gpt-4-32k",
|
|
object: "model",
|
|
created: 1687979321,
|
|
owned_by: "openai",
|
|
organization: "OpenAi",
|
|
},
|
|
{
|
|
name: "gpt-3.5-turbo-16k",
|
|
id: "gpt-3.5-turbo-16k",
|
|
object: "model",
|
|
created: 1683758102,
|
|
owned_by: "openai-internal",
|
|
organization: "OpenAi",
|
|
},
|
|
];
|
|
});
|
|
|
|
const gpts = allModels
|
|
.filter(
|
|
(model) =>
|
|
(model.id.includes("gpt") && !model.id.startsWith("ft:")) ||
|
|
model.id.startsWith("o") // o1, o1-mini, o3, etc
|
|
)
|
|
.filter(
|
|
(model) =>
|
|
!model.id.includes("vision") &&
|
|
!model.id.includes("instruct") &&
|
|
!model.id.includes("audio") &&
|
|
!model.id.includes("realtime") &&
|
|
!model.id.includes("image") &&
|
|
!model.id.includes("moderation") &&
|
|
!model.id.includes("transcribe")
|
|
)
|
|
.map((model) => {
|
|
return {
|
|
...model,
|
|
name: model.id,
|
|
organization: "OpenAi",
|
|
};
|
|
});
|
|
|
|
const customModels = allModels
|
|
.filter(
|
|
(model) =>
|
|
!model.owned_by.includes("openai") && model.owned_by !== "system"
|
|
)
|
|
.map((model) => {
|
|
return {
|
|
...model,
|
|
name: model.id,
|
|
organization: "Your Fine-Tunes",
|
|
};
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if ((gpts.length > 0 || customModels.length > 0) && !!apiKey)
|
|
process.env.OPEN_AI_KEY = apiKey;
|
|
return { models: [...gpts, ...customModels], error: null };
|
|
}
|
|
|
|
async function openAiSttModels(apiKey = null) {
|
|
const fallback = [
|
|
{ id: "whisper-1", name: "whisper-1", organization: "OpenAi" },
|
|
{
|
|
id: "gpt-4o-transcribe",
|
|
name: "gpt-4o-transcribe",
|
|
organization: "OpenAi",
|
|
},
|
|
{
|
|
id: "gpt-4o-mini-transcribe",
|
|
name: "gpt-4o-mini-transcribe",
|
|
organization: "OpenAi",
|
|
},
|
|
];
|
|
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
apiKey: apiKey || process.env.OPEN_AI_KEY,
|
|
});
|
|
|
|
const allModels = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`OpenAI:listModels (stt)`, e.message);
|
|
return null;
|
|
});
|
|
|
|
if (!allModels) return { models: fallback, error: null };
|
|
|
|
// The /v1/models response has no category/type field, so we filter by id.
|
|
// Realtime variants use a separate WebSocket API and are not compatible
|
|
// with the audio.transcriptions.create endpoint we use server-side.
|
|
const models = allModels
|
|
.filter(
|
|
(m) =>
|
|
(m.id.includes("whisper") || m.id.includes("transcribe")) &&
|
|
!m.id.includes("realtime")
|
|
)
|
|
.map((m) => ({ ...m, name: m.id, organization: "OpenAi" }));
|
|
|
|
return { models: models.length ? models : fallback, error: null };
|
|
}
|
|
|
|
async function anthropicModels(_apiKey = null) {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.ANTHROPIC_API_KEY
|
|
: _apiKey || process.env.ANTHROPIC_API_KEY || null;
|
|
const AnthropicAI = require("@anthropic-ai/sdk");
|
|
const anthropic = new AnthropicAI({ apiKey });
|
|
const models = await anthropic.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then((models) => {
|
|
return models
|
|
.filter((model) => model.type === "model")
|
|
.map((model) => {
|
|
return {
|
|
id: model.id,
|
|
name: model.display_name,
|
|
};
|
|
});
|
|
})
|
|
.catch((e) => {
|
|
console.error(`Anthropic:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.ANTHROPIC_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function localAIModels(basePath = null, apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: basePath || process.env.LOCAL_AI_BASE_PATH,
|
|
apiKey: apiKey || process.env.LOCAL_AI_API_KEY || null,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`LocalAI:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.LOCAL_AI_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getGroqAiModels(_apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.GROQ_API_KEY
|
|
: _apiKey || process.env.GROQ_API_KEY || null;
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.groq.com/openai/v1",
|
|
apiKey,
|
|
});
|
|
const models = (
|
|
await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`GroqAi:listModels`, e.message);
|
|
return [];
|
|
})
|
|
).filter(
|
|
(model) => !model.id.includes("whisper") && !model.id.includes("tool-use")
|
|
);
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.GROQ_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getGroqSTTModels(_apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.STT_GROQ_API_KEY
|
|
: _apiKey || process.env.STT_GROQ_API_KEY || null;
|
|
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.groq.com/openai/v1",
|
|
apiKey,
|
|
});
|
|
const models = (
|
|
await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`GroqSTT:listModels`, e.message);
|
|
return [];
|
|
})
|
|
).filter((model) => model.id.includes("whisper"));
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.GROQ_STT_API_KEY = apiKey;
|
|
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, _apiKey = null) {
|
|
try {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.LMSTUDIO_AUTH_TOKEN
|
|
: _apiKey || process.env.LMSTUDIO_AUTH_TOKEN || null;
|
|
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: parseLMStudioBasePath(
|
|
basePath || process.env.LMSTUDIO_BASE_PATH
|
|
),
|
|
apiKey: apiKey || null,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`LMStudio:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`LMStudio:getLMStudioModels`, e.message);
|
|
return { models: [], error: "Could not fetch LMStudio Models" };
|
|
}
|
|
}
|
|
|
|
async function getKoboldCPPModels(basePath = null) {
|
|
try {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: basePath || process.env.KOBOLD_CPP_BASE_PATH,
|
|
apiKey: null,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`KoboldCPP:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`KoboldCPP:getKoboldCPPModels`, e.message);
|
|
return { models: [], error: "Could not fetch KoboldCPP Models" };
|
|
}
|
|
}
|
|
|
|
async function ollamaAIModels(basePath = null, _authToken = null) {
|
|
let url;
|
|
try {
|
|
let urlPath = basePath ?? process.env.OLLAMA_BASE_PATH;
|
|
new URL(urlPath);
|
|
if (urlPath.split("").slice(-1)?.[0] === "/")
|
|
throw new Error("BasePath Cannot end in /!");
|
|
url = urlPath;
|
|
} catch {
|
|
return { models: [], error: "Not a valid URL." };
|
|
}
|
|
|
|
const authToken = _authToken || process.env.OLLAMA_AUTH_TOKEN || null;
|
|
const headers = authToken ? { Authorization: `Bearer ${authToken}` } : {};
|
|
const models = await fetch(`${url}/api/tags`, { headers: headers })
|
|
.then((res) => {
|
|
if (!res.ok)
|
|
throw new Error(`Could not reach Ollama server! ${res.status}`);
|
|
return res.json();
|
|
})
|
|
.then((data) => data?.models || [])
|
|
.then((models) =>
|
|
models.map((model) => {
|
|
return { id: model.name };
|
|
})
|
|
)
|
|
.catch((e) => {
|
|
console.error(e);
|
|
return [];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!authToken)
|
|
process.env.OLLAMA_AUTH_TOKEN = authToken;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getTogetherAiModels(apiKey = null) {
|
|
const _apiKey =
|
|
apiKey === true
|
|
? process.env.TOGETHER_AI_API_KEY
|
|
: apiKey || process.env.TOGETHER_AI_API_KEY || null;
|
|
try {
|
|
const { togetherAiModels } = require("../AiProviders/togetherAi");
|
|
const models = await togetherAiModels(_apiKey);
|
|
if (models.length > 0 && !!_apiKey)
|
|
process.env.TOGETHER_AI_API_KEY = _apiKey;
|
|
return { models, error: null };
|
|
} catch (error) {
|
|
console.error("Error in getTogetherAiModels:", error);
|
|
return { models: [], error: "Failed to fetch Together AI models" };
|
|
}
|
|
}
|
|
|
|
async function getFireworksAiModels(apiKey = null) {
|
|
const knownModels = await fireworksAiModels(apiKey);
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
|
|
const models = Object.values(knownModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getPerplexityModels() {
|
|
const knownModels = perplexityModels();
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
|
|
const models = Object.values(knownModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getOpenRouterModels() {
|
|
const knownModels = await fetchOpenRouterModels();
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
|
|
const models = Object.values(knownModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getNovitaModels() {
|
|
const knownModels = await fetchNovitaModels();
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
const models = Object.values(knownModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getCometApiModels() {
|
|
const knownModels = await fetchCometApiModels();
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
const models = Object.values(knownModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getAPIPieModels(apiKey = null) {
|
|
const knownModels = await fetchApiPieModels(apiKey);
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
|
|
const models = Object.values(knownModels)
|
|
.filter((model) => {
|
|
// Filter for chat models
|
|
return (
|
|
model.subtype &&
|
|
(model.subtype.includes("chat") || model.subtype.includes("chatx"))
|
|
);
|
|
})
|
|
.map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getMistralModels(apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
apiKey: apiKey || process.env.MISTRAL_API_KEY || null,
|
|
baseURL: "https://api.mistral.ai/v1",
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) =>
|
|
results.data.filter((model) => !model.id.includes("embed"))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`Mistral:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.MISTRAL_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getElevenLabsModels(apiKey = null) {
|
|
const models = (await ElevenLabsTTS.voices(apiKey)).map((model) => {
|
|
return {
|
|
id: model.voice_id,
|
|
organization: model.category,
|
|
name: model.name,
|
|
};
|
|
});
|
|
|
|
if (models.length === 0) {
|
|
return {
|
|
models: [
|
|
{
|
|
id: "21m00Tcm4TlvDq8ikWAM",
|
|
organization: "premade",
|
|
name: "Rachel (default)",
|
|
},
|
|
],
|
|
error: null,
|
|
};
|
|
}
|
|
|
|
if (models.length > 0 && !!apiKey) process.env.TTS_ELEVEN_LABS_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getMinimaxModels(_apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.MINIMAX_API_KEY
|
|
: _apiKey || process.env.MINIMAX_API_KEY || null;
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.minimax.io/v1",
|
|
apiKey,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then((models) =>
|
|
models.map((model) => ({
|
|
id: model.id,
|
|
name: model.id,
|
|
organization: model.owned_by || "minimax",
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`Minimax:listModels`, e.message);
|
|
return [
|
|
{
|
|
id: "MiniMax-M2.7",
|
|
name: "MiniMax-M2.7",
|
|
organization: "minimax",
|
|
},
|
|
{
|
|
id: "MiniMax-M2.7-highspeed",
|
|
name: "MiniMax-M2.7-highspeed",
|
|
organization: "minimax",
|
|
},
|
|
{
|
|
id: "MiniMax-M2.5",
|
|
name: "MiniMax-M2.5",
|
|
organization: "minimax",
|
|
},
|
|
{
|
|
id: "MiniMax-M2.5-highspeed",
|
|
name: "MiniMax-M2.5-highspeed",
|
|
organization: "minimax",
|
|
},
|
|
{
|
|
id: "MiniMax-M2.1",
|
|
name: "MiniMax-M2.1",
|
|
organization: "minimax",
|
|
},
|
|
{
|
|
id: "MiniMax-M2.1-highspeed",
|
|
name: "MiniMax-M2.1-highspeed",
|
|
organization: "minimax",
|
|
},
|
|
{
|
|
id: "MiniMax-M2",
|
|
name: "MiniMax-M2",
|
|
organization: "minimax",
|
|
},
|
|
];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.MINIMAX_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getDeepSeekModels(apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
apiKey: apiKey || process.env.DEEPSEEK_API_KEY,
|
|
baseURL: "https://api.deepseek.com/v1",
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then((models) =>
|
|
models.map((model) => ({
|
|
id: model.id,
|
|
name: model.id,
|
|
organization: model.owned_by,
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`DeepSeek:listModels`, e.message);
|
|
return [
|
|
{
|
|
id: "deepseek-chat",
|
|
name: "deepseek-chat",
|
|
organization: "deepseek",
|
|
},
|
|
{
|
|
id: "deepseek-reasoner",
|
|
name: "deepseek-reasoner",
|
|
organization: "deepseek",
|
|
},
|
|
];
|
|
});
|
|
|
|
if (models.length > 0 && !!apiKey) process.env.DEEPSEEK_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getGiteeAIModels() {
|
|
const { giteeAiModels } = require("../AiProviders/giteeai");
|
|
const modelMap = await giteeAiModels();
|
|
if (!Object.keys(modelMap).length === 0) return { models: [], error: null };
|
|
const models = Object.values(modelMap).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization ?? "GiteeAI",
|
|
name: model.id,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getXAIModels(_apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.XAI_LLM_API_KEY
|
|
: _apiKey || process.env.XAI_LLM_API_KEY || null;
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.x.ai/v1",
|
|
apiKey,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`XAI:listModels`, e.message);
|
|
return [
|
|
{
|
|
created: 1725148800,
|
|
id: "grok-beta",
|
|
object: "model",
|
|
owned_by: "xai",
|
|
},
|
|
];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.XAI_LLM_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getNvidiaNimModels(basePath = null) {
|
|
try {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: parseNvidiaNimBasePath(
|
|
basePath ?? process.env.NVIDIA_NIM_LLM_BASE_PATH
|
|
),
|
|
apiKey: null,
|
|
});
|
|
const modelResponse = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
throw new Error(e.message);
|
|
});
|
|
|
|
const models = modelResponse.map((model) => {
|
|
return {
|
|
id: model.id,
|
|
name: model.id,
|
|
organization: model.owned_by,
|
|
};
|
|
});
|
|
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`NVIDIA NIM:getNvidiaNimModels`, e.message);
|
|
return { models: [], error: "Could not fetch NVIDIA NIM Models" };
|
|
}
|
|
}
|
|
|
|
async function getGeminiModels(_apiKey = null) {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.GEMINI_API_KEY
|
|
: _apiKey || process.env.GEMINI_API_KEY || null;
|
|
const models = await GeminiLLM.fetchModels(apiKey);
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.GEMINI_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getPPIOModels() {
|
|
const ppioModels = await fetchPPIOModels();
|
|
if (!Object.keys(ppioModels).length === 0) return { models: [], error: null };
|
|
const models = Object.values(ppioModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
function getNativeEmbedderModels() {
|
|
const { NativeEmbedder } = require("../EmbeddingEngines/native");
|
|
return { models: NativeEmbedder.availableModels(), error: null };
|
|
}
|
|
|
|
async function getMoonshotAiModels(_apiKey = null) {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.MOONSHOT_AI_API_KEY
|
|
: _apiKey || process.env.MOONSHOT_AI_API_KEY || null;
|
|
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.moonshot.ai/v1",
|
|
apiKey,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`MoonshotAi:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0) process.env.MOONSHOT_AI_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getFoundryModels(basePath = null) {
|
|
try {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: parseFoundryBasePath(basePath || process.env.FOUNDRY_BASE_PATH),
|
|
apiKey: null,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) =>
|
|
results.data.map((model) => ({
|
|
...model,
|
|
name: model.id,
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`Foundry:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`Foundry:getFoundryModels`, e.message);
|
|
return { models: [], error: "Could not fetch Foundry Models" };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Cohere models
|
|
* @param {string} _apiKey - The API key to use
|
|
* @param {'chat' | 'embed'} type - The type of model to get
|
|
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
|
|
*/
|
|
async function getCohereModels(_apiKey = null, type = "chat") {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.COHERE_API_KEY
|
|
: _apiKey || process.env.COHERE_API_KEY || null;
|
|
|
|
// Cohere's models endpoint is queried directly so we can keep filtering by
|
|
// endpoint (chat/embed) which the OpenAI-compatible /models route does not support.
|
|
const models = await fetch(
|
|
`https://api.cohere.com/v1/models?page_size=1000&endpoint=${type}`,
|
|
{
|
|
method: "GET",
|
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
}
|
|
)
|
|
.then((res) => res.json())
|
|
.then((data) => data?.models || [])
|
|
.then((models) =>
|
|
models.map((model) => ({
|
|
id: model.name,
|
|
name: model.name,
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`Cohere:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getZAiModels(_apiKey = null) {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.ZAI_API_KEY
|
|
: _apiKey || process.env.ZAI_API_KEY || null;
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.z.ai/api/paas/v4",
|
|
apiKey,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.catch((e) => {
|
|
console.error(`Z.AI:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && !!apiKey) process.env.ZAI_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getOpenRouterEmbeddingModels() {
|
|
const knownModels = await fetchOpenRouterEmbeddingModels();
|
|
if (!Object.keys(knownModels).length === 0)
|
|
return { models: [], error: null };
|
|
|
|
const models = Object.values(knownModels).map((model) => {
|
|
return {
|
|
id: model.id,
|
|
organization: model.organization,
|
|
name: model.name,
|
|
};
|
|
});
|
|
return { models, error: null };
|
|
}
|
|
|
|
async function getDockerModelRunnerModels(basePath = null) {
|
|
try {
|
|
const models = await getDockerModels(basePath);
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`DockerModelRunner:getDockerModelRunnerModels`, e.message);
|
|
return {
|
|
models: [],
|
|
error: "Could not fetch Docker Model Runner Models",
|
|
};
|
|
}
|
|
}
|
|
|
|
async function getLemonadeModels(basePath = null, task = "chat") {
|
|
try {
|
|
const models = await getAllLemonadeModels(basePath, task);
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`Lemonade:getLemonadeModels`, e.message);
|
|
return { models: [], error: "Could not fetch Lemonade Models" };
|
|
}
|
|
}
|
|
|
|
async function getLemonadeSTTModels(basePath = null) {
|
|
try {
|
|
const models = await getAllLemonadeModels(basePath, "transcription");
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`Lemonade:getLemonadeSTTModels`, e.message);
|
|
return { models: [], error: "Could not fetch Lemonade STT Models" };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Deepgram STT models from the Management API.
|
|
* https://api.deepgram.com/v1/models returns { stt: [...], tts: [...] }.
|
|
* @param {string} _apiKey - Deepgram API key. Falls back to STT_DEEPGRAM_API_KEY.
|
|
* @returns {Promise<{models: Array<{id: string, name: string, organization: string}>, error: string | null}>}
|
|
*/
|
|
async function getDeepgramSTTModels(_apiKey = null) {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.STT_DEEPGRAM_API_KEY
|
|
: _apiKey || process.env.STT_DEEPGRAM_API_KEY || null;
|
|
if (!apiKey)
|
|
return { models: [], error: "No Deepgram API key was provided." };
|
|
|
|
try {
|
|
const response = await fetch("https://api.deepgram.com/v1/models", {
|
|
method: "GET",
|
|
headers: { Authorization: `Token ${apiKey}` },
|
|
});
|
|
if (!response.ok) throw new Error(`Deepgram returned ${response.status}`);
|
|
|
|
let models = new Map();
|
|
const data = await response.json();
|
|
(data?.stt ?? [])
|
|
.filter((m) => m.batch !== false)
|
|
.forEach((m) => {
|
|
if (models.has(m.canonical_name)) return;
|
|
models.set(m.canonical_name, {
|
|
id: m.canonical_name,
|
|
name: m.canonical_name,
|
|
organization: "Deepgram",
|
|
});
|
|
});
|
|
|
|
models = Array.from(models.values());
|
|
// Api Key was successful so lets save it for future uses
|
|
if (models.length > 0 && _apiKey) process.env.STT_DEEPGRAM_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`Deepgram:getDeepgramSTTModels`, e.message);
|
|
return { models: [], error: "Could not fetch Deepgram STT models" };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Privatemode models
|
|
* @param {string} basePath - The base path of the Privatemode endpoint.
|
|
* @param {'any' | 'generate' | 'embed' | 'transcribe'} task - The task to fetch the models for.
|
|
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
|
|
*/
|
|
async function getPrivatemodeModels(basePath = null, task = "any") {
|
|
try {
|
|
const { PrivatemodeLLM } = require("../AiProviders/privatemode");
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: PrivatemodeLLM.parseBasePath(
|
|
basePath || process.env.PRIVATEMODE_LLM_BASE_PATH
|
|
),
|
|
apiKey: null,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then(
|
|
(models) =>
|
|
models
|
|
.filter((model) => !model.id.includes("/")) // remove legacy prefixed models
|
|
.filter((model) =>
|
|
task === "any" ? true : model.tasks.includes(task)
|
|
) // filter by task or show all if task is any
|
|
)
|
|
.then((models) =>
|
|
models.map((model) => ({
|
|
id: model.id,
|
|
organization: "Privatemode",
|
|
name: model.id
|
|
.split("-")
|
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
.join(" "),
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`Privatemode:listModels`, e.message);
|
|
return [];
|
|
});
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`Privatemode:getPrivatemodeModels`, e.message);
|
|
return { models: [], error: "Could not fetch Privatemode Models" };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get SambaNova models
|
|
* @param {string} _apiKey - The API key to use
|
|
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
|
|
*/
|
|
async function getSambaNovaModels(_apiKey = null) {
|
|
try {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.SAMBANOVA_LLM_API_KEY
|
|
: _apiKey || process.env.SAMBANOVA_LLM_API_KEY || null;
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: "https://api.sambanova.ai/v1",
|
|
apiKey,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then((models) =>
|
|
models.filter((model) => !model.id.toLowerCase().startsWith("whisper"))
|
|
)
|
|
.then((models) =>
|
|
models.map((model) => {
|
|
const organization =
|
|
model.hasOwnProperty("owned_by") &&
|
|
model.owned_by !== "no-reply@sambanova.ai"
|
|
? model.owned_by
|
|
: "SambaNova";
|
|
return {
|
|
id: model.id,
|
|
organization,
|
|
name: model.id,
|
|
};
|
|
})
|
|
)
|
|
.catch((e) => {
|
|
console.error(`SambaNova:listModels`, e.message);
|
|
return [];
|
|
});
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`SambaNova:getSambaNovaModels`, e.message);
|
|
return { models: [], error: "Could not fetch SambaNova Models" };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Use the Cerebras PUBLIC API to fetch the public models
|
|
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
|
|
*/
|
|
async function getCerebrasModels() {
|
|
try {
|
|
const models = await fetch("https://api.cerebras.ai/public/v1/models")
|
|
.then((response) => response.json())
|
|
.then(({ data = [] }) => {
|
|
return data.map((model) => ({
|
|
id: model.id,
|
|
name: model.name,
|
|
organization: model.owned_by ?? "Cerebras",
|
|
}));
|
|
})
|
|
.catch((error) => {
|
|
console.error(`Cerebras:listModels`, error.message);
|
|
return [];
|
|
});
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`Cerebras:getCerebrasModels`, e.message);
|
|
return { models: [], error: "Could not fetch Cerebras Models" };
|
|
}
|
|
}
|
|
|
|
async function getGenericOpenAiModels(basePath = null, apiKey = null) {
|
|
try {
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
baseURL: basePath || process.env.GENERIC_OPEN_AI_BASE_PATH,
|
|
apiKey: apiKey || process.env.GENERIC_OPEN_AI_API_KEY || null,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then((models) =>
|
|
models.map((model) => ({
|
|
id: model.id,
|
|
name: model.id,
|
|
organization: model.owned_by ?? "generic-openai",
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`GenericOpenAI:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
if (models.length > 0 && !!apiKey)
|
|
process.env.GENERIC_OPEN_AI_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`GenericOpenAI:getGenericOpenAiModels`, e.message);
|
|
return { models: [], error: "Could not fetch Generic OpenAI Models" };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pulls the live voice list from a self-hosted kokoro-fastapi server's
|
|
* /audio/voices endpoint. basePath is the OpenAI-compatible base URL the
|
|
* user pointed at their kokoro instance (e.g. http://localhost:8880/v1).
|
|
* @param {string} basePath - The base path to the Kokoro instance.
|
|
* @param {string} apiKey - The API key to use.
|
|
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
|
|
*/
|
|
async function kokoroTtsVoices(basePath = null, apiKey = null) {
|
|
let endpoint = basePath || process.env.TTS_KOKORO_ENDPOINT;
|
|
if (!endpoint)
|
|
return { models: [], error: "No Kokoro endpoint was provided." };
|
|
|
|
endpoint = new URL(endpoint);
|
|
endpoint.pathname = "/v1/audio/voices";
|
|
const headers = { "Content-Type": "application/json" };
|
|
const key = typeof apiKey === "boolean" ? null : apiKey;
|
|
if (key) headers.Authorization = `Bearer ${key}`;
|
|
|
|
const voices = await fetch(endpoint.toString(), { method: "GET", headers })
|
|
.then((res) => {
|
|
if (!res.ok) throw new Error(res.statusText || "Failed to load voices");
|
|
return res.json();
|
|
})
|
|
.then((data) => (Array.isArray(data?.voices) ? data.voices : []))
|
|
.catch((e) => {
|
|
console.error(`Kokoro:listVoices`, e.message);
|
|
return null;
|
|
});
|
|
|
|
if (!voices || !Array.isArray(voices))
|
|
return { models: [], error: "Could not fetch Kokoro voices." };
|
|
|
|
// kokoro-fastapi < 0.3.x returns voices as plain id strings while >= 0.3.x
|
|
// returns { id, name } objects. Normalize both shapes to { id, name } so the
|
|
// voice list renders regardless of the kokoro-fastapi version being used.
|
|
const models = voices
|
|
.map((voice) => {
|
|
if (typeof voice === "string")
|
|
return { id: voice, name: voice, organization: "Kokoro" };
|
|
if (voice && typeof voice === "object" && voice.id)
|
|
return {
|
|
id: voice.id,
|
|
name: voice.name || voice.id,
|
|
organization: "Kokoro",
|
|
};
|
|
return null;
|
|
})
|
|
.filter(Boolean);
|
|
return { models, error: null };
|
|
}
|
|
|
|
/**
|
|
* Get AWS Bedrock models
|
|
* @param {string} _apiKey - The API key to use
|
|
* @param {Object} options - The options to use
|
|
* @param {string} [options.region] - The region to use
|
|
* @returns {Promise<{models: Array<{id: string, organization: string, name: string}>, error: string | null}>}
|
|
*/
|
|
async function getBedrockModels(_apiKey = null, options = {}) {
|
|
try {
|
|
const apiKey =
|
|
_apiKey === true
|
|
? process.env.AWS_BEDROCK_LLM_API_KEY
|
|
: _apiKey || process.env.AWS_BEDROCK_LLM_API_KEY || null;
|
|
const region =
|
|
options?.region || process.env.AWS_BEDROCK_LLM_REGION || "us-west-2";
|
|
|
|
const { OpenAI: OpenAIApi } = require("openai");
|
|
const openai = new OpenAIApi({
|
|
apiKey,
|
|
baseURL: `https://bedrock-mantle.${region}.api.aws/v1`,
|
|
});
|
|
const models = await openai.models
|
|
.list()
|
|
.then((results) => results.data)
|
|
.then((models) =>
|
|
models.map((model) => ({
|
|
id: model.id,
|
|
name: model.id,
|
|
organization: model.owned_by ?? "AWS Bedrock",
|
|
}))
|
|
)
|
|
.catch((e) => {
|
|
console.error(`AWSBedrock:listModels`, e.message);
|
|
return [];
|
|
});
|
|
|
|
if (models.length > 0 && !!apiKey)
|
|
process.env.AWS_BEDROCK_LLM_API_KEY = apiKey;
|
|
return { models, error: null };
|
|
} catch (e) {
|
|
console.error(`AWSBedrock:getBedrockModels`, e.message);
|
|
return { models: [], error: "Could not fetch AWS Bedrock Models" };
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getCustomModels,
|
|
SUPPORT_CUSTOM_MODELS,
|
|
};
|