forked from XiaoMo/ChatGPT-Next-Web
Merge branch 'main' of https://github.com/Yidadaa/ChatGPT-Next-Web
This commit is contained in:
commit
9c36fcec81
@ -9,7 +9,7 @@ const serverConfig = getServerSideConfig();
|
|||||||
const DANGER_CONFIG = {
|
const DANGER_CONFIG = {
|
||||||
needCode: serverConfig.needCode,
|
needCode: serverConfig.needCode,
|
||||||
hideUserApiKey: serverConfig.hideUserApiKey,
|
hideUserApiKey: serverConfig.hideUserApiKey,
|
||||||
enableGPT4: serverConfig.enableGPT4,
|
disableGPT4: serverConfig.disableGPT4,
|
||||||
hideBalanceQuery: serverConfig.hideBalanceQuery,
|
hideBalanceQuery: serverConfig.hideBalanceQuery,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { type OpenAIListModelResponse } from "@/app/client/platforms/openai";
|
||||||
|
import { getServerSideConfig } from "@/app/config/server";
|
||||||
import { OpenaiPath } from "@/app/constant";
|
import { OpenaiPath } from "@/app/constant";
|
||||||
import { prettyObject } from "@/app/utils/format";
|
import { prettyObject } from "@/app/utils/format";
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
@ -6,6 +8,18 @@ import { requestOpenai } from "../../common";
|
|||||||
|
|
||||||
const ALLOWD_PATH = new Set(Object.values(OpenaiPath));
|
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(
|
async function handle(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
{ params }: { params: { path: string[] } },
|
{ params }: { params: { path: string[] } },
|
||||||
@ -39,7 +53,18 @@ async function handle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
console.error("[OpenAI] ", e);
|
console.error("[OpenAI] ", e);
|
||||||
return NextResponse.json(prettyObject(e));
|
return NextResponse.json(prettyObject(e));
|
||||||
|
@ -38,9 +38,15 @@ export interface LLMUsage {
|
|||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LLMModel {
|
||||||
|
name: string;
|
||||||
|
available: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class LLMApi {
|
export abstract class LLMApi {
|
||||||
abstract chat(options: ChatOptions): Promise<void>;
|
abstract chat(options: ChatOptions): Promise<void>;
|
||||||
abstract usage(): Promise<LLMUsage>;
|
abstract usage(): Promise<LLMUsage>;
|
||||||
|
abstract models(): Promise<LLMModel[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProviderName = "openai" | "azure" | "claude" | "palm";
|
type ProviderName = "openai" | "azure" | "claude" | "palm";
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from "@/app/constant";
|
} from "@/app/constant";
|
||||||
import { useAccessStore, useAppConfig, useChatStore } from "@/app/store";
|
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 Locale from "../../locales";
|
||||||
import {
|
import {
|
||||||
EventStreamContentType,
|
EventStreamContentType,
|
||||||
@ -13,6 +13,15 @@ import {
|
|||||||
} from "@fortaine/fetch-event-source";
|
} from "@fortaine/fetch-event-source";
|
||||||
import { prettyObject } from "@/app/utils/format";
|
import { prettyObject } from "@/app/utils/format";
|
||||||
|
|
||||||
|
export interface OpenAIListModelResponse {
|
||||||
|
object: string;
|
||||||
|
data: Array<{
|
||||||
|
id: string;
|
||||||
|
object: string;
|
||||||
|
root: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
export class ChatGPTApi implements LLMApi {
|
export class ChatGPTApi implements LLMApi {
|
||||||
path(path: string): string {
|
path(path: string): string {
|
||||||
let openaiUrl = useAccessStore.getState().openaiUrl;
|
let openaiUrl = useAccessStore.getState().openaiUrl;
|
||||||
@ -22,6 +31,9 @@ export class ChatGPTApi implements LLMApi {
|
|||||||
if (openaiUrl.endsWith("/")) {
|
if (openaiUrl.endsWith("/")) {
|
||||||
openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1);
|
openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1);
|
||||||
}
|
}
|
||||||
|
if (!openaiUrl.startsWith("http") && !openaiUrl.startsWith("/api/openai")) {
|
||||||
|
openaiUrl = "https://" + openaiUrl;
|
||||||
|
}
|
||||||
return [openaiUrl, path].join("/");
|
return [openaiUrl, path].join("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,5 +244,23 @@ export class ChatGPTApi implements LLMApi {
|
|||||||
total: total.hard_limit_usd,
|
total: total.hard_limit_usd,
|
||||||
} as LLMUsage;
|
} 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 };
|
export { OpenaiPath };
|
||||||
|
@ -42,12 +42,11 @@ import {
|
|||||||
Theme,
|
Theme,
|
||||||
useAppConfig,
|
useAppConfig,
|
||||||
DEFAULT_TOPIC,
|
DEFAULT_TOPIC,
|
||||||
ALL_MODELS,
|
ModelType,
|
||||||
} from "../store";
|
} from "../store";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
copyToClipboard,
|
copyToClipboard,
|
||||||
downloadAs,
|
|
||||||
selectOrCopy,
|
selectOrCopy,
|
||||||
autoGrowTextArea,
|
autoGrowTextArea,
|
||||||
useMobileScreen,
|
useMobileScreen,
|
||||||
@ -387,12 +386,12 @@ export function ChatActions(props: {
|
|||||||
// switch model
|
// switch model
|
||||||
const currentModel = chatStore.currentSession().mask.modelConfig.model;
|
const currentModel = chatStore.currentSession().mask.modelConfig.model;
|
||||||
function nextModel() {
|
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 modelIndex = models.indexOf(currentModel);
|
||||||
const nextIndex = (modelIndex + 1) % models.length;
|
const nextIndex = (modelIndex + 1) % models.length;
|
||||||
const nextModel = models[nextIndex];
|
const nextModel = models[nextIndex];
|
||||||
chatStore.updateCurrentSession((session) => {
|
chatStore.updateCurrentSession((session) => {
|
||||||
session.mask.modelConfig.model = nextModel;
|
session.mask.modelConfig.model = nextModel as ModelType;
|
||||||
session.mask.syncGlobalConfig = false;
|
session.mask.syncGlobalConfig = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -911,6 +910,7 @@ export function Chat() {
|
|||||||
const newMessage = await showPrompt(
|
const newMessage = await showPrompt(
|
||||||
Locale.Chat.Actions.Edit,
|
Locale.Chat.Actions.Edit,
|
||||||
message.content,
|
message.content,
|
||||||
|
10,
|
||||||
);
|
);
|
||||||
chatStore.updateCurrentSession((session) => {
|
chatStore.updateCurrentSession((session) => {
|
||||||
const m = session.messages.find(
|
const m = session.messages.find(
|
||||||
|
@ -27,6 +27,7 @@ import { SideBar } from "./sidebar";
|
|||||||
import { useAppConfig } from "../store/config";
|
import { useAppConfig } from "../store/config";
|
||||||
import { AuthPage } from "./auth";
|
import { AuthPage } from "./auth";
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
|
import { api } from "../client/api";
|
||||||
|
|
||||||
export function Loading(props: { noLogo?: boolean }) {
|
export function Loading(props: { noLogo?: boolean }) {
|
||||||
return (
|
return (
|
||||||
@ -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() {
|
export function Home() {
|
||||||
useSwitchTheme();
|
useSwitchTheme();
|
||||||
|
useLoadData();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("[Config] got config from build time", getClientConfig());
|
console.log("[Config] got config from build time", getClientConfig());
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ALL_MODELS, ModalConfigValidator, ModelConfig } from "../store";
|
import { ModalConfigValidator, ModelConfig, useAppConfig } from "../store";
|
||||||
|
|
||||||
import Locale from "../locales";
|
import Locale from "../locales";
|
||||||
import { InputRange } from "./input-range";
|
import { InputRange } from "./input-range";
|
||||||
@ -8,6 +8,8 @@ export function ModelConfigList(props: {
|
|||||||
modelConfig: ModelConfig;
|
modelConfig: ModelConfig;
|
||||||
updateConfig: (updater: (config: ModelConfig) => void) => void;
|
updateConfig: (updater: (config: ModelConfig) => void) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const config = useAppConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ListItem title={Locale.Settings.Model}>
|
<ListItem title={Locale.Settings.Model}>
|
||||||
@ -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}>
|
<option value={v.name} key={v.name} disabled={!v.available}>
|
||||||
{v.name}
|
{v.name}
|
||||||
</option>
|
</option>
|
||||||
|
@ -340,6 +340,10 @@ export function Settings() {
|
|||||||
};
|
};
|
||||||
const [loadingUsage, setLoadingUsage] = useState(false);
|
const [loadingUsage, setLoadingUsage] = useState(false);
|
||||||
function checkUsage(force = false) {
|
function checkUsage(force = false) {
|
||||||
|
if (accessStore.hideBalanceQuery) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setLoadingUsage(true);
|
setLoadingUsage(true);
|
||||||
updateStore.updateUsage(force).finally(() => {
|
updateStore.updateUsage(force).finally(() => {
|
||||||
setLoadingUsage(false);
|
setLoadingUsage(false);
|
||||||
@ -595,19 +599,34 @@ export function Settings() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!accessStore.hideUserApiKey ? (
|
{!accessStore.hideUserApiKey ? (
|
||||||
<ListItem
|
<>
|
||||||
title={Locale.Settings.Token.Title}
|
<ListItem
|
||||||
subTitle={Locale.Settings.Token.SubTitle}
|
title={Locale.Settings.Endpoint.Title}
|
||||||
>
|
subTitle={Locale.Settings.Endpoint.SubTitle}
|
||||||
<PasswordInput
|
>
|
||||||
value={accessStore.token}
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Token.Placeholder}
|
value={accessStore.openaiUrl}
|
||||||
onChange={(e) => {
|
placeholder="https://api.openai.com/"
|
||||||
accessStore.updateToken(e.currentTarget.value);
|
onChange={(e) =>
|
||||||
}}
|
accessStore.updateOpenAiUrl(e.currentTarget.value)
|
||||||
/>
|
}
|
||||||
</ListItem>
|
></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}
|
) : null}
|
||||||
|
|
||||||
{!accessStore.hideBalanceQuery ? (
|
{!accessStore.hideBalanceQuery ? (
|
||||||
@ -635,22 +654,6 @@ export function Settings() {
|
|||||||
)}
|
)}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
) : null}
|
) : 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>
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
|
@ -72,7 +72,9 @@
|
|||||||
box-shadow: var(--card-shadow);
|
box-shadow: var(--card-shadow);
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
width: 60vw;
|
width: 80vw;
|
||||||
|
max-width: 900px;
|
||||||
|
min-width: 300px;
|
||||||
animation: slide-in ease 0.3s;
|
animation: slide-in ease 0.3s;
|
||||||
|
|
||||||
--modal-padding: 20px;
|
--modal-padding: 20px;
|
||||||
@ -242,7 +244,6 @@
|
|||||||
resize: none;
|
resize: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-height: 30vh;
|
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border: 1px solid var(--primary);
|
border: 1px solid var(--primary);
|
||||||
|
@ -321,6 +321,7 @@ export function showConfirm(content: any) {
|
|||||||
function PromptInput(props: {
|
function PromptInput(props: {
|
||||||
value: string;
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
|
rows?: number;
|
||||||
}) {
|
}) {
|
||||||
const [input, setInput] = useState(props.value);
|
const [input, setInput] = useState(props.value);
|
||||||
const onInput = (value: string) => {
|
const onInput = (value: string) => {
|
||||||
@ -334,11 +335,12 @@ function PromptInput(props: {
|
|||||||
autoFocus
|
autoFocus
|
||||||
value={input}
|
value={input}
|
||||||
onInput={(e) => onInput(e.currentTarget.value)}
|
onInput={(e) => onInput(e.currentTarget.value)}
|
||||||
|
rows={props.rows ?? 3}
|
||||||
></textarea>
|
></textarea>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showPrompt(content: any, value = "") {
|
export function showPrompt(content: any, value = "", rows = 3) {
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.className = "modal-mask";
|
div.className = "modal-mask";
|
||||||
document.body.appendChild(div);
|
document.body.appendChild(div);
|
||||||
@ -386,6 +388,7 @@ export function showPrompt(content: any, value = "") {
|
|||||||
<PromptInput
|
<PromptInput
|
||||||
onChange={(val) => (userInput = val)}
|
onChange={(val) => (userInput = val)}
|
||||||
value={value}
|
value={value}
|
||||||
|
rows={rows}
|
||||||
></PromptInput>
|
></PromptInput>
|
||||||
</Modal>,
|
</Modal>,
|
||||||
);
|
);
|
||||||
|
@ -46,7 +46,7 @@ export const getServerSideConfig = () => {
|
|||||||
proxyUrl: process.env.PROXY_URL,
|
proxyUrl: process.env.PROXY_URL,
|
||||||
isVercel: !!process.env.VERCEL,
|
isVercel: !!process.env.VERCEL,
|
||||||
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
|
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
|
||||||
enableGPT4: !process.env.DISABLE_GPT4,
|
disableGPT4: !!process.env.DISABLE_GPT4,
|
||||||
hideBalanceQuery: !!process.env.HIDE_BALANCE_QUERY,
|
hideBalanceQuery: !!process.env.HIDE_BALANCE_QUERY,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -53,6 +53,7 @@ export const OpenaiPath = {
|
|||||||
ChatPath: "v1/chat/completions",
|
ChatPath: "v1/chat/completions",
|
||||||
UsagePath: "dashboard/billing/usage",
|
UsagePath: "dashboard/billing/usage",
|
||||||
SubsPath: "dashboard/billing/subscription",
|
SubsPath: "dashboard/billing/subscription",
|
||||||
|
ListModelPath: "v1/models",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_INPUT_TEMPLATE = `{{input}}`; // input / time / model / lang
|
export const DEFAULT_INPUT_TEMPLATE = `{{input}}`; // input / time / model / lang
|
||||||
@ -61,3 +62,70 @@ You are ChatGPT, a large language model trained by OpenAI.
|
|||||||
Knowledge cutoff: 2021-09
|
Knowledge cutoff: 2021-09
|
||||||
Current model: {{model}}
|
Current model: {{model}}
|
||||||
Current time: {{time}}`;
|
Current time: {{time}}`;
|
||||||
|
|
||||||
|
export const DEFAULT_MODELS = [
|
||||||
|
{
|
||||||
|
name: "gpt-4",
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-0314",
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-0613",
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-32k",
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-32k-0314",
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-32k-0613",
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-0301",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-0613",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-16k",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-16k-0613",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "qwen-v1", // 通义千问
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ernie", // 文心一言
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "spark", // 讯飞星火
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "llama", // llama
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "chatglm", // chatglm-6b
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
@ -3,7 +3,6 @@ import { persist } from "zustand/middleware";
|
|||||||
import { DEFAULT_API_HOST, StoreKey } from "../constant";
|
import { DEFAULT_API_HOST, StoreKey } from "../constant";
|
||||||
import { getHeaders } from "../client/api";
|
import { getHeaders } from "../client/api";
|
||||||
import { BOT_HELLO } from "./chat";
|
import { BOT_HELLO } from "./chat";
|
||||||
import { ALL_MODELS } from "./config";
|
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
|
|
||||||
export interface AccessControlStore {
|
export interface AccessControlStore {
|
||||||
@ -76,14 +75,6 @@ export const useAccessStore = create<AccessControlStore>()(
|
|||||||
console.log("[Config] got config from server", res);
|
console.log("[Config] got config from server", res);
|
||||||
set(() => ({ ...res }));
|
set(() => ({ ...res }));
|
||||||
|
|
||||||
if (!res.enableGPT4) {
|
|
||||||
ALL_MODELS.forEach((model) => {
|
|
||||||
if (model.name.startsWith("gpt-4")) {
|
|
||||||
(model as any).available = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res as any).botHello) {
|
if ((res as any).botHello) {
|
||||||
BOT_HELLO.content = (res as any).botHello;
|
BOT_HELLO.content = (res as any).botHello;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
|
import { LLMModel } from "../client/api";
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
import { DEFAULT_INPUT_TEMPLATE, StoreKey } from "../constant";
|
import { DEFAULT_INPUT_TEMPLATE, DEFAULT_MODELS, StoreKey } from "../constant";
|
||||||
|
|
||||||
|
export type ModelType = (typeof DEFAULT_MODELS)[number]["name"];
|
||||||
|
|
||||||
export enum SubmitKey {
|
export enum SubmitKey {
|
||||||
Enter = "Enter",
|
Enter = "Enter",
|
||||||
@ -31,6 +34,8 @@ export const DEFAULT_CONFIG = {
|
|||||||
dontShowMaskSplashScreen: false, // dont show splash screen when create chat
|
dontShowMaskSplashScreen: false, // dont show splash screen when create chat
|
||||||
dontAddBuiltinMasks: false, // dont add builtin masks
|
dontAddBuiltinMasks: false, // dont add builtin masks
|
||||||
|
|
||||||
|
models: DEFAULT_MODELS as any as LLMModel[],
|
||||||
|
|
||||||
modelConfig: {
|
modelConfig: {
|
||||||
model: "gpt-3.5-turbo" as ModelType,
|
model: "gpt-3.5-turbo" as ModelType,
|
||||||
temperature: 0.5,
|
temperature: 0.5,
|
||||||
@ -50,81 +55,11 @@ export type ChatConfig = typeof DEFAULT_CONFIG;
|
|||||||
export type ChatConfigStore = ChatConfig & {
|
export type ChatConfigStore = ChatConfig & {
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
update: (updater: (config: ChatConfig) => void) => void;
|
update: (updater: (config: ChatConfig) => void) => void;
|
||||||
|
mergeModels: (newModels: LLMModel[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModelConfig = ChatConfig["modelConfig"];
|
export type ModelConfig = ChatConfig["modelConfig"];
|
||||||
|
|
||||||
const ENABLE_GPT4 = true;
|
|
||||||
|
|
||||||
export const ALL_MODELS = [
|
|
||||||
{
|
|
||||||
name: "gpt-4",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-0314",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-0613",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-32k",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-32k-0314",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-32k-0613",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-0301",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-0613",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-16k",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-16k-0613",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "qwen-v1", // 通义千问
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ernie", // 文心一言
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "spark", // 讯飞星火
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "llama", // llama
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "chatglm", // chatglm-6b
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export type ModelType = (typeof ALL_MODELS)[number]["name"];
|
|
||||||
|
|
||||||
export function limitNumber(
|
export function limitNumber(
|
||||||
x: number,
|
x: number,
|
||||||
min: number,
|
min: number,
|
||||||
@ -139,7 +74,8 @@ export function limitNumber(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function limitModel(name: string) {
|
export function limitModel(name: string) {
|
||||||
return ALL_MODELS.some((m) => m.name === name && m.available)
|
const allModels = useAppConfig.getState().models;
|
||||||
|
return allModels.some((m) => m.name === name && m.available)
|
||||||
? name
|
? name
|
||||||
: "gpt-3.5-turbo";
|
: "gpt-3.5-turbo";
|
||||||
}
|
}
|
||||||
@ -179,6 +115,25 @@ export const useAppConfig = create<ChatConfigStore>()(
|
|||||||
updater(config);
|
updater(config);
|
||||||
set(() => config);
|
set(() => config);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mergeModels(newModels) {
|
||||||
|
const oldModels = get().models;
|
||||||
|
const modelMap: Record<string, LLMModel> = {};
|
||||||
|
|
||||||
|
for (const model of oldModels) {
|
||||||
|
model.available = false;
|
||||||
|
modelMap[model.name] = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const model of newModels) {
|
||||||
|
model.available = true;
|
||||||
|
modelMap[model.name] = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(() => ({
|
||||||
|
models: Object.values(modelMap),
|
||||||
|
}));
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: StoreKey.Config,
|
name: StoreKey.Config,
|
||||||
|
Loading…
Reference in New Issue
Block a user