Skip to content

Commit

Permalink
Merge pull request ChatGPTNextWeb#2253 from Yidadaa/bugfix-0704
Browse files Browse the repository at this point in the history
feat: close ChatGPTNextWeb#2192 use /list/models to get model ids
  • Loading branch information
Yidadaa authored Jul 4, 2023
2 parents 394c5bd + 121e237 commit 9021dab
Show file tree
Hide file tree
Showing 14 changed files with 222 additions and 124 deletions.
2 changes: 1 addition & 1 deletion app/api/config/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const serverConfig = getServerSideConfig();
const DANGER_CONFIG = {
needCode: serverConfig.needCode,
hideUserApiKey: serverConfig.hideUserApiKey,
enableGPT4: serverConfig.enableGPT4,
disableGPT4: serverConfig.disableGPT4,
hideBalanceQuery: serverConfig.hideBalanceQuery,
};

Expand Down
27 changes: 26 additions & 1 deletion app/api/openai/[...path]/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type OpenAIListModelResponse } from "@/app/client/platforms/openai";
import { getServerSideConfig } from "@/app/config/server";
import { OpenaiPath } from "@/app/constant";
import { prettyObject } from "@/app/utils/format";
import { NextRequest, NextResponse } from "next/server";
Expand All @@ -6,6 +8,18 @@ import { requestOpenai } from "../../common";

const ALLOWD_PATH = new Set(Object.values(OpenaiPath));

function getModels(remoteModelRes: OpenAIListModelResponse) {
const config = getServerSideConfig();

if (config.disableGPT4) {
remoteModelRes.data = remoteModelRes.data.filter(
(m) => !m.id.startsWith("gpt-4"),
);
}

return remoteModelRes;
}

async function handle(
req: NextRequest,
{ params }: { params: { path: string[] } },
Expand Down Expand Up @@ -39,7 +53,18 @@ async function handle(
}

try {
return await requestOpenai(req);
const response = await requestOpenai(req);

// list models
if (subpath === OpenaiPath.ListModelPath && response.status === 200) {
const resJson = (await response.json()) as OpenAIListModelResponse;
const availableModels = getModels(resJson);
return NextResponse.json(availableModels, {
status: response.status,
});
}

return response;
} catch (e) {
console.error("[OpenAI] ", e);
return NextResponse.json(prettyObject(e));
Expand Down
6 changes: 6 additions & 0 deletions app/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@ export interface LLMUsage {
total: number;
}

export interface LLMModel {
name: string;
available: boolean;
}

export abstract class LLMApi {
abstract chat(options: ChatOptions): Promise<void>;
abstract usage(): Promise<LLMUsage>;
abstract models(): Promise<LLMModel[]>;
}

type ProviderName = "openai" | "azure" | "claude" | "palm";
Expand Down
32 changes: 31 additions & 1 deletion app/client/platforms/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@ import {
} from "@/app/constant";
import { useAccessStore, useAppConfig, useChatStore } from "@/app/store";

import { ChatOptions, getHeaders, LLMApi, LLMUsage } from "../api";
import { ChatOptions, getHeaders, LLMApi, LLMModel, LLMUsage } from "../api";
import Locale from "../../locales";
import {
EventStreamContentType,
fetchEventSource,
} from "@fortaine/fetch-event-source";
import { prettyObject } from "@/app/utils/format";

export interface OpenAIListModelResponse {
object: string;
data: Array<{
id: string;
object: string;
root: string;
}>;
}

export class ChatGPTApi implements LLMApi {
path(path: string): string {
let openaiUrl = useAccessStore.getState().openaiUrl;
Expand All @@ -22,6 +31,9 @@ export class ChatGPTApi implements LLMApi {
if (openaiUrl.endsWith("/")) {
openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1);
}
if (!openaiUrl.startsWith("http") && !openaiUrl.startsWith("/api/openai")) {
openaiUrl = "https://" + openaiUrl;
}
return [openaiUrl, path].join("/");
}

Expand Down Expand Up @@ -232,5 +244,23 @@ export class ChatGPTApi implements LLMApi {
total: total.hard_limit_usd,
} as LLMUsage;
}

async models(): Promise<LLMModel[]> {
const res = await fetch(this.path(OpenaiPath.ListModelPath), {
method: "GET",
headers: {
...getHeaders(),
},
});

const resJson = (await res.json()) as OpenAIListModelResponse;
const chatModels = resJson.data.filter((m) => m.id.startsWith("gpt-"));
console.log("[Models]", chatModels);

return chatModels.map((m) => ({
name: m.id,
available: true,
}));
}
}
export { OpenaiPath };
8 changes: 4 additions & 4 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ import {
Theme,
useAppConfig,
DEFAULT_TOPIC,
ALL_MODELS,
ModelType,
} from "../store";

import {
copyToClipboard,
downloadAs,
selectOrCopy,
autoGrowTextArea,
useMobileScreen,
Expand Down Expand Up @@ -387,12 +386,12 @@ export function ChatActions(props: {
// switch model
const currentModel = chatStore.currentSession().mask.modelConfig.model;
function nextModel() {
const models = ALL_MODELS.filter((m) => m.available).map((m) => m.name);
const models = config.models.filter((m) => m.available).map((m) => m.name);
const modelIndex = models.indexOf(currentModel);
const nextIndex = (modelIndex + 1) % models.length;
const nextModel = models[nextIndex];
chatStore.updateCurrentSession((session) => {
session.mask.modelConfig.model = nextModel;
session.mask.modelConfig.model = nextModel as ModelType;
session.mask.syncGlobalConfig = false;
});
}
Expand Down Expand Up @@ -911,6 +910,7 @@ export function Chat() {
const newMessage = await showPrompt(
Locale.Chat.Actions.Edit,
message.content,
10,
);
chatStore.updateCurrentSession((session) => {
const m = session.messages.find(
Expand Down
14 changes: 14 additions & 0 deletions app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { SideBar } from "./sidebar";
import { useAppConfig } from "../store/config";
import { AuthPage } from "./auth";
import { getClientConfig } from "../config/client";
import { api } from "../client/api";

export function Loading(props: { noLogo?: boolean }) {
return (
Expand Down Expand Up @@ -152,8 +153,21 @@ function Screen() {
);
}

export function useLoadData() {
const config = useAppConfig();

useEffect(() => {
(async () => {
const models = await api.llm.models();
config.mergeModels(models);
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}

export function Home() {
useSwitchTheme();
useLoadData();

useEffect(() => {
console.log("[Config] got config from build time", getClientConfig());
Expand Down
6 changes: 4 additions & 2 deletions app/components/model-config.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ALL_MODELS, ModalConfigValidator, ModelConfig } from "../store";
import { ModalConfigValidator, ModelConfig, useAppConfig } from "../store";

import Locale from "../locales";
import { InputRange } from "./input-range";
Expand All @@ -8,6 +8,8 @@ export function ModelConfigList(props: {
modelConfig: ModelConfig;
updateConfig: (updater: (config: ModelConfig) => void) => void;
}) {
const config = useAppConfig();

return (
<>
<ListItem title={Locale.Settings.Model}>
Expand All @@ -22,7 +24,7 @@ export function ModelConfigList(props: {
);
}}
>
{ALL_MODELS.map((v) => (
{config.models.map((v) => (
<option value={v.name} key={v.name} disabled={!v.available}>
{v.name}
</option>
Expand Down
61 changes: 32 additions & 29 deletions app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,10 @@ export function Settings() {
};
const [loadingUsage, setLoadingUsage] = useState(false);
function checkUsage(force = false) {
if (accessStore.hideBalanceQuery) {
return;
}

setLoadingUsage(true);
updateStore.updateUsage(force).finally(() => {
setLoadingUsage(false);
Expand Down Expand Up @@ -577,19 +581,34 @@ export function Settings() {
)}

{!accessStore.hideUserApiKey ? (
<ListItem
title={Locale.Settings.Token.Title}
subTitle={Locale.Settings.Token.SubTitle}
>
<PasswordInput
value={accessStore.token}
type="text"
placeholder={Locale.Settings.Token.Placeholder}
onChange={(e) => {
accessStore.updateToken(e.currentTarget.value);
}}
/>
</ListItem>
<>
<ListItem
title={Locale.Settings.Endpoint.Title}
subTitle={Locale.Settings.Endpoint.SubTitle}
>
<input
type="text"
value={accessStore.openaiUrl}
placeholder="https://api.openai.com/"
onChange={(e) =>
accessStore.updateOpenAiUrl(e.currentTarget.value)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.Token.Title}
subTitle={Locale.Settings.Token.SubTitle}
>
<PasswordInput
value={accessStore.token}
type="text"
placeholder={Locale.Settings.Token.Placeholder}
onChange={(e) => {
accessStore.updateToken(e.currentTarget.value);
}}
/>
</ListItem>
</>
) : null}

{!accessStore.hideBalanceQuery ? (
Expand Down Expand Up @@ -617,22 +636,6 @@ export function Settings() {
)}
</ListItem>
) : null}

{!accessStore.hideUserApiKey ? (
<ListItem
title={Locale.Settings.Endpoint.Title}
subTitle={Locale.Settings.Endpoint.SubTitle}
>
<input
type="text"
value={accessStore.openaiUrl}
placeholder="https://api.openai.com/"
onChange={(e) =>
accessStore.updateOpenAiUrl(e.currentTarget.value)
}
></input>
</ListItem>
) : null}
</List>

<List>
Expand Down
5 changes: 3 additions & 2 deletions app/components/ui-lib.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@
box-shadow: var(--card-shadow);
background-color: var(--white);
border-radius: 12px;
width: 60vw;
width: 80vw;
max-width: 900px;
min-width: 300px;
animation: slide-in ease 0.3s;

--modal-padding: 20px;
Expand Down Expand Up @@ -242,7 +244,6 @@
resize: none;
outline: none;
box-sizing: border-box;
min-height: 30vh;

&:focus {
border: 1px solid var(--primary);
Expand Down
5 changes: 4 additions & 1 deletion app/components/ui-lib.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ export function showConfirm(content: any) {
function PromptInput(props: {
value: string;
onChange: (value: string) => void;
rows?: number;
}) {
const [input, setInput] = useState(props.value);
const onInput = (value: string) => {
Expand All @@ -334,11 +335,12 @@ function PromptInput(props: {
autoFocus
value={input}
onInput={(e) => onInput(e.currentTarget.value)}
rows={props.rows ?? 3}
></textarea>
);
}

export function showPrompt(content: any, value = "") {
export function showPrompt(content: any, value = "", rows = 3) {
const div = document.createElement("div");
div.className = "modal-mask";
document.body.appendChild(div);
Expand Down Expand Up @@ -386,6 +388,7 @@ export function showPrompt(content: any, value = "") {
<PromptInput
onChange={(val) => (userInput = val)}
value={value}
rows={rows}
></PromptInput>
</Modal>,
);
Expand Down
2 changes: 1 addition & 1 deletion app/config/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const getServerSideConfig = () => {
proxyUrl: process.env.PROXY_URL,
isVercel: !!process.env.VERCEL,
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
enableGPT4: !process.env.DISABLE_GPT4,
disableGPT4: !!process.env.DISABLE_GPT4,
hideBalanceQuery: !!process.env.HIDE_BALANCE_QUERY,
};
};
Loading

0 comments on commit 9021dab

Please sign in to comment.