diff --git a/.changeset/old-cycles-add.md b/.changeset/old-cycles-add.md new file mode 100644 index 00000000..2391fc97 --- /dev/null +++ b/.changeset/old-cycles-add.md @@ -0,0 +1,5 @@ +--- +"@inngest/ai": patch +--- + +Add Deepseek support diff --git a/packages/ai/src/env.ts b/packages/ai/src/env.ts index 2d9ea2e4..14a99572 100644 --- a/packages/ai/src/env.ts +++ b/packages/ai/src/env.ts @@ -66,4 +66,5 @@ export enum envKeys { OpenAiApiKey = "OPENAI_API_KEY", GeminiApiKey = "GEMINI_API_KEY", AnthropicApiKey = "ANTHROPIC_API_KEY", + DeepSeekApiKey = "DEEPSEEK_API_KEY", } diff --git a/packages/ai/src/models/deepseek.ts b/packages/ai/src/models/deepseek.ts new file mode 100644 index 00000000..f2ba5b97 --- /dev/null +++ b/packages/ai/src/models/deepseek.ts @@ -0,0 +1,72 @@ +import { type AiAdapter } from "../adapter.js"; +import { type OpenAiAiAdapter } from "../adapters/openai.js"; +import { envKeys, processEnv } from "../env"; + +/** + * Create a DeepSeek model using the OpenAI-compatible chat format. + * + * By default it targets the `https://api.deepseek.com/v1/` base URL. + */ +export const deepseek: AiAdapter.ModelCreator< + [options: DeepSeek.AiModelOptions], + DeepSeek.AiModel +> = (options) => { + const authKey = options.apiKey || processEnv(envKeys.DeepSeekApiKey) || ""; + + // Ensure we add a trailing slash to our base URL if it doesn't have one, + // otherwise we'll replace the path instead of appending it. + let baseUrl = options.baseUrl || "https://api.deepseek.com/v1/"; + if (!baseUrl.endsWith("/")) { + baseUrl += "/"; + } + + const url = new URL("chat/completions", baseUrl); + + return { + url: url.href, + authKey, + format: "openai-chat", + onCall(_, body) { + body.model ||= options.model; + }, + options, + } as DeepSeek.AiModel; +}; + +export namespace DeepSeek { + /** + * IDs of models available in the DeepSeek API. + */ + export type Model = "deepseek-chat" | "deepseek-reasoner" | (string & {}); + + /** + * Options for creating a DeepSeek model. + */ + export interface AiModelOptions { + /** + * ID of the model to use. Currently supports 'deepseek-chat' (DeepSeek-V3) + * and 'deepseek-reasoner' (DeepSeek-R1). + */ + model: Model; + + /** + * The DeepSeek API key to use for authenticating your request. By default we'll + * search for and use the `DEEPSEEK_API_KEY` environment variable. + */ + apiKey?: string; + + /** + * The base URL for the DeepSeek API. + * + * @default "https://api.deepseek.com/v1/" + */ + baseUrl?: string; + } + + /** + * A DeepSeek model using the OpenAI-compatible format for I/O. + */ + export interface AiModel extends OpenAiAiAdapter { + options: AiModelOptions; + } +} diff --git a/packages/ai/src/models/index.ts b/packages/ai/src/models/index.ts index e75e764f..af0f5fa3 100644 --- a/packages/ai/src/models/index.ts +++ b/packages/ai/src/models/index.ts @@ -1,3 +1,4 @@ -export * from "./anthropic"; -export * from "./gemini"; -export * from "./openai"; +export * from "./anthropic.js"; +export * from "./gemini.js"; +export * from "./openai.js"; +export * from "./deepseek.js";