Skip to content

Commit

Permalink
feat: close ChatGPTNextWeb#3187 use CUSTOM_MODELS to control model list
Browse files Browse the repository at this point in the history
(cherry picked from commit d93f05f)
  • Loading branch information
Yidadaa authored and Endlessworld committed Nov 16, 2023
1 parent 9671d3c commit 842a922
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 182 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,13 @@ If you do want users to query balance, set this value to 1, or you should set it
If you want to disable parse settings from url, set this to 1.

### `CUSTOM_MODELS` (optional)

> Default: Empty
> Example: `+llama,+claude-2,-gpt-3.5-turbo` means add `llama, claude-2` to model list, and remove `gpt-3.5-turbo` from list.
To control custom models, use `+` to add a custom model, use `-` to hide a model, separated by comma.

## Requirements

NodeJS >= 18, Docker >= 20
Expand Down
6 changes: 6 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ OpenAI 接口代理 URL,如果你手动配置了 openai 接口代理,请填

如果你想禁用从链接解析预制设置,将此环境变量设置为 1 即可。

### `CUSTOM_MODELS` (可选)

> 示例:`+qwen-7b-chat,+glm-6b,-gpt-3.5-turbo` 表示增加 `qwen-7b-chat``glm-6b` 到模型列表,而从列表中删除 `gpt-3.5-turbo`
用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,用英文逗号隔开。

## 开发

点击下方按钮,开始二次开发:
Expand Down
31 changes: 16 additions & 15 deletions app/api/common.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { NextRequest, NextResponse } from "next/server";
import { getServerSideConfig } from "../config/server";
import { DEFAULT_MODELS, OPENAI_BASE_URL } from "../constant";
import { collectModelTable, collectModels } from "../utils/model";

export const OPENAI_URL = "api.openai.com";
const DEFAULT_PROTOCOL = "https";
const PROTOCOL = process.env.PROTOCOL || DEFAULT_PROTOCOL;
const BASE_URL = process.env.BASE_URL || OPENAI_URL;
const DISABLE_GPT4 = !!process.env.DISABLE_GPT4;
const serverConfig = getServerSideConfig();

