merge upstream

This commit is contained in:
sijinhui
2023-12-27 22:47:01 +08:00
32 changed files with 1460 additions and 296 deletions

View File

@@ -64,6 +64,17 @@ export function AuthPage() {
);
}}
/>
<input
className={styles["auth-input"]}
type="password"
placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder}
value={accessStore.googleApiKey}
onChange={(e) => {
accessStore.update(
(access) => (access.googleApiKey = e.currentTarget.value),
);
}}
/>
</>
) : null}

View File

@@ -10,7 +10,10 @@ import BotIcon from "../icons/bot.svg";
import BlackBotIcon from "../icons/black-bot.svg";
export function getEmojiUrl(unified: string, style: EmojiStyle) {
return `https://cdn.staticfile.org/emoji-datasource-apple/14.0.0/img/${style}/64/${unified}.png`;
// Whoever owns this Content Delivery Network (CDN), I am using your CDN to serve emojis
// Old CDN broken, so I had to switch to this one
// Author: https://github.com/H0llyW00dzZ
return `https://cdn.jsdelivr.net/npm/emoji-datasource-apple/img/${style}/64/${unified}.png`;
}
export function AvatarPicker(props: {

View File

@@ -29,10 +29,11 @@ import NextImage from "next/image";
import { toBlob, toPng } from "html-to-image";
import { DEFAULT_MASK_AVATAR } from "../store/mask";
import { api } from "../client/api";
import { prettyObject } from "../utils/format";
import { EXPORT_MESSAGE_CLASS_NAME } from "../constant";
import { EXPORT_MESSAGE_CLASS_NAME, ModelProvider } from "../constant";
import { getClientConfig } from "../config/client";
import { ClientApi } from "../client/api";
const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
loading: () => <LoadingIcon />,
@@ -301,10 +302,17 @@ export function PreviewActions(props: {
}) {
const [loading, setLoading] = useState(false);
const [shouldExport, setShouldExport] = useState(false);
const config = useAppConfig();
const onRenderMsgs = (msgs: ChatMessage[]) => {
setShouldExport(false);
var api: ClientApi;
if (config.modelConfig.model === "gemini-pro") {
api = new ClientApi(ModelProvider.GeminiPro);
} else {
api = new ClientApi(ModelProvider.GPT);
}
api
.share(msgs)
.then((res) => {
@@ -530,7 +538,7 @@ export function ImagePreviewer(props: {
</div>
<div>
<div className={styles["main-title"]}>ChatGPT Next Web</div>
<div className={styles["main-title"]}>NextChat</div>
<div className={styles["sub-title"]}>
github.com/Yidadaa/ChatGPT-Next-Web
</div>

View File

@@ -12,7 +12,7 @@ import LoadingIcon from "../icons/three-dots.svg";
import { getCSSVar, useMobileScreen } from "../utils";
import dynamic from "next/dynamic";
import { Path, SlotID } from "../constant";
import { ModelProvider, Path, SlotID } from "../constant";
import { ErrorBoundary } from "./error";
import { getISOLang, getLang } from "../locales";
@@ -27,7 +27,7 @@ import { SideBar } from "./sidebar";
import { useAppConfig } from "@/app/store";
import { AuthPage } from "./auth";
import { getClientConfig } from "../config/client";
import { api } from "../client/api";
import { ClientApi } from "../client/api";
import { useAccessStore } from "../store";
export function Loading(props: { noLogo?: boolean }) {
@@ -173,6 +173,12 @@ function Screen() {
export function useLoadData() {
const config = useAppConfig();
var api: ClientApi;
if (config.modelConfig.model === "gemini-pro") {
api = new ClientApi(ModelProvider.GeminiPro);
} else {
api = new ClientApi(ModelProvider.GPT);
}
useEffect(() => {
(async () => {
const models = await api.llm.models();

View File

@@ -29,7 +29,7 @@ export function ModelConfigList(props: {
.filter((v) => v.available)
.map((v, i) => (
<option value={v.name} key={i}>
{v.displayName}
{v.displayName}({v.provider?.providerName})
</option>
))}
</Select>
@@ -91,79 +91,84 @@ export function ModelConfigList(props: {
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.PresencePenalty.Title}
subTitle={Locale.Settings.PresencePenalty.SubTitle}
>
<InputRange
value={props.modelConfig.presence_penalty?.toFixed(1)}
min="-2"
max="2"
step="0.1"
onChange={(e) => {
props.updateConfig(
(config) =>
(config.presence_penalty =
ModalConfigValidator.presence_penalty(
e.currentTarget.valueAsNumber,
)),
);
}}
></InputRange>
</ListItem>
<ListItem
title={Locale.Settings.FrequencyPenalty.Title}
subTitle={Locale.Settings.FrequencyPenalty.SubTitle}
>
<InputRange
value={props.modelConfig.frequency_penalty?.toFixed(1)}
min="-2"
max="2"
step="0.1"
onChange={(e) => {
props.updateConfig(
(config) =>
(config.frequency_penalty =
ModalConfigValidator.frequency_penalty(
e.currentTarget.valueAsNumber,
)),
);
}}
></InputRange>
</ListItem>
{props.modelConfig.model === "gemini-pro" ? null : (
<>
<ListItem
title={Locale.Settings.PresencePenalty.Title}
subTitle={Locale.Settings.PresencePenalty.SubTitle}
>
<InputRange
value={props.modelConfig.presence_penalty?.toFixed(1)}
min="-2"
max="2"
step="0.1"
onChange={(e) => {
props.updateConfig(
(config) =>
(config.presence_penalty =
ModalConfigValidator.presence_penalty(
e.currentTarget.valueAsNumber,
)),
);
}}
></InputRange>
</ListItem>
<ListItem
title={Locale.Settings.InjectSystemPrompts.Title}
subTitle={Locale.Settings.InjectSystemPrompts.SubTitle}
>
<input
type="checkbox"
checked={props.modelConfig.enableInjectSystemPrompts}
onChange={(e) =>
props.updateConfig(
(config) =>
(config.enableInjectSystemPrompts = e.currentTarget.checked),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.FrequencyPenalty.Title}
subTitle={Locale.Settings.FrequencyPenalty.SubTitle}
>
<InputRange
value={props.modelConfig.frequency_penalty?.toFixed(1)}
min="-2"
max="2"
step="0.1"
onChange={(e) => {
props.updateConfig(
(config) =>
(config.frequency_penalty =
ModalConfigValidator.frequency_penalty(
e.currentTarget.valueAsNumber,
)),
);
}}
></InputRange>
</ListItem>
<ListItem
title={Locale.Settings.InputTemplate.Title}
subTitle={Locale.Settings.InputTemplate.SubTitle}
>
<input
type="text"
value={props.modelConfig.template}
onChange={(e) =>
props.updateConfig(
(config) => (config.template = e.currentTarget.value),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.InjectSystemPrompts.Title}
subTitle={Locale.Settings.InjectSystemPrompts.SubTitle}
>
<input
type="checkbox"
checked={props.modelConfig.enableInjectSystemPrompts}
onChange={(e) =>
props.updateConfig(
(config) =>
(config.enableInjectSystemPrompts =
e.currentTarget.checked),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.InputTemplate.Title}
subTitle={Locale.Settings.InputTemplate.SubTitle}
>
<input
type="text"
value={props.modelConfig.template}
onChange={(e) =>
props.updateConfig(
(config) => (config.template = e.currentTarget.value),
)
}
></input>
</ListItem>
</>
)}
<ListItem
title={Locale.Settings.HistoryCount.Title}
subTitle={Locale.Settings.HistoryCount.SubTitle}

View File

@@ -52,6 +52,7 @@ import { copyToClipboard } from "../utils";
import Link from "next/link";
import {
Azure,
Google,
OPENAI_BASE_URL,
Path,
RELEASE_URL,
@@ -583,6 +584,7 @@ export function Settings() {
const accessStore = useAccessStore();
const shouldHideBalanceQuery = useMemo(() => {
const isOpenAiUrl = accessStore.openaiUrl.includes(OPENAI_BASE_URL);
return (
accessStore.hideBalanceQuery ||
isOpenAiUrl ||
@@ -959,109 +961,168 @@ export function Settings() {
{/* </Select>*/}
{/* </ListItem>*/}
{/* {accessStore.provider === "OpenAI" ? (*/}
{/* <>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.OpenAI.Endpoint.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.OpenAI.Endpoint.SubTitle*/}
{/* {accessStore.provider === "OpenAI" ? (*/}
{/* <>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.OpenAI.Endpoint.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.OpenAI.Endpoint.SubTitle*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.openaiUrl}*/}
{/* placeholder={OPENAI_BASE_URL}*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.openaiUrl = e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.openaiUrl}*/}
{/* placeholder={OPENAI_BASE_URL}*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.openaiUrl = e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.OpenAI.ApiKey.Title}*/}
{/* subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}*/}
{/* >*/}
{/* <PasswordInput*/}
{/* value={accessStore.openaiApiKey}*/}
{/* type="text"*/}
{/* placeholder={*/}
{/* Locale.Settings.Access.OpenAI.ApiKey.Placeholder*/}
{/* }*/}
{/* onChange={(e) => {*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.openaiApiKey = e.currentTarget.value),*/}
{/* );*/}
{/* }}*/}
{/* />*/}
{/* </ListItem>*/}
{/* </>*/}
{/* ) : (*/}
{/* <>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.Endpoint.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.Azure.Endpoint.SubTitle +*/}
{/* Azure.ExampleEndpoint*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.OpenAI.ApiKey.Title}*/}
{/* subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}*/}
{/* >*/}
{/* <PasswordInput*/}
{/* value={accessStore.openaiApiKey}*/}
{/* type="text"*/}
{/* placeholder={*/}
{/* Locale.Settings.Access.OpenAI.ApiKey.Placeholder*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.azureUrl}*/}
{/* placeholder={Azure.ExampleEndpoint}*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.azureUrl = e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.ApiKey.Title}*/}
{/* subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}*/}
{/* >*/}
{/* <PasswordInput*/}
{/* value={accessStore.azureApiKey}*/}
{/* type="text"*/}
{/* placeholder={*/}
{/* Locale.Settings.Access.Azure.ApiKey.Placeholder*/}
{/* }*/}
{/* onChange={(e) => {*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.azureApiKey = e.currentTarget.value),*/}
{/* );*/}
{/* }}*/}
{/* />*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.ApiVerion.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.Azure.ApiVerion.SubTitle*/}
{/* onChange={(e) => {*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.openaiApiKey = e.currentTarget.value),*/}
{/* );*/}
{/* }}*/}
{/* />*/}
{/* </ListItem>*/}
{/* </>*/}
{/* ) : accessStore.provider === "Azure" ? (*/}
{/* <>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.Endpoint.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.Azure.Endpoint.SubTitle +*/}
{/* Azure.ExampleEndpoint*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.azureUrl}*/}
{/* placeholder={Azure.ExampleEndpoint}*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.azureUrl = e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.azureApiVersion}*/}
{/* placeholder="2023-08-01-preview"*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.azureApiVersion =*/}
{/* e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* </>*/}
{/* )}*/}
{/* </>*/}
{/* )}*/}
{/* </>*/}
{/* )}*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.ApiKey.Title}*/}
{/* subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}*/}
{/* >*/}
{/* <PasswordInput*/}
{/* value={accessStore.azureApiKey}*/}
{/* type="text"*/}
{/* placeholder={*/}
{/* Locale.Settings.Access.Azure.ApiKey.Placeholder*/}
{/* }*/}
{/* onChange={(e) => {*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.azureApiKey = e.currentTarget.value),*/}
{/* );*/}
{/* }}*/}
{/* />*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.ApiVerion.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.Azure.ApiVerion.SubTitle*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.azureApiVersion}*/}
{/* placeholder="2023-08-01-preview"*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.azureApiVersion =*/}
{/* e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* </>*/}
{/* ) : accessStore.provider === "Google" ? (*/}
{/* <>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Google.Endpoint.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.Google.Endpoint.SubTitle +*/}
{/* Google.ExampleEndpoint*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.googleUrl}*/}
{/* placeholder={Google.ExampleEndpoint}*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.googleUrl = e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Azure.ApiKey.Title}*/}
{/* subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}*/}
{/* >*/}
{/* <PasswordInput*/}
{/* value={accessStore.googleApiKey}*/}
{/* type="text"*/}
{/* placeholder={*/}
{/* Locale.Settings.Access.Google.ApiKey.Placeholder*/}
{/* }*/}
{/* onChange={(e) => {*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.googleApiKey = e.currentTarget.value),*/}
{/* );*/}
{/* }}*/}
{/* />*/}
{/* </ListItem>*/}
{/* <ListItem*/}
{/* title={Locale.Settings.Access.Google.ApiVerion.Title}*/}
{/* subTitle={*/}
{/* Locale.Settings.Access.Google.ApiVerion.SubTitle*/}
{/* }*/}
{/* >*/}
{/* <input*/}
{/* type="text"*/}
{/* value={accessStore.googleApiVersion}*/}
{/* placeholder="2023-08-01-preview"*/}
{/* onChange={(e) =>*/}
{/* accessStore.update(*/}
{/* (access) =>*/}
{/* (access.googleApiVersion =*/}
{/* e.currentTarget.value),*/}
{/* )*/}
{/* }*/}
{/* ></input>*/}
{/* </ListItem>*/}
{/* </>*/}
{/* ) : null}*/}
{/* </>*/}
{/* )}*/}
{/* </>*/}
{/*)}*/}
{/*{!shouldHideBalanceQuery && !clientConfig?.isApp ? (*/}
{/* <ListItem*/}