diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index 5f376bec..df6ee1c1 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -124,8 +124,12 @@ const AddModal: FC = (props) => { const [collapsed, setCollapsed] = useState(false); const [isGGUF, setIsGGUF] = useState(false); const modelFileRef = useRef(null); - const evaluateStateRef = useRef<{ state: EvaluateProccessType }>({ - state: 'form' + const evaluateStateRef = useRef<{ + state: EvaluateProccessType; + requestModelId: number; + }>({ + state: 'form', + requestModelId: 0 }); const requestModelIdRef = useRef(0); @@ -143,8 +147,20 @@ const AddModal: FC = (props) => { * @param state target to distinguish the evaluate state, current evaluate state * can be 'model', 'file' or 'form'. */ - const setEvaluteState = (state: EvaluateProccessType) => { - evaluateStateRef.current.state = state; + const setEvaluteState = (state: { + state: EvaluateProccessType; + requestModelId: number; + }) => { + evaluateStateRef.current = state; + }; + + const updateEvaluateState = (state: EvaluateProccessType) => { + const currentRequestModelId = evaluateStateRef.current.requestModelId; + setEvaluteState({ + ...evaluateStateRef.current, + state + }); + return currentRequestModelId; }; const handleOnValuesChange = (data: { @@ -152,7 +168,10 @@ const AddModal: FC = (props) => { allValues: any; source: SourceType; }) => { - setEvaluteState(EvaluateProccess.form); + setEvaluteState({ + state: EvaluateProccess.form, + requestModelId: updateRequestModelId() + }); handleOnValuesChangeBefore(data); }; @@ -172,7 +191,13 @@ const AddModal: FC = (props) => { return categories || null; }; - const handleSelectModelFile = async (item: any) => { + const handleSelectModelFile = async (item: any, requestModelId: number) => { + if ( + evaluateStateRef.current.state !== EvaluateProccess.file || + requestModelId !== evaluateStateRef.current.requestModelId + ) { + return; + } form.current?.form?.resetFields(resetFieldsByFile); const modelInfo = onSelectModel(selectedModel, props.source); @@ -193,8 +218,6 @@ const AddModal: FC = (props) => { // evaluate the form data when select a model file if (item.fakeName) { unlockWarningStatus(); - const currentModelId = updateRequestModelId(); - setEvaluteState(EvaluateProccess.file); const evaluateRes = await handleOnValuesChangeBefore?.({ changedValues: {}, @@ -202,11 +225,6 @@ const AddModal: FC = (props) => { source: props.source }); - if (currentModelId !== requestModelIdRef.current) { - // if the request model id has changed, do not update the form - return; - } - const defaultSpec = getDefaultSpec({ evaluateResult: evaluateRes }); @@ -233,6 +251,7 @@ const AddModal: FC = (props) => { const handleOnSelectModel = async (item: any) => { // If the item is empty or the same as the selected model, do nothing console.log('handleOnSelectModel', item, selectedModel); + modelFileRef.current?.cancelRequest(); if ( _.isEmpty(item) || (item.isGGUF === selectedModel.isGGUF && item.name === selectedModel.name) @@ -242,7 +261,10 @@ const AddModal: FC = (props) => { setIsGGUF(item.isGGUF); clearCahceFormValues(); unlockWarningStatus(); - setEvaluteState(EvaluateProccess.model); + setEvaluteState({ + state: EvaluateProccess.model, + requestModelId: updateRequestModelId() + }); setSelectedModel(item); form.current?.form?.resetFields(resetFieldsByModel); @@ -278,7 +300,13 @@ const AddModal: FC = (props) => { const handleOnSelectModelAfterEvaluate = (item: any) => { setIsGGUF(item.isGGUF); setSelectedModel(item); + setEvaluteState({ + state: EvaluateProccess.model, + requestModelId: updateRequestModelId() + }); + modelFileRef.current?.cancelRequest(); const modelInfo = onSelectModel(item, props.source); + if ( evaluateStateRef.current.state === EvaluateProccess.model && item.evaluateResult @@ -473,6 +501,7 @@ const AddModal: FC = (props) => { selectedModel={selectedModel} modelSource={props.source} onSelectFile={handleSelectModelFile} + updateEvaluteState={updateEvaluateState} collapsed={collapsed} gpuOptions={props.gpuOptions} > diff --git a/src/pages/llmodels/components/hf-model-file.tsx b/src/pages/llmodels/components/hf-model-file.tsx index 6d67fa84..39dd52a3 100644 --- a/src/pages/llmodels/components/hf-model-file.tsx +++ b/src/pages/llmodels/components/hf-model-file.tsx @@ -41,7 +41,8 @@ interface HFModelFileProps { modelSource: string; ref: any; gpuOptions?: any[]; - onSelectFile?: (file: any) => void; + onSelectFile?: (file: any, flagId: number) => void; + updateEvaluteState: (state: 'model' | 'form' | 'file') => number; onSelectFileAfterEvaluate?: (file: any) => void; } @@ -52,8 +53,13 @@ const includeReg = /\.(safetensors|gguf)$/i; const filterRegGGUF = /\.(gguf)$/i; const HFModelFile: React.FC = forwardRef((props, ref) => { - const { collapsed, modelSource, isDownload, onSelectFileAfterEvaluate } = - props; + const { + collapsed, + modelSource, + isDownload, + updateEvaluteState, + onSelectFileAfterEvaluate + } = props; const intl = useIntl(); const [isEvaluating, setIsEvaluating] = useState(false); const [dataSource, setDataSource] = useState({ @@ -76,9 +82,10 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { const axiosTokenRef = useRef(null); const checkTokenRef = useRef(null); const timer = useRef(null); + const parentRequestModelId = useRef(0); const handleSelectModelFile = (item: any) => { - props.onSelectFile?.(item); + props.onSelectFile?.(item, parentRequestModelId.current); setCurrent(item.path); currentPathRef.current = item.path; }; @@ -276,6 +283,7 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { handleSelectModelFile({}); return; } + parentRequestModelId.current = updateEvaluteState?.('file'); checkTokenRef.current?.cancel?.(); axiosTokenRef.current?.abort?.(); axiosTokenRef.current = new AbortController(); @@ -311,8 +319,17 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { setDataSource({ ...dataSource, fileList: list }); }; + const cancelRequest = () => { + axiosTokenRef.current?.abort?.(); + checkTokenRef.current?.cancel?.(); + if (timer.current) { + clearTimeout(timer.current); + } + }; + useImperativeHandle(ref, () => ({ - fetchModelFiles: handleFetchModelFiles + fetchModelFiles: handleFetchModelFiles, + cancelRequest: cancelRequest })); useEffect(() => { @@ -324,11 +341,7 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { useEffect(() => { return () => { - axiosTokenRef.current?.abort?.(); - checkTokenRef.current?.cancel?.(); - if (timer.current) { - clearTimeout(timer.current); - } + cancelRequest(); }; }, []); diff --git a/src/pages/llmodels/hooks/index.ts b/src/pages/llmodels/hooks/index.ts index 3f459eb0..26f397c5 100644 --- a/src/pages/llmodels/hooks/index.ts +++ b/src/pages/llmodels/hooks/index.ts @@ -607,7 +607,7 @@ export const useCheckCompatibility = () => { unlockWarningStatus, cancelEvaluate, handleBackendChangeBefore, - handleOnValuesChange: debounceHandleValuesChange, + handleOnValuesChange: handleOnValuesChange, handleEvaluateOnChange: handleOnValuesChange, clearCahceFormValues, warningStatus,