diff --git a/frontend/src/_locales/zh-hans/main.json b/frontend/src/_locales/zh-hans/main.json index 18ba264..f7bc167 100644 --- a/frontend/src/_locales/zh-hans/main.json +++ b/frontend/src/_locales/zh-hans/main.json @@ -88,5 +88,7 @@ "Downloads": "下载", "Pause": "暂停", "Continue": "继续", - "Check": "查看" + "Check": "查看", + "Model file not found": "模型文件不存在", + "Can not find download url": "找不到下载地址" } \ No newline at end of file diff --git a/frontend/src/components/RunButton.tsx b/frontend/src/components/RunButton.tsx index 63bfdef..7005503 100644 --- a/frontend/src/components/RunButton.tsx +++ b/frontend/src/components/RunButton.tsx @@ -1,16 +1,16 @@ import React, {FC, MouseEventHandler, ReactElement} from 'react'; import commonStore, {ModelStatus} from '../stores/commonStore'; -import {StartServer} from '../../wailsjs/go/backend_golang/App'; +import {AddToDownloadList, FileExists, StartServer} from '../../wailsjs/go/backend_golang/App'; import {Button} from '@fluentui/react-components'; import {observer} from 'mobx-react-lite'; import {exit, readRoot, switchModel, updateConfig} from '../apis'; import {toast} from 'react-toastify'; import manifest from '../../../manifest.json'; -import {getStrategy} from '../utils'; +import {getStrategy, toastWithButton} from '../utils'; import {useTranslation} from 'react-i18next'; -import {t} from 'i18next'; import {ToolTipButton} from './ToolTipButton'; import {Play16Regular, Stop16Regular} from '@fluentui/react-icons'; +import {useNavigate} from 'react-router'; const mainButtonText = { [ModelStatus.Offline]: 'Run', @@ -26,69 +26,90 @@ const iconModeButtonIcon: { [modelStatus: number]: ReactElement } = { [ModelStatus.Working]: }; -const onClickMainButton = async () => { - const modelConfig = commonStore.getCurrentModelConfig(); - const port = modelConfig.apiParameters.apiPort; - - if (commonStore.modelStatus === ModelStatus.Offline) { - commonStore.setModelStatus(ModelStatus.Starting); - await exit(1000).catch(() => { - }); - StartServer(port); - - let timeoutCount = 6; - let loading = false; - const intervalId = setInterval(() => { - readRoot() - .then(r => { - if (r.ok && !loading) { - clearInterval(intervalId); - commonStore.setModelStatus(ModelStatus.Loading); - loading = true; - toast(t('Loading Model'), {type: 'info'}); - updateConfig({ - max_tokens: modelConfig.apiParameters.maxResponseToken, - temperature: modelConfig.apiParameters.temperature, - top_p: modelConfig.apiParameters.topP, - presence_penalty: modelConfig.apiParameters.presencePenalty, - frequency_penalty: modelConfig.apiParameters.frequencyPenalty - }); - switchModel({ - model: `${manifest.localModelDir}/${modelConfig.modelParameters.modelName}`, - strategy: getStrategy(modelConfig) - }).then((r) => { - if (r.ok) { - commonStore.setModelStatus(ModelStatus.Working); - toast(t('Startup Completed'), {type: 'success'}); - } else if (r.status === 304) { - toast(t('Loading Model'), {type: 'info'}); - } else { - commonStore.setModelStatus(ModelStatus.Offline); - toast(t('Failed to switch model'), {type: 'error'}); - } - }); - } - }).catch(() => { - if (timeoutCount <= 0) { - clearInterval(intervalId); - commonStore.setModelStatus(ModelStatus.Offline); - } - }); - - timeoutCount--; - }, 1000); - } else { - commonStore.setModelStatus(ModelStatus.Offline); - exit(); - } -}; - export const RunButton: FC<{ onClickRun?: MouseEventHandler, iconMode?: boolean }> = observer(({ onClickRun, iconMode }) => { const {t} = useTranslation(); + const navigate = useNavigate(); + + const onClickMainButton = async () => { + const modelConfig = commonStore.getCurrentModelConfig(); + const modelName = modelConfig.modelParameters.modelName; + const modelPath = `./${manifest.localModelDir}/${modelName}`; + + if (!await FileExists(modelPath)) { + toastWithButton(t('Model file not found'), t('Download'), () => { + const downloadUrl = commonStore.modelSourceList.find(item => item.name === modelName)?.downloadUrl; + if (downloadUrl) { + toastWithButton(`${t('Downloading')} ${modelName}`, t('Check'), () => { + navigate({pathname: '/downloads'}); + }, + {autoClose: 3000}); + AddToDownloadList(modelPath, downloadUrl); + } else { + toast(t('Can not find download url'), {type: 'error'}); + } + }); + + return; + } + + const port = modelConfig.apiParameters.apiPort; + + if (commonStore.modelStatus === ModelStatus.Offline) { + commonStore.setModelStatus(ModelStatus.Starting); + await exit(1000).catch(() => { + }); + StartServer(port); + + let timeoutCount = 6; + let loading = false; + const intervalId = setInterval(() => { + readRoot() + .then(r => { + if (r.ok && !loading) { + clearInterval(intervalId); + commonStore.setModelStatus(ModelStatus.Loading); + loading = true; + toast(t('Loading Model'), {type: 'info'}); + updateConfig({ + max_tokens: modelConfig.apiParameters.maxResponseToken, + temperature: modelConfig.apiParameters.temperature, + top_p: modelConfig.apiParameters.topP, + presence_penalty: modelConfig.apiParameters.presencePenalty, + frequency_penalty: modelConfig.apiParameters.frequencyPenalty + }); + switchModel({ + model: `${manifest.localModelDir}/${modelConfig.modelParameters.modelName}`, + strategy: getStrategy(modelConfig) + }).then((r) => { + if (r.ok) { + commonStore.setModelStatus(ModelStatus.Working); + toast(t('Startup Completed'), {type: 'success'}); + } else if (r.status === 304) { + toast(t('Loading Model'), {type: 'info'}); + } else { + commonStore.setModelStatus(ModelStatus.Offline); + toast(t('Failed to switch model'), {type: 'error'}); + } + }); + } + }).catch(() => { + if (timeoutCount <= 0) { + clearInterval(intervalId); + commonStore.setModelStatus(ModelStatus.Offline); + } + }); + + timeoutCount--; + }, 1000); + } else { + commonStore.setModelStatus(ModelStatus.Offline); + exit(); + } + }; const onClick = async (e: any) => { if (commonStore.modelStatus === ModelStatus.Offline) diff --git a/frontend/src/pages/Models.tsx b/frontend/src/pages/Models.tsx index 6510838..044d096 100644 --- a/frontend/src/pages/Models.tsx +++ b/frontend/src/pages/Models.tsx @@ -138,7 +138,7 @@ const columns: TableColumnDefinition[] = [ toastWithButton(`${t('Downloading')} ${item.name}`, t('Check'), () => { navigate({pathname: '/downloads'}); }, - {autoClose: 3000, position: 'top-center'}); + {autoClose: 3000}); AddToDownloadList(`./${manifest.localModelDir}/${item.name}`, item.downloadUrl!); }}/>} {item.url && } onClick={() => { diff --git a/frontend/src/utils/index.tsx b/frontend/src/utils/index.tsx index fe550cf..1be8660 100644 --- a/frontend/src/utils/index.tsx +++ b/frontend/src/utils/index.tsx @@ -225,6 +225,9 @@ export async function checkUpdate() { }); }); }, 500); + }, { + autoClose: false, + position: 'bottom-left' }); } } else { @@ -248,8 +251,6 @@ export function toastWithButton(text: string, buttonText: string, onClickButton: , { - autoClose: false, - position: 'bottom-left', type: 'info', ...options });