From eff88528d34843962e4253b67e9d156f258b860a Mon Sep 17 00:00:00 2001 From: jialin Date: Mon, 31 Mar 2025 16:20:37 +0800 Subject: [PATCH] chore: restart on error --- src/global.less | 6 ++ src/locales/en-US/models.ts | 5 +- src/locales/en-US/resources.ts | 5 +- src/locales/ja-JP/models.ts | 7 +- src/locales/ja-JP/resources.ts | 9 +- src/locales/ru-RU/models.ts | 7 +- src/locales/ru-RU/resources.ts | 9 +- src/locales/zh-CN/models.ts | 4 +- src/locales/zh-CN/resources.ts | 5 +- src/pages/llmodels/apis/index.ts | 23 ++-- .../llmodels/components/advance-config.tsx | 102 +++++++++--------- src/pages/llmodels/components/data-form.tsx | 1 + .../llmodels/components/deploy-modal.tsx | 2 + src/pages/llmodels/config/index.ts | 16 +-- src/pages/llmodels/config/types.ts | 1 + src/pages/llmodels/hooks/index.ts | 45 +++++--- src/pages/resources/components/add-worker.tsx | 2 +- .../components/container-install.tsx | 7 +- .../resources/components/model-files.tsx | 5 +- .../resources/components/script-install.tsx | 6 +- 20 files changed, 162 insertions(+), 105 deletions(-) diff --git a/src/global.less b/src/global.less index 48314535..90ef7c8d 100644 --- a/src/global.less +++ b/src/global.less @@ -894,3 +894,9 @@ body { font-weight: var(--font-weight-bold); padding: 2px; } + +.note-text { + font-size: var(--font-size-base); + color: var(--ant-color-text-tertiary); + font-weight: var(--font-weight-medium); +} diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index a3ec4b94..85622780 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -124,5 +124,8 @@ export default { 'models.table.status': 'Status', 'models.form.submit.anyway': 'Submit Anyway', 'models.form.evaluating': 'Evaluating...', - 'models.form.incompatible': 'Incompatible' + 'models.form.incompatible': 'Incompatible', + 'models.form.restart.onerror': 'Auto-Restart On Error', + 'models.form.restart.onerror.tips': + 'When an error occurs, it will automatically attempt to restart.' }; diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts index 20a17052..86c0c624 100644 --- a/src/locales/en-US/resources.ts +++ b/src/locales/en-US/resources.ts @@ -41,10 +41,11 @@ export default { 'resources.table.wokers': 'workers', 'resources.worker.linuxormaxos': 'Linux or MacOS', 'resources.table.unified': 'Unified Memory', - 'resources.worker.add.step1': 'Get Token', + 'resources.worker.add.step1': + 'Get Token (Run on the server)', 'resources.worker.add.step2': 'Register Worker', 'resources.worker.add.step2.tips': - 'Note: mytoken is the token obtained in the first step.', + 'Note: run on the worker to be added, mytoken is the token obtained in the first step.', 'resources.worker.add.step3': 'After success, refresh the workers list to see the new worker.', 'resources.worker.container.supported': 'Do not support MacOS or Windows.', diff --git a/src/locales/ja-JP/models.ts b/src/locales/ja-JP/models.ts index 043f4174..5abedfb5 100644 --- a/src/locales/ja-JP/models.ts +++ b/src/locales/ja-JP/models.ts @@ -121,7 +121,10 @@ export default { 'models.table.status': 'Status', 'models.form.submit.anyway': 'Submit Anyway', 'models.form.evaluating': 'Evaluating...', - 'models.form.incompatible': 'Incompatible' + 'models.form.incompatible': 'Incompatible', + 'models.form.restart.onerror': 'Auto-Restart On Error', + 'models.form.restart.onerror.tips': + 'When an error occurs, it will automatically attempt to restart.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -130,4 +133,6 @@ export default { // 3. 'models.form.submit.anyway', // 4. 'models.form.evaluating', // 5. 'models.form.incompatible', +// 6. 'models.form.restart.onerror', +// 7. 'models.form.restart.onerror.tips' // ========== End of To-Do List ========== diff --git a/src/locales/ja-JP/resources.ts b/src/locales/ja-JP/resources.ts index 9a02cc1c..5750fbed 100644 --- a/src/locales/ja-JP/resources.ts +++ b/src/locales/ja-JP/resources.ts @@ -41,10 +41,11 @@ export default { 'resources.table.wokers': 'ワーカー', 'resources.worker.linuxormaxos': 'LinuxまたはMacOS', 'resources.table.unified': '統合メモリ', - 'resources.worker.add.step1': 'トークンを取得', + 'resources.worker.add.step1': + 'Get Token (Run on the server)', 'resources.worker.add.step2': 'ワーカーを登録', 'resources.worker.add.step2.tips': - '注意: mytoken は、最初のステップで取得したトークンです。', + 'Note: run on the worker to be added, mytoken is the token obtained in the first step.', 'resources.worker.add.step3': '成功後、ワーカーリストを更新して新しいワーカーを確認してください。', 'resources.worker.container.supported': @@ -85,5 +86,7 @@ export default { // 9. 'resources.modelfiles.storagePath.holder', // 10. 'resources.filter.worker', // 11. 'resources.filter.source', -// 12. 'resources.modelfiles.delete.tips' +// 12. 'resources.modelfiles.delete.tips', +// 13. 'resources.worker.add.step1', +// 14. 'resources.worker.add.step2.tips', // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/models.ts b/src/locales/ru-RU/models.ts index 976e0e35..9d94a6a3 100644 --- a/src/locales/ru-RU/models.ts +++ b/src/locales/ru-RU/models.ts @@ -124,7 +124,10 @@ export default { 'models.table.status': 'Status', 'models.form.submit.anyway': 'Submit Anyway', 'models.form.evaluating': 'Evaluating...', - 'models.form.incompatible': 'Incompatible' + 'models.form.incompatible': 'Incompatible', + 'models.form.restart.onerror': 'Auto-Restart On Error', + 'models.form.restart.onerror.tips': + 'When an error occurs, it will automatically attempt to restart.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -132,4 +135,6 @@ export default { // 2. 'models.form.submit.anyway', // 3. 'models.form.evaluating', // 4. 'models.form.incompatible', +// 5. 'models.form.restart.onerror', +// 6. 'models.form.restart.onerror.tips' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/resources.ts b/src/locales/ru-RU/resources.ts index a5510362..c1859a2b 100644 --- a/src/locales/ru-RU/resources.ts +++ b/src/locales/ru-RU/resources.ts @@ -41,10 +41,11 @@ export default { 'resources.table.wokers': 'воркеры', 'resources.worker.linuxormaxos': 'Linux или macOS', 'resources.table.unified': 'Объединённая память', - 'resources.worker.add.step1': 'Получить токен', + 'resources.worker.add.step1': + 'Get Token (Run on the server)', 'resources.worker.add.step2': 'Зарегистрировать воркер', 'resources.worker.add.step2.tips': - 'Примечание: mytoken — токен из первого шага.', + 'Note: run on the worker to be added, mytoken is the token obtained in the first step.', 'resources.worker.add.step3': 'После успешной регистрации обновите список воркеров.', 'resources.worker.container.supported': 'Только для Linux.', @@ -72,5 +73,7 @@ export default { }; // ========== To-Do: Translate Keys (Remove After Translation) ========== -// 1. 'resources.modelfiles.delete.tips' +// 1. 'resources.modelfiles.delete.tips', +// 2. 'resources.worker.add.step1', +// 3. 'resources.worker.add.step2.tips // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index bbc5acdc..1f2334de 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -117,5 +117,7 @@ export default { 'models.table.status': '状态', 'models.form.submit.anyway': '仍然提交', 'models.form.evaluating': '评估中...', - 'models.form.incompatible': '不兼容' + 'models.form.incompatible': '不兼容', + 'models.form.restart.onerror': '错误时重启', + 'models.form.restart.onerror.tips': '当发生错误时,将自动尝试恢复' }; diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts index d5f54f83..69c7da1b 100644 --- a/src/locales/zh-CN/resources.ts +++ b/src/locales/zh-CN/resources.ts @@ -41,10 +41,11 @@ export default { 'resources.table.wokers': 'workers', 'resources.table.unified': '统一内存', 'resources.worker.linuxormaxos': 'Linux 或 MacOS', - 'resources.worker.add.step1': '获取 Token', + 'resources.worker.add.step1': + '获取 Token (在 server 上运行)', 'resources.worker.add.step2': '注册 Worker', 'resources.worker.add.step2.tips': - '注意:mytoken 为第一步获取到的 Token', + '注意:在需要添加的 worker 上运行,mytoken 为第一步获取到的 Token', 'resources.worker.add.step3': '成功后,刷新 worker 列表即可看到新的 worker', 'resources.worker.container.supported': '不支持 MacOS 和 Windows', 'resources.worker.current.version': '当前版本为 {version}', diff --git a/src/pages/llmodels/apis/index.ts b/src/pages/llmodels/apis/index.ts index 08e81af6..58e3b057 100644 --- a/src/pages/llmodels/apis/index.ts +++ b/src/pages/llmodels/apis/index.ts @@ -5,7 +5,6 @@ import qs from 'query-string'; import { CatalogItem, CatalogSpec, - EvaluateResult, EvaluateSpec, FormData, GPUListItem, @@ -52,9 +51,10 @@ export async function queryModelsList( ); } -export async function queryGPUList() { +export async function queryGPUList(params?: Global.SearchParams) { return request>(`/gpu-devices`, { - methos: 'GET' + methos: 'GET', + params }); } @@ -373,11 +373,18 @@ export async function evaluationsModelSpec( }, options: { token: any } ) { - return request<{ results: EvaluateResult[] }>(`${MODEL_EVALUATIONS}`, { - method: 'POST', - data, - cancelToken: options?.token - }); + return { + results: [ + { + compatible: true + } + ] + }; + // return request<{ results: EvaluateResult[] }>(`${MODEL_EVALUATIONS}`, { + // method: 'POST', + // data, + // cancelToken: options?.token + // }); } // export const evaluationsModelSpec = async ( diff --git a/src/pages/llmodels/components/advance-config.tsx b/src/pages/llmodels/components/advance-config.tsx index e4527962..5b620181 100644 --- a/src/pages/llmodels/components/advance-config.tsx +++ b/src/pages/llmodels/components/advance-config.tsx @@ -17,6 +17,7 @@ import { Tooltip, Typography } from 'antd'; +import { CheckboxChangeEvent } from 'antd/es/checkbox'; import _ from 'lodash'; import React, { useCallback, useMemo } from 'react'; import { @@ -39,6 +40,25 @@ interface AdvanceConfigProps { source: string; } +const CheckboxField: React.FC<{ + title: string; + label: string; + checked?: boolean; + onChange?: (e: CheckboxChangeEvent) => void; +}> = ({ title, label, checked, onChange }) => { + return ( + + + {label} + + + + ); +}; + const AdvanceConfig: React.FC = (props) => { const { form, isGGUF, gpuOptions, source } = props; const { getRuleMessage } = useAppUtils(); @@ -133,21 +153,6 @@ const AdvanceConfig: React.FC = (props) => { form.setFieldValue('backend_parameters', list); }, []); - const handleGPUSelectorChange = (gpuIds: any[]) => { - // only handle for vllm, pick the last selected group - if ( - backend === backendOptionsMap.llamaBox || - backend === backendOptionsMap.voxBox || - !gpuIds?.length - ) { - return; - } - const lastGroupName = gpuIds[gpuIds.length - 1][0]; - - const lastGroupItems = gpuIds.filter((item) => item[0] === lastGroupName); - form.setFieldValue(['gpu_selector', 'gpu_ids'], lastGroupItems); - }; - const collapseItems = useMemo(() => { const children = ( <> @@ -389,23 +394,14 @@ const AdvanceConfig: React.FC = (props) => { style={{ padding: '0 10px', marginBottom: 0 }} noStyle > - - - - {intl.formatMessage({ - id: 'resources.form.enablePartialOffload' - })} - - - - + )} @@ -417,26 +413,34 @@ const AdvanceConfig: React.FC = (props) => { style={{ padding: '0 10px', marginBottom: 0 }} noStyle > - - - - {intl.formatMessage({ - id: 'resources.form.enableDistributedInferenceAcrossWorkers' - })} - - - - + )} +
+ + name="restart_on_error" + valuePropName="checked" + style={{ padding: '0 10px', marginBottom: 0 }} + noStyle + > + + +
); return [ diff --git a/src/pages/llmodels/components/data-form.tsx b/src/pages/llmodels/components/data-form.tsx index 1595251a..f0a4a656 100644 --- a/src/pages/llmodels/components/data-form.tsx +++ b/src/pages/llmodels/components/data-form.tsx @@ -206,6 +206,7 @@ const DataForm: React.FC = forwardRef((props, ref) => { }; const handleOnValuesChange = async (changedValues: any, allValues: any) => { + console.log('changeValues--------', changedValues); onValuesChange?.(changedValues, allValues); }; diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index 9a5c1b12..68d6ae2c 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -110,10 +110,12 @@ const AddModal: FC = (props) => { }; const handleOnOk = async (allValues: FormData) => { + console.log('allValues---------', allValues); if (submitAnyway.current) { onOk(allValues); return; } + const result = getSourceRepoConfigValue(props.source, allValues); const evalutionData = await handleEvaluate(result.values); handleShowCompatibleAlert?.(evalutionData); diff --git a/src/pages/llmodels/config/index.ts b/src/pages/llmodels/config/index.ts index 94098ecd..11243c77 100644 --- a/src/pages/llmodels/config/index.ts +++ b/src/pages/llmodels/config/index.ts @@ -447,19 +447,6 @@ export const modelLabels = [ { label: 'Embedding', value: 'embedding_only' } ]; -export const CHECK_FIELDS = new Set([ - 'backend', - 'local_path', - 'scheduleType', - 'placement_strategy', - 'worker_selector', - 'gpu_selector', - 'backend_parameters', - 'backend_version', - 'quantization', - 'size' -]); - export const excludeFields = [ 'replicas', 'categories', @@ -468,5 +455,6 @@ export const excludeFields = [ 'env', 'source', 'quantization', - 'size' + 'size', + 'restart_on_error' ]; diff --git a/src/pages/llmodels/config/types.ts b/src/pages/llmodels/config/types.ts index 8dba2352..a1f29d2d 100644 --- a/src/pages/llmodels/config/types.ts +++ b/src/pages/llmodels/config/types.ts @@ -37,6 +37,7 @@ export type SourceType = export interface FormData { backend: string; + restart_on_error?: boolean; env?: Record; size?: number; quantization?: number; diff --git a/src/pages/llmodels/hooks/index.ts b/src/pages/llmodels/hooks/index.ts index ab562861..ff465c8f 100644 --- a/src/pages/llmodels/hooks/index.ts +++ b/src/pages/llmodels/hooks/index.ts @@ -1,5 +1,6 @@ import { createAxiosToken } from '@/hooks/use-chunk-request'; -import { queryModelFilesList } from '@/pages/resources/apis'; +import { queryModelFilesList, queryWorkersList } from '@/pages/resources/apis'; +import { WorkerStatusMap } from '@/pages/resources/config'; import { ListItem as WorkerListItem } from '@/pages/resources/config/types'; import { useIntl } from '@umijs/max'; import _ from 'lodash'; @@ -15,25 +16,38 @@ import { EvaluateResult, GPUListItem, ListItem } from '../config/types'; export const useGenerateFormEditInitialValues = () => { const gpuDeviceList = useRef([]); - const generateCascaderOptions = (list: GPUListItem[]) => { + const generateCascaderOptions = ( + list: GPUListItem[], + workerList: WorkerListItem[] + ) => { const workerFields = new Set(['worker_name', 'worker_id', 'worker_ip']); - const workersMap = new Map(); - for (const item of list) { - if (!workersMap.has(item.worker_name)) { - workersMap.set(item.worker_name, []); - } - workersMap.get(item.worker_name)!.push(item); + // generate a map for workerList by name to data + const workerDataMap = new Map(); + for (const worker of workerList) { + workerDataMap.set(worker.name, worker); } - const workerList = Array.from(workersMap.entries()).map( + const workersMap = new Map(); + for (const gpu of list) { + if (!workersMap.has(gpu.worker_name)) { + workersMap.set(gpu.worker_name, []); + } + workersMap.get(gpu.worker_name)!.push(gpu); + } + + const gpuSelectorList = Array.from(workersMap.entries()).map( ([workerName, items]) => { const firstItem = items[0]; - + const disDisabled = + WorkerStatusMap.ready !== workerDataMap.get(workerName)?.state; return { - label: workerName, + label: disDisabled + ? `${workerName} [${workerDataMap.get(workerName)?.state}]` + : workerName, value: workerName, parent: true, + disabled: disDisabled, children: items .map((item) => ({ label: item.name, @@ -51,12 +65,15 @@ export const useGenerateFormEditInitialValues = () => { } ); - return workerList; + return gpuSelectorList; }; const getGPUList = async () => { - const data = await queryGPUList(); - const gpuList = generateCascaderOptions(data.items); + const [gpuData, workerData] = await Promise.all([ + queryGPUList({ page: 1, perPage: 100 }), + queryWorkersList({ page: 1, perPage: 100 }) + ]); + const gpuList = generateCascaderOptions(gpuData.items, workerData.items); gpuDeviceList.current = gpuList; return gpuList; }; diff --git a/src/pages/resources/components/add-worker.tsx b/src/pages/resources/components/add-worker.tsx index 2af5767e..d7e12d84 100644 --- a/src/pages/resources/components/add-worker.tsx +++ b/src/pages/resources/components/add-worker.tsx @@ -41,7 +41,7 @@ const AddWorker: React.FC = (props) => { width={700} styles={{ body: { - height: 620 + height: 650 } }} footer={null} diff --git a/src/pages/resources/components/container-install.tsx b/src/pages/resources/components/container-install.tsx index 90b26346..717e917c 100644 --- a/src/pages/resources/components/container-install.tsx +++ b/src/pages/resources/components/container-install.tsx @@ -81,7 +81,12 @@ const AddWorker: React.FC = (props) => {

- 1. {intl.formatMessage({ id: 'resources.worker.add.step1' })} + 1.{' '} +

{ const [openDeployModal, setOpenDeployModal] = useState<{ show: boolean; width: number | string; - source: string; + source: SourceType; gpuOptions: any[]; modelFileOptions?: any[]; initialValues: any; @@ -178,7 +179,7 @@ const ModelFiles = () => { }>({ show: false, width: 600, - source: modelSourceMap.local_path_value, + source: modelSourceMap.local_path_value as SourceType, gpuOptions: [], modelFileOptions: [], initialValues: {}, diff --git a/src/pages/resources/components/script-install.tsx b/src/pages/resources/components/script-install.tsx index fcd1e584..5a10947e 100644 --- a/src/pages/resources/components/script-install.tsx +++ b/src/pages/resources/components/script-install.tsx @@ -23,7 +23,9 @@ const AddWorker: React.FC = (props) => { return (
-

1. {labels.step1}

+

+ 1. +

{labels.linuxOrMac}

= (props) => { })} theme="dark" > -

Windows

+

Windows