-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add deepseek support * lint * update deepseek context length * add deepseek to onboarding --------- Co-authored-by: Timothy Carambat <[email protected]>
- Loading branch information
1 parent
3064583
commit 7390bae
Showing
18 changed files
with
440 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
frontend/src/components/LLMSelection/DeepSeekOptions/index.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { useState, useEffect } from "react"; | ||
import System from "@/models/system"; | ||
|
||
export default function DeepSeekOptions({ settings }) { | ||
const [inputValue, setInputValue] = useState(settings?.DeepSeekApiKey); | ||
const [deepSeekApiKey, setDeepSeekApiKey] = useState( | ||
settings?.DeepSeekApiKey | ||
); | ||
|
||
return ( | ||
<div className="flex gap-[36px] mt-1.5"> | ||
<div className="flex flex-col w-60"> | ||
<label className="text-white text-sm font-semibold block mb-3"> | ||
API Key | ||
</label> | ||
<input | ||
type="password" | ||
name="DeepSeekApiKey" | ||
className="bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" | ||
placeholder="DeepSeek API Key" | ||
defaultValue={settings?.DeepSeekApiKey ? "*".repeat(20) : ""} | ||
required={true} | ||
autoComplete="off" | ||
spellCheck={false} | ||
onChange={(e) => setInputValue(e.target.value)} | ||
onBlur={() => setDeepSeekApiKey(inputValue)} | ||
/> | ||
</div> | ||
{!settings?.credentialsOnly && ( | ||
<DeepSeekModelSelection settings={settings} apiKey={deepSeekApiKey} /> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
function DeepSeekModelSelection({ apiKey, settings }) { | ||
const [models, setModels] = useState([]); | ||
const [loading, setLoading] = useState(true); | ||
|
||
useEffect(() => { | ||
async function findCustomModels() { | ||
if (!apiKey) { | ||
setModels([]); | ||
setLoading(true); | ||
return; | ||
} | ||
|
||
setLoading(true); | ||
const { models } = await System.customModels( | ||
"deepseek", | ||
typeof apiKey === "boolean" ? null : apiKey | ||
); | ||
setModels(models || []); | ||
setLoading(false); | ||
} | ||
findCustomModels(); | ||
}, [apiKey]); | ||
|
||
if (loading) { | ||
return ( | ||
<div className="flex flex-col w-60"> | ||
<label className="text-white text-sm font-semibold block mb-3"> | ||
Chat Model Selection | ||
</label> | ||
<select | ||
name="DeepSeekModelPref" | ||
disabled={true} | ||
className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5" | ||
> | ||
<option disabled={true} selected={true}> | ||
-- loading available models -- | ||
</option> | ||
</select> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="flex flex-col w-60"> | ||
<label className="text-white text-sm font-semibold block mb-3"> | ||
Chat Model Selection | ||
</label> | ||
<select | ||
name="DeepSeekModelPref" | ||
required={true} | ||
className="bg-zinc-900 border-gray-500 text-white text-sm rounded-lg block w-full p-2.5" | ||
> | ||
{models.map((model) => ( | ||
<option | ||
key={model.id} | ||
value={model.id} | ||
selected={settings?.DeepSeekModelPref === model.id} | ||
> | ||
{model.name} | ||
</option> | ||
))} | ||
</select> | ||
</div> | ||
); | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
const { NativeEmbedder } = require("../../EmbeddingEngines/native"); | ||
const { | ||
handleDefaultStreamResponseV2, | ||
} = require("../../helpers/chat/responses"); | ||
const { MODEL_MAP } = require("../modelMap"); | ||
|
||
class DeepSeekLLM { | ||
constructor(embedder = null, modelPreference = null) { | ||
if (!process.env.DEEPSEEK_API_KEY) | ||
throw new Error("No DeepSeek API key was set."); | ||
const { OpenAI: OpenAIApi } = require("openai"); | ||
|
||
this.openai = new OpenAIApi({ | ||
apiKey: process.env.DEEPSEEK_API_KEY, | ||
baseURL: "https://api.deepseek.com/v1", | ||
}); | ||
this.model = | ||
modelPreference || process.env.DEEPSEEK_MODEL_PREF || "deepseek-chat"; | ||
this.limits = { | ||
history: this.promptWindowLimit() * 0.15, | ||
system: this.promptWindowLimit() * 0.15, | ||
user: this.promptWindowLimit() * 0.7, | ||
}; | ||
|
||
this.embedder = embedder ?? new NativeEmbedder(); | ||
this.defaultTemp = 0.7; | ||
} | ||
|
||
#appendContext(contextTexts = []) { | ||
if (!contextTexts || !contextTexts.length) return ""; | ||
return ( | ||
"\nContext:\n" + | ||
contextTexts | ||
.map((text, i) => { | ||
return `[CONTEXT ${i}]:\n${text}\n[END CONTEXT ${i}]\n\n`; | ||
}) | ||
.join("") | ||
); | ||
} | ||
|
||
streamingEnabled() { | ||
return "streamGetChatCompletion" in this; | ||
} | ||
|
||
static promptWindowLimit(modelName) { | ||
return MODEL_MAP.deepseek[modelName] ?? 8192; | ||
} | ||
|
||
promptWindowLimit() { | ||
return MODEL_MAP.deepseek[this.model] ?? 8192; | ||
} | ||
|
||
async isValidChatCompletionModel(modelName = "") { | ||
const models = await this.openai.models.list().catch(() => ({ data: [] })); | ||
return models.data.some((model) => model.id === modelName); | ||
} | ||
|
||
constructPrompt({ | ||
systemPrompt = "", | ||
contextTexts = [], | ||
chatHistory = [], | ||
userPrompt = "", | ||
}) { | ||
const prompt = { | ||
role: "system", | ||
content: `${systemPrompt}${this.#appendContext(contextTexts)}`, | ||
}; | ||
return [prompt, ...chatHistory, { role: "user", content: userPrompt }]; | ||
} | ||
|
||
async getChatCompletion(messages = null, { temperature = 0.7 }) { | ||
if (!(await this.isValidChatCompletionModel(this.model))) | ||
throw new Error( | ||
`DeepSeek chat: ${this.model} is not valid for chat completion!` | ||
); | ||
|
||
const result = await this.openai.chat.completions | ||
.create({ | ||
model: this.model, | ||
messages, | ||
temperature, | ||
}) | ||
.catch((e) => { | ||
throw new Error(e.message); | ||
}); | ||
|
||
if (!result.hasOwnProperty("choices") || result.choices.length === 0) | ||
return null; | ||
return result.choices[0].message.content; | ||
} | ||
|
||
async streamGetChatCompletion(messages = null, { temperature = 0.7 }) { | ||
if (!(await this.isValidChatCompletionModel(this.model))) | ||
throw new Error( | ||
`DeepSeek chat: ${this.model} is not valid for chat completion!` | ||
); | ||
|
||
const streamRequest = await this.openai.chat.completions.create({ | ||
model: this.model, | ||
stream: true, | ||
messages, | ||
temperature, | ||
}); | ||
return streamRequest; | ||
} | ||
|
||
handleStream(response, stream, responseProps) { | ||
return handleDefaultStreamResponseV2(response, stream, responseProps); | ||
} | ||
|
||
async embedTextInput(textInput) { | ||
return await this.embedder.embedTextInput(textInput); | ||
} | ||
async embedChunks(textChunks = []) { | ||
return await this.embedder.embedChunks(textChunks); | ||
} | ||
|
||
async compressMessages(promptArgs = {}, rawHistory = []) { | ||
const { messageArrayCompressor } = require("../../helpers/chat"); | ||
const messageArray = this.constructPrompt(promptArgs); | ||
return await messageArrayCompressor(this, messageArray, rawHistory); | ||
} | ||
} | ||
|
||
module.exports = { | ||
DeepSeekLLM, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.