feat: init support for deepseek
This commit is contained in:
parent
3513c6801e
commit
27ac18d9d7
|
@ -54,10 +54,11 @@ ANTHROPIC_API_KEY=
|
|||
### anthropic claude Api version. (optional)
|
||||
ANTHROPIC_API_VERSION=
|
||||
|
||||
|
||||
# deepseek api key (optional)
|
||||
DEEPSEEK_API_KEY=
|
||||
|
||||
### anthropic claude Api url (optional)
|
||||
ANTHROPIC_URL=
|
||||
|
||||
### (optional)
|
||||
WHITE_WEBDEV_ENDPOINTS=
|
||||
WEBDEV_ENDPOINTS_WHITELIST=
|
11
README.md
11
README.md
|
@ -212,6 +212,10 @@ anthropic claude Api version.
|
|||
|
||||
anthropic claude Api Url.
|
||||
|
||||
### `DEEPSEEK_API_KEY` (optional)
|
||||
|
||||
deepseek Api Key.
|
||||
|
||||
### `HIDE_USER_API_KEY` (optional)
|
||||
|
||||
> Default: Empty
|
||||
|
@ -245,11 +249,12 @@ To control custom models, use `+` to add a custom model, use `-` to hide a model
|
|||
|
||||
User `-all` to disable all default models, `+all` to enable all default models.
|
||||
|
||||
### `WHITE_WEBDEV_ENDPOINTS` (可选)
|
||||
### `WEBDEV_ENDPOINTS_WHITELIST` (可选)
|
||||
|
||||
You can use this option if you want to increase the number of webdav service addresses you are allowed to access, as required by the format:
|
||||
- Each address must be a complete endpoint
|
||||
> `https://xxxx/yyy`
|
||||
|
||||
- Each address must be a complete endpoint
|
||||
> `https://xxxx/yyy`
|
||||
- Multiple addresses are connected by ', '
|
||||
|
||||
## Requirements
|
||||
|
|
|
@ -126,6 +126,10 @@ anthropic claude Api version.
|
|||
|
||||
anthropic claude Api Url.
|
||||
|
||||
### `DEEPSEEK_API_KEY` (optional)
|
||||
|
||||
deepseek Api Key.
|
||||
|
||||
### `HIDE_USER_API_KEY` (可选)
|
||||
|
||||
如果你不想让用户自行填入 API Key,将此环境变量设置为 1 即可。
|
||||
|
@ -142,11 +146,12 @@ anthropic claude Api Url.
|
|||
|
||||
如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。
|
||||
|
||||
### `WHITE_WEBDEV_ENDPOINTS` (可选)
|
||||
### `WEBDEV_ENDPOINTS_WHITELIST` (可选)
|
||||
|
||||
如果你想增加允许访问的webdav服务地址,可以使用该选项,格式要求:
|
||||
|
||||
- 每一个地址必须是一个完整的 endpoint
|
||||
> `https://xxxx/xxx`
|
||||
> `https://xxxx/xxx`
|
||||
- 多个地址以`,`相连
|
||||
|
||||
### `CUSTOM_MODELS` (可选)
|
||||
|
|
|
@ -73,6 +73,10 @@ export function auth(req: NextRequest, modelProvider: ModelProvider) {
|
|||
case ModelProvider.Claude:
|
||||
systemApiKey = serverConfig.anthropicApiKey;
|
||||
break;
|
||||
|
||||
case ModelProvider.Deepseek:
|
||||
systemApiKey = serverConfig.deepseekApiKey;
|
||||
break;
|
||||
case ModelProvider.GPT:
|
||||
default:
|
||||
if (serverConfig.isAzure) {
|
||||
|
|
|
@ -87,6 +87,8 @@ export async function requestOpenai(req: NextRequest) {
|
|||
DEFAULT_MODELS,
|
||||
serverConfig.customModels,
|
||||
);
|
||||
|
||||
// check if deepseek model
|
||||
const clonedBody = await req.text();
|
||||
fetchOptions.body = clonedBody;
|
||||
|
||||
|
@ -112,16 +114,16 @@ export async function requestOpenai(req: NextRequest) {
|
|||
try {
|
||||
const res = await fetch(fetchUrl, fetchOptions);
|
||||
|
||||
// Extract the OpenAI-Organization header from the response
|
||||
const openaiOrganizationHeader = res.headers.get("OpenAI-Organization");
|
||||
// Extract the OpenAI-Organization header from the response
|
||||
const openaiOrganizationHeader = res.headers.get("OpenAI-Organization");
|
||||
|
||||
// Check if serverConfig.openaiOrgId is defined and not an empty string
|
||||
if (serverConfig.openaiOrgId && serverConfig.openaiOrgId.trim() !== "") {
|
||||
// If openaiOrganizationHeader is present, log it; otherwise, log that the header is not present
|
||||
console.log("[Org ID]", openaiOrganizationHeader);
|
||||
} else {
|
||||
console.log("[Org ID] is not set up.");
|
||||
}
|
||||
// Check if serverConfig.openaiOrgId is defined and not an empty string
|
||||
if (serverConfig.openaiOrgId && serverConfig.openaiOrgId.trim() !== "") {
|
||||
// If openaiOrganizationHeader is present, log it; otherwise, log that the header is not present
|
||||
console.log("[Org ID]", openaiOrganizationHeader);
|
||||
} else {
|
||||
console.log("[Org ID] is not set up.");
|
||||
}
|
||||
|
||||
// to prevent browser prompt for credentials
|
||||
const newHeaders = new Headers(res.headers);
|
||||
|
@ -129,7 +131,6 @@ export async function requestOpenai(req: NextRequest) {
|
|||
// to disable nginx buffering
|
||||
newHeaders.set("X-Accel-Buffering", "no");
|
||||
|
||||
|
||||
// Conditionally delete the OpenAI-Organization header from the response if [Org ID] is undefined or empty (not setup in ENV)
|
||||
// Also, this is to prevent the header from being sent to the client
|
||||
if (!serverConfig.openaiOrgId || serverConfig.openaiOrgId.trim() === "") {
|
||||
|
@ -142,7 +143,6 @@ export async function requestOpenai(req: NextRequest) {
|
|||
// The browser will try to decode the response with brotli and fail
|
||||
newHeaders.delete("content-encoding");
|
||||
|
||||
|
||||
return new Response(res.body, {
|
||||
status: res.status,
|
||||
statusText: res.statusText,
|
||||
|
|
|
@ -70,7 +70,7 @@ export abstract class LLMApi {
|
|||
abstract models(): Promise<LLMModel[]>;
|
||||
}
|
||||
|
||||
type ProviderName = "openai" | "azure" | "claude" | "palm";
|
||||
type ProviderName = "openai" | "azure" | "claude" | "palm" | "deepseek";
|
||||
|
||||
interface Model {
|
||||
name: string;
|
||||
|
@ -162,6 +162,7 @@ export function getHeaders() {
|
|||
const modelConfig = useChatStore.getState().currentSession().mask.modelConfig;
|
||||
const isGoogle = modelConfig.model.startsWith("gemini");
|
||||
const isAzure = accessStore.provider === ServiceProvider.Azure;
|
||||
const isDeepSeek = accessStore.provider === ServiceProvider.DeepSeek;
|
||||
const authHeader = isAzure ? "api-key" : "Authorization";
|
||||
const apiKey = isGoogle
|
||||
? accessStore.googleApiKey
|
||||
|
|
|
@ -89,6 +89,7 @@ export const getServerSideConfig = () => {
|
|||
const isAzure = !!process.env.AZURE_URL;
|
||||
const isGoogle = !!process.env.GOOGLE_API_KEY;
|
||||
const isAnthropic = !!process.env.ANTHROPIC_API_KEY;
|
||||
const isDeepSeek = !!process.env.DEEPSEEK_API_KEY;
|
||||
|
||||
// const apiKeyEnvVar = process.env.OPENAI_API_KEY ?? "";
|
||||
// const apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim());
|
||||
|
@ -99,7 +100,7 @@ export const getServerSideConfig = () => {
|
|||
// );
|
||||
|
||||
const allowedWebDevEndpoints = (
|
||||
process.env.WHITE_WEBDEV_ENDPOINTS ?? ""
|
||||
process.env.WEBDEV_ENDPOINTS_WHITELIST ?? ""
|
||||
).split(",");
|
||||
|
||||
return {
|
||||
|
@ -121,6 +122,8 @@ export const getServerSideConfig = () => {
|
|||
anthropicApiVersion: process.env.ANTHROPIC_API_VERSION,
|
||||
anthropicUrl: process.env.ANTHROPIC_URL,
|
||||
|
||||
deepseekApiKey: getApiKey(process.env.DEEPSEEK_API_KEY),
|
||||
|
||||
gtmId: process.env.GTM_ID,
|
||||
|
||||
needCode: ACCESS_CODES.size > 0,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { Chat } from "./components/chat";
|
||||
|
||||
export const OWNER = "Yidadaa";
|
||||
export const REPO = "ChatGPT-Next-Web";
|
||||
export const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
|
||||
|
@ -70,12 +72,14 @@ export enum ServiceProvider {
|
|||
Azure = "Azure",
|
||||
Google = "Google",
|
||||
Anthropic = "Anthropic",
|
||||
DeepSeek = "DeepSeek",
|
||||
}
|
||||
|
||||
export enum ModelProvider {
|
||||
GPT = "GPT",
|
||||
GeminiPro = "GeminiPro",
|
||||
Claude = "Claude",
|
||||
Deepseek = "DeepSeek",
|
||||
}
|
||||
|
||||
export const Anthropic = {
|
||||
|
@ -136,16 +140,11 @@ export const KnowledgeCutOffDate: Record<string, string> = {
|
|||
|
||||
const openaiModels = [
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-1106",
|
||||
"gpt-3.5-turbo-0125",
|
||||
"gpt-4",
|
||||
"gpt-4-0613",
|
||||
"gpt-4-32k",
|
||||
"gpt-4-32k-0613",
|
||||
"gpt-4-turbo",
|
||||
"gpt-4-turbo-preview",
|
||||
"gpt-4-vision-preview",
|
||||
"gpt-4-turbo-2024-04-09",
|
||||
];
|
||||
|
||||
const googleModels = [
|
||||
|
@ -163,6 +162,8 @@ const anthropicModels = [
|
|||
"claude-3-haiku-20240307",
|
||||
];
|
||||
|
||||
const deepseekModels = ["deepseek-chat"];
|
||||
|
||||
export const DEFAULT_MODELS = [
|
||||
...openaiModels.map((name) => ({
|
||||
name,
|
||||
|
@ -191,6 +192,15 @@ export const DEFAULT_MODELS = [
|
|||
providerType: "anthropic",
|
||||
},
|
||||
})),
|
||||
...deepseekModels.map((name) => ({
|
||||
name,
|
||||
available: true,
|
||||
provider: {
|
||||
id: "deepseek",
|
||||
providerName: "DeepSeek",
|
||||
providerType: "deepseek",
|
||||
},
|
||||
})),
|
||||
] as const;
|
||||
|
||||
export const CHAT_PAGE_SIZE = 15;
|
||||
|
|
Loading…
Reference in New Issue