mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-08-06 22:59:07 +08:00
feat: add model config to settings
This commit is contained in:
@@ -50,6 +50,8 @@
|
||||
.window-content {
|
||||
width: var(--window-content-width);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mobile {
|
||||
@@ -111,7 +113,8 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.chat-list {}
|
||||
.chat-list {
|
||||
}
|
||||
|
||||
.chat-item {
|
||||
padding: 10px 14px;
|
||||
@@ -165,12 +168,12 @@
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.chat-item:hover>.chat-item-delete {
|
||||
.chat-item:hover > .chat-item-delete {
|
||||
opacity: 0.5;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.chat-item:hover>.chat-item-delete:hover {
|
||||
.chat-item:hover > .chat-item-delete:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -182,9 +185,11 @@
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.chat-item-count {}
|
||||
.chat-item-count {
|
||||
}
|
||||
|
||||
.chat-item-date {}
|
||||
.chat-item-date {
|
||||
}
|
||||
|
||||
.sidebar-tail {
|
||||
display: flex;
|
||||
@@ -232,7 +237,7 @@
|
||||
animation: slide-in ease 0.3s;
|
||||
}
|
||||
|
||||
.chat-message-user>.chat-message-container {
|
||||
.chat-message-user > .chat-message-container {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
@@ -271,7 +276,7 @@
|
||||
border: var(--border-in-light);
|
||||
}
|
||||
|
||||
.chat-message-user>.chat-message-container>.chat-message-item {
|
||||
.chat-message-user > .chat-message-container > .chat-message-item {
|
||||
background-color: var(--second);
|
||||
}
|
||||
|
||||
@@ -346,4 +351,4 @@
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
.settings {
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.settings-title {
|
||||
@@ -9,6 +10,11 @@
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.settings-sub-title {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
import EmojiPicker, { Theme as EmojiTheme } from "emoji-picker-react";
|
||||
|
||||
@@ -11,26 +11,50 @@ import ClearIcon from "../icons/clear.svg";
|
||||
import { List, ListItem, Popover } from "./ui-lib";
|
||||
|
||||
import { IconButton } from "./button";
|
||||
import { SubmitKey, useChatStore, Theme } from "../store";
|
||||
import { SubmitKey, useChatStore, Theme, ALL_MODELS } from "../store";
|
||||
import { Avatar } from "./home";
|
||||
|
||||
import Locale, { changeLang, getLang } from '../locales'
|
||||
import Locale, { changeLang, getLang } from "../locales";
|
||||
|
||||
function SettingItem(props: {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
children: JSX.Element;
|
||||
}) {
|
||||
return (
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>
|
||||
<div>{props.title}</div>
|
||||
{props.subTitle && (
|
||||
<div className={styles["settings-sub-title"]}>{props.subTitle}</div>
|
||||
)}
|
||||
</div>
|
||||
<div>{props.children}</div>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
|
||||
export function Settings(props: { closeSettings: () => void }) {
|
||||
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
||||
const [config, updateConfig, resetConfig, clearAllData] = useChatStore((state) => [
|
||||
state.config,
|
||||
state.updateConfig,
|
||||
state.resetConfig,
|
||||
state.clearAllData,
|
||||
]);
|
||||
const [config, updateConfig, resetConfig, clearAllData] = useChatStore(
|
||||
(state) => [
|
||||
state.config,
|
||||
state.updateConfig,
|
||||
state.resetConfig,
|
||||
state.clearAllData,
|
||||
]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles["window-header"]}>
|
||||
<div className={styles["window-header-title"]}>
|
||||
<div className={styles["window-header-main-title"]}>{Locale.Settings.Title}</div>
|
||||
<div className={styles["window-header-sub-title"]}>{Locale.Settings.SubTitle}</div>
|
||||
<div className={styles["window-header-main-title"]}>
|
||||
{Locale.Settings.Title}
|
||||
</div>
|
||||
<div className={styles["window-header-sub-title"]}>
|
||||
{Locale.Settings.SubTitle}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles["window-actions"]}>
|
||||
<div className={styles["window-action-button"]}>
|
||||
@@ -61,8 +85,7 @@ export function Settings(props: { closeSettings: () => void }) {
|
||||
</div>
|
||||
<div className={styles["settings"]}>
|
||||
<List>
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>{Locale.Settings.Avatar}</div>
|
||||
<SettingItem title={Locale.Settings.Avatar}>
|
||||
<Popover
|
||||
onClose={() => setShowEmojiPicker(false)}
|
||||
content={
|
||||
@@ -84,51 +107,47 @@ export function Settings(props: { closeSettings: () => void }) {
|
||||
<Avatar role="user" />
|
||||
</div>
|
||||
</Popover>
|
||||
</ListItem>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title={Locale.Settings.SendKey}>
|
||||
<select
|
||||
value={config.submitKey}
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) =>
|
||||
(config.submitKey = e.target.value as any as SubmitKey)
|
||||
);
|
||||
}}
|
||||
>
|
||||
{Object.values(SubmitKey).map((v) => (
|
||||
<option value={v} key={v}>
|
||||
{v}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</SettingItem>
|
||||
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>{Locale.Settings.SendKey}</div>
|
||||
<div className="">
|
||||
<select
|
||||
value={config.submitKey}
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) =>
|
||||
(config.submitKey = e.target.value as any as SubmitKey)
|
||||
);
|
||||
}}
|
||||
>
|
||||
{Object.values(SubmitKey).map((v) => (
|
||||
<option value={v} key={v}>
|
||||
{v}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div className={styles["settings-title"]}>
|
||||
{Locale.Settings.Theme}
|
||||
</div>
|
||||
<select
|
||||
value={config.theme}
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) => (config.theme = e.target.value as any as Theme)
|
||||
);
|
||||
}}
|
||||
>
|
||||
{Object.values(Theme).map((v) => (
|
||||
<option value={v} key={v}>
|
||||
{v}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>{Locale.Settings.Theme}</div>
|
||||
<div className="">
|
||||
<select
|
||||
value={config.theme}
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) => (config.theme = e.target.value as any as Theme)
|
||||
);
|
||||
}}
|
||||
>
|
||||
{Object.values(Theme).map((v) => (
|
||||
<option value={v} key={v}>
|
||||
{v}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>{Locale.Settings.TightBorder}</div>
|
||||
<SettingItem title={Locale.Settings.TightBorder}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={config.tightBorder}
|
||||
@@ -138,31 +157,32 @@ export function Settings(props: { closeSettings: () => void }) {
|
||||
)
|
||||
}
|
||||
></input>
|
||||
</ListItem>
|
||||
</SettingItem>
|
||||
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>{Locale.Settings.Lang.Name}</div>
|
||||
<SettingItem title={Locale.Settings.Lang.Name}>
|
||||
<div className="">
|
||||
<select
|
||||
value={getLang()}
|
||||
onChange={(e) => {
|
||||
changeLang(e.target.value as any)
|
||||
changeLang(e.target.value as any);
|
||||
}}
|
||||
>
|
||||
<option value='en' key='en'>
|
||||
<option value="en" key="en">
|
||||
{Locale.Settings.Lang.Options.en}
|
||||
</option>
|
||||
|
||||
<option value='cn' key='cn'>
|
||||
<option value="cn" key="cn">
|
||||
{Locale.Settings.Lang.Options.cn}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</ListItem>
|
||||
</SettingItem>
|
||||
</List>
|
||||
<List>
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>{Locale.Settings.HistoryCount}</div>
|
||||
<SettingItem
|
||||
title={Locale.Settings.HistoryCount.Title}
|
||||
subTitle={Locale.Settings.HistoryCount.SubTitle}
|
||||
>
|
||||
<input
|
||||
type="range"
|
||||
title={config.historyMessageCount.toString()}
|
||||
@@ -177,12 +197,12 @@ export function Settings(props: { closeSettings: () => void }) {
|
||||
)
|
||||
}
|
||||
></input>
|
||||
</ListItem>
|
||||
</SettingItem>
|
||||
|
||||
<ListItem>
|
||||
<div className={styles["settings-title"]}>
|
||||
{Locale.Settings.CompressThreshold}
|
||||
</div>
|
||||
<SettingItem
|
||||
title={Locale.Settings.CompressThreshold.Title}
|
||||
subTitle={Locale.Settings.CompressThreshold.SubTitle}
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
min={500}
|
||||
@@ -190,11 +210,88 @@ export function Settings(props: { closeSettings: () => void }) {
|
||||
value={config.compressMessageLengthThreshold}
|
||||
onChange={(e) =>
|
||||
updateConfig(
|
||||
(config) => (config.compressMessageLengthThreshold = e.currentTarget.valueAsNumber)
|
||||
(config) =>
|
||||
(config.compressMessageLengthThreshold =
|
||||
e.currentTarget.valueAsNumber)
|
||||
)
|
||||
}
|
||||
></input>
|
||||
</ListItem>
|
||||
</SettingItem>
|
||||
</List>
|
||||
|
||||
<List>
|
||||
<SettingItem title={Locale.Settings.Model}>
|
||||
<select
|
||||
value={config.modelConfig.model}
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) => (config.modelConfig.model = e.currentTarget.value)
|
||||
);
|
||||
}}
|
||||
>
|
||||
{ALL_MODELS.map((v) => (
|
||||
<option value={v.name} key={v.name} disabled={!v.available}>
|
||||
{v.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
title={Locale.Settings.Temperature.Title}
|
||||
subTitle={Locale.Settings.Temperature.SubTitle}
|
||||
>
|
||||
<input
|
||||
type="range"
|
||||
value={config.modelConfig.temperature.toFixed(1)}
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.1"
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) =>
|
||||
(config.modelConfig.temperature =
|
||||
e.currentTarget.valueAsNumber)
|
||||
);
|
||||
}}
|
||||
></input>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
title={Locale.Settings.MaxTokens.Title}
|
||||
subTitle={Locale.Settings.MaxTokens.SubTitle}
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
min={100}
|
||||
max={4000}
|
||||
value={config.modelConfig.max_tokens}
|
||||
onChange={(e) =>
|
||||
updateConfig(
|
||||
(config) =>
|
||||
(config.modelConfig.max_tokens =
|
||||
e.currentTarget.valueAsNumber)
|
||||
)
|
||||
}
|
||||
></input>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
title={Locale.Settings.PresencePenlty.Title}
|
||||
subTitle={Locale.Settings.PresencePenlty.SubTitle}
|
||||
>
|
||||
<input
|
||||
type="range"
|
||||
value={config.modelConfig.presence_penalty.toFixed(1)}
|
||||
min="-2"
|
||||
max="2"
|
||||
step="0.5"
|
||||
onChange={(e) => {
|
||||
updateConfig(
|
||||
(config) =>
|
||||
(config.modelConfig.presence_penalty =
|
||||
e.currentTarget.valueAsNumber)
|
||||
);
|
||||
}}
|
||||
></input>
|
||||
</SettingItem>
|
||||
</List>
|
||||
</div>
|
||||
</>
|
||||
|
Reference in New Issue
Block a user