feat: Add SiliconFlow support for chat and embedding models (#1979)

This commit is contained in:
QiyuanChen 2025-10-30 14:02:12 +08:00 committed by GitHub
parent 42b078075c
commit 856ca91b29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 102 additions and 1 deletions

View file

@ -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;

View file

@ -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 =

View file

@ -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<Provider, ProviderMetadata> = {
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<SettingKeyProviders, keyof CopilotSe
mistralai: "mistralApiKey",
deepseek: "deepseekApiKey",
"amazon-bedrock": "amazonBedrockApiKey",
siliconflow: "siliconflowApiKey",
};
export enum VAULT_VECTOR_STORE_STRATEGY {
@ -749,6 +790,7 @@ export const DEFAULT_SETTINGS: CopilotSettings = {
deepseekApiKey: "",
amazonBedrockApiKey: "",
amazonBedrockRegion: "",
siliconflowApiKey: "",
defaultChainType: ChainType.LLM_CHAIN,
defaultModelKey: ChatModels.OPENROUTER_GEMINI_2_5_FLASH + "|" + ChatModelProviders.OPENROUTERAI,
embeddingModelKey: EmbeddingModels.OPENAI_EMBEDDING_SMALL + "|" + EmbeddingModelProviders.OPENAI,

View file

@ -67,6 +67,7 @@ export interface CopilotSettings {
deepseekApiKey: string;
amazonBedrockApiKey: string;
amazonBedrockRegion: string;
siliconflowApiKey: string;
defaultChainType: ChainType;
defaultModelKey: string;
embeddingModelKey: string;

View file

@ -323,6 +323,27 @@ export interface OpenRouterAIModel {
per_request_limits?: Record<string, string>;
}
// 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,
})) || [],
};
/**