diff --git a/src/renderer/packages/model-setting-utils/burncloud-setting-util.ts b/src/renderer/packages/model-setting-utils/burncloud-setting-util.ts new file mode 100644 index 000000000..1f4231f04 --- /dev/null +++ b/src/renderer/packages/model-setting-utils/burncloud-setting-util.ts @@ -0,0 +1,106 @@ +import { ModelProvider, ProviderSettings, SessionType } from 'src/shared/types' +import { ModelSettingUtil } from './interface' +import BurnCloud from '../models/burncloud' +import BaseConfig from './base-config' + +export default class BurnCloudSettingUtil extends BaseConfig implements ModelSettingUtil { + public provider: ModelProvider = ModelProvider.BurnCloud + + async getCurrentModelDisplayName( + model: string, + sessionType: SessionType, + providerSettings?: ProviderSettings + ): Promise { + if (sessionType === 'picture') { + return `BurnCloud API (DALL-E-3)` + } else { + return `BurnCloud API (${providerSettings?.models?.find((m) => m.modelId === model)?.nickname || model})` + } + } + + public getLocalOptionGroups() { + // BurnCloud支持的所有模型 + const claudeModels = [ + 'claude-sonnet-4-20250514', + 'claude-3-7-sonnet-20250219', + 'claude-3-5-sonnet-20241022', + ] + + const gptModels = [ + 'gpt-4o', + 'gpt-4o-mini', + 'o1', + 'gpt-4.5-preview', + 'o1-mini', + ] + + const imageModels = [ + 'gpt-image-1', + ] + + const geminiModels = [ + 'gemini-2.5-pro-preview-05-06', + 'gemini-2.0', + ] + + const deepseekModels = [ + 'deepseek-r1', + 'deepseek-v3', + ] + + return [ + { + group_name: 'Claude 系列', + options: claudeModels.map((value) => ({ + label: value, + value: value, + })), + collapsable: true, + }, + { + group_name: 'GPT 系列', + options: gptModels.map((value) => ({ + label: value, + value: value, + })), + collapsable: true, + }, + { + group_name: '图像生成', + options: imageModels.map((value) => ({ + label: value, + value: value, + })), + collapsable: true, + }, + { + group_name: 'Gemini 系列', + options: geminiModels.map((value) => ({ + label: value, + value: value, + })), + collapsable: true, + }, + { + group_name: 'DeepSeek 系列', + options: deepseekModels.map((value) => ({ + label: value, + value: value, + })), + collapsable: true, + }, + ] + } + + protected async listProviderModels() { + return [] + } + + isCurrentModelSupportImageInput(model: string): boolean { + return BurnCloud.helpers.isModelSupportVision(model) + } + + isCurrentModelSupportToolUse(model: string): boolean { + return BurnCloud.helpers.isModelSupportToolUse(model) + } +} \ No newline at end of file diff --git a/src/renderer/packages/model-setting-utils/index.ts b/src/renderer/packages/model-setting-utils/index.ts index 0d943f573..cb8c151b8 100644 --- a/src/renderer/packages/model-setting-utils/index.ts +++ b/src/renderer/packages/model-setting-utils/index.ts @@ -16,6 +16,7 @@ import PerplexitySettingUtil from './perplexity-setting-util' import SiliconFlowSettingUtil from './siliconflow-setting-util' import VolcEngineSettingUtil from './volcengine-setting-util' import XAISettingUtil from './xai-setting-util' +import BurnCloudSettingUtil from './burncloud-setting-util' export function getModelSettingUtil(aiProvider: ModelProvider): ModelSettingUtil { const hash: Record ModelSettingUtil> = { @@ -33,6 +34,7 @@ export function getModelSettingUtil(aiProvider: ModelProvider): ModelSettingUtil [ModelProviderEnum.LMStudio]: LMStudioSettingUtil, [ModelProviderEnum.Perplexity]: PerplexitySettingUtil, [ModelProviderEnum.XAI]: XAISettingUtil, + [ModelProvider.BurnCloud]: BurnCloudSettingUtil, [ModelProviderEnum.Custom]: CustomModelSettingUtil, } const Class = hash[aiProvider] || CustomModelSettingUtil diff --git a/src/renderer/packages/models/burncloud.ts b/src/renderer/packages/models/burncloud.ts new file mode 100644 index 000000000..673bceffd --- /dev/null +++ b/src/renderer/packages/models/burncloud.ts @@ -0,0 +1,111 @@ +import { fetchWithProxy } from '@/utils/request' +import { createOpenAICompatible } from '@ai-sdk/openai-compatible' +import { extractReasoningMiddleware, wrapLanguageModel } from 'ai' +import AbstractAISDKModel from './abstract-ai-sdk' +import { ModelHelpers } from './types' +import { fetchRemoteModels } from './openai-compatible' + +const helpers: ModelHelpers = { + isModelSupportVision: (model: string) => { + // BurnCloud支持视觉的模型 + const visionModels = [ + 'claude-sonnet-4-20250514', 'claude-3-7-sonnet-20250219', 'claude-3-5-sonnet-20241022', // Claude系列都支持视觉 + 'gpt-4o', 'gpt-4o-mini', 'gpt-4.5-preview', // GPT视觉模型 + 'gemini-2.5-pro-preview-05-06', 'gemini-2.0', // Gemini系列支持视觉 + ] + return visionModels.some(visionModel => model.includes(visionModel.replace(/[.-]/g, ''))) || + model.includes('claude') || + model.includes('gpt-4o') || + model.includes('gemini') + }, + isModelSupportToolUse: (model: string) => { + // BurnCloud支持工具使用的模型(除了纯图像生成和推理专用模型) + const nonToolModels = [ + 'gpt-image-1', // 图像生成模型不支持工具 + 'o1', 'o1-mini', // 推理模型通常不支持工具调用 + ] + return !nonToolModels.some(nonToolModel => model.includes(nonToolModel)) + }, +} + +interface Options { + apiKey: string + apiHost: string + model: string + temperature?: number + topP?: number + useProxy?: boolean +} + +export default class BurnCloud extends AbstractAISDKModel { + public name = 'BurnCloud' + public static helpers = helpers + public options: Options + + constructor(options: Options) { + super() + this.options = { + ...options, + apiHost: options.apiHost || 'https://ai.burncloud.com/v1', + } + } + + public isSupportToolUse() { + return helpers.isModelSupportToolUse(this.options.model) + } + + private getProvider() { + return createOpenAICompatible({ + name: 'BurnCloud', + apiKey: this.options.apiKey, + baseURL: this.options.apiHost, + fetch: this.options.useProxy ? fetchWithProxy : undefined, + }) + } + + protected getChatModel() { + const provider = this.getProvider() + return wrapLanguageModel({ + model: provider.languageModel(this.options.model), + middleware: extractReasoningMiddleware({ tagName: 'think' }), + }) + } + + protected getImageModel() { + const provider = this.getProvider() + return provider.imageModel('dall-e-3') + } + + protected getCallSettings() { + return { + temperature: this.options.temperature, + topP: this.options.topP, + } + } + + public async listModels(): Promise { + return fetchRemoteModels({ + apiHost: this.options.apiHost, + apiKey: this.options.apiKey, + useProxy: this.options.useProxy, + }).catch((err) => { + console.error('BurnCloud models fetch error:', err) + // 返回BurnCloud支持的常见模型作为备选 + return [ + 'claude-sonnet-4-20250514', + 'claude-3-7-sonnet-20250219', + 'claude-3-5-sonnet-20241022', + 'gpt-4o', + 'gpt-4o-mini', + 'o1', + 'gpt-4.5-preview', + 'o1-mini', + 'gpt-image-1', + 'gemini-2.5-pro-preview-05-06', + 'gemini-2.0', + 'deepseek-r1', + 'deepseek-v3', + ] + }) + } +} \ No newline at end of file diff --git a/src/renderer/packages/models/index.ts b/src/renderer/packages/models/index.ts index b05f38984..6831429b7 100644 --- a/src/renderer/packages/models/index.ts +++ b/src/renderer/packages/models/index.ts @@ -12,6 +12,8 @@ import LMStudio from './lmstudio' import Ollama from './ollama' import OpenAI from './openai' import Perplexity from './perplexity' +import XAI from './xai' +import BurnCloud from './burncloud' import SiliconFlow from './siliconflow' import type { ModelInterface } from './types' import VolcEngine from './volcengine' @@ -165,6 +167,17 @@ export function getModel(setting: Settings, config: Config): ModelInterface { temperature: setting.temperature, topP: setting.topP, }) + + case ModelProvider.BurnCloud: + return new BurnCloud({ + apiKey: providerSetting.apiKey || '', + apiHost: formattedApiHost, + model: setting.modelId || '', + temperature: setting.temperature, + topP: setting.topP, + useProxy: providerSetting.useProxy, + }) + default: if (providerBaseInfo.isCustom) { return new CustomOpenAI({ @@ -197,6 +210,7 @@ export const aiProviderNameHash: Record = { [ModelProviderEnum.LMStudio]: 'LM Studio API', [ModelProviderEnum.Perplexity]: 'Perplexity API', [ModelProviderEnum.XAI]: 'xAI API', + [ModelProvider.BurnCloud]: 'BurnCloud API', [ModelProviderEnum.Custom]: 'Custom Provider', } @@ -267,6 +281,11 @@ export const AIModelProviderMenuOptionList = [ label: aiProviderNameHash[ModelProviderEnum.ChatGLM6B], disabled: false, }, + { + value: ModelProvider.BurnCloud, + label: aiProviderNameHash[ModelProvider.BurnCloud], + disabled: false, + }, // { // value: 'hunyuan', // label: '腾讯混元', diff --git a/src/renderer/static/icons/providers/burncloud.png b/src/renderer/static/icons/providers/burncloud.png new file mode 100644 index 000000000..65748adfd Binary files /dev/null and b/src/renderer/static/icons/providers/burncloud.png differ diff --git a/src/shared/defaults.ts b/src/shared/defaults.ts index cdef74d28..72ee7262e 100644 --- a/src/shared/defaults.ts +++ b/src/shared/defaults.ts @@ -592,4 +592,87 @@ export const SystemProviders: ProviderBaseInfo[] = [ ], }, }, + { + id: ModelProvider.BurnCloud, + name: 'BurnCloud', + type: ModelProviderType.OpenAI, + urls: { + website: 'https://burncloud.com', + }, + defaultSettings: { + apiHost: 'https://ai.burncloud.com/v1', + models: [ + // Claude 系列 + { + modelId: 'claude-sonnet-4-20250514', + capabilities: ['vision', 'tool_use'], + contextWindow: 200_000, + }, + { + modelId: 'claude-3-7-sonnet-20250219', + capabilities: ['vision', 'tool_use'], + contextWindow: 200_000, + }, + { + modelId: 'claude-3-5-sonnet-20241022', + capabilities: ['vision', 'tool_use'], + contextWindow: 200_000, + }, + // GPT 系列 + { + modelId: 'gpt-4o', + capabilities: ['vision', 'tool_use'], + contextWindow: 128_000, + }, + { + modelId: 'gpt-4o-mini', + capabilities: ['vision', 'tool_use'], + contextWindow: 128_000, + }, + { + modelId: 'o1', + capabilities: ['reasoning'], + contextWindow: 128_000, + }, + { + modelId: 'gpt-4.5-preview', + capabilities: ['vision', 'tool_use'], + contextWindow: 128_000, + }, + { + modelId: 'o1-mini', + capabilities: ['reasoning'], + contextWindow: 128_000, + }, + // 图像生成模型 + { + modelId: 'gpt-image-1', + capabilities: [], + contextWindow: 4_000, + }, + // Gemini 系列 + { + modelId: 'gemini-2.5-pro-preview-05-06', + capabilities: ['vision', 'tool_use'], + contextWindow: 1_000_000, + }, + { + modelId: 'gemini-2.0', + capabilities: ['vision', 'tool_use'], + contextWindow: 1_000_000, + }, + // DeepSeek 系列 + { + modelId: 'deepseek-r1', + capabilities: ['reasoning', 'tool_use'], + contextWindow: 64_000, + }, + { + modelId: 'deepseek-v3', + capabilities: ['tool_use'], + contextWindow: 64_000, + }, + ], + }, + }, ] diff --git a/src/shared/types.ts b/src/shared/types.ts index 83e7756ab..4895bb2d4 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -229,6 +229,7 @@ export enum ModelProviderEnum { LMStudio = 'lm-studio', Perplexity = 'perplexity', XAI = 'xAI', + BurnCloud = 'burncloud', Custom = 'custom', } export type ModelProvider = ModelProviderEnum | string