export async function requestOpenai(req: NextRequest) {
const controller = new AbortController();
Expand All @@ -14,10 +13,10 @@ export async function requestOpenai(req: NextRequest) {
"",
);

let baseUrl = BASE_URL;
let baseUrl = serverConfig.baseUrl ?? OPENAI_BASE_URL;

if (!baseUrl.startsWith("http")) {
baseUrl = `${PROTOCOL}://${baseUrl}`;
baseUrl = `https://${baseUrl}`;
}

if (baseUrl.endsWith("/")) {
Expand All @@ -26,10 +25,7 @@ export async function requestOpenai(req: NextRequest) {

console.log("[Proxy] ", openaiPath);
console.log("[Base Url]", baseUrl);

if (process.env.OPENAI_ORG_ID) {
console.log("[Org ID]", process.env.OPENAI_ORG_ID);
}
console.log("[Org ID]", serverConfig.openaiOrgId);

const timeoutId = setTimeout(
() => {
Expand Down Expand Up @@ -58,18 +54,23 @@ export async function requestOpenai(req: NextRequest) {
};

// #1815 try to refuse gpt4 request
if (DISABLE_GPT4 && req.body) {
if (serverConfig.customModels && req.body) {
try {
const modelTable = collectModelTable(
DEFAULT_MODELS,
serverConfig.customModels,
);
const clonedBody = await req.text();
fetchOptions.body = clonedBody;

const jsonBody = JSON.parse(clonedBody);
const jsonBody = JSON.parse(clonedBody) as { model?: string };

if ((jsonBody?.model ?? "").includes("gpt-4")) {
// not undefined and is false
if (modelTable[jsonBody?.model ?? ""] === false) {
return NextResponse.json(
{
error: true,
message: "you are not allowed to use gpt-4 model",
message: `you are not allowed to use ${jsonBody?.model} model`,
},
{
status: 403,
Expand Down
1 change: 1 addition & 0 deletions app/api/config/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const DANGER_CONFIG = {
hideBalanceQuery: serverConfig.hideBalanceQuery,
workers: WORKERS_LIST,
disableFastLink: serverConfig.disableFastLink,
customModels: serverConfig.customModels,
};

declare global {
Expand Down
18 changes: 12 additions & 6 deletions app/components/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ export function AuthPage() {
const goHome = () => navigate(Path.Home);
const goChat = () => navigate(Path.Chat);
const resetAccessCode = () => {
accessStore.updateCode("");
accessStore.updateToken("");
accessStore.update((access) => {
access.openaiApiKey = "";
access.accessCode = "";
});
}; // Reset access code to empty string

useEffect(() => {
Expand All @@ -43,7 +45,9 @@ export function AuthPage() {
placeholder={Locale.Auth.Input}
value={accessStore.accessCode}
onChange={(e) => {
accessStore.updateCode(e.currentTarget.value);
accessStore.update(
(access) => (access.accessCode = e.currentTarget.value),
);
}}
/>
{!accessStore.hideUserApiKey ? (
Expand All @@ -52,10 +56,12 @@ export function AuthPage() {
<input
className={styles["auth-input"]}
type="password"
placeholder={Locale.Settings.Token.Placeholder}
value={accessStore.token}
placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder}
value={accessStore.openaiApiKey}
onChange={(e) => {
accessStore.updateToken(e.currentTarget.value);
accessStore.update(
(access) => (access.openaiApiKey = e.currentTarget.value),
);
}}
/>
</>
Expand Down
12 changes: 4 additions & 8 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import { prettyObject } from "../utils/format";
import { ExportMessageModal } from "./exporter";
import { getClientConfig } from "../config/client";
import AddIcon from "@/app/icons/add.svg";
import { useAllModels } from "../utils/hooks";

const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
loading: () => <LoadingIcon />,
Expand Down Expand Up @@ -542,14 +543,9 @@ export function ChatActions(props: {

// switch model
const currentModel = chatStore.currentSession().mask.modelConfig.model;
const models = useMemo(
() =>
config
.allModels()
.filter((m) => m.available)
.map((m) => m.name),
[],
);
const models = useAllModels()
.filter((m) => m.available)
.map((m) => m.name);
const [showModelSelector, setShowModelSelector] = useState(false);

return (
Expand Down
7 changes: 4 additions & 3 deletions app/components/model-config.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { ModalConfigValidator, ModelConfig, useAppConfig } from "../store";
import { ModalConfigValidator, ModelConfig } from "../store";

import Locale from "../locales";
import { InputRange } from "./input-range";
import { ListItem, Select } from "./ui-lib";
import { useAllModels } from "../utils/hooks";

export function ModelConfigList(props: {
modelConfig: ModelConfig;
updateConfig: (updater: (config: ModelConfig) => void) => void;
}) {
const config = useAppConfig();
const allModels = useAllModels();

return (
<>
Expand All @@ -31,7 +32,7 @@ export function ModelConfigList(props: {
});
}}
>
{config.allModels().map((v, i) => (
{allModels.map((v, i) => (
<option value={v.name} key={i} disabled={!v.available}>
{v.name}
</option>
Expand Down
31 changes: 17 additions & 14 deletions app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ export function Settings() {
});
}

const updateOpenaiUrl = accessStore.updateOpenaiUrl;
// const updateOpenaiUrl = accessStore.updateOpenaiUrl;
const enabledAccessControl = useMemo(
() => accessStore.enabledAccessControl(),
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down Expand Up @@ -921,15 +921,17 @@ export function Settings() {
<List>
{showAccessCode ? (
<ListItem
title={Locale.Settings.AccessCode.Title}
subTitle={Locale.Settings.AccessCode.SubTitle}
title={Locale.Settings.Access.AccessCode.Title}
subTitle={Locale.Settings.Access.AccessCode.SubTitle}
>
<PasswordInput
value={accessStore.accessCode}
type="text"
placeholder={Locale.Settings.AccessCode.Placeholder}
placeholder={Locale.Settings.Access.AccessCode.Placeholder}
onChange={(e) => {
accessStore.updateCode(e.currentTarget.value);
accessStore.update(
(s) => (s.accessCode = e.currentTarget.value),
);
}}
/>
</ListItem>
Expand Down Expand Up @@ -963,7 +965,9 @@ export function Settings() {
type="text"
placeholder={Locale.Settings.Token.Placeholder}
onChange={(e) => {
accessStore.updateToken(e.currentTarget.value);
accessStore.update(
(s) => (s.token = e.currentTarget.value),
);
}}
/>
</ListItem>
Expand All @@ -979,15 +983,14 @@ export function Settings() {
<Select
value={accessStore.openaiUrl}
onChange={(e) => {
// console.log(e);
const url = e.target.value as string;
accessStore.updateWorkers(
accessStore.workers.map((e) => {
accessStore.update((s) => {
s.workers.map((e) => {
e.checked = e?.api == url;
return e;
}),
);
updateOpenaiUrl(url);
});
s.openaiUrl = url;
});
}}
>
{Object.values(accessStore.workers).map((worker, index) => {
Expand Down Expand Up @@ -1032,8 +1035,8 @@ export function Settings() {

<List>
<ListItem
title={Locale.Settings.CustomModel.Title}
subTitle={Locale.Settings.CustomModel.SubTitle}
title={Locale.Settings.Access.CustomModel.Title}
subTitle={Locale.Settings.Access.CustomModel.SubTitle}
>
<input
type="text"
Expand Down
17 changes: 16 additions & 1 deletion app/config/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import md5 from "spark-md5";
import { DEFAULT_MODELS } from "../constant";

declare global {
namespace NodeJS {
Expand All @@ -7,13 +8,15 @@ declare global {
CODE?: string;
BASE_URL?: string;
PROXY_URL?: string;
OPENAI_ORG_ID?: string;
VERCEL?: string;
HIDE_USER_API_KEY?: string; // disable user's api key input
DISABLE_GPT4?: string; // allow user to use gpt-4 or not
BUILD_MODE?: "standalone" | "export";
BUILD_APP?: string; // is building desktop app
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
}
}
}
Expand All @@ -38,17 +41,29 @@ export const getServerSideConfig = () => {
);
}

let disableGPT4 = !!process.env.DISABLE_GPT4;
let customModels = process.env.CUSTOM_MODELS ?? "";

if (disableGPT4) {
if (customModels) customModels += ",";
customModels += DEFAULT_MODELS.filter((m) => m.name.startsWith("gpt-4"))
.map((m) => "-" + m.name)
.join(",");
}

return {
apiKey: process.env.OPENAI_API_KEY,
code: process.env.CODE,
codes: ACCESS_CODES,
needCode: ACCESS_CODES.size > 0,
baseUrl: process.env.BASE_URL,
proxyUrl: process.env.PROXY_URL,
openaiOrgId: process.env.OPENAI_ORG_ID,
isVercel: !!process.env.VERCEL,
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
disableGPT4: !!process.env.DISABLE_GPT4,
disableGPT4,
hideBalanceQuery: !process.env.ENABLE_BALANCE_QUERY,
disableFastLink: !!process.env.DISABLE_FAST_LINK,
customModels,
};
};
1 change: 1 addition & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export const LOGIN_HOST =

export const DEFAULT_CORS_HOST = "https://nb.nextweb.fun";
export const DEFAULT_API_HOST = "https://api.eu.xr21.me";
export const OPENAI_BASE_URL = "https://api.eu.xr21.me";

export enum Path {
Home = "/",
Expand Down
Loading

0 comments on commit 842a922

Please sign in to comment.