diff --git a/src/LLMProviders/chatModelManager.ts b/src/LLMProviders/chatModelManager.ts index dc002926..1c0ba691 100644 --- a/src/LLMProviders/chatModelManager.ts +++ b/src/LLMProviders/chatModelManager.ts @@ -52,6 +52,7 @@ const CHAT_PROVIDER_CONSTRUCTORS = { [ChatModelProviders.LM_STUDIO]: ChatOpenAI, [ChatModelProviders.GROQ]: ChatGroq, [ChatModelProviders.OPENAI_FORMAT]: ChatOpenAI, + [ChatModelProviders.SILICONFLOW]: ChatOpenAI, [ChatModelProviders.COPILOT_PLUS]: ChatOpenAI, [ChatModelProviders.MISTRAL]: ChatMistralAI, [ChatModelProviders.DEEPSEEK]: ChatDeepSeek, @@ -88,6 +89,7 @@ export default class ChatModelManager { [ChatModelProviders.MISTRAL]: () => getSettings().mistralApiKey, [ChatModelProviders.DEEPSEEK]: () => getSettings().deepseekApiKey, [ChatModelProviders.AMAZON_BEDROCK]: () => getSettings().amazonBedrockApiKey, + [ChatModelProviders.SILICONFLOW]: () => getSettings().siliconflowApiKey, } as const; private constructor() { @@ -297,6 +299,20 @@ export default class ChatModelManager { customModel ), }, + [ChatModelProviders.SILICONFLOW]: { + modelName: modelName, + apiKey: await getDecryptedKey(customModel.apiKey || settings.siliconflowApiKey), + configuration: { + baseURL: customModel.baseUrl || ProviderInfo[ChatModelProviders.SILICONFLOW].host, + fetch: customModel.enableCors ? safeFetch : undefined, + }, + ...this.getOpenAISpecialConfig( + modelName, + customModel.maxTokens ?? settings.maxTokens, + customModel.temperature ?? settings.temperature, + customModel + ), + }, [ChatModelProviders.COPILOT_PLUS]: { modelName: modelName, apiKey: await getDecryptedKey(settings.plusLicenseKey), @@ -477,6 +493,7 @@ export default class ChatModelManager { ChatModelProviders.OPENAI_FORMAT, ChatModelProviders.MISTRAL, ChatModelProviders.DEEPSEEK, + ChatModelProviders.SILICONFLOW, ].includes(provider) ) { params.topP = customModel.topP; @@ -496,6 +513,7 @@ export default class ChatModelManager { ChatModelProviders.OPENAI_FORMAT, ChatModelProviders.MISTRAL, ChatModelProviders.DEEPSEEK, + ChatModelProviders.SILICONFLOW, ].includes(provider) ) { params.frequencyPenalty = customModel.frequencyPenalty; diff --git a/src/LLMProviders/embeddingManager.ts b/src/LLMProviders/embeddingManager.ts index d5c5ad30..dd42fca6 100644 --- a/src/LLMProviders/embeddingManager.ts +++ b/src/LLMProviders/embeddingManager.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { CustomModel } from "@/aiParams"; -import { BREVILABS_MODELS_BASE_URL, EmbeddingModelProviders } from "@/constants"; +import { BREVILABS_MODELS_BASE_URL, EmbeddingModelProviders, ProviderInfo } from "@/constants"; import { getDecryptedKey } from "@/encryptionService"; import { CustomError } from "@/error"; import { getModelKeyFromModel, getSettings, subscribeToSettingsChange } from "@/settings/model"; @@ -27,6 +27,7 @@ const EMBEDDING_PROVIDER_CONSTRUCTORS = { [EmbeddingModelProviders.OLLAMA]: OllamaEmbeddings, [EmbeddingModelProviders.LM_STUDIO]: CustomOpenAIEmbeddings, [EmbeddingModelProviders.OPENAI_FORMAT]: OpenAIEmbeddings, + [EmbeddingModelProviders.SILICONFLOW]: CustomOpenAIEmbeddings, } as const; type EmbeddingProviderConstructorMap = typeof EMBEDDING_PROVIDER_CONSTRUCTORS; @@ -54,6 +55,7 @@ export default class EmbeddingManager { [EmbeddingModelProviders.OLLAMA]: () => "default-key", [EmbeddingModelProviders.LM_STUDIO]: () => "default-key", [EmbeddingModelProviders.OPENAI_FORMAT]: () => "default-key", + [EmbeddingModelProviders.SILICONFLOW]: () => getSettings().siliconflowApiKey, }; private constructor() { @@ -279,6 +281,15 @@ export default class EmbeddingManager { dangerouslyAllowBrowser: true, }, }, + [EmbeddingModelProviders.SILICONFLOW]: { + modelName, + apiKey: await getDecryptedKey(customModel.apiKey || settings.siliconflowApiKey), + batchSize: getSettings().embeddingBatchSize, + configuration: { + baseURL: customModel.baseUrl || ProviderInfo[EmbeddingModelProviders.SILICONFLOW].host, + fetch: customModel.enableCors ? safeFetch : undefined, + }, + }, }; const selectedProviderConfig = diff --git a/src/constants.ts b/src/constants.ts index 7f9bee5a..dd7795bd 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -166,6 +166,8 @@ export enum ChatModels { OPENROUTER_GPT_41 = "openai/gpt-4.1", OPENROUTER_GPT_41_MINI = "openai/gpt-4.1-mini", OPENROUTER_GROK_4_FAST = "x-ai/grok-4-fast", + SILICONFLOW_DEEPSEEK_V3 = "deepseek-ai/DeepSeek-V3", + SILICONFLOW_DEEPSEEK_R1 = "deepseek-ai/DeepSeek-R1", } // Model Providers @@ -185,6 +187,7 @@ export enum ChatModelProviders { MISTRAL = "mistralai", DEEPSEEK = "deepseek", AMAZON_BEDROCK = "amazon-bedrock", + SILICONFLOW = "siliconflow", } export enum ModelCapability { @@ -381,6 +384,25 @@ export const BUILTIN_CHAT_MODELS: CustomModel[] = [ isBuiltIn: true, capabilities: [ModelCapability.REASONING], }, + { + name: ChatModels.SILICONFLOW_DEEPSEEK_V3, + provider: ChatModelProviders.SILICONFLOW, + enabled: true, + isBuiltIn: true, + core: true, + projectEnabled: true, + baseUrl: "https://api.siliconflow.com/v1", + }, + { + name: ChatModels.SILICONFLOW_DEEPSEEK_R1, + provider: ChatModelProviders.SILICONFLOW, + enabled: true, + isBuiltIn: true, + core: true, + projectEnabled: true, + baseUrl: "https://api.siliconflow.com/v1", + capabilities: [ModelCapability.REASONING], + }, ]; export enum EmbeddingModelProviders { @@ -393,6 +415,7 @@ export enum EmbeddingModelProviders { OPENAI_FORMAT = "3rd party (openai-format)", COPILOT_PLUS = "copilot-plus", COPILOT_PLUS_JINA = "copilot-plus-jina", + SILICONFLOW = "siliconflow", } export enum EmbeddingModels { @@ -406,6 +429,7 @@ export enum EmbeddingModels { COPILOT_PLUS_SMALL = "copilot-plus-small", COPILOT_PLUS_LARGE = "copilot-plus-large", COPILOT_PLUS_MULTILINGUAL = "copilot-plus-multilingual", + SILICONFLOW_QWEN3_EMBEDDING_0_6B = "Qwen/Qwen3-Embedding-0.6B", } export const BUILTIN_EMBEDDING_MODELS: CustomModel[] = [ @@ -483,6 +507,15 @@ export const BUILTIN_EMBEDDING_MODELS: CustomModel[] = [ isBuiltIn: true, isEmbeddingModel: true, }, + { + name: EmbeddingModels.SILICONFLOW_QWEN3_EMBEDDING_0_6B, + provider: EmbeddingModelProviders.SILICONFLOW, + enabled: true, + isBuiltIn: true, + isEmbeddingModel: true, + core: true, + baseUrl: "https://api.siliconflow.com/v1", + }, ]; // Embedding Models @@ -530,6 +563,13 @@ export const ProviderInfo: Record = { listModelURL: "https://api.openai.com/v1/models", testModel: ChatModels.GPT_41, }, + [ChatModelProviders.SILICONFLOW]: { + label: "SiliconFlow", + host: "https://api.siliconflow.com/v1", + keyManagementURL: "https://cloud.siliconflow.com/me/account/ak", + listModelURL: "https://api.siliconflow.com/v1/models", + testModel: ChatModels.SILICONFLOW_DEEPSEEK_V3, + }, [ChatModelProviders.AZURE_OPENAI]: { label: "Azure OpenAI", host: "", @@ -631,6 +671,7 @@ export const ProviderSettingsKeyMap: Record; } +// SiliconFlow response model definition +export interface SiliconFlowModelResponse { + object: string; + data: SiliconFlowModel[]; +} + +/** + { + "id": "deepseek-ai/DeepSeek-V3", + "object": "model", + "created": 0, + "owned_by": "" + } + */ +export interface SiliconFlowModel { + id: string; + object: string; + created: number; + owned_by: string; +} + // Response type mapping export interface ProviderResponseMap { [ChatModelProviders.OPENAI]: OpenAIModelResponse; @@ -334,6 +355,7 @@ export interface ProviderResponseMap { [ChatModelProviders.GROQ]: GroqModelResponse; [ChatModelProviders.XAI]: XAIModelResponse; [ChatModelProviders.OPENROUTERAI]: OpenRouterAIModelResponse; + [ChatModelProviders.SILICONFLOW]: SiliconFlowModelResponse; [ChatModelProviders.COPILOT_PLUS]: null; [ChatModelProviders.AZURE_OPENAI]: null; [ChatModelProviders.AMAZON_BEDROCK]: unknown; @@ -421,6 +443,13 @@ export const providerAdapters: ProviderModelAdapters = { name: model.id, provider: ChatModelProviders.OPENROUTERAI, })) || [], + + [ChatModelProviders.SILICONFLOW]: (data): StandardModel[] => + data.data?.map((model) => ({ + id: model.id, + name: model.id, + provider: ChatModelProviders.SILICONFLOW, + })) || [], }; /**