diff --git a/README.md b/README.md index a8199403..65c529b1 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ AnythingLLM divides your documents into objects called `workspaces`. A Workspace - [xAI](https://x.ai/) - [Novita AI (chat models)](https://novita.ai/model-api/product/llm-api?utm_source=github_anything-llm&utm_medium=github_readme&utm_campaign=link) - [PPIO](https://ppinfra.com?utm_source=github_anything-llm) +- [Moonshot AI](https://www.moonshot.ai/) **Embedder models:** diff --git a/docker/.env.example b/docker/.env.example index d0b6dbeb..6a5d8b33 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -133,6 +133,10 @@ GID='1000' # PPIO_API_KEY='your-ppio-api-key-here' # PPIO_MODEL_PREF=deepseek/deepseek-v3/community +# LLM_PROVIDER='moonshotai' +# MOONSHOT_AI_API_KEY='your-moonshot-api-key-here' +# MOONSHOT_AI_MODEL_PREF='moonshot-v1-32k' + ########################################### ######## Embedding API SElECTION ########## ########################################### diff --git a/frontend/src/components/LLMSelection/MoonshotAiOptions/index.jsx b/frontend/src/components/LLMSelection/MoonshotAiOptions/index.jsx new file mode 100644 index 00000000..4546fef0 --- /dev/null +++ b/frontend/src/components/LLMSelection/MoonshotAiOptions/index.jsx @@ -0,0 +1,117 @@ +import { useState, useEffect } from "react"; +import System from "@/models/system"; + +export default function MoonshotAiOptions({ settings }) { + const [inputValue, setInputValue] = useState(settings?.MoonshotAiApiKey); + const [moonshotAiKey, setMoonshotAiKey] = useState( + settings?.MoonshotAiApiKey + ); + + return ( +
+
+ + setInputValue(e.target.value)} + onBlur={() => setMoonshotAiKey(inputValue)} + /> +
+ {!settings?.credentialsOnly && ( + + )} +
+ ); +} + +function MoonshotAiModelSelection({ apiKey, settings }) { + const [models, setModels] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function findCustomModels() { + setLoading(true); + const { models: availableModels } = await System.customModels( + "moonshotai", + typeof apiKey === "boolean" ? null : apiKey + ); + + if (availableModels?.length > 0) { + setModels(availableModels); + } + + setLoading(false); + } + findCustomModels(); + }, [apiKey]); + + if (!apiKey) { + return ( +
+ + +
+ ); + } + + if (loading) { + return ( +
+ + +
+ ); + } + + return ( +
+ + +
+ ); +} diff --git a/frontend/src/media/llmprovider/moonshotai.png b/frontend/src/media/llmprovider/moonshotai.png new file mode 100644 index 00000000..71f40805 Binary files /dev/null and b/frontend/src/media/llmprovider/moonshotai.png differ diff --git a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx index f9aceec1..9ef12944 100644 --- a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx +++ b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx @@ -32,6 +32,7 @@ import XAILogo from "@/media/llmprovider/xai.png"; import NvidiaNimLogo from "@/media/llmprovider/nvidia-nim.png"; import PPIOLogo from "@/media/llmprovider/ppio.png"; import DellProAiStudioLogo from "@/media/llmprovider/dpais.png"; +import MoonshotAiLogo from "@/media/llmprovider/moonshotai.png"; import PreLoader from "@/components/Preloader"; import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions"; @@ -61,6 +62,7 @@ import XAILLMOptions from "@/components/LLMSelection/XAiLLMOptions"; import NvidiaNimOptions from "@/components/LLMSelection/NvidiaNimOptions"; import PPIOLLMOptions from "@/components/LLMSelection/PPIOLLMOptions"; import DellProAiStudioOptions from "@/components/LLMSelection/DPAISOptions"; +import MoonshotAiOptions from "@/components/LLMSelection/MoonshotAiOptions"; import LLMItem from "@/components/LLMSelection/LLMItem"; import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react"; @@ -293,6 +295,14 @@ export const AVAILABLE_LLM_PROVIDERS = [ description: "A unified API of AI services from leading providers", requiredConfig: ["ApipieLLMApiKey", "ApipieLLMModelPref"], }, + { + name: "Moonshot AI", + value: "moonshotai", + logo: MoonshotAiLogo, + options: (settings) => , + description: "Run Moonshot AI's powerful LLMs.", + requiredConfig: ["MoonshotAiApiKey"], + }, { 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 bc48209d..67be19ce 100644 --- a/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx +++ b/frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx @@ -38,6 +38,8 @@ import VoyageAiLogo from "@/media/embeddingprovider/voyageai.png"; import PPIOLogo from "@/media/llmprovider/ppio.png"; import PGVectorLogo from "@/media/vectordbs/pgvector.png"; import DPAISLogo from "@/media/llmprovider/dpais.png"; +import MoonshotAiLogo from "@/media/llmprovider/moonshotai.png"; + import React, { useState, useEffect } from "react"; import paths from "@/utils/paths"; import { useNavigate } from "react-router-dom"; @@ -242,6 +244,14 @@ export const LLM_SELECTION_PRIVACY = { ], logo: DPAISLogo, }, + moonshotai: { + name: "Moonshot AI", + description: [ + "Your chats may be used by Moonshot AI for training and model refinement", + "Your prompts and document text used in response creation are visible to Moonshot AI", + ], + logo: MoonshotAiLogo, + }, }; 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 02d97893..4ce2745d 100644 --- a/frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx +++ b/frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx @@ -27,6 +27,7 @@ import NvidiaNimLogo from "@/media/llmprovider/nvidia-nim.png"; import CohereLogo from "@/media/llmprovider/cohere.png"; import PPIOLogo from "@/media/llmprovider/ppio.png"; import DellProAiStudioLogo from "@/media/llmprovider/dpais.png"; +import MoonshotAiLogo from "@/media/llmprovider/moonshotai.png"; import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions"; import GenericOpenAiOptions from "@/components/LLMSelection/GenericOpenAiOptions"; @@ -55,6 +56,7 @@ import XAILLMOptions from "@/components/LLMSelection/XAiLLMOptions"; import NvidiaNimOptions from "@/components/LLMSelection/NvidiaNimOptions"; import PPIOLLMOptions from "@/components/LLMSelection/PPIOLLMOptions"; import DellProAiStudioOptions from "@/components/LLMSelection/DPAISOptions"; +import MoonshotAiOptions from "@/components/LLMSelection/MoonshotAiOptions"; import LLMItem from "@/components/LLMSelection/LLMItem"; import System from "@/models/system"; @@ -263,6 +265,13 @@ const LLMS = [ options: (settings) => , description: "Run xAI's powerful LLMs like Grok-2 and more.", }, + { + name: "Moonshot AI", + value: "moonshotai", + logo: MoonshotAiLogo, + options: (settings) => , + description: "Run Moonshot AI's powerful LLMs.", + }, ]; export default function LLMPreference({ diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/index.jsx index 6baae1dd..31b7327b 100644 --- a/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/AgentLLMSelection/index.jsx @@ -31,6 +31,7 @@ const ENABLED_PROVIDERS = [ "xai", "nvidia-nim", "gemini", + "moonshotai", // TODO: More agent support. // "cohere", // Has tool calling and will need to build explicit support // "huggingface" // Can be done but already has issues with no-chat templated. Needs to be tested. diff --git a/server/.env.example b/server/.env.example index 12fa5ec2..65e97481 100644 --- a/server/.env.example +++ b/server/.env.example @@ -131,6 +131,10 @@ SIG_SALT='salt' # Please generate random string at least 32 chars long. # PPIO_API_KEY='your-ppio-api-key-here' # PPIO_MODEL_PREF='deepseek/deepseek-v3/community' +# LLM_PROVIDER='moonshotai' +# MOONSHOT_AI_API_KEY='your-moonshot-api-key-here' +# MOONSHOT_AI_MODEL_PREF='moonshot-v1-32k' + ########################################### ######## Embedding API SElECTION ########## ########################################### diff --git a/server/endpoints/utils.js b/server/endpoints/utils.js index cf418325..425d44f9 100644 --- a/server/endpoints/utils.js +++ b/server/endpoints/utils.js @@ -142,6 +142,9 @@ function getModelTag() { case "gemini": model = process.env.GEMINI_LLM_MODEL_PREF; break; + case "moonshotai": + model = process.env.MOONSHOT_AI_MODEL_PREF; + break; default: model = "--"; break; diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js index 8de54f6c..df2eca13 100644 --- a/server/models/systemSettings.js +++ b/server/models/systemSettings.js @@ -544,6 +544,11 @@ const SystemSettings = { LiteLLMBasePath: process.env.LITE_LLM_BASE_PATH, LiteLLMApiKey: !!process.env.LITE_LLM_API_KEY, + // Moonshot AI Keys + MoonshotAiApiKey: !!process.env.MOONSHOT_AI_API_KEY, + MoonshotAiModelPref: + process.env.MOONSHOT_AI_MODEL_PREF || "moonshot-v1-32k", + // 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/modelMap/index.js b/server/utils/AiProviders/modelMap/index.js index 4f5740be..8ff713ee 100644 --- a/server/utils/AiProviders/modelMap/index.js +++ b/server/utils/AiProviders/modelMap/index.js @@ -18,6 +18,7 @@ class ContextWindowFinder { groq: "groq", xai: "xai", deepseek: "deepseek", + moonshot: "moonshot", }; static expiryMs = 1000 * 60 * 60 * 24 * 3; // 3 days static remoteUrl = diff --git a/server/utils/AiProviders/moonshotAi/index.js b/server/utils/AiProviders/moonshotAi/index.js new file mode 100644 index 00000000..c4bc7b65 --- /dev/null +++ b/server/utils/AiProviders/moonshotAi/index.js @@ -0,0 +1,169 @@ +const { NativeEmbedder } = require("../../EmbeddingEngines/native"); +const { + LLMPerformanceMonitor, +} = require("../../helpers/chat/LLMPerformanceMonitor"); +const { + handleDefaultStreamResponseV2, + formatChatHistory, +} = require("../../helpers/chat/responses"); +const { MODEL_MAP } = require("../modelMap"); + +class MoonshotAiLLM { + constructor(embedder = null, modelPreference = null) { + if (!process.env.MOONSHOT_AI_API_KEY) + throw new Error("No Moonshot AI API key was set."); + const { OpenAI: OpenAIApi } = require("openai"); + + this.openai = new OpenAIApi({ + baseURL: "https://api.moonshot.ai/v1", + apiKey: process.env.MOONSHOT_AI_API_KEY, + }); + this.model = + modelPreference || + process.env.MOONSHOT_AI_MODEL_PREF || + "moonshot-v1-32k"; + this.limits = { + history: this.promptWindowLimit() * 0.15, + system: this.promptWindowLimit() * 0.15, + user: this.promptWindowLimit() * 0.7, + }; + + this.embedder = embedder ?? new NativeEmbedder(); + this.defaultTemp = 0.7; + this.log( + `Initialized ${this.model} with context window ${this.promptWindowLimit()}` + ); + } + + 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("") + ); + } + + /** + * Generates appropriate content array for a message + attachments. + * @param {{userPrompt:string, attachments: import("../../helpers").Attachment[]}} + * @returns {string|object[]} + */ + #generateContent({ userPrompt, attachments = [] }) { + if (!attachments.length) { + return userPrompt; + } + + const content = [{ type: "text", text: userPrompt }]; + for (let attachment of attachments) { + content.push({ + type: "image_url", + image_url: { + url: attachment.contentString, + }, + }); + } + return content.flat(); + } + + streamingEnabled() { + return true; + } + + promptWindowLimit() { + return MODEL_MAP.get("moonshot", this.model) ?? 8_192; + } + + constructPrompt({ + systemPrompt = "", + contextTexts = [], + chatHistory = [], + userPrompt = "", + attachments = [], + }) { + const prompt = { + role: "system", + content: `${systemPrompt}${this.#appendContext(contextTexts)}`, + }; + return [ + prompt, + ...formatChatHistory(chatHistory, this.#generateContent), + { + role: "user", + content: this.#generateContent({ userPrompt, attachments }), + }, + ]; + } + + async compressMessages(promptArgs = {}, rawHistory = []) { + const { messageArrayCompressor } = require("../../helpers/chat"); + const messageArray = this.constructPrompt(promptArgs); + return await messageArrayCompressor(this, messageArray, rawHistory); + } + + async getChatCompletion(messages = null, { temperature = 0.7 }) { + const result = await LLMPerformanceMonitor.measureAsyncFunction( + this.openai.chat.completions + .create({ + model: this.model, + messages, + temperature, + }) + .catch((e) => { + throw new Error(e.message); + }) + ); + + if ( + !Object.prototype.hasOwnProperty.call(result.output, "choices") || + result.output.choices.length === 0 + ) + return null; + + return { + textResponse: result.output.choices[0].message.content, + metrics: { + prompt_tokens: result.output.usage.prompt_tokens || 0, + completion_tokens: result.output.usage.completion_tokens || 0, + total_tokens: result.output.usage.total_tokens || 0, + outputTps: result.output.usage.completion_tokens / result.duration, + duration: result.duration, + }, + }; + } + + async streamGetChatCompletion(messages = null, { temperature = 0.7 }) { + const measuredStreamRequest = await LLMPerformanceMonitor.measureStream( + this.openai.chat.completions.create({ + model: this.model, + stream: true, + messages, + temperature, + }), + messages + ); + + return measuredStreamRequest; + } + + handleStream(response, stream, responseProps) { + return handleDefaultStreamResponseV2(response, stream, responseProps); + } + + // 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); + } +} + +module.exports = { MoonshotAiLLM }; diff --git a/server/utils/agents/aibitat/index.js b/server/utils/agents/aibitat/index.js index 6e069def..d6b22d3a 100644 --- a/server/utils/agents/aibitat/index.js +++ b/server/utils/agents/aibitat/index.js @@ -812,6 +812,8 @@ ${this.getHistory({ to: route.to }) return new Providers.FireworksAIProvider({ model: config.model }); case "nvidia-nim": return new Providers.NvidiaNimProvider({ model: config.model }); + case "moonshotai": + return new Providers.MoonshotAiProvider({ model: config.model }); case "deepseek": return new Providers.DeepSeekProvider({ model: config.model }); case "litellm": diff --git a/server/utils/agents/aibitat/providers/ai-provider.js b/server/utils/agents/aibitat/providers/ai-provider.js index 5085fdcf..07867e4c 100644 --- a/server/utils/agents/aibitat/providers/ai-provider.js +++ b/server/utils/agents/aibitat/providers/ai-provider.js @@ -184,7 +184,14 @@ class Provider { apiKey: process.env.GEMINI_API_KEY ?? null, ...config, }); - + case "moonshotai": + return new ChatOpenAI({ + configuration: { + baseURL: "https://api.moonshot.ai/v1", + }, + apiKey: process.env.MOONSHOT_AI_API_KEY ?? null, + ...config, + }); // OSS Model Runners // case "anythingllm_ollama": // return new ChatOllama({ diff --git a/server/utils/agents/aibitat/providers/index.js b/server/utils/agents/aibitat/providers/index.js index d8c17486..859ad9de 100644 --- a/server/utils/agents/aibitat/providers/index.js +++ b/server/utils/agents/aibitat/providers/index.js @@ -23,6 +23,7 @@ const NvidiaNimProvider = require("./nvidiaNim.js"); const PPIOProvider = require("./ppio.js"); const GeminiProvider = require("./gemini.js"); const DellProAiStudioProvider = require("./dellProAiStudio.js"); +const MoonshotAiProvider = require("./moonshotAi.js"); module.exports = { OpenAIProvider, @@ -50,4 +51,5 @@ module.exports = { PPIOProvider, GeminiProvider, DellProAiStudioProvider, + MoonshotAiProvider, }; diff --git a/server/utils/agents/aibitat/providers/moonshotAi.js b/server/utils/agents/aibitat/providers/moonshotAi.js new file mode 100644 index 00000000..b6bb3beb --- /dev/null +++ b/server/utils/agents/aibitat/providers/moonshotAi.js @@ -0,0 +1,103 @@ +const OpenAI = require("openai"); +const Provider = require("./ai-provider.js"); +const InheritMultiple = require("./helpers/classes.js"); +const UnTooled = require("./helpers/untooled.js"); + +class MoonshotAiProvider extends InheritMultiple([Provider, UnTooled]) { + model; + + constructor(config = {}) { + const { model = "moonshot-v1-32k" } = config; + super(); + const client = new OpenAI({ + baseURL: "https://api.moonshot.ai/v1", + apiKey: process.env.MOONSHOT_AI_API_KEY, + maxRetries: 3, + }); + + this._client = client; + this.model = model; + this.verbose = true; + } + + /** + * Create a completion based on the received messages. + * + * @param messages A list of messages to send to the API. + * @param functions + * @returns The completion. + */ + get client() { + return this._client; + } + + async #handleFunctionCallChat({ messages = [] }) { + return await this.client.chat.completions + .create({ + model: this.model, + temperature: 0, + messages, + }) + .then((result) => { + if (!result.hasOwnProperty("choices")) + throw new Error("Moonshot chat: No results!"); + if (result.choices.length === 0) + throw new Error("Moonshot chat: No results length!"); + return result.choices[0].message.content; + }) + .catch((_) => { + return null; + }); + } + + async complete(messages, functions = []) { + try { + let completion; + if (functions.length > 0) { + const { toolCall, text } = await this.functionCall( + messages, + functions, + this.#handleFunctionCallChat.bind(this) + ); + + if (toolCall !== null) { + this.providerLog(`Valid tool call found - running ${toolCall.name}.`); + this.deduplicator.trackRun(toolCall.name, toolCall.arguments); + return { + result: null, + functionCall: { + name: toolCall.name, + arguments: toolCall.arguments, + }, + cost: 0, + }; + } + completion = { content: text }; + } + + if (!completion?.content) { + this.providerLog( + "Will assume chat completion without tool call inputs." + ); + const response = await this.client.chat.completions.create({ + model: this.model, + messages: this.cleanMsgs(messages), + }); + completion = response.choices[0].message; + } + + // The UnTooled class inherited Deduplicator is mostly useful to prevent the agent + // from calling the exact same function over and over in a loop within a single chat exchange + // _but_ we should enable it to call previously used tools in a new chat interaction. + this.deduplicator.reset("runs"); + return { + result: completion.content, + cost: 0, + }; + } catch (error) { + throw error; + } + } +} + +module.exports = MoonshotAiProvider; diff --git a/server/utils/agents/index.js b/server/utils/agents/index.js index 915e5a59..4527ee78 100644 --- a/server/utils/agents/index.js +++ b/server/utils/agents/index.js @@ -199,6 +199,10 @@ class AgentHandler { "Dell Pro AI Studio model must be set to use agents." ); break; + case "moonshotai": + if (!process.env.MOONSHOT_AI_MODEL_PREF) + throw new Error("Moonshot AI model must be set to use agents."); + break; default: throw new Error( @@ -254,6 +258,8 @@ class AgentHandler { return process.env.DEEPSEEK_MODEL_PREF ?? "deepseek-chat"; case "litellm": return process.env.LITE_LLM_MODEL_PREF ?? null; + case "moonshotai": + return process.env.MOONSHOT_AI_MODEL_PREF ?? "moonshot-v1-32k"; case "apipie": return process.env.APIPIE_LLM_MODEL_PREF ?? null; case "xai": diff --git a/server/utils/helpers/customModels.js b/server/utils/helpers/customModels.js index cff97ff8..de855f0b 100644 --- a/server/utils/helpers/customModels.js +++ b/server/utils/helpers/customModels.js @@ -33,6 +33,7 @@ const SUPPORT_CUSTOM_MODELS = [ "gemini", "ppio", "dpais", + "moonshotai", ]; async function getCustomModels(provider = "", apiKey = null, basePath = null) { @@ -84,6 +85,8 @@ async function getCustomModels(provider = "", apiKey = null, basePath = null) { return await getPPIOModels(apiKey); case "dpais": return await getDellProAiStudioModels(basePath); + case "moonshotai": + return await getMoonshotAiModels(apiKey); default: return { models: [], error: "Invalid provider for custom models" }; } @@ -675,6 +678,31 @@ async function getDellProAiStudioModels(basePath = 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 }; +} + module.exports = { getCustomModels, + SUPPORT_CUSTOM_MODELS, }; diff --git a/server/utils/helpers/index.js b/server/utils/helpers/index.js index 2017c618..9e101a2b 100644 --- a/server/utils/helpers/index.js +++ b/server/utils/helpers/index.js @@ -203,6 +203,9 @@ function getLLMProvider({ provider = null, model = null } = {}) { case "ppio": const { PPIOLLM } = require("../AiProviders/ppio"); return new PPIOLLM(embedder, model); + case "moonshotai": + const { MoonshotAiLLM } = require("../AiProviders/moonshotAi"); + return new MoonshotAiLLM(embedder, model); case "dpais": const { DellProAiStudioLLM } = require("../AiProviders/dellProAiStudio"); return new DellProAiStudioLLM(embedder, model); @@ -353,6 +356,9 @@ function getLLMProviderClass({ provider = null } = {}) { case "dpais": const { DellProAiStudioLLM } = require("../AiProviders/dellProAiStudio"); return DellProAiStudioLLM; + case "moonshotai": + const { MoonshotAiLLM } = require("../AiProviders/moonshotAi"); + return MoonshotAiLLM; default: return null; } @@ -419,6 +425,8 @@ function getBaseLLMProviderModel({ provider = null } = {}) { return process.env.PPIO_API_KEY; case "dpais": return process.env.DPAIS_LLM_MODEL_PREF; + case "moonshotai": + return process.env.MOONSHOT_AI_MODEL_PREF; default: return null; } diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js index 87670830..ce28e73a 100644 --- a/server/utils/helpers/updateENV.js +++ b/server/utils/helpers/updateENV.js @@ -676,6 +676,16 @@ const KEY_MAPPING = { envKey: "PPIO_MODEL_PREF", checks: [isNotEmpty], }, + + // Moonshot AI Options + MoonshotAiApiKey: { + envKey: "MOONSHOT_AI_API_KEY", + checks: [isNotEmpty], + }, + MoonshotAiModelPref: { + envKey: "MOONSHOT_AI_MODEL_PREF", + checks: [isNotEmpty], + }, }; function isNotEmpty(input = "") { @@ -784,6 +794,7 @@ function supportedLLM(input = "") { "nvidia-nim", "ppio", "dpais", + "moonshotai", ].includes(input); return validSelection ? null : `${input} is not a valid LLM provider.`; }