diff --git a/core/src/providers/provider.rs b/core/src/providers/provider.rs index 02a7f769731a..1eadc66aaf6e 100644 --- a/core/src/providers/provider.rs +++ b/core/src/providers/provider.rs @@ -57,6 +57,7 @@ impl FromStr for ProviderID { "mistral" => Ok(ProviderID::Mistral), "google_ai_studio" => Ok(ProviderID::GoogleAiStudio), "togetherai" => Ok(ProviderID::TogetherAI), + "deepseek" => Ok(ProviderID::Deepseek), _ => Err(ParseError::with_message( "Unknown provider ID \ (possible values: openai, azure_openai, anthropic, mistral, google_ai_studio)", diff --git a/front/components/providers/DeepseekSetup.tsx b/front/components/providers/DeepseekSetup.tsx new file mode 100644 index 000000000000..aa9098d5bf04 --- /dev/null +++ b/front/components/providers/DeepseekSetup.tsx @@ -0,0 +1,199 @@ +import { Button } from "@dust-tt/sparkle"; +import type { WorkspaceType } from "@dust-tt/types"; +import { Dialog, Transition } from "@headlessui/react"; +import { Fragment, useEffect, useState } from "react"; +import { useSWRConfig } from "swr"; + +import { checkProvider } from "@app/lib/providers"; + +export default function DeepseekSetup({ + owner, + open, + setOpen, + config, + enabled, +}: { + owner: WorkspaceType; + open: boolean; + setOpen: (open: boolean) => void; + config: { [key: string]: string }; + enabled: boolean; +}) { + const { mutate } = useSWRConfig(); + + const [apiKey, setApiKey] = useState(config ? config.api_key : ""); + const [testSuccessful, setTestSuccessful] = useState(false); + const [testRunning, setTestRunning] = useState(false); + const [testError, setTestError] = useState(""); + const [enableRunning, setEnableRunning] = useState(false); + + useEffect(() => { + if (config && config.api_key.length > 0 && apiKey.length == 0) { + setApiKey(config.api_key); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [config]); + + const runTest = async () => { + setTestRunning(true); + setTestError(""); + const check = await checkProvider(owner, "deepseek", { + api_key: apiKey, + }); + + if (!check.ok) { + setTestError(check.error); + setTestSuccessful(false); + setTestRunning(false); + } else { + setTestError(""); + setTestSuccessful(true); + setTestRunning(false); + } + }; + + const handleEnable = async () => { + setEnableRunning(true); + const res = await fetch(`/api/w/${owner.sId}/providers/deepseek`, { + headers: { + "Content-Type": "application/json", + }, + method: "POST", + body: JSON.stringify({ + config: JSON.stringify({ + api_key: apiKey, + }), + }), + }); + await res.json(); + setEnableRunning(false); + setOpen(false); + await mutate(`/api/w/${owner.sId}/providers`); + }; + + const handleDisable = async () => { + const res = await fetch(`/api/w/${owner.sId}/providers/deepseek`, { + method: "DELETE", + }); + await res.json(); + setOpen(false); + await mutate(`/api/w/${owner.sId}/providers`); + }; + + return ( + + setOpen(false)}> + +
+ + +
+
+ + +
+
+ + Setup Deepseek + +
+

+ To use Deepseek models you must provide your API key. +

+

+ We'll never use your API key for anything other than to + run your apps. +

+
+
+ { + setApiKey(e.target.value); + setTestSuccessful(false); + }} + /> +
+
+
+
+ {testError?.length > 0 ? ( + Error: {testError} + ) : testSuccessful ? ( + + Test succeeded! You can enable Deepseek. + + ) : ( +   + )} +
+
+ {enabled ? ( +
handleDisable()} + > + Disable +
+ ) : ( + <> + )} +
+
+
+
+ {testSuccessful ? ( +
+
+
+
+
+
+
+
+ ); +} diff --git a/front/components/providers/types.ts b/front/components/providers/types.ts index ec7bb86a9968..a8ce9e63362f 100644 --- a/front/components/providers/types.ts +++ b/front/components/providers/types.ts @@ -35,6 +35,7 @@ export const MODEL_PROVIDER_LOGOS: Record = { mistral: MistralLogo, google_ai_studio: GoogleLogo, togetherai: PlanetIcon, + deepseek: PlanetIcon, }; export const USED_MODEL_CONFIGS: readonly ModelConfig[] = [ diff --git a/front/components/workspace/ProviderManagementModal.tsx b/front/components/workspace/ProviderManagementModal.tsx index e25f8b3a3b16..1a97a4377753 100644 --- a/front/components/workspace/ProviderManagementModal.tsx +++ b/front/components/workspace/ProviderManagementModal.tsx @@ -33,6 +33,7 @@ const prettyfiedProviderNames: { [key in ModelProviderIdType]: string } = { mistral: "Mistral AI", google_ai_studio: "Google", togetherai: "TogetherAI", + deepseek: "Deepseek", }; const modelProviders: Record = diff --git a/front/lib/providers.ts b/front/lib/providers.ts index c22c2fbc8608..bb365bf62123 100644 --- a/front/lib/providers.ts +++ b/front/lib/providers.ts @@ -62,6 +62,14 @@ export const modelProviders: ModelProvider[] = [ chat: true, embed: false, }, + { + providerId: "deepseek", + name: "Deepseek", + built: true, + enabled: false, + chat: true, + embed: false, + }, ]; export const APP_MODEL_PROVIDER_IDS: string[] = [ @@ -71,6 +79,7 @@ export const APP_MODEL_PROVIDER_IDS: string[] = [ "google_ai_studio", "togetherai", "azure_openai", + "deepseek", ] as const; type ServiceProvider = { diff --git a/front/pages/api/w/[wId]/providers/[pId]/check.ts b/front/pages/api/w/[wId]/providers/[pId]/check.ts index b9f9cc293d71..f98fd6049c2d 100644 --- a/front/pages/api/w/[wId]/providers/[pId]/check.ts +++ b/front/pages/api/w/[wId]/providers/[pId]/check.ts @@ -258,6 +258,22 @@ async function handler( } return; + case "deepseek": + const testDeepseek = await fetch(`https://api.deepseek.com/models`, { + method: "GET", + headers: { + Authorization: `Bearer ${config.api_key}`, + }, + }); + if (!testDeepseek.ok) { + const err = await testDeepseek.json(); + res.status(400).json({ ok: false, error: err.error }); + } else { + await testDeepseek.json(); + res.status(200).json({ ok: true }); + } + return; + default: return apiError(req, res, { status_code: 404, diff --git a/front/pages/api/w/[wId]/providers/[pId]/models.ts b/front/pages/api/w/[wId]/providers/[pId]/models.ts index 20bc0260320e..a10f05446bbc 100644 --- a/front/pages/api/w/[wId]/providers/[pId]/models.ts +++ b/front/pages/api/w/[wId]/providers/[pId]/models.ts @@ -258,6 +258,15 @@ async function handler( ], }); + case "deepseek": + if (embed) { + res.status(200).json({ models: [] }); + return; + } + return res.status(200).json({ + models: [{ id: "deepseek-chat" }], + }); + default: return apiError(req, res, { status_code: 404, diff --git a/front/pages/w/[wId]/developers/providers.tsx b/front/pages/w/[wId]/developers/providers.tsx index f68639223335..68856f207b7c 100644 --- a/front/pages/w/[wId]/developers/providers.tsx +++ b/front/pages/w/[wId]/developers/providers.tsx @@ -9,6 +9,7 @@ import { subNavigationAdmin } from "@app/components/navigation/config"; import AnthropicSetup from "@app/components/providers/AnthropicSetup"; import AzureOpenAISetup from "@app/components/providers/AzureOpenAISetup"; import BrowserlessAPISetup from "@app/components/providers/BrowserlessAPISetup"; +import DeepseekSetup from "@app/components/providers/DeepseekSetup"; import GoogleAiStudioSetup from "@app/components/providers/GoogleAiStudioSetup"; import MistralAISetup from "@app/components/providers/MistralAISetup"; import OpenAISetup from "@app/components/providers/OpenAISetup"; @@ -58,7 +59,7 @@ export function Providers({ owner }: { owner: WorkspaceType }) { const [serperOpen, setSerperOpen] = useState(false); const [browserlessapiOpen, setBrowserlessapiOpen] = useState(false); const [togetherAiOpen, setTogetherAiOpen] = useState(false); - + const [deepseekOpen, setDeepseekOpen] = useState(false); const { providers, isProvidersLoading, isProvidersError } = useProviders({ owner, }); @@ -139,6 +140,13 @@ export function Providers({ owner }: { owner: WorkspaceType }) { enabled={!!configs["togetherai"]} config={configs["togetherai"] ?? null} /> + () => }); const ModelProviderIdSchema = FlexibleEnumSchema< - "openai" | "anthropic" | "mistral" | "google_ai_studio" | "togetherai" + | "openai" + | "anthropic" + | "mistral" + | "google_ai_studio" + | "togetherai" + | "deepseek" >(); const ModelLLMIdSchema = FlexibleEnumSchema< @@ -42,6 +47,7 @@ const ModelLLMIdSchema = FlexibleEnumSchema< | "Qwen/Qwen2.5-Coder-32B-Instruct" | "Qwen/QwQ-32B-Preview" | "Qwen/Qwen2-72B-Instruct" + | "deepseek-chat" >(); const EmbeddingProviderIdSchema = FlexibleEnumSchema<"openai" | "mistral">(); diff --git a/types/src/front/lib/api/credentials.ts b/types/src/front/lib/api/credentials.ts index b46075be2089..e7988789f7c2 100644 --- a/types/src/front/lib/api/credentials.ts +++ b/types/src/front/lib/api/credentials.ts @@ -11,6 +11,7 @@ const { DUST_MANAGED_SERP_API_KEY = "", DUST_MANAGED_BROWSERLESS_API_KEY = "", DUST_MANAGED_TOGETHERAI_API_KEY = "", + DUST_MANAGED_DEEPSEEK_API_KEY = "", } = process.env; export const credentialsFromProviders = ( @@ -62,6 +63,9 @@ export const credentialsFromProviders = ( case "togetherai": credentials["TOGETHERAI_API_KEY"] = config.api_key; break; + case "deepseek": + credentials["DEEPSEEK_API_KEY"] = config.api_key; + break; } }); return credentials; @@ -79,5 +83,6 @@ export const dustManagedCredentials = (): CredentialsType => { SERP_API_KEY: DUST_MANAGED_SERP_API_KEY, BROWSERLESS_API_KEY: DUST_MANAGED_BROWSERLESS_API_KEY, TOGETHERAI_API_KEY: DUST_MANAGED_TOGETHERAI_API_KEY, + DEEPSEEK_API_KEY: DUST_MANAGED_DEEPSEEK_API_KEY, }; }; diff --git a/types/src/front/lib/assistant.ts b/types/src/front/lib/assistant.ts index 7459630e1b09..6057cab577fb 100644 --- a/types/src/front/lib/assistant.ts +++ b/types/src/front/lib/assistant.ts @@ -18,6 +18,7 @@ export const MODEL_PROVIDER_IDS = [ "mistral", "google_ai_studio", "togetherai", + "deepseek", ] as const; export type ModelProviderIdType = (typeof MODEL_PROVIDER_IDS)[number]; @@ -121,6 +122,7 @@ export const TOGETHERAI_QWEN_32B_PREVIEW_MODEL_ID = "Qwen/QwQ-32B-Preview" as const; export const TOGETHERAI_QWEN_72B_INSTRUCT_MODEL_ID = "Qwen/Qwen2-72B-Instruct" as const; +export const DEEPSEEK_CHAT_MODEL_ID = "deepseek-chat" as const; export const MODEL_IDS = [ GPT_3_5_TURBO_MODEL_ID, @@ -147,6 +149,7 @@ export const MODEL_IDS = [ TOGETHERAI_QWEN_2_5_CODER_32B_INSTRUCT_MODEL_ID, TOGETHERAI_QWEN_32B_PREVIEW_MODEL_ID, TOGETHERAI_QWEN_72B_INSTRUCT_MODEL_ID, + DEEPSEEK_CHAT_MODEL_ID, ] as const; export type ModelIdType = (typeof MODEL_IDS)[number]; diff --git a/types/src/front/provider.ts b/types/src/front/provider.ts index b5f5785cf0d9..56600144d654 100644 --- a/types/src/front/provider.ts +++ b/types/src/front/provider.ts @@ -17,4 +17,5 @@ export type CredentialsType = { BROWSERLESS_API_KEY?: string; GOOGLE_AI_STUDIO_API_KEY?: string; TOGETHERAI_API_KEY?: string; + DEEPSEEK_API_KEY?: string; };