From d3e58c85cfa93e4526be6b89d5d4fabdfb699e5f Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 2 Apr 2025 17:46:05 +0800 Subject: [PATCH] fix: categories value error --- src/locales/en-US/models.ts | 6 +-- src/locales/zh-CN/models.ts | 4 +- src/pages/llmodels/components/data-form.tsx | 22 ++++++----- .../components/deploy-builtin-modal.tsx | 5 ++- .../llmodels/components/update-modal.tsx | 6 +++ src/pages/llmodels/config/index.ts | 4 +- src/pages/llmodels/forms/local-path.tsx | 4 +- ...{ollama-library.tsx => ollama_library.tsx} | 0 src/pages/llmodels/hooks/index.ts | 39 +++++++------------ 9 files changed, 46 insertions(+), 44 deletions(-) rename src/pages/llmodels/forms/{ollama-library.tsx => ollama_library.tsx} (100%) diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index 146bd962..997179ba 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -13,10 +13,8 @@ export default { 'models.form.env': 'Environment Variables', 'models.form.configurations': 'Configurations', 'models.form.s3address': 'S3 Address', - 'models.form.partialoffload.tips': - 'After enabling CPU offloading, GPUStack prioritizes loading as many layers as possible onto the GPU to maximize performance. If GPU resources are limited, some layers will be offloaded to the CPU, with full CPU inference used only when no GPU is available.', - 'models.form.distribution.tips': - 'Allows for offloading part of the computation to single or multiple remote workers when the resources of a single GPU or worker are insufficient.', + 'models.form.partialoffload.tips': `When CPU offloading is enabled, if GPU resources are insufficient, part of the model's layers will be offloaded to the CPU. If no GPU is available, full CPU inference will be used.`, + 'models.form.distribution.tips': `Allows for offloading part of the model's layers to single or multiple remote workers when the resources of a worker are insufficient.`, 'models.openinplayground': 'Open in Playground', 'models.instances': 'instances', 'models.table.replicas.edit': 'Edit Replicas', diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index 1a223fe9..7320c577 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -14,9 +14,9 @@ export default { 'models.form.configurations': '配置', 'models.form.s3address': 'S3 地址', 'models.form.partialoffload.tips': - '在启用 CPU 卸载后,GPUStack 优先将尽可能多的层加载到 GPU 上,以最大化性能。如果 GPU 资源有限,则某些层将被卸载到 CPU 上,只有在没有 GPU 可用时,才会完全使用 CPU 进行推理。', + '启用 CPU 卸载的说明:启用 CPU 卸载时,如果 GPU 资源不足,则模型的一部分层将被卸载到 CPU 上,在没有 GPU 可用时,会使用纯 CPU 推理。', 'models.form.distribution.tips': - '允许在单个 GPU 或 worker 资源不足时,将部分计算卸载到一个或多个远程 woker。', + '允许在单个 worker 资源不足时,将部分计算卸载到一个或多个远程 worker。', 'models.openinplayground': '在 Playground 中打开', 'models.instances': '实例', 'models.table.replicas.edit': '调整副本数', diff --git a/src/pages/llmodels/components/data-form.tsx b/src/pages/llmodels/components/data-form.tsx index 3c71b4ea..adb12d75 100644 --- a/src/pages/llmodels/components/data-form.tsx +++ b/src/pages/llmodels/components/data-form.tsx @@ -13,6 +13,7 @@ import { ModelscopeTaskMap, backendOptionsMap, backendTipsList, + excludeFields, modelSourceMap, modelTaskMap, sourceOptions @@ -23,7 +24,7 @@ import { FormData, SourceType } from '../config/types'; import CatalogFrom from '../forms/catalog'; import HuggingFaceForm from '../forms/hugging-face'; import LocalPathForm from '../forms/local-path'; -import OllamaForm from '../forms/ollama-library'; +import OllamaForm from '../forms/ollama_library'; import AdvanceConfig from './advance-config'; interface DataFormProps { @@ -190,19 +191,17 @@ const DataForm: React.FC = forwardRef((props, ref) => { const handleOk = async (formdata: FormData) => { let data = _.cloneDeep(formdata); - if (data.categories) { - data.categories = [data.categories]; - } else { - data.categories = []; - } + data.categories = Array.isArray(data.categories) + ? data.categories + : data.categories + ? [data.categories] + : []; const gpuSelector = generateGPUIds(data); const allValues = { ..._.omit(data, ['scheduleType']), ...gpuSelector }; - console.log('allValues--------', allValues); - onOk(allValues); }; @@ -211,7 +210,10 @@ const DataForm: React.FC = forwardRef((props, ref) => { }; const handleOnValuesChange = async (changedValues: any, allValues: any) => { - console.log('changeValues--------', changedValues); + const fieldName = Object.keys(changedValues)[0]; + if (excludeFields.includes(fieldName)) { + return; + } onValuesChange?.(changedValues, allValues); }; @@ -251,6 +253,7 @@ const DataForm: React.FC = forwardRef((props, ref) => { style={{ padding: '16px 24px' }} clearOnDestroy={true} onValuesChange={handleOnValuesChange} + scrollToFirstError={true} initialValues={{ replicas: 1, source: props.source, @@ -258,6 +261,7 @@ const DataForm: React.FC = forwardRef((props, ref) => { cpu_offloading: true, scheduleType: 'auto', categories: null, + restart_on_error: true, distributed_inference_across_workers: true, ...initialValues }} diff --git a/src/pages/llmodels/components/deploy-builtin-modal.tsx b/src/pages/llmodels/components/deploy-builtin-modal.tsx index 60704df6..c0e55a6f 100644 --- a/src/pages/llmodels/components/deploy-builtin-modal.tsx +++ b/src/pages/llmodels/components/deploy-builtin-modal.tsx @@ -419,7 +419,10 @@ const AddModal: React.FC = (props) => { }; const handleOk = async (values: FormData) => { - const data = generateSubmitData(values); + const data = { + ..._.omit(selectSpecRef.current, ['name']), + ...values + }; onOk(data); }; diff --git a/src/pages/llmodels/components/update-modal.tsx b/src/pages/llmodels/components/update-modal.tsx index cf6e52c5..31211333 100644 --- a/src/pages/llmodels/components/update-modal.tsx +++ b/src/pages/llmodels/components/update-modal.tsx @@ -14,6 +14,7 @@ import React, { useEffect, useMemo, useRef } from 'react'; import { backendOptionsMap, backendTipsList, + excludeFields, getSourceRepoConfigValue, localPathTipsList, modelSourceMap, @@ -319,6 +320,10 @@ const UpdateModal: React.FC = (props) => { }; const onValuesChange = (changedValues: any, allValues: any) => { + const fieldName = Object.keys(changedValues)[0]; + if (excludeFields.includes(fieldName)) { + return; + } handleOnValuesChange({ changedValues, allValues, @@ -423,6 +428,7 @@ const UpdateModal: React.FC = (props) => { form={form} onFinish={handleOk} onValuesChange={onValuesChange} + scrollToFirstError={true} preserve={false} clearOnDestroy={true} initialValues={{ diff --git a/src/pages/llmodels/config/index.ts b/src/pages/llmodels/config/index.ts index 11243c77..aeabc068 100644 --- a/src/pages/llmodels/config/index.ts +++ b/src/pages/llmodels/config/index.ts @@ -456,5 +456,7 @@ export const excludeFields = [ 'source', 'quantization', 'size', - 'restart_on_error' + 'restart_on_error', + 'worker_selector', + 'backend_parameters' ]; diff --git a/src/pages/llmodels/forms/local-path.tsx b/src/pages/llmodels/forms/local-path.tsx index bdb22bea..7bda70da 100644 --- a/src/pages/llmodels/forms/local-path.tsx +++ b/src/pages/llmodels/forms/local-path.tsx @@ -22,7 +22,7 @@ const LocalPathForm: React.FC = () => { const { modelFileOptions, byBuiltIn } = formCtx; const { getRuleMessage } = useAppUtils(); const intl = useIntl(); - const localPathCache = useRef(form.getFieldValue('local_path')); + const localPathCache = useRef(form.getFieldValue('local_path') || ''); if (![modelSourceMap.local_path_value].includes(source) || byBuiltIn) { return null; @@ -30,7 +30,7 @@ const LocalPathForm: React.FC = () => { const handleLocalPathBlur = (e: any) => { const value = e.target.value; - if (value === localPathCache.current && value) { + if (value === localPathCache.current || !value) { return; } const isEndwithGGUF = _.endsWith(value, '.gguf'); diff --git a/src/pages/llmodels/forms/ollama-library.tsx b/src/pages/llmodels/forms/ollama_library.tsx similarity index 100% rename from src/pages/llmodels/forms/ollama-library.tsx rename to src/pages/llmodels/forms/ollama_library.tsx diff --git a/src/pages/llmodels/hooks/index.ts b/src/pages/llmodels/hooks/index.ts index 420cc273..a6ca4be5 100644 --- a/src/pages/llmodels/hooks/index.ts +++ b/src/pages/llmodels/hooks/index.ts @@ -8,7 +8,6 @@ import { useEffect, useRef, useState } from 'react'; import { evaluationsModelSpec, queryGPUList } from '../apis'; import { backendOptionsMap, - excludeFields, getSourceRepoConfigValue, modelSourceMap, setSourceRepoConfigValue @@ -157,7 +156,10 @@ export const useGenerateModelFileOptions = () => { labels: worker.labels, parent: true, children: list - .filter((item) => item.worker_id === worker.id) + .filter( + (item) => + item.worker_id === worker.id && !!item.resolved_paths?.length + ) .map((item) => { const resolved_paths = Array.isArray(item.resolved_paths) && item.resolved_paths.length @@ -384,34 +386,21 @@ export const useCheckCompatibility = () => { source: string; }) => { const { changedValues, allValues, source } = params; - const keys = Object.keys(changedValues); - const isExcludeField = keys.some((key) => excludeFields.includes(key)); - const hasValue = keys.every((key) => { - return !!changedValues[key]; - }); - - if ( - !isExcludeField && - hasValue && - !_.has(changedValues, 'backend') && - !_.has(changedValues, 'local_path') - ) { - const data = getSourceRepoConfigValue(source, allValues); - const gpuSelector = generateGPUIds(data.values); + const data = getSourceRepoConfigValue(source, allValues); + const gpuSelector = generateGPUIds(data.values); - const currentRequestId = updateRequestId(); - const evalutionData = await handleEvaluate({ - ...data.values, - ...gpuSelector - }); + const currentRequestId = updateRequestId(); + const evalutionData = await handleEvaluate({ + ...data.values, + ...gpuSelector + }); - if (currentRequestId === requestIdRef.current) { - handleShowCompatibleAlert?.(evalutionData); - } + if (currentRequestId === requestIdRef.current) { + handleShowCompatibleAlert?.(evalutionData); } }; - const debounceHandleValuesChange = _.debounce(handleOnValuesChange, 300); + const debounceHandleValuesChange = _.debounce(handleOnValuesChange, 500); const cancelEvaluate = () => { checkTokenRef.current?.cancel();