mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-06-07 05:10:19 +09:00

Adds support for using models hosted on AWS Bedrock, specifically Anthropic Claude models. Key changes: - Added '@aws-sdk/client-bedrock-runtime' dependency. - Updated constants, server config, and auth logic for Bedrock. - Implemented backend API handler () to communicate with the Bedrock API, handling streaming and non-streaming responses, and formatting output to be OpenAI compatible. - Updated dynamic API router () to dispatch requests to the Bedrock handler. - Created frontend client () and updated client factory (). - Updated with necessary Bedrock environment variables (AWS keys, region, enable flag) and an example for using to alias Bedrock models.
276 lines
7.9 KiB
TypeScript
276 lines
7.9 KiB
TypeScript
import md5 from "spark-md5";
|
|
import { DEFAULT_MODELS, DEFAULT_GA_ID } from "../constant";
|
|
import { isGPT4Model } from "../utils/model";
|
|
|
|
declare global {
|
|
namespace NodeJS {
|
|
interface ProcessEnv {
|
|
PROXY_URL?: string; // docker only
|
|
|
|
OPENAI_API_KEY?: string;
|
|
CODE?: string;
|
|
|
|
BASE_URL?: string;
|
|
OPENAI_ORG_ID?: string; // openai only
|
|
|
|
VERCEL?: string;
|
|
BUILD_MODE?: "standalone" | "export";
|
|
BUILD_APP?: string; // is building desktop app
|
|
|
|
HIDE_USER_API_KEY?: string; // disable user's api key input
|
|
DISABLE_GPT4?: string; // allow user to use gpt-4 or not
|
|
ENABLE_BALANCE_QUERY?: string; // allow user to query balance or not
|
|
DISABLE_FAST_LINK?: string; // disallow parse settings from url or not
|
|
CUSTOM_MODELS?: string; // to control custom models
|
|
DEFAULT_MODEL?: string; // to control default model in every new chat window
|
|
VISION_MODELS?: string; // to control vision models
|
|
|
|
// stability only
|
|
STABILITY_URL?: string;
|
|
STABILITY_API_KEY?: string;
|
|
|
|
// azure only
|
|
AZURE_URL?: string; // https://{azure-url}/openai/deployments/{deploy-name}
|
|
AZURE_API_KEY?: string;
|
|
AZURE_API_VERSION?: string;
|
|
|
|
// google only
|
|
GOOGLE_API_KEY?: string;
|
|
GOOGLE_URL?: string;
|
|
|
|
// google tag manager
|
|
GTM_ID?: string;
|
|
|
|
// anthropic only
|
|
ANTHROPIC_URL?: string;
|
|
ANTHROPIC_API_KEY?: string;
|
|
ANTHROPIC_API_VERSION?: string;
|
|
|
|
// baidu only
|
|
BAIDU_URL?: string;
|
|
BAIDU_API_KEY?: string;
|
|
BAIDU_SECRET_KEY?: string;
|
|
|
|
// bytedance only
|
|
BYTEDANCE_URL?: string;
|
|
BYTEDANCE_API_KEY?: string;
|
|
|
|
// alibaba only
|
|
ALIBABA_URL?: string;
|
|
ALIBABA_API_KEY?: string;
|
|
|
|
// tencent only
|
|
TENCENT_URL?: string;
|
|
TENCENT_SECRET_KEY?: string;
|
|
TENCENT_SECRET_ID?: string;
|
|
|
|
// moonshot only
|
|
MOONSHOT_URL?: string;
|
|
MOONSHOT_API_KEY?: string;
|
|
|
|
// iflytek only
|
|
IFLYTEK_URL?: string;
|
|
IFLYTEK_API_KEY?: string;
|
|
IFLYTEK_API_SECRET?: string;
|
|
|
|
DEEPSEEK_URL?: string;
|
|
DEEPSEEK_API_KEY?: string;
|
|
|
|
// xai only
|
|
XAI_URL?: string;
|
|
XAI_API_KEY?: string;
|
|
|
|
// chatglm only
|
|
CHATGLM_URL?: string;
|
|
CHATGLM_API_KEY?: string;
|
|
|
|
// siliconflow only
|
|
SILICONFLOW_URL?: string;
|
|
SILICONFLOW_API_KEY?: string;
|
|
|
|
// custom template for preprocessing user input
|
|
DEFAULT_INPUT_TEMPLATE?: string;
|
|
|
|
ENABLE_MCP?: string; // enable mcp functionality
|
|
}
|
|
}
|
|
}
|
|
|
|
const ACCESS_CODES = (function getAccessCodes(): Set<string> {
|
|
const code = process.env.CODE;
|
|
|
|
try {
|
|
const codes = (code?.split(",") ?? [])
|
|
.filter((v) => !!v)
|
|
.map((v) => md5.hash(v.trim()));
|
|
return new Set(codes);
|
|
} catch (e) {
|
|
return new Set();
|
|
}
|
|
})();
|
|
|
|
function getApiKey(keys?: string) {
|
|
const apiKeyEnvVar = keys ?? "";
|
|
const apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim());
|
|
const randomIndex = Math.floor(Math.random() * apiKeys.length);
|
|
const apiKey = apiKeys[randomIndex];
|
|
if (apiKey) {
|
|
console.log(
|
|
`[Server Config] using ${randomIndex + 1} of ${
|
|
apiKeys.length
|
|
} api key - ${apiKey}`,
|
|
);
|
|
}
|
|
|
|
return apiKey;
|
|
}
|
|
|
|
export const getServerSideConfig = () => {
|
|
if (typeof process === "undefined") {
|
|
throw Error(
|
|
"[Server Config] you are importing a nodejs-only module outside of nodejs",
|
|
);
|
|
}
|
|
|
|
const disableGPT4 = !!process.env.DISABLE_GPT4;
|
|
let customModels = process.env.CUSTOM_MODELS ?? "";
|
|
let defaultModel = process.env.DEFAULT_MODEL ?? "";
|
|
let visionModels = process.env.VISION_MODELS ?? "";
|
|
|
|
if (disableGPT4) {
|
|
if (customModels) customModels += ",";
|
|
customModels += DEFAULT_MODELS.filter((m) => isGPT4Model(m.name))
|
|
.map((m) => "-" + m.name)
|
|
.join(",");
|
|
if (defaultModel && isGPT4Model(defaultModel)) {
|
|
defaultModel = "";
|
|
}
|
|
}
|
|
|
|
const isStability = !!process.env.STABILITY_API_KEY;
|
|
|
|
const isAzure = !!process.env.AZURE_URL;
|
|
const isGoogle = !!process.env.GOOGLE_API_KEY;
|
|
const isAnthropic = !!process.env.ANTHROPIC_API_KEY;
|
|
const isTencent = !!process.env.TENCENT_API_KEY;
|
|
|
|
const isBaidu = !!process.env.BAIDU_API_KEY;
|
|
const isBytedance = !!process.env.BYTEDANCE_API_KEY;
|
|
const isAlibaba = !!process.env.ALIBABA_API_KEY;
|
|
const isMoonshot = !!process.env.MOONSHOT_API_KEY;
|
|
const isIflytek = !!process.env.IFLYTEK_API_KEY;
|
|
const isDeepSeek = !!process.env.DEEPSEEK_API_KEY;
|
|
const isXAI = !!process.env.XAI_API_KEY;
|
|
const isChatGLM = !!process.env.CHATGLM_API_KEY;
|
|
const isSiliconFlow = !!process.env.SILICONFLOW_API_KEY;
|
|
|
|
const isBedrock =
|
|
process.env.ENABLE_AWS_BEDROCK === "true" &&
|
|
!!process.env.AWS_ACCESS_KEY_ID &&
|
|
!!process.env.AWS_SECRET_ACCESS_KEY &&
|
|
!!process.env.AWS_REGION;
|
|
|
|
const allowedWebDavEndpoints = (
|
|
process.env.WHITE_WEBDAV_ENDPOINTS ?? ""
|
|
).split(",");
|
|
|
|
const config = {
|
|
baseUrl: process.env.BASE_URL,
|
|
apiKey: getApiKey(process.env.OPENAI_API_KEY),
|
|
openaiOrgId: process.env.OPENAI_ORG_ID,
|
|
|
|
isStability,
|
|
stabilityUrl: process.env.STABILITY_URL,
|
|
stabilityApiKey: getApiKey(process.env.STABILITY_API_KEY),
|
|
|
|
isAzure,
|
|
azureUrl: process.env.AZURE_URL,
|
|
azureApiKey: getApiKey(process.env.AZURE_API_KEY),
|
|
azureApiVersion: process.env.AZURE_API_VERSION,
|
|
|
|
isGoogle,
|
|
googleApiKey: getApiKey(process.env.GOOGLE_API_KEY),
|
|
googleUrl: process.env.GOOGLE_URL,
|
|
|
|
isAnthropic,
|
|
anthropicApiKey: getApiKey(process.env.ANTHROPIC_API_KEY),
|
|
anthropicApiVersion: process.env.ANTHROPIC_API_VERSION,
|
|
anthropicUrl: process.env.ANTHROPIC_URL,
|
|
|
|
isBaidu,
|
|
baiduUrl: process.env.BAIDU_URL,
|
|
baiduApiKey: getApiKey(process.env.BAIDU_API_KEY),
|
|
baiduSecretKey: process.env.BAIDU_SECRET_KEY,
|
|
|
|
isBytedance,
|
|
bytedanceApiKey: getApiKey(process.env.BYTEDANCE_API_KEY),
|
|
bytedanceUrl: process.env.BYTEDANCE_URL,
|
|
|
|
isAlibaba,
|
|
alibabaUrl: process.env.ALIBABA_URL,
|
|
alibabaApiKey: getApiKey(process.env.ALIBABA_API_KEY),
|
|
|
|
isTencent,
|
|
tencentUrl: process.env.TENCENT_URL,
|
|
tencentSecretKey: getApiKey(process.env.TENCENT_SECRET_KEY),
|
|
tencentSecretId: process.env.TENCENT_SECRET_ID,
|
|
|
|
isMoonshot,
|
|
moonshotUrl: process.env.MOONSHOT_URL,
|
|
moonshotApiKey: getApiKey(process.env.MOONSHOT_API_KEY),
|
|
|
|
isIflytek,
|
|
iflytekUrl: process.env.IFLYTEK_URL,
|
|
iflytekApiKey: process.env.IFLYTEK_API_KEY,
|
|
iflytekApiSecret: process.env.IFLYTEK_API_SECRET,
|
|
|
|
isDeepSeek,
|
|
deepseekUrl: process.env.DEEPSEEK_URL,
|
|
deepseekApiKey: getApiKey(process.env.DEEPSEEK_API_KEY),
|
|
|
|
isXAI,
|
|
xaiUrl: process.env.XAI_URL,
|
|
xaiApiKey: getApiKey(process.env.XAI_API_KEY),
|
|
|
|
isChatGLM,
|
|
chatglmUrl: process.env.CHATGLM_URL,
|
|
chatglmApiKey: getApiKey(process.env.CHATGLM_API_KEY),
|
|
|
|
cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,
|
|
cloudflareKVNamespaceId: process.env.CLOUDFLARE_KV_NAMESPACE_ID,
|
|
cloudflareKVApiKey: getApiKey(process.env.CLOUDFLARE_KV_API_KEY),
|
|
cloudflareKVTTL: process.env.CLOUDFLARE_KV_TTL,
|
|
|
|
isSiliconFlow,
|
|
siliconFlowUrl: process.env.SILICONFLOW_URL,
|
|
siliconFlowApiKey: getApiKey(process.env.SILICONFLOW_API_KEY),
|
|
|
|
isBedrock,
|
|
bedrockRegion: process.env.AWS_REGION,
|
|
bedrockAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
bedrockSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
bedrockEndpoint: process.env.AWS_BEDROCK_ENDPOINT,
|
|
|
|
gtmId: process.env.GTM_ID,
|
|
gaId: process.env.GA_ID || DEFAULT_GA_ID,
|
|
|
|
needCode: ACCESS_CODES.size > 0,
|
|
code: process.env.CODE,
|
|
codes: ACCESS_CODES,
|
|
|
|
proxyUrl: process.env.PROXY_URL,
|
|
isVercel: !!process.env.VERCEL,
|
|
|
|
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
|
|
disableGPT4,
|
|
hideBalanceQuery: !process.env.ENABLE_BALANCE_QUERY,
|
|
disableFastLink: !!process.env.DISABLE_FAST_LINK,
|
|
customModels,
|
|
defaultModel,
|
|
visionModels,
|
|
allowedWebDavEndpoints,
|
|
enableMcp: process.env.ENABLE_MCP === "true",
|
|
};
|
|
return config;
|
|
};
|