Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DeepSeek API bots #891

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Typical users of ChatALL are:
| [Cohere Command R Models](https://cohere.com/command) | No | Yes | |
| [Copilot](https://copilot.microsoft.com/) | Yes | No API | |
| [Dedao Learning Assistant](https://ai.dedao.cn/) | Coming soon | No API | |
| [DeepSeek](https://chat.deepseek.com/) | Coming soon | Yes | |
| [Falcon 180B](https://huggingface.co/tiiuae/falcon-180B-chat) | Yes | No API | |
| [Gemini](https://gemini.google.com/) | Yes | Yes | |
| [Gemma 2B & 7B](https://blog.google/technology/developers/gemma-open-models/) | Yes | No API | |
Expand Down
6 changes: 6 additions & 0 deletions public/bots/deepseek.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions src/bots/deepseek/DeepSeekAPIBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import LangChainBot from "../LangChainBot";
import { ChatOpenAI } from "@langchain/openai";
import store from "@/store";

export default class DeepSeekAPIBot extends LangChainBot {
static _brandId = "deepSeekApi"; // Brand id of the bot, should be unique. Used in i18n.
static _className = "DeepSeekAPIBot";
static _logoFilename = "deepseek.svg";

Comment on lines +5 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add missing static _model property declaration

The _model property is referenced in _setupModel() but not declared as a static property. Consider adding it to maintain consistency with other static properties.

 export default class DeepSeekAPIBot extends LangChainBot {
   static _brandId = "deepSeekApi"; // Brand id of the bot, should be unique. Used in i18n.
   static _className = "DeepSeekAPIBot";
   static _logoFilename = "deepseek.svg";
+  static _model = ""; // Default model name
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default class DeepSeekAPIBot extends LangChainBot {
static _brandId = "deepSeekApi"; // Brand id of the bot, should be unique. Used in i18n.
static _className = "DeepSeekAPIBot";
static _logoFilename = "deepseek.svg";
export default class DeepSeekAPIBot extends LangChainBot {
static _brandId = "deepSeekApi"; // Brand id of the bot, should be unique. Used in i18n.
static _className = "DeepSeekAPIBot";
static _logoFilename = "deepseek.svg";
static _model = ""; // Default model name

constructor() {
super();
}

async _checkAvailability() {
let available = false;

if (store.state.deepSeekApi.apiKey) {
this.setupModel();
available = true;
}
return available;
}
Comment on lines +14 to +22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix method name mismatch and add error handling

  1. The method calls setupModel() but the actual method is named _setupModel().
  2. Consider adding API key validation before setting availability to true.
   async _checkAvailability() {
     let available = false;
 
-    if (store.state.deepSeekApi.apiKey) {
-      this.setupModel();
+    const apiKey = store.state.deepSeekApi.apiKey;
+    if (apiKey && typeof apiKey === 'string' && apiKey.trim()) {
+      this._setupModel();
       available = true;
     }
     return available;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async _checkAvailability() {
let available = false;
if (store.state.deepSeekApi.apiKey) {
this.setupModel();
available = true;
}
return available;
}
async _checkAvailability() {
let available = false;
const apiKey = store.state.deepSeekApi.apiKey;
if (apiKey && typeof apiKey === 'string' && apiKey.trim()) {
this._setupModel();
available = true;
}
return available;
}


_setupModel() {
PeterDaveHello marked this conversation as resolved.
Show resolved Hide resolved
const chatModel = new ChatOpenAI({
configuration: {
basePath: "https://api.deepseek.com/v1",
},
openAIApiKey: store.state.deepSeekApi.apiKey,
modelName: this.constructor._model ? this.constructor._model : "",
temperature: store.state.deepSeekApi.temperature,
streaming: true,
});
return chatModel;
}
Comment on lines +24 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve configuration management and error handling

  1. The DeepSeek API URL should be configurable rather than hardcoded
  2. Add error handling for model initialization
  3. Validate temperature value (should be between 0 and 1)
   _setupModel() {
+    const temperature = store.state.deepSeekApi.temperature;
+    if (temperature < 0 || temperature > 1) {
+      throw new Error('Temperature must be between 0 and 1');
+    }
+
+    try {
       const chatModel = new ChatOpenAI({
         configuration: {
-          basePath: "https://api.deepseek.com/v1",
+          basePath: store.state.deepSeekApi.basePath || "https://api.deepseek.com/v1",
         },
         openAIApiKey: store.state.deepSeekApi.apiKey,
         modelName: this.constructor._model ? this.constructor._model : "",
-        temperature: store.state.deepSeekApi.temperature,
+        temperature,
         streaming: true,
       });
       return chatModel;
+    } catch (error) {
+      throw new Error(`Failed to initialize DeepSeek chat model: ${error.message}`);
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_setupModel() {
const chatModel = new ChatOpenAI({
configuration: {
basePath: "https://api.deepseek.com/v1",
},
openAIApiKey: store.state.deepSeekApi.apiKey,
modelName: this.constructor._model ? this.constructor._model : "",
temperature: store.state.deepSeekApi.temperature,
streaming: true,
});
return chatModel;
}
_setupModel() {
const temperature = store.state.deepSeekApi.temperature;
if (temperature < 0 || temperature > 1) {
throw new Error('Temperature must be between 0 and 1');
}
try {
const chatModel = new ChatOpenAI({
configuration: {
basePath: store.state.deepSeekApi.basePath || "https://api.deepseek.com/v1",
},
openAIApiKey: store.state.deepSeekApi.apiKey,
modelName: this.constructor._model ? this.constructor._model : "",
temperature,
streaming: true,
});
return chatModel;
} catch (error) {
throw new Error(`Failed to initialize DeepSeek chat model: ${error.message}`);
}
}


getPastRounds() {
return store.state.deepSeekApi.pastRounds;
}
}
10 changes: 10 additions & 0 deletions src/bots/deepseek/DeepSeekAPIChatBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import DeepSeekAPIBot from "./DeepSeekAPIBot";

export default class DeepSeekAPIChatBot extends DeepSeekAPIBot {
static _className = "DeepSeekAPIChatBot";
static _model = "deepseek-chat";

constructor() {
super();
}
Comment on lines +7 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unnecessary constructor.

The constructor only calls super() without any additional initialization. In ES6, this will be automatically handled when extending a class.

Apply this diff to remove the unnecessary constructor:

-  constructor() {
-    super();
-  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
constructor() {
super();
}
🧰 Tools
🪛 Biome

[error] 7-9: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)

}
10 changes: 10 additions & 0 deletions src/bots/deepseek/DeepSeekAPICoderBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import DeepSeekAPIBot from "./DeepSeekAPIBot";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Remove unnecessary constructor in DeepSeekAPICoderBot

The parent class DeepSeekAPIBot exists and the inheritance chain is properly set up (DeepSeekAPICoderBot → DeepSeekAPIBot → LangChainBot). However, the constructor in DeepSeekAPICoderBot is unnecessary since:

  • It only calls super() with no parameters
  • It adds no additional initialization logic
  • JavaScript will automatically create an implicit constructor that calls super()
  • Remove the constructor from src/bots/deepseek/DeepSeekAPICoderBot.js (lines 7-9)
🔗 Analysis chain

Verify parent class implementation

The import statement looks correct, but let's verify the existence and implementation of the parent class.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and basic structure of DeepSeekAPIBot

# Check if the parent class file exists and contains the expected class definition
ast-grep --pattern 'export $_ class DeepSeekAPIBot {
  $$$
}'

Length of output: 63


Script:

#!/bin/bash
# Let's try a different approach to verify the parent class

# First, let's find the exact file location
fd "DeepSeekAPIBot.js" --type f

# Then let's check the content of any files containing DeepSeekAPIBot
rg "class DeepSeekAPIBot" -A 5

Length of output: 566


Script:

#!/bin/bash
# Let's verify the complete implementation of both classes to ensure proper inheritance

# Check DeepSeekAPIBot's complete implementation
rg "class DeepSeekAPIBot" -B 2 -A 15 src/bots/deepseek/DeepSeekAPIBot.js

# Check DeepSeekAPICoderBot's complete implementation
rg "class DeepSeekAPICoderBot" -B 2 -A 15 src/bots/deepseek/DeepSeekAPICoderBot.js

# Check if LangChainBot exists since DeepSeekAPIBot extends it
fd "LangChainBot.js" --type f

Length of output: 901


export default class DeepSeekAPICoderBot extends DeepSeekAPIBot {
static _className = "DeepSeekAPICoderBot";
static _model = "deepseek-coder";

constructor() {
super();
}
PeterDaveHello marked this conversation as resolved.
Show resolved Hide resolved
}
10 changes: 10 additions & 0 deletions src/bots/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ import ClaudeAPISonnetBot from "./anthropic/ClaudeAPISonnetBot";
import ClaudeAPI35SonnetBot from "./anthropic/ClaudeAPI35SonnetBot";
import ClaudeAPIHaikuBot from "./anthropic/ClaudeAPIHaikuBot";
import ClaudeAPIInstant12Bot from "./anthropic/ClaudeAPIInstant12Bot";
import DeepSeekAPICoderBot from "./deepseek/DeepSeekAPICoderBot";
import DeepSeekAPIChatBot from "./deepseek/DeepSeekAPIChatBot";

const all = [
Qihoo360AIBrainBot.getInstance(),
Expand Down Expand Up @@ -172,6 +174,8 @@ const all = [
Wizardlm70bBot.getInstance(),
Zephyr7bBot.getInstance(),
YouChatBot.getInstance(),
DeepSeekAPICoderBot.getInstance(),
DeepSeekAPIChatBot.getInstance(),
];

const disabled = [
Expand Down Expand Up @@ -289,6 +293,8 @@ export const botTags = {
bots.getBotByClassName("Gemma7bItBot"),
bots.getBotByClassName("Claude3SonnetBot"),
bots.getBotByClassName("Claude3OpusBot"),
bots.getBotByClassName("DeepSeekAPICoderBot"),
bots.getBotByClassName("DeepSeekAPIChatBot"),
],
api: [
bots.getBotByClassName("GeminiAPIBot"),
Expand Down Expand Up @@ -319,6 +325,8 @@ export const botTags = {
bots.getBotByClassName("Llama38bGroqAPIBot"),
bots.getBotByClassName("Llama370bGroqAPIBot"),
bots.getBotByClassName("Mixtral8x7bGroqAPIBot"),
bots.getBotByClassName("DeepSeekAPICoderBot"),
bots.getBotByClassName("DeepSeekAPIChatBot"),
],
madeInChina: [
bots.getBotByClassName("Qihoo360AIBrainBot"),
Expand All @@ -334,6 +342,8 @@ export const botTags = {
bots.getBotByClassName("ChatGLM6bBot"),
bots.getBotByClassName("ChatGLM36bBot"),
bots.getBotByClassName("KimiBot"),
bots.getBotByClassName("DeepSeekAPICoderBot"),
bots.getBotByClassName("DeepSeekAPIChatBot"),
],
};
export default bots;
63 changes: 63 additions & 0 deletions src/components/BotSettings/DeepSeekAPIBotSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<template>
<CommonBotSettings
:settings="settings"
:brand-id="brandId"
mutation-type="setDeepSeekApi"
:watcher="watcher"
></CommonBotSettings>
</template>

<script>
import Bot from "@/bots/deepseek/DeepSeekAPIBot";
import CommonBotSettings from "@/components/BotSettings/CommonBotSettings.vue";
import { Type } from "./settings.const";

const settings = [
{
type: Type.Text,
name: "apiKey",
title: "common.apiKey",
description: "settings.secretPrompt",
placeholder: "sk-...",
},
{
type: Type.Slider,
name: "temperature",
title: "openaiApi.temperature",
description: "openaiApi.temperaturePrompt",
default: 1.0,
min: 0,
max: 2,
step: 0.05,
ticks: {
0: "openaiApi.temperature0",
2: "openaiApi.temperature2",
},
},
{
type: Type.Slider,
name: "pastRounds",
title: "bot.pastRounds",
description: "bot.pastRoundsPrompt",
min: 0,
max: 10,
step: 1,
},
];
export default {
components: {
CommonBotSettings,
},
data() {
return {
settings: settings,
brandId: Bot._brandId,
};
},
methods: {
watcher() {
Bot.getInstance().setupModel();
},
},
};
Comment on lines +47 to +62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve component implementation robustness.

Several improvements can be made to enhance code reliability:

  1. Accessing Bot._brandId directly is not recommended as it's a private property
  2. The watcher method lacks error handling
  3. No type checking for Bot.getInstance()

Consider applying these improvements:

 data() {
   return {
     settings: settings,
-    brandId: Bot._brandId,
+    brandId: Bot.getBrandId(), // Add this method to Bot class
   };
 },
 methods: {
   watcher() {
+    try {
+      const bot = Bot.getInstance();
+      if (!bot) {
+        throw new Error('Failed to get Bot instance');
+      }
       Bot.getInstance().setupModel();
+    } catch (error) {
+      console.error('Failed to setup model:', error);
+      // Consider adding user notification here
+    }
   },
 },

Committable suggestion skipped: line range outside the PR's diff.

</script>
2 changes: 2 additions & 0 deletions src/components/SettingsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ import ClaudeAIBotSettings from "./BotSettings/ClaudeAIBotSettings.vue";
import ChatGLMBotSettings from "./BotSettings/ChatGLMBotSettings.vue";
import CohereAPIBotSettings from "./BotSettings/CohereAPIBotSettings.vue";
import KimiBotSettings from "./BotSettings/KimiBotSettings.vue";
import DeepSeekAPIBotSettings from "./BotSettings/DeepSeekAPIBotSettings.vue";

import { resolveTheme, applyTheme, Mode } from "../theme";
import ClaudeAPIBotSettings from "./BotSettings/ClaudeAPIBotSettings.vue";
Expand All @@ -152,6 +153,7 @@ const botSettings = [
{ brand: "claudeAi", component: ClaudeAIBotSettings },
{ brand: "claudeApi", component: ClaudeAPIBotSettings },
{ brand: "cohereApi", component: CohereAPIBotSettings },
{ brand: "deepSeekApi", component: DeepSeekAPIBotSettings },
{ brand: "falcon", component: Falcon180bBotSettings },
{ brand: "geminiApi", component: GeminiAPIBotSettings },
{ brand: "gradio", component: GradioAppBotSettings },
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@
"temperature0": "More deterministic",
"temperature2": "More random"
},
"deepSeekApi": {
"name": "DeepSeek API",
"deepseek-chat": "deepseek-chat",
"deepseek-coder": "deepseek-coder"
},
"poe": {
"name": "Poe",
"a2": "Claude-instant",
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@
"temperature0": "更具确定性",
"temperature2": "更具随机性"
},
"deepSeekApi": {
"name": "DeepSeek API",
"deepseek-chat": "deepseek-chat",
"deepseek-coder": "deepseek-coder"
},
"poe": {
"name": "Poe",
"a2": "Claude-instant",
Expand Down
8 changes: 8 additions & 0 deletions src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export default createStore({
temperature: 0.8,
pastRounds: 5,
},
deepSeekApi: {
apiKey: "",
temperature: 1.0,
pastRounds: 10,
},
openaiApi: {
apiKey: "",
temperature: 1,
Expand Down Expand Up @@ -213,6 +218,9 @@ export default createStore({
setChatgpt(state, refreshCycle) {
state.chatgpt.refreshCycle = refreshCycle;
},
setDeepSeekApi(state, values) {
state.deepSeekApi = { ...state.deepSeekApi, ...values };
},
setGeminiApi(state, values) {
state.geminiApi = { ...state.geminiApi, ...values };
},
Expand Down