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