chore: check compatibility in edit
This commit is contained in:
@@ -5,6 +5,7 @@ import qs from 'query-string';
|
||||
import {
|
||||
CatalogItem,
|
||||
CatalogSpec,
|
||||
EvaluateResult,
|
||||
EvaluateSpec,
|
||||
FormData,
|
||||
GPUListItem,
|
||||
@@ -373,18 +374,11 @@ export async function evaluationsModelSpec(
|
||||
},
|
||||
options: { token: any }
|
||||
) {
|
||||
return {
|
||||
results: [
|
||||
{
|
||||
compatible: true
|
||||
}
|
||||
]
|
||||
};
|
||||
// return request<{ results: EvaluateResult[] }>(`${MODEL_EVALUATIONS}`, {
|
||||
// method: 'POST',
|
||||
// data,
|
||||
// cancelToken: options?.token
|
||||
// });
|
||||
return request<{ results: EvaluateResult[] }>(`${MODEL_EVALUATIONS}`, {
|
||||
method: 'POST',
|
||||
data,
|
||||
cancelToken: options?.token
|
||||
});
|
||||
}
|
||||
|
||||
// export const evaluationsModelSpec = async (
|
||||
|
||||
@@ -26,6 +26,7 @@ const CloseWrapper = styled.div`
|
||||
top: 6px;
|
||||
right: 18px;
|
||||
cursor: pointer;
|
||||
background-color: var(--ant-color-warning-bg);
|
||||
`;
|
||||
|
||||
const MessageWrapper = styled.div`
|
||||
|
||||
@@ -8,7 +8,6 @@ import { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
backendOptionsMap,
|
||||
excludeFields,
|
||||
getSourceRepoConfigValue,
|
||||
modelSourceMap
|
||||
} from '../config';
|
||||
@@ -44,6 +43,7 @@ const FormWrapper = styled.div`
|
||||
|
||||
type AddModalProps = {
|
||||
title: string;
|
||||
hasLinuxWorker?: boolean;
|
||||
action: PageActionType;
|
||||
open: boolean;
|
||||
source: SourceType;
|
||||
@@ -63,6 +63,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
open,
|
||||
onOk,
|
||||
onCancel,
|
||||
hasLinuxWorker,
|
||||
source,
|
||||
action,
|
||||
width = 600,
|
||||
@@ -79,6 +80,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
handleUpdateWarning,
|
||||
setWarningStatus,
|
||||
handleEvaluate,
|
||||
handleOnValuesChange,
|
||||
checkTokenRef,
|
||||
warningStatus
|
||||
} = useCheckCompatibility();
|
||||
@@ -103,14 +105,12 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
const handleOnSelectModel = (item: any, isgguf?: boolean) => {
|
||||
setSelectedModel(item);
|
||||
form.current?.handleOnSelectModel?.(item);
|
||||
console.log('isgguf+++++++', isgguf, item);
|
||||
if (!isgguf) {
|
||||
handleShowCompatibleAlert(item.evaluateResult);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnOk = async (allValues: FormData) => {
|
||||
console.log('allValues---------', allValues);
|
||||
if (submitAnyway.current) {
|
||||
onOk(allValues);
|
||||
return;
|
||||
@@ -181,38 +181,12 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnValuesChange = async (changedValues: any, allValues: any) => {
|
||||
const keys = Object.keys(changedValues);
|
||||
const isExcludeField = keys.some((key) => excludeFields.includes(key));
|
||||
const hasValue = keys.every((key) => {
|
||||
return !!changedValues[key];
|
||||
const onValuesChange = async (changedValues: any, allValues: any) => {
|
||||
handleOnValuesChange?.({
|
||||
changedValues,
|
||||
allValues,
|
||||
source: props.source
|
||||
});
|
||||
|
||||
// let hasExcludeField = false;
|
||||
// let allFieldsHaveValue = true;
|
||||
|
||||
// for (const key of keys) {
|
||||
// if (excludeFields.includes(key)) {
|
||||
// hasExcludeField = true;
|
||||
// break;
|
||||
// }
|
||||
// if (!changedValues[key]) {
|
||||
// allFieldsHaveValue = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (
|
||||
!isExcludeField &&
|
||||
hasValue &&
|
||||
!_.has(changedValues, 'backend') &&
|
||||
!_.has(changedValues, 'local_path')
|
||||
) {
|
||||
const values = form.current?.form.getFieldsValue?.();
|
||||
const data = getSourceRepoConfigValue(props.source, values);
|
||||
|
||||
const evalutionData = await handleEvaluate(data.values);
|
||||
handleShowCompatibleAlert?.(evalutionData);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
@@ -285,6 +259,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
<ColWrapper>
|
||||
<ColumnWrapper>
|
||||
<SearchModel
|
||||
hasLinuxWorker={hasLinuxWorker}
|
||||
modelSource={props.source}
|
||||
onSelectModel={handleOnSelectModel}
|
||||
></SearchModel>
|
||||
@@ -382,7 +357,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
gpuOptions={props.gpuOptions}
|
||||
modelFileOptions={props.modelFileOptions}
|
||||
onBackendChange={handleBackendChange}
|
||||
onValuesChange={handleOnValuesChange}
|
||||
onValuesChange={onValuesChange}
|
||||
></DataForm>
|
||||
</>
|
||||
</ColumnWrapper>
|
||||
|
||||
@@ -27,6 +27,7 @@ import SearchInput from './search-input';
|
||||
import SearchResult from './search-result';
|
||||
|
||||
interface SearchInputProps {
|
||||
hasLinuxWorker?: boolean;
|
||||
modelSource: string;
|
||||
isDownload?: boolean;
|
||||
setLoadingModel?: (flag: boolean) => void;
|
||||
@@ -36,7 +37,13 @@ interface SearchInputProps {
|
||||
|
||||
const SearchModel: React.FC<SearchInputProps> = (props) => {
|
||||
const intl = useIntl();
|
||||
const { modelSource, isDownload, setLoadingModel, onSelectModel } = props;
|
||||
const {
|
||||
modelSource,
|
||||
isDownload,
|
||||
hasLinuxWorker,
|
||||
setLoadingModel,
|
||||
onSelectModel
|
||||
} = props;
|
||||
const [dataSource, setDataSource] = useState<{
|
||||
repoOptions: any[];
|
||||
loading: boolean;
|
||||
@@ -57,12 +64,10 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
||||
const cacheRepoOptions = useRef<any[]>([]);
|
||||
const axiosTokenRef = useRef<any>(null);
|
||||
const checkTokenRef = useRef<any>(null);
|
||||
const evaluateTokenRef = useRef<any>(null);
|
||||
const searchInputRef = useRef<any>('');
|
||||
const filterGGUFRef = useRef<boolean | undefined>();
|
||||
const filterGGUFRef = useRef<boolean | undefined>(!hasLinuxWorker);
|
||||
const filterTaskRef = useRef<string>('');
|
||||
const timer = useRef<any>(null);
|
||||
const workerRef = useRef<any>(null);
|
||||
const modelFilesSortOptions = useRef<any[]>([
|
||||
{
|
||||
label: intl.formatMessage({ id: 'models.sort.trending' }),
|
||||
@@ -219,41 +224,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleEvaluateWorker = (params: {
|
||||
list: any[];
|
||||
modelSource: string;
|
||||
modelSourceMap: any;
|
||||
}) => {
|
||||
console.log('handleEvaluateWorker=======');
|
||||
const { list, modelSource, modelSourceMap } = params;
|
||||
workerRef.current?.terminate();
|
||||
setIsEvaluating(true);
|
||||
workerRef.current = new Worker(
|
||||
// @ts-ignore
|
||||
new URL('../apis/evaluateWorker.ts', import.meta.url)
|
||||
);
|
||||
workerRef.current.postMessage({
|
||||
list,
|
||||
modelSource,
|
||||
modelSourceMap
|
||||
});
|
||||
workerRef.current.onmessage = function (event: any) {
|
||||
const { success, resultList } = event.data;
|
||||
if (success) {
|
||||
setDataSource((pre) => {
|
||||
return {
|
||||
...pre,
|
||||
repoOptions: resultList
|
||||
};
|
||||
});
|
||||
}
|
||||
setIsEvaluating(false);
|
||||
handleOnSelectModel(resultList[0]);
|
||||
workerRef.current.terminate();
|
||||
workerRef.current = null;
|
||||
};
|
||||
};
|
||||
|
||||
const handleOnSearchRepo = async (sortType?: string) => {
|
||||
if (!SUPPORTEDSOURCE.includes(modelSource)) {
|
||||
return;
|
||||
|
||||
@@ -180,11 +180,13 @@ const Models: React.FC<ModelsProps> = ({
|
||||
const [openDeployModal, setOpenDeployModal] = useState<{
|
||||
show: boolean;
|
||||
width: number | string;
|
||||
hasLinuxWorker?: boolean;
|
||||
source: SourceType;
|
||||
gpuOptions: any[];
|
||||
modelFileOptions?: any[];
|
||||
}>({
|
||||
show: false,
|
||||
hasLinuxWorker: false,
|
||||
width: 600,
|
||||
source: modelSourceMap.huggingface_value as SourceType,
|
||||
gpuOptions: [],
|
||||
@@ -516,10 +518,14 @@ const Models: React.FC<ModelsProps> = ({
|
||||
}
|
||||
|
||||
const config = modalConfig[item.key];
|
||||
console.log('modelFileOptions:', modelFileOptions);
|
||||
const hasLinuxWorker = workerList.some(
|
||||
(worker) => worker.labels?.os === 'linux'
|
||||
);
|
||||
|
||||
if (config) {
|
||||
setOpenDeployModal({
|
||||
...config,
|
||||
hasLinuxWorker: hasLinuxWorker,
|
||||
gpuOptions: gpuDeviceList.current,
|
||||
modelFileOptions: modelFileOptions
|
||||
});
|
||||
@@ -835,6 +841,7 @@ const Models: React.FC<ModelsProps> = ({
|
||||
title={intl.formatMessage({ id: 'models.button.deploy' })}
|
||||
source={openDeployModal.source}
|
||||
width={openDeployModal.width}
|
||||
hasLinuxWorker={openDeployModal.hasLinuxWorker}
|
||||
gpuOptions={openDeployModal.gpuOptions}
|
||||
modelFileOptions={openDeployModal.modelFileOptions || []}
|
||||
onCancel={handleDeployModalCancel}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import AlertBlockInfo from '@/components/alert-info/block';
|
||||
import IconFont from '@/components/icon-font';
|
||||
import ModalFooter from '@/components/modal-footer';
|
||||
import SealAutoComplete from '@/components/seal-form/auto-complete';
|
||||
@@ -9,20 +8,23 @@ import { PageAction } from '@/config';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import useAppUtils from '@/hooks/use-app-utils';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form, Modal, Typography } from 'antd';
|
||||
import { Button, Form, Modal, Typography } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import {
|
||||
backendOptionsMap,
|
||||
backendTipsList,
|
||||
getSourceRepoConfigValue,
|
||||
localPathTipsList,
|
||||
modelSourceMap,
|
||||
ollamaModelOptions,
|
||||
sourceOptions
|
||||
} from '../config';
|
||||
import { FormData, ListItem } from '../config/types';
|
||||
import { useCheckCompatibility } from '../hooks';
|
||||
import AdvanceConfig from './advance-config';
|
||||
import ColumnWrapper from './column-wrapper';
|
||||
import CompatibilityAlert from './compatible-alert';
|
||||
|
||||
type AddModalProps = {
|
||||
title: string;
|
||||
@@ -51,17 +53,21 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
onCancel,
|
||||
updateFormInitials: { gpuOptions, isGGUF, data: formData }
|
||||
} = props || {};
|
||||
const {
|
||||
handleShowCompatibleAlert,
|
||||
handleUpdateWarning,
|
||||
setWarningStatus,
|
||||
handleEvaluate,
|
||||
generateGPUIds,
|
||||
handleOnValuesChange,
|
||||
checkTokenRef,
|
||||
warningStatus
|
||||
} = useCheckCompatibility();
|
||||
const { getRuleMessage } = useAppUtils();
|
||||
const [form] = Form.useForm();
|
||||
const intl = useIntl();
|
||||
const localPathCache = useRef<string>('');
|
||||
const [warningStatus, setWarningStatus] = useState<{
|
||||
show: boolean;
|
||||
message: string;
|
||||
}>({
|
||||
show: false,
|
||||
message: ''
|
||||
});
|
||||
const submitAnyway = useRef<boolean>(false);
|
||||
|
||||
const handleSetGPUIds = (backend: string) => {
|
||||
if (backend === backendOptionsMap.llamaBox) {
|
||||
@@ -77,37 +83,30 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const updateShowWarning = (backend: string) => {
|
||||
// trigger from local_path change or backend change
|
||||
const handleBackendChangeHook = async () => {
|
||||
const localPath = form.getFieldValue?.('local_path');
|
||||
const backend = form.getFieldValue?.('backend');
|
||||
|
||||
if (formData?.source !== modelSourceMap.local_path_value || !localPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isBlobFile = localPath?.split('/').pop()?.includes('sha256');
|
||||
const isOllamaModel = localPath?.includes('ollama');
|
||||
const isGGUFFile = localPath.endsWith('.gguf');
|
||||
|
||||
let warningMessage = '';
|
||||
|
||||
if (isBlobFile && isOllamaModel && backend === backendOptionsMap.llamaBox) {
|
||||
warningMessage = '';
|
||||
} else if (
|
||||
isBlobFile &&
|
||||
isOllamaModel &&
|
||||
backend !== backendOptionsMap.llamaBox
|
||||
) {
|
||||
warningMessage = 'models.form.ollama.warning';
|
||||
} else if (isGGUFFile && backend !== backendOptionsMap.llamaBox) {
|
||||
warningMessage = 'models.form.backend.warning';
|
||||
} else if (!isGGUFFile && backend === backendOptionsMap.llamaBox) {
|
||||
warningMessage = 'models.form.backend.warning.llamabox';
|
||||
}
|
||||
|
||||
setWarningStatus({
|
||||
show: !!warningMessage,
|
||||
message: warningMessage
|
||||
const res = handleUpdateWarning?.({
|
||||
backend,
|
||||
localPath: localPath,
|
||||
source: formData?.source as string
|
||||
});
|
||||
|
||||
if (!res.show) {
|
||||
const values = form.getFieldsValue?.();
|
||||
const data = getSourceRepoConfigValue(formData?.source as string, values);
|
||||
const evalutionData = await handleEvaluate(
|
||||
_.omit(data.values, [
|
||||
'cpu_offloading',
|
||||
'distributed_inference_across_workers'
|
||||
])
|
||||
);
|
||||
handleShowCompatibleAlert?.(evalutionData);
|
||||
} else {
|
||||
setWarningStatus?.(res);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBackendChange = (val: string) => {
|
||||
@@ -119,7 +118,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
}
|
||||
form.setFieldValue('backend_version', '');
|
||||
handleSetGPUIds(val);
|
||||
updateShowWarning(val);
|
||||
handleBackendChangeHook();
|
||||
};
|
||||
|
||||
const handleOnFocus = () => {
|
||||
@@ -289,37 +288,14 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
form.submit();
|
||||
};
|
||||
|
||||
const generateGPUIds = (data: FormData) => {
|
||||
const gpu_ids = _.get(data, 'gpu_selector.gpu_ids', []);
|
||||
if (!gpu_ids.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const result = _.reduce(
|
||||
gpu_ids,
|
||||
(acc: string[], item: string | string[], index: number) => {
|
||||
if (Array.isArray(item)) {
|
||||
acc.push(item[1]);
|
||||
} else if (index === 1) {
|
||||
acc.push(item);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
if (result.length) {
|
||||
return {
|
||||
gpu_selector: {
|
||||
gpu_ids: result
|
||||
}
|
||||
};
|
||||
}
|
||||
return {};
|
||||
const handleSubmitAnyway = async () => {
|
||||
submitAnyway.current = true;
|
||||
form.submit?.();
|
||||
};
|
||||
|
||||
const handleOk = (formdata: FormData) => {
|
||||
const handleOk = async (formdata: FormData) => {
|
||||
let obj = {};
|
||||
let submitData = {} as FormData;
|
||||
if (
|
||||
[backendOptionsMap.vllm, backendOptionsMap.voxBox].includes(
|
||||
formdata.backend
|
||||
@@ -332,26 +308,40 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
}
|
||||
if (formdata.scheduleType === 'manual') {
|
||||
const gpuSelector = generateGPUIds(formdata);
|
||||
onOk({
|
||||
submitData = {
|
||||
..._.omit(formdata, ['scheduleType']),
|
||||
categories: formdata.categories ? [formdata.categories] : [],
|
||||
worker_selector: null,
|
||||
gpu_selector: formdata.gpu_selector?.gpu_ids?.length
|
||||
? {
|
||||
gpu_ids: formdata.gpu_selector.gpu_ids
|
||||
}
|
||||
: null,
|
||||
...obj,
|
||||
...gpuSelector
|
||||
});
|
||||
};
|
||||
} else {
|
||||
onOk({
|
||||
submitData = {
|
||||
..._.omit(formdata, ['scheduleType']),
|
||||
categories: formdata.categories ? [formdata.categories] : [],
|
||||
gpu_selector: null,
|
||||
...obj
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (submitAnyway.current) {
|
||||
onOk(submitData);
|
||||
return;
|
||||
}
|
||||
|
||||
const evalutionData = await handleEvaluate(submitData);
|
||||
handleShowCompatibleAlert?.(evalutionData);
|
||||
if (evalutionData?.compatible) {
|
||||
onOk(submitData);
|
||||
}
|
||||
};
|
||||
|
||||
const onValuesChange = (changedValues: any, allValues: any) => {
|
||||
handleOnValuesChange({
|
||||
changedValues,
|
||||
allValues,
|
||||
source: formData?.source as string
|
||||
});
|
||||
};
|
||||
|
||||
const handleOnClose = () => {
|
||||
@@ -363,6 +353,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
form.setFieldsValue(formData);
|
||||
}
|
||||
if (!open) {
|
||||
checkTokenRef.current?.cancel?.();
|
||||
setWarningStatus({
|
||||
show: false,
|
||||
message: ''
|
||||
@@ -401,40 +392,55 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
}}
|
||||
footer={
|
||||
<>
|
||||
<ModalFooter onCancel={onCancel} onOk={handleSumit}></ModalFooter>
|
||||
<ModalFooter
|
||||
onCancel={onCancel}
|
||||
onOk={handleSumit}
|
||||
showOkBtn={!warningStatus.show}
|
||||
extra={
|
||||
warningStatus.show && (
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSubmitAnyway}
|
||||
style={{ width: '130px' }}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'models.form.submit.anyway'
|
||||
})}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
></ModalFooter>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<ColumnWrapper
|
||||
maxHeight={550}
|
||||
paddingBottom={warningStatus.show ? 70 : 0}
|
||||
paddingBottom={
|
||||
warningStatus.show
|
||||
? Array.isArray(warningStatus.message)
|
||||
? 100
|
||||
: 70
|
||||
: 0
|
||||
}
|
||||
footer={
|
||||
<div style={{ paddingInline: 12 }}>
|
||||
{warningStatus.show && (
|
||||
<AlertBlockInfo
|
||||
ellipsis={false}
|
||||
message={
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: intl.formatMessage({
|
||||
id: warningStatus.message
|
||||
})
|
||||
}}
|
||||
></span>
|
||||
}
|
||||
title={intl.formatMessage({
|
||||
id: 'common.text.tips'
|
||||
})}
|
||||
type="warning"
|
||||
></AlertBlockInfo>
|
||||
)}
|
||||
</div>
|
||||
<CompatibilityAlert
|
||||
showClose={true}
|
||||
onClose={() => {
|
||||
setWarningStatus({
|
||||
show: false,
|
||||
message: ''
|
||||
});
|
||||
}}
|
||||
warningStatus={warningStatus}
|
||||
contentStyle={{ paddingInline: 0 }}
|
||||
></CompatibilityAlert>
|
||||
}
|
||||
>
|
||||
<Form
|
||||
name="addModalForm"
|
||||
form={form}
|
||||
onFinish={handleOk}
|
||||
onValuesChange={onValuesChange}
|
||||
preserve={false}
|
||||
clearOnDestroy={true}
|
||||
initialValues={{
|
||||
|
||||
@@ -8,13 +8,21 @@ import { useEffect, useRef, useState } from 'react';
|
||||
import { evaluationsModelSpec, queryGPUList } from '../apis';
|
||||
import {
|
||||
backendOptionsMap,
|
||||
excludeFields,
|
||||
getSourceRepoConfigValue,
|
||||
modelSourceMap,
|
||||
setSourceRepoConfigValue
|
||||
} from '../config';
|
||||
import { EvaluateResult, GPUListItem, ListItem } from '../config/types';
|
||||
import {
|
||||
EvaluateResult,
|
||||
FormData,
|
||||
GPUListItem,
|
||||
ListItem
|
||||
} from '../config/types';
|
||||
|
||||
export const useGenerateFormEditInitialValues = () => {
|
||||
const gpuDeviceList = useRef<any[]>([]);
|
||||
const workerList = useRef<any[]>([]);
|
||||
|
||||
const generateCascaderOptions = (
|
||||
list: GPUListItem[],
|
||||
@@ -75,6 +83,7 @@ export const useGenerateFormEditInitialValues = () => {
|
||||
]);
|
||||
const gpuList = generateCascaderOptions(gpuData.items, workerData.items);
|
||||
gpuDeviceList.current = gpuList;
|
||||
workerList.current = workerData.items;
|
||||
return gpuList;
|
||||
};
|
||||
|
||||
@@ -115,7 +124,8 @@ export const useGenerateFormEditInitialValues = () => {
|
||||
return {
|
||||
getGPUList,
|
||||
generateFormValues,
|
||||
gpuDeviceList
|
||||
gpuDeviceList,
|
||||
workerList
|
||||
};
|
||||
};
|
||||
|
||||
@@ -331,6 +341,65 @@ export const useCheckCompatibility = () => {
|
||||
return warningMessage;
|
||||
};
|
||||
|
||||
const generateGPUIds = (data: FormData) => {
|
||||
const gpu_ids = _.get(data, 'gpu_selector.gpu_ids', []);
|
||||
if (!gpu_ids.length) {
|
||||
return {
|
||||
gpu_selector: null
|
||||
};
|
||||
}
|
||||
|
||||
const result = _.reduce(
|
||||
gpu_ids,
|
||||
(acc: string[], item: string | string[], index: number) => {
|
||||
if (Array.isArray(item)) {
|
||||
acc.push(item[1]);
|
||||
} else if (index === 1) {
|
||||
acc.push(item);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return {
|
||||
gpu_selector: {
|
||||
gpu_ids: result
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleOnValuesChange = async (params: {
|
||||
changedValues: any;
|
||||
allValues: any;
|
||||
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 evalutionData = await handleEvaluate({
|
||||
...data.values,
|
||||
...gpuSelector
|
||||
});
|
||||
handleShowCompatibleAlert?.(evalutionData);
|
||||
}
|
||||
};
|
||||
|
||||
const debounceHandleValuesChange = _.debounce(handleOnValuesChange, 300);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
checkTokenRef.current?.cancel();
|
||||
@@ -341,8 +410,10 @@ export const useCheckCompatibility = () => {
|
||||
return {
|
||||
handleShowCompatibleAlert,
|
||||
handleUpdateWarning,
|
||||
handleOnValuesChange: debounceHandleValuesChange,
|
||||
warningStatus,
|
||||
checkTokenRef,
|
||||
generateGPUIds,
|
||||
handleEvaluate,
|
||||
setWarningStatus
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ export interface ListItem {
|
||||
name: string;
|
||||
hostname: string;
|
||||
address: string;
|
||||
labels: object;
|
||||
labels: Record<string, string>;
|
||||
state: string;
|
||||
ip: string;
|
||||
state_message: string;
|
||||
|
||||
Reference in New Issue
Block a user