RWKV-Runner/frontend/src/pages/Settings.tsx

279 lines
11 KiB
TypeScript
Raw Normal View History

2023-05-31 07:21:47 +00:00
import React, { FC, useEffect, useRef } from 'react';
2023-05-21 16:04:18 +00:00
import { Page } from '../components/Page';
2023-05-31 07:21:47 +00:00
import {
Accordion,
AccordionHeader,
AccordionItem,
AccordionPanel,
Dropdown,
Input,
Option,
Switch
} from '@fluentui/react-components';
2023-05-21 16:04:18 +00:00
import { Labeled } from '../components/Labeled';
2023-05-17 15:27:52 +00:00
import commonStore from '../stores/commonStore';
2023-05-21 16:04:18 +00:00
import { observer } from 'mobx-react-lite';
import { useTranslation } from 'react-i18next';
2023-06-20 14:22:14 +00:00
import { checkUpdate, toastWithButton } from '../utils';
import { RestartApp } from '../../wailsjs/go/backend_golang/App';
2023-05-20 08:07:08 +00:00
export const Languages = {
dev: 'English', // i18n default
zh: '简体中文'
};
export type Language = keyof typeof Languages;
2023-05-20 08:33:32 +00:00
export type SettingsType = {
2023-05-31 07:21:47 +00:00
language: Language
2023-05-20 08:07:08 +00:00
darkMode: boolean
autoUpdatesCheck: boolean
2023-05-21 16:04:18 +00:00
giteeUpdatesSource: boolean
2023-05-21 02:49:45 +00:00
cnMirror: boolean
2023-05-24 14:03:30 +00:00
host: string
2023-06-20 14:22:14 +00:00
dpiScaling: number
2023-05-31 07:21:47 +00:00
customModelsPath: string
customPythonPath: string
2023-06-20 15:24:51 +00:00
apiUrl: string
apiKey: string
apiChatModelName: string
apiCompletionModelName: string
2023-05-20 08:07:08 +00:00
}
2023-05-05 15:23:34 +00:00
2023-05-17 15:27:52 +00:00
export const Settings: FC = observer(() => {
2023-05-21 16:04:18 +00:00
const { t, i18n } = useTranslation();
2023-05-31 07:21:47 +00:00
const advancedHeaderRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (advancedHeaderRef.current)
(advancedHeaderRef.current.firstElementChild as HTMLElement).style.padding = '0';
}, []);
2023-05-18 11:25:13 +00:00
2023-05-05 15:23:34 +00:00
return (
2023-05-18 11:25:13 +00:00
<Page title={t('Settings')} content={
2023-06-20 14:22:14 +00:00
<div className="flex flex-col gap-2 overflow-y-auto overflow-x-hidden p-1">
2023-05-18 12:48:53 +00:00
<Labeled label={t('Language')} flex spaceBetween content={
2023-05-21 16:04:18 +00:00
<Dropdown style={{ minWidth: 0 }} listbox={{ style: { minWidth: 0 } }}
value={Languages[commonStore.settings.language]}
selectedOptions={[commonStore.settings.language]}
onOptionSelect={(_, data) => {
if (data.optionValue) {
const lang = data.optionValue as Language;
commonStore.setSettings({
language: lang
});
}
}}>
2023-05-18 11:25:13 +00:00
{
Object.entries(Languages).map(([langKey, desc]) =>
<Option key={langKey} value={langKey}>{desc}</Option>)
}
2023-05-17 15:27:52 +00:00
</Dropdown>
2023-05-21 16:04:18 +00:00
} />
2023-06-20 14:22:14 +00:00
{
commonStore.platform === 'windows' &&
<Labeled label={t('DPI Scaling')} flex spaceBetween content={
<Dropdown style={{ minWidth: 0 }} listbox={{ style: { minWidth: 0 } }}
value={commonStore.settings.dpiScaling + '%'}
selectedOptions={[commonStore.settings.dpiScaling.toString()]}
onOptionSelect={(_, data) => {
if (data.optionValue) {
commonStore.setSettings({
dpiScaling: Number(data.optionValue)
});
toastWithButton(t('Restart the app to apply DPI Scaling.'), t('Restart'), () => {
RestartApp();
}, {
autoClose: 5000
});
}
}}>
{
Array.from({ length: 7 }, (_, i) => (i + 2) * 25).map((v, i) =>
<Option key={i} value={v.toString()}>{v + '%'}</Option>)
}
</Dropdown>
} />
}
2023-05-18 12:48:53 +00:00
<Labeled label={t('Dark Mode')} flex spaceBetween content={
2023-05-17 15:27:52 +00:00
<Switch checked={commonStore.settings.darkMode}
2023-05-21 16:04:18 +00:00
onChange={(e, data) => {
commonStore.setSettings({
darkMode: data.checked
});
}} />
} />
2023-05-18 12:48:53 +00:00
<Labeled label={t('Automatic Updates Check')} flex spaceBetween content={
2023-05-17 15:27:52 +00:00
<Switch checked={commonStore.settings.autoUpdatesCheck}
2023-05-21 16:04:18 +00:00
onChange={(e, data) => {
commonStore.setSettings({
autoUpdatesCheck: data.checked
});
if (data.checked)
checkUpdate(true);
}} />
} />
{
commonStore.settings.language === 'zh' &&
<Labeled label={t('Use Gitee Updates Source')} flex spaceBetween content={
<Switch checked={commonStore.settings.giteeUpdatesSource}
onChange={(e, data) => {
commonStore.setSettings({
giteeUpdatesSource: data.checked
});
}} />
} />
}
2023-05-21 02:49:45 +00:00
{
2023-06-06 14:12:26 +00:00
commonStore.settings.language === 'zh' && commonStore.platform != 'linux' &&
2023-05-21 02:49:45 +00:00
<Labeled label={t('Use Tsinghua Pip Mirrors')} flex spaceBetween content={
<Switch checked={commonStore.settings.cnMirror}
2023-05-21 16:04:18 +00:00
onChange={(e, data) => {
commonStore.setSettings({
cnMirror: data.checked
});
}} />
} />
2023-05-21 02:49:45 +00:00
}
2023-05-29 13:34:24 +00:00
<Labeled label={t('Allow external access to the API (service must be restarted)')} flex spaceBetween content={
<Switch checked={commonStore.settings.host !== '127.0.0.1'}
2023-05-24 14:03:30 +00:00
onChange={(e, data) => {
commonStore.setSettings({
2023-05-29 13:34:24 +00:00
host: data.checked ? '0.0.0.0' : '127.0.0.1'
2023-05-24 14:03:30 +00:00
});
}} />
} />
2023-06-20 15:24:51 +00:00
<Accordion collapsible openItems={!commonStore.advancedCollapsed && 'advanced'} onToggle={(e, data) => {
if (data.value === 'advanced')
commonStore.setAdvancedCollapsed(!commonStore.advancedCollapsed);
}}>
<AccordionItem value="advanced">
2023-05-31 07:21:47 +00:00
<AccordionHeader ref={advancedHeaderRef} size="large">{t('Advanced')}</AccordionHeader>
<AccordionPanel>
<div className="flex flex-col gap-2 overflow-hidden">
2023-06-02 14:20:57 +00:00
{commonStore.platform !== 'darwin' &&
<Labeled label={t('Custom Models Path')}
content={
<Input className="grow" placeholder="./models" value={commonStore.settings.customModelsPath}
onChange={(e, data) => {
commonStore.setSettings({
customModelsPath: data.value
});
}} />
} />
}
<Labeled label={t('Custom Python Path')} // if set, will not use precompiled cuda kernel
2023-05-31 07:21:47 +00:00
content={
<Input className="grow" placeholder="./py310/python" value={commonStore.settings.customPythonPath}
onChange={(e, data) => {
2023-06-29 12:14:52 +00:00
commonStore.setDepComplete(false);
2023-05-31 07:21:47 +00:00
commonStore.setSettings({
customPythonPath: data.value
});
}} />
} />
2023-06-20 15:24:51 +00:00
<Labeled label={'API URL'}
content={
<div className="flex gap-2">
<Input style={{ minWidth: 0 }} className="grow" value={commonStore.settings.apiUrl}
onChange={(e, data) => {
commonStore.setSettings({
apiUrl: data.value
});
}} />
<Dropdown style={{ minWidth: 0 }} listbox={{ style: { minWidth: 0 } }}
value="..." selectedOptions={[]} expandIcon={null}
onOptionSelect={(_, data) => {
commonStore.setSettings({
apiUrl: data.optionValue
});
if (data.optionText === 'OpenAI') {
if (commonStore.settings.apiChatModelName === 'rwkv')
commonStore.setSettings({
apiChatModelName: 'gpt-3.5-turbo'
});
if (commonStore.settings.apiCompletionModelName === 'rwkv')
commonStore.setSettings({
apiCompletionModelName: 'text-davinci-003'
});
}
}}>
2023-06-20 16:46:57 +00:00
<Option value="">{t('Localhost')!}</Option>
2023-06-20 15:24:51 +00:00
<Option value="https://api.openai.com">OpenAI</Option>
</Dropdown>
</div>
} />
<Labeled label={'API Key'}
content={
<Input className="grow" placeholder="sk-" value={commonStore.settings.apiKey}
onChange={(e, data) => {
commonStore.setSettings({
apiKey: data.value
});
}} />
} />
<Labeled label={t('API Chat Model Name')}
content={
<div className="flex gap-2">
<Input style={{ minWidth: 0 }} className="grow" placeholder="rwkv"
value={commonStore.settings.apiChatModelName}
onChange={(e, data) => {
commonStore.setSettings({
apiChatModelName: data.value
});
}} />
<Dropdown style={{ minWidth: 0 }} listbox={{ style: { minWidth: 0 } }}
value="..." selectedOptions={[]} expandIcon={null}
onOptionSelect={(_, data) => {
if (data.optionValue) {
commonStore.setSettings({
apiChatModelName: data.optionValue
});
}
}}>
{
['rwkv', 'gpt-4', 'gpt-4-0613', 'gpt-4-32k', 'gpt-4-32k-0613', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-16k-0613']
.map((v, i) =>
<Option key={i} value={v}>{v}</Option>
)
}
</Dropdown>
</div>
} />
<Labeled label={t('API Completion Model Name')}
content={
<div className="flex gap-2">
<Input style={{ minWidth: 0 }} className="grow" placeholder="rwkv"
value={commonStore.settings.apiCompletionModelName}
onChange={(e, data) => {
commonStore.setSettings({
apiCompletionModelName: data.value
});
}} />
<Dropdown style={{ minWidth: 0 }} listbox={{ style: { minWidth: 0 } }}
value="..." selectedOptions={[]} expandIcon={null}
onOptionSelect={(_, data) => {
if (data.optionValue) {
commonStore.setSettings({
apiCompletionModelName: data.optionValue
});
}
}}>
{
['rwkv', 'text-davinci-003', 'text-davinci-002', 'text-curie-001', 'text-babbage-001', 'text-ada-001']
.map((v, i) =>
<Option key={i} value={v}>{v}</Option>
)
}
</Dropdown>
</div>
} />
2023-05-31 07:21:47 +00:00
</div>
</AccordionPanel>
</AccordionItem>
</Accordion>
2023-05-17 15:27:52 +00:00
</div>
2023-05-21 16:04:18 +00:00
} />
2023-05-05 15:23:34 +00:00
);
2023-05-17 15:27:52 +00:00
});