Skip to content

Commit

Permalink
make it work with dust apps
Browse files Browse the repository at this point in the history
  • Loading branch information
Henry Fontanier committed Dec 27, 2024
1 parent 822b33f commit da08c0e
Show file tree
Hide file tree
Showing 12 changed files with 264 additions and 2 deletions.
1 change: 1 addition & 0 deletions core/src/providers/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)",
Expand Down
199 changes: 199 additions & 0 deletions front/components/providers/DeepseekSetup.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Transition.Root show={open} as={Fragment}>
<Dialog as="div" className="relative z-30" onClose={() => setOpen(false)}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-800 bg-opacity-75 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 z-30 overflow-y-auto">
<div className="flex min-h-full items-end items-center justify-center p-4">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
leave="ease-in duration-200"
leaveTo="opacity-0"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6 lg:max-w-lg">
<div>
<div className="mt-3">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-900"
>
Setup Deepseek
</Dialog.Title>
<div className="mt-4">
<p className="text-sm text-gray-500">
To use Deepseek models you must provide your API key.
</p>
<p className="mt-2 text-sm text-gray-500">
We'll never use your API key for anything other than to
run your apps.
</p>
</div>
<div className="mt-6">
<input
type="text"
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-action-500 focus:ring-action-500 sm:text-sm"
placeholder="Deepseek API Key"
value={apiKey}
onChange={(e) => {
setApiKey(e.target.value);
setTestSuccessful(false);
}}
/>
</div>
</div>
</div>
<div className="mt-1 px-2 text-sm">
{testError?.length > 0 ? (
<span className="text-red-500">Error: {testError}</span>
) : testSuccessful ? (
<span className="text-green-600">
Test succeeded! You can enable Deepseek.
</span>
) : (
<span>&nbsp;</span>
)}
</div>
<div className="mt-5 flex flex-row items-center space-x-2 sm:mt-6">
{enabled ? (
<div
className="flex-initial cursor-pointer text-sm font-bold text-red-500"
onClick={() => handleDisable()}
>
Disable
</div>
) : (
<></>
)}
<div className="flex-1"></div>
<div className="flex flex-initial">
<Button
onClick={() => setOpen(false)}
label="Cancel"
variant="outline"
/>
</div>
<div className="flex flex-initial">
{testSuccessful ? (
<Button
onClick={() => handleEnable()}
disabled={enableRunning}
label={
enabled
? enableRunning
? "Updating..."
: "Update"
: enableRunning
? "Enabling..."
: "Enable"
}
/>
) : (
<Button
disabled={apiKey.length == 0 || testRunning}
onClick={() => runTest()}
label={testRunning ? "Testing..." : "Test"}
/>
)}
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}
1 change: 1 addition & 0 deletions front/components/providers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const MODEL_PROVIDER_LOGOS: Record<ModelProvider, ComponentType> = {
mistral: MistralLogo,
google_ai_studio: GoogleLogo,
togetherai: PlanetIcon,
deepseek: PlanetIcon,
};

export const USED_MODEL_CONFIGS: readonly ModelConfig[] = [
Expand Down
1 change: 1 addition & 0 deletions front/components/workspace/ProviderManagementModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const prettyfiedProviderNames: { [key in ModelProviderIdType]: string } = {
mistral: "Mistral AI",
google_ai_studio: "Google",
togetherai: "TogetherAI",
deepseek: "Deepseek",
};

const modelProviders: Record<ModelProviderIdType, string[]> =
Expand Down
9 changes: 9 additions & 0 deletions front/lib/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [
Expand All @@ -71,6 +79,7 @@ export const APP_MODEL_PROVIDER_IDS: string[] = [
"google_ai_studio",
"togetherai",
"azure_openai",
"deepseek",
] as const;

type ServiceProvider = {
Expand Down
16 changes: 16 additions & 0 deletions front/pages/api/w/[wId]/providers/[pId]/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 9 additions & 0 deletions front/pages/api/w/[wId]/providers/[pId]/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 12 additions & 1 deletion front/pages/w/[wId]/developers/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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,
});
Expand Down Expand Up @@ -139,6 +140,13 @@ export function Providers({ owner }: { owner: WorkspaceType }) {
enabled={!!configs["togetherai"]}
config={configs["togetherai"] ?? null}
/>
<DeepseekSetup
owner={owner}
open={deepseekOpen}
setOpen={setDeepseekOpen}
enabled={!!configs["deepseek"]}
config={configs["deepseek"] ?? null}
/>
<SerpAPISetup
owner={owner}
open={serpapiOpen}
Expand Down Expand Up @@ -226,6 +234,9 @@ export function Providers({ owner }: { owner: WorkspaceType }) {
case "togetherai":
setTogetherAiOpen(true);
break;
case "deepseek":
setDeepseekOpen(true);
break;
}
}}
label={
Expand Down
8 changes: 7 additions & 1 deletion sdks/js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ const FlexibleEnumSchema = <T extends string>() =>
});

const ModelProviderIdSchema = FlexibleEnumSchema<
"openai" | "anthropic" | "mistral" | "google_ai_studio" | "togetherai"
| "openai"
| "anthropic"
| "mistral"
| "google_ai_studio"
| "togetherai"
| "deepseek"
>();

const ModelLLMIdSchema = FlexibleEnumSchema<
Expand Down Expand Up @@ -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">();
Expand Down
5 changes: 5 additions & 0 deletions types/src/front/lib/api/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
Expand Down Expand Up @@ -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;
Expand All @@ -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,
};
};
3 changes: 3 additions & 0 deletions types/src/front/lib/assistant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down Expand Up @@ -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,
Expand All @@ -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];

Expand Down
Loading

0 comments on commit da08c0e

Please sign in to comment.