This commit is contained in:
Suksham 2026-01-30 04:24:17 -07:00 committed by GitHub
commit 179df9284c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 197 additions and 0 deletions

View File

@ -0,0 +1,64 @@
---
summary: "Configure DeepSeek API (Chat + Reasoner models)"
read_when:
- You want to use DeepSeek models
- You need to configure DeepSeek API key
- You want cost-effective reasoning models
---
# DeepSeek
DeepSeek provides cost-effective AI models with OpenAI-compatible endpoints. Moltbot supports both the Chat and Reasoner models.
## Models
| Model ID | Name | Reasoning | Context |
|----------|------|-----------|---------|
| `deepseek-chat` | DeepSeek Chat | No | 64K |
| `deepseek-reasoner` | DeepSeek Reasoner | Yes | 64K |
## Quick start
```bash
moltbot onboard --auth-choice deepseek-api-key
```
Or set the environment variable:
```bash
export DEEPSEEK_API_KEY="sk-..."
moltbot models set deepseek/deepseek-chat
```
## Config snippet
```json5
{
env: { DEEPSEEK_API_KEY: "sk-..." },
agents: {
defaults: {
model: { primary: "deepseek/deepseek-chat" }
}
}
}
```
## Using the Reasoner model
For tasks requiring chain-of-thought reasoning:
```json5
{
agents: {
defaults: {
model: { primary: "deepseek/deepseek-reasoner" }
}
}
}
```
## Notes
- DeepSeek uses an OpenAI-compatible API at `https://api.deepseek.com`
- Get your API key from [platform.deepseek.com](https://platform.deepseek.com/)
- Pricing is very competitive compared to other providers

View File

@ -39,6 +39,7 @@ See [Venice AI](/providers/venice).
- [OpenRouter](/providers/openrouter)
- [Vercel AI Gateway](/providers/vercel-ai-gateway)
- [Moonshot AI (Kimi + Kimi Code)](/providers/moonshot)
- [DeepSeek (Chat + Reasoner)](/providers/deepseek)
- [OpenCode Zen](/providers/opencode)
- [Amazon Bedrock](/bedrock)
- [Z.AI](/providers/zai)

View File

@ -286,6 +286,7 @@ export function resolveEnvApiKey(provider: string): EnvApiKeyResult | null {
venice: "VENICE_API_KEY",
mistral: "MISTRAL_API_KEY",
opencode: "OPENCODE_API_KEY",
deepseek: "DEEPSEEK_API_KEY",
};
const envVar = envMap[normalized];
if (!envVar) return null;

View File

@ -0,0 +1,85 @@
import { mkdtempSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
buildDeepSeekProvider,
DEEPSEEK_API_BASE_URL,
DEEPSEEK_CHAT_MODEL_ID,
DEEPSEEK_REASONER_MODEL_ID,
resolveImplicitProviders,
} from "./models-config.providers.js";
describe("DeepSeek provider", () => {
describe("buildDeepSeekProvider", () => {
it("returns correct provider configuration", () => {
const provider = buildDeepSeekProvider();
expect(provider.baseUrl).toBe(DEEPSEEK_API_BASE_URL);
expect(provider.api).toBe("openai-completions");
expect(provider.models).toHaveLength(2);
});
it("includes deepseek-chat model with correct config", () => {
const provider = buildDeepSeekProvider();
const chatModel = provider.models.find((m) => m.id === DEEPSEEK_CHAT_MODEL_ID);
expect(chatModel).toBeDefined();
expect(chatModel?.name).toBe("DeepSeek Chat");
expect(chatModel?.reasoning).toBe(false);
expect(chatModel?.input).toEqual(["text"]);
expect(chatModel?.contextWindow).toBe(64000);
expect(chatModel?.maxTokens).toBe(8192);
});
it("includes deepseek-reasoner model with reasoning enabled", () => {
const provider = buildDeepSeekProvider();
const reasonerModel = provider.models.find((m) => m.id === DEEPSEEK_REASONER_MODEL_ID);
expect(reasonerModel).toBeDefined();
expect(reasonerModel?.name).toBe("DeepSeek Reasoner");
expect(reasonerModel?.reasoning).toBe(true);
expect(reasonerModel?.input).toEqual(["text"]);
});
});
describe("resolveImplicitProviders", () => {
let previousKey: string | undefined;
beforeEach(() => {
previousKey = process.env.DEEPSEEK_API_KEY;
});
afterEach(() => {
if (previousKey === undefined) {
delete process.env.DEEPSEEK_API_KEY;
} else {
process.env.DEEPSEEK_API_KEY = previousKey;
}
vi.resetModules();
});
it("does not include deepseek when no API key is configured", async () => {
delete process.env.DEEPSEEK_API_KEY;
const agentDir = mkdtempSync(join(tmpdir(), "clawd-test-deepseek-"));
const providers = await resolveImplicitProviders({ agentDir });
expect(providers?.deepseek).toBeUndefined();
});
it("includes deepseek when DEEPSEEK_API_KEY env var is set", async () => {
process.env.DEEPSEEK_API_KEY = "sk-test-deepseek-key";
const agentDir = mkdtempSync(join(tmpdir(), "clawd-test-deepseek-"));
vi.resetModules();
const { resolveImplicitProviders: freshResolve } =
await import("./models-config.providers.js");
const providers = await freshResolve({ agentDir });
expect(providers?.deepseek).toBeDefined();
expect(providers?.deepseek?.baseUrl).toBe(DEEPSEEK_API_BASE_URL);
expect(providers?.deepseek?.apiKey).toBe("DEEPSEEK_API_KEY");
expect(providers?.deepseek?.models).toHaveLength(2);
});
});
});

View File

@ -86,6 +86,18 @@ const OLLAMA_DEFAULT_COST = {
cacheWrite: 0,
};
export const DEEPSEEK_API_BASE_URL = "https://api.deepseek.com";
export const DEEPSEEK_CHAT_MODEL_ID = "deepseek-chat";
export const DEEPSEEK_REASONER_MODEL_ID = "deepseek-reasoner";
const DEEPSEEK_DEFAULT_CONTEXT_WINDOW = 64000;
const DEEPSEEK_DEFAULT_MAX_TOKENS = 8192;
const DEEPSEEK_DEFAULT_COST = {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
};
interface OllamaModel {
name: string;
modified_at: string;
@ -388,6 +400,33 @@ async function buildOllamaProvider(): Promise<ProviderConfig> {
};
}
export function buildDeepSeekProvider(): ProviderConfig {
return {
baseUrl: DEEPSEEK_API_BASE_URL,
api: "openai-completions",
models: [
{
id: DEEPSEEK_CHAT_MODEL_ID,
name: "DeepSeek Chat",
reasoning: false,
input: ["text"],
cost: DEEPSEEK_DEFAULT_COST,
contextWindow: DEEPSEEK_DEFAULT_CONTEXT_WINDOW,
maxTokens: DEEPSEEK_DEFAULT_MAX_TOKENS,
},
{
id: DEEPSEEK_REASONER_MODEL_ID,
name: "DeepSeek Reasoner",
reasoning: true,
input: ["text"],
cost: DEEPSEEK_DEFAULT_COST,
contextWindow: DEEPSEEK_DEFAULT_CONTEXT_WINDOW,
maxTokens: DEEPSEEK_DEFAULT_MAX_TOKENS,
},
],
};
}
export async function resolveImplicitProviders(params: {
agentDir: string;
}): Promise<ModelsConfig["providers"]> {
@ -454,6 +493,13 @@ export async function resolveImplicitProviders(params: {
providers.ollama = { ...(await buildOllamaProvider()), apiKey: ollamaKey };
}
const deepseekKey =
resolveEnvApiKeyVarName("deepseek") ??
resolveApiKeyFromProfiles({ provider: "deepseek", store: authStore });
if (deepseekKey) {
providers.deepseek = { ...buildDeepSeekProvider(), apiKey: deepseekKey };
}
return providers;
}