diff --git a/src/app/(main)/settings/provider/(detail)/doubao/page.tsx b/src/app/(main)/settings/provider/(detail)/doubao/page.tsx new file mode 100644 index 0000000000000..88a05c1ee1eef --- /dev/null +++ b/src/app/(main)/settings/provider/(detail)/doubao/page.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { DoubaoProviderCard } from '@/config/modelProviders'; +import { ModelProvider } from '@/libs/agent-runtime'; +import { useUserStore } from '@/store/user'; +import { modelProviderSelectors } from '@/store/user/selectors'; + +import { ProviderItem } from '../../type'; +import ProviderDetail from '../[id]'; + +const providerKey = ModelProvider.Doubao; + +const useProviderCard = (): ProviderItem => { + + // Get the first model card's deployment name as the check model + const checkModel = useUserStore((s) => { + const chatModelCards = modelProviderSelectors.getModelCardsById(providerKey)(s); + + if (chatModelCards.length > 0) { + return chatModelCards[0].deploymentName; + } + + return 'Doubao-lite-4k'; + }); + return { + ...DoubaoProviderCard, + checkModel, + modelList: { + azureDeployName: true, + }, + }; +}; + +const Page = () => { + const card = useProviderCard(); + + return ; + }; + + export default Page; \ No newline at end of file diff --git a/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx b/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx index 1e17115ab1cae..566227e4e9000 100644 --- a/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx +++ b/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx @@ -66,7 +66,7 @@ const ModelConfigModal = memo(({ id, open, setOpen }) => idEditable={false} initialValues={model} onFormInstanceReady={setFormInstance} - showAzureDeployName={editingProvider === ModelProvider.Azure} + showAzureDeployName={editingProvider === ModelProvider.Azure || editingProvider === ModelProvider.Doubao} type={model?.type} /> diff --git a/src/config/aiModels/doubao.ts b/src/config/aiModels/doubao.ts new file mode 100644 index 0000000000000..52cc0ee4fbd29 --- /dev/null +++ b/src/config/aiModels/doubao.ts @@ -0,0 +1,65 @@ +import { AIChatModelCard } from '@/types/aiModel'; + +const doubaoChatModels: AIChatModelCard[] = [ + { + contextWindowTokens: 4096, + description: + '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 4k 上下文窗口的推理和精调。', + displayName: 'Doubao Lite 4k', + enabled: true, + id: 'Doubao-lite-4k', + type: 'chat', + }, + { + contextWindowTokens: 32_768, + description: + '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 32k 上下文窗口的推理和精调。', + displayName: 'Doubao Lite 32k', + enabled: true, + id: 'Doubao-lite-32k', + type: 'chat', + }, + { + contextWindowTokens: 128_000, + description: + '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 128k 上下文窗口的推理和精调。', + displayName: 'Doubao Lite 128k', + enabled: true, + id: 'Doubao-lite-128k', + type: 'chat', + }, + { + contextWindowTokens: 4096, + description: + '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 4k 上下文窗口的推理和精调。', + displayName: 'Doubao Pro 4k', + enabled: true, + id: 'Doubao-pro-4k', + type: 'chat', + }, + { + config: { + deploymentName: 'Doubao-pro-test', + }, + contextWindowTokens: 32_768, + description: + '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 32k 上下文窗口的推理和精调。', + displayName: 'Doubao Pro 32k', + enabled: true, + id: 'Doubao-pro-32k', + type: 'chat', + }, + { + contextWindowTokens: 128_000, + description: + '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 128k 上下文窗口的推理和精调。', + displayName: 'Doubao Pro 128k', + enabled: true, + id: 'Doubao-pro-128k', + type: 'chat', + }, +]; + +export const allModels = [...doubaoChatModels]; + +export default allModels; diff --git a/src/config/aiModels/index.ts b/src/config/aiModels/index.ts index ee9cf0d0d1ec5..53d099ef9854b 100644 --- a/src/config/aiModels/index.ts +++ b/src/config/aiModels/index.ts @@ -8,6 +8,7 @@ import { default as baichuan } from './baichuan'; import { default as bedrock } from './bedrock'; import { default as cloudflare } from './cloudflare'; import { default as deepseek } from './deepseek'; +import { default as doubao } from './doubao'; import { default as fireworksai } from './fireworksai'; import { default as giteeai } from './giteeai'; import { default as github } from './github'; @@ -67,6 +68,7 @@ export const LOBE_DEFAULT_MODEL_LIST = buildDefaultModelList({ bedrock, cloudflare, deepseek, + doubao, fireworksai, giteeai, github, @@ -107,6 +109,7 @@ export { default as baichuan } from './baichuan'; export { default as bedrock } from './bedrock'; export { default as cloudflare } from './cloudflare'; export { default as deepseek } from './deepseek'; +export { default as doubao } from './doubao'; export { default as fireworksai } from './fireworksai'; export { default as giteeai } from './giteeai'; export { default as github } from './github'; diff --git a/src/config/llm.ts b/src/config/llm.ts index 89b0ac242638c..c5f15c3f0acf6 100644 --- a/src/config/llm.ts +++ b/src/config/llm.ts @@ -123,6 +123,9 @@ export const getLLMConfig = () => { ENABLED_HIGRESS: z.boolean(), HIGRESS_API_KEY: z.string().optional(), + + ENABLED_DOUBAO: z.boolean(), + DOUBAO_API_KEY: z.string().optional(), }, runtimeEnv: { API_KEY_SELECT_MODE: process.env.API_KEY_SELECT_MODE, @@ -244,6 +247,9 @@ export const getLLMConfig = () => { ENABLED_HIGRESS: !!process.env.HIGRESS_API_KEY, HIGRESS_API_KEY: process.env.HIGRESS_API_KEY, + + ENABLED_DOUBAO: !!process.env.DOUBAO_API_KEY, + DOUBAO_API_KEY: process.env.DOUBAO_API_KEY, }, }); }; diff --git a/src/config/modelProviders/doubao.ts b/src/config/modelProviders/doubao.ts new file mode 100644 index 0000000000000..1af75312759da --- /dev/null +++ b/src/config/modelProviders/doubao.ts @@ -0,0 +1,23 @@ +import { ModelProviderCard } from '@/types/llm'; + +// ref https://www.volcengine.com/docs/82379/1330310 +const Doubao: ModelProviderCard = { + chatModels: [], + // checkModel: 'Doubao-lite-4k', + description: '字节跳动推出的自研大模型。通过字节跳动内部50+业务场景实践验证,每日万亿级tokens大使用量持续打磨,提供多种模态能力,以优质模型效果为企业打造丰富的业务体验。', + id: 'doubao', + modelsUrl: 'https://www.volcengine.com/product/doubao', + name: '豆包', + settings: { + disableBrowserRequest: true, // CORS error + sdkType: 'doubao', + // showModelFetcher: false, + smoothing: { + speed: 2, + text: true, + }, + }, + url: 'https://www.volcengine.com/product/doubao', +}; + +export default Doubao; diff --git a/src/config/modelProviders/index.ts b/src/config/modelProviders/index.ts index b482b3e982d45..ab6f75bf072fb 100644 --- a/src/config/modelProviders/index.ts +++ b/src/config/modelProviders/index.ts @@ -8,6 +8,7 @@ import BaichuanProvider from './baichuan'; import BedrockProvider from './bedrock'; import CloudflareProvider from './cloudflare'; import DeepSeekProvider from './deepseek'; +import DoubaoProvider from './doubao'; import FireworksAIProvider from './fireworksai'; import GiteeAIProvider from './giteeai'; import GithubProvider from './github'; @@ -120,6 +121,7 @@ export const DEFAULT_MODEL_PROVIDER_LIST = [ GiteeAIProvider, TaichuProvider, Ai360Provider, + DoubaoProvider, ]; export const filterEnabledModels = (provider: ModelProviderCard) => { @@ -139,6 +141,7 @@ export { default as BaichuanProviderCard } from './baichuan'; export { default as BedrockProviderCard } from './bedrock'; export { default as CloudflareProviderCard } from './cloudflare'; export { default as DeepSeekProviderCard } from './deepseek'; +export { default as DoubaoProviderCard } from './doubao'; export { default as FireworksAIProviderCard } from './fireworksai'; export { default as GiteeAIProviderCard } from './giteeai'; export { default as GithubProviderCard } from './github'; diff --git a/src/libs/agent-runtime/AgentRuntime.ts b/src/libs/agent-runtime/AgentRuntime.ts index 74799b6affe17..c2b46ea6d6618 100644 --- a/src/libs/agent-runtime/AgentRuntime.ts +++ b/src/libs/agent-runtime/AgentRuntime.ts @@ -11,6 +11,7 @@ import { LobeBaichuanAI } from './baichuan'; import { LobeBedrockAI, LobeBedrockAIParams } from './bedrock'; import { LobeCloudflareAI, LobeCloudflareParams } from './cloudflare'; import { LobeDeepSeekAI } from './deepseek'; +import { LobeDoubaoAI } from './doubao'; import { LobeFireworksAI } from './fireworksai'; import { LobeGiteeAI } from './giteeai'; import { LobeGithubAI } from './github'; @@ -139,6 +140,7 @@ class AgentRuntime { bedrock: Partial; cloudflare: Partial; deepseek: Partial; + doubao: Partial; fireworksai: Partial; giteeai: Partial; github: Partial; @@ -363,6 +365,11 @@ class AgentRuntime { runtimeModel = new LobeHigressAI(params.higress); break; } + + case ModelProvider.Doubao: { + runtimeModel = new LobeDoubaoAI(params.doubao); + break; + } } return new AgentRuntime(runtimeModel); } diff --git a/src/libs/agent-runtime/doubao/index.ts b/src/libs/agent-runtime/doubao/index.ts new file mode 100644 index 0000000000000..a06c5398403a5 --- /dev/null +++ b/src/libs/agent-runtime/doubao/index.ts @@ -0,0 +1,10 @@ +import { ModelProvider } from '../types'; +import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory'; + +export const LobeDoubaoAI = LobeOpenAICompatibleFactory({ + baseURL: 'https://ark.cn-beijing.volces.com/api/v3', + debug: { + chatCompletion: () => process.env.DEBUG_DOUBAO_CHAT_COMPLETION === '1', + }, + provider: ModelProvider.Doubao, +}); \ No newline at end of file diff --git a/src/libs/agent-runtime/index.ts b/src/libs/agent-runtime/index.ts index 308cd40ca4529..4988b78cf9eee 100644 --- a/src/libs/agent-runtime/index.ts +++ b/src/libs/agent-runtime/index.ts @@ -4,6 +4,7 @@ export { LobeAzureOpenAI } from './azureOpenai'; export * from './BaseAI'; export { LobeBedrockAI } from './bedrock'; export { LobeDeepSeekAI } from './deepseek'; +export { LobeDoubaoAI } from './doubao'; export * from './error'; export { LobeGoogleAI } from './google'; export { LobeGroq } from './groq'; diff --git a/src/libs/agent-runtime/types/type.ts b/src/libs/agent-runtime/types/type.ts index 3f5a692ed5d37..f089e45cb2c40 100644 --- a/src/libs/agent-runtime/types/type.ts +++ b/src/libs/agent-runtime/types/type.ts @@ -30,6 +30,7 @@ export enum ModelProvider { Bedrock = 'bedrock', Cloudflare = 'cloudflare', DeepSeek = 'deepseek', + Doubao = 'doubao', FireworksAI = 'fireworksai', GiteeAI = 'giteeai', Github = 'github', diff --git a/src/server/globalConfig/index.ts b/src/server/globalConfig/index.ts index 83251cd4b3858..f1980234e4c1f 100644 --- a/src/server/globalConfig/index.ts +++ b/src/server/globalConfig/index.ts @@ -25,6 +25,9 @@ export const getServerGlobalConfig = () => { enabledKey: 'ENABLED_AWS_BEDROCK', modelListKey: 'AWS_BEDROCK_MODEL_LIST', }, + doubao: { + withDeploymentName: true, + }, giteeai: { enabledKey: 'ENABLED_GITEE_AI', modelListKey: 'GITEE_AI_MODEL_LIST', diff --git a/src/services/chat.ts b/src/services/chat.ts index 24326a5846b41..aab22366a1973 100644 --- a/src/services/chat.ts +++ b/src/services/chat.ts @@ -221,7 +221,7 @@ class ChatService { let model = res.model || DEFAULT_AGENT_CONFIG.model; // if the provider is Azure, get the deployment name as the request model - if (provider === ModelProvider.Azure) { + if (provider === ModelProvider.Azure || provider === ModelProvider.Doubao) { model = findAzureDeploymentName(model); } diff --git a/src/types/aiProvider.ts b/src/types/aiProvider.ts index 8fcb1ce6d8694..704a6010128c5 100644 --- a/src/types/aiProvider.ts +++ b/src/types/aiProvider.ts @@ -18,6 +18,7 @@ export const AiProviderSDKEnum = { Azure: 'azure', Bedrock: 'bedrock', Cloudflare: 'cloudflare', + Doubao: 'doubao', Google: 'google', Huggingface: 'huggingface', Ollama: 'ollama', diff --git a/src/types/user/settings/keyVaults.ts b/src/types/user/settings/keyVaults.ts index 53ba7fe269af6..97c910c37bdd3 100644 --- a/src/types/user/settings/keyVaults.ts +++ b/src/types/user/settings/keyVaults.ts @@ -39,6 +39,7 @@ export interface UserKeyVaults { bedrock?: AWSBedrockKeyVault; cloudflare?: CloudflareKeyVault; deepseek?: OpenAICompatibleKeyVault; + doubao?: OpenAICompatibleKeyVault; fireworksai?: OpenAICompatibleKeyVault; giteeai?: OpenAICompatibleKeyVault; github?: OpenAICompatibleKeyVault